您的位置:首页 > 其它

Windows内核驱动中操作文件(转载一)

2013-07-17 18:34 411 查看
一. 在驱动中使用文件

在Windows执行体中,通过文件对象来代表文件,该文件对象是一种由对象管理器管理的执行体对象。例如:目录也是由文件对象代表的。
内核组件通过对象名来引用文件,即在文件的全路径前面加\DosDevices。(在Windows 2000及后续操作系统中,\??等同于\DosDevices)。例如,文件C:\WINDOWS\example.txt的对象名为\DosDevices\C:\WINDOWS\example.txt。你需要用对象名来打开文件以获取句柄。
对象名在下面会讲述。
使用文件步骤:
打开文件返回文件句柄。
调用合适的ZwXxxFile 函数以完成对文件的操作。
调用ZwClose函数关闭打开的文件句柄。
当打开一个指向文件的文件句柄时,Windows执行体就创建了一个文件对象来代表该文件,同时返回一个代表该对象的文件句柄。因此,对于单个文件来说,会存在多个文件对象的情况。同样,由于用户模式的应用程序可能会复制文件句柄,因此,对于同一个文件对象,也会存在多个文件句柄。只有当所有指向一个文件对象的文件句柄都关闭后,Windows执行体才会删除该文件对象。
二. 对象名

内核模式的对象可以是具名的或者是无名的。对象名是一个Unicode字符串,不管是用户模式还是内核模式,都可以额用它来引用对象。例如,\KernelObjects\LowMemoryCondition是一个指示在系统中总的可用内存偏低的标准事件对象名称。

用户模式和内核模式都利用对象名来打开指向对象的句柄。所有的后续操作都需要用该打开的句柄来完成。

如果对象是无名的,用户模式的组件无法打开指向该对象的句柄。内核模式则不同,它可以通过指针或句柄来引用无名对象。

具名对象被组织成层状结构。每个对象的命名同其父对象有关系。每个组件的对象名以反斜杠开头。例如,\KernelObjects对象是\KernelObjects\LowMemoryCondition对象的父对象。

    只有某些类型的对象才拥有子对象。下面列出其中的一部分:

1. 目录对象。对象管理器利用目录对象管理对象,例如,\KernelObjects是一个目录对象,它用来维护标准事件对象。目录对象不与真实的磁盘目录相对应。这里,目录的意思不是普通我们讲的文件夹目录的意思。

2. 磁盘驱动设备对象。这与磁盘文件(含常规目录)相对应。

3. 代表目录的文件对象。对应指定目录下的所有文件,此处的目录同常规理解的目录相同。

4. WDM驱动设备对象,具有自己的命名空间,可以用在驱动定义的方式中。

    文件具有对象名,其命名与\DosDevices有关。例如,文件C:\Directory\File的对象名为\DosDevices\C:\Directory\File

下表描述了一组典型的对象名

对象名
描述
\DosDevices

对象目录

\DosDevices\C:

代表C盘的设备对象

\DosDevices\C:\Directory

代表名为C:\Director的文件对象

\DosDevices\C:\Directory\File

代表名为C:\Directo\Filer的文件对象

驱动可以在指定的对象目录中创建具名对象

三. 打开指向文件的句柄

按如下步骤来打开指向文件的句柄:

1. 定义各一个OBJECT_ATTRIBUTES结构体变量,然后调用InitializeObjectAttributes函数初始化该变量。关键是设置改变量的ObjectName字段为文件对象名。

2. 调用IoCreateFile,
ZwCreateFile
, 或者 ZwOpenFile,传递上面定义的结构体变量,成功就会返回执行该文件的句柄。

注:驱动一般用ZwCreateFileZwOpenFileIoCreateFile很少使用

    当调用ZwCreateFileZwOpenFileIoCreateFile时,Windows执行体创建一个代表该文件的新的文件对象,并返回一个指向该对象的句柄。文件对象一直存在,知道你关闭了所有指向它的文件句柄。
四. 使用文件句柄操作文件

    下表列出了驱动中常用的利用文件句柄操作文件的函数
操作
函数
读文件
ZwReadFile
写文件
ZwWriteFile
读文件熟悉
ZwQueryInformationFile
设置文件熟悉
ZwSetInformationFile
 

五. 驱动中使用文件代码示例

 


/** @file 


*Copyright(C):     Information Technology Co Ltd., All rights reserved.


*@n


*@n 文件:            MyKFile.h


*@n 功能:            处理内核文件的操作


*@n 作者:            aurain(zhangqiushui@gmail.com) 2009-12-31


*/


#ifndef __MYKFILE_H__


#define __MYKFILE_H__




#include "debug.h"




/**


* 创建或打开文件


* @param lpFileHandle 返回打开的文件句柄指针


* @param usFileName 需要打开的文件路径,使用对象路径,如\\??\\c:\test.txt


* @param dwDesiredAccess 申请权限,可以用|(或)组合以下操作


写文件内容-FILE_WRITE_DATA,设置文件熟悉-FILE_WRITE_ATTRIBUTES,通用写-GENERIC_WRITE


读文件内容-FILE_READ_DATA,设置文件熟悉-FILE_READE_ATTRIBUTES,通用写-GENERIC_READ


删除文件-DELETE


全部权限-GENERIC_ALL


同步打开文件-SYNCHRONIZE


* @param dwShareAccess 共享方式(是指本代码打开这个文件时,允许别的代码同时打开这个文件所具有的权限


可以用|(或)组合以下操作


共享读-FILE_SHARE_READ


共享写-FILE_SHARE_WRITE


共享删除-FILE_SHARE_DELETE


* @param dwCreateDisposition 创建或打开文件的目的


新建文件-FILE_CREATE


打开文件-FILE_OPEN


打开或新建-FILE_OPEN_IF


覆盖-FILE_OVERWRITE


新建或覆盖-FILE_OVERWRITE_IF


新建或取代-FILE_SUPERSEDE


* @param dwCreateOptions 打开文件时选项设置


一般用FILE_NOT_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT


* @return 读取成功: STATUS_SUCCESS;读取失败:NTSTATUS error code


*/


__inline


NTSTATUS MyCreateFile(OUT PHANDLE lpFileHandle,


                      IN PUNICODE_STRING usFileName,


                      IN ULONG dwDesiredAccess,


                      IN ULONG dwShareAccess,


                      IN ULONG dwCreateDisposition,


                      IN ULONG dwCreateOptions)


{


    NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;


    OBJECT_ATTRIBUTES oaName;


    IO_STATUS_BLOCK iosBlock;


    if (lpFileHandle != NULL && usFileName != NULL && usFileName->Buffer != NULL)


    {


        if (PASSIVE_LEVEL != KeGetCurrentIrql()) 


        {


            return ntStatus;


        }


        InitializeObjectAttributes(&oaName,


            usFileName,


            OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,


            NULL,


            NULL);


        ntStatus = ZwCreateFile(lpFileHandle,


            dwDesiredAccess,


            &oaName,


            &iosBlock,


            NULL,


            FILE_ATTRIBUTE_NORMAL,


            dwShareAccess,


            dwCreateDisposition,


            dwCreateOptions,


            NULL,


            0);


        if (!NT_SUCCESS(ntStatus))


        {    


            DEBUG_ERROR(("[MyCreateFile]ZwCreateFile(%ws)failed with error:%08x\r\n", usFileName->Buffer, ntStatus));    


            return ntStatus;


        }


    }


    return ntStatus;


}




/**


* 关闭打开的文件句柄


* @param hFile 文件句柄


* @return 读取成功: STATUS_SUCCESS;读取失败:NTSTATUS error code


*/


__inline


NTSTATUS MyCloseFile(IN HANDLE hFile)


{


    return ZwClose(hFile);


}




/**


* 读取文件内容


* @param hFile 文件句柄


* @param pBuffer 缓冲区


* @param ulBufferSize 缓冲区大小


* @param pulBytesRead 实际读取的大小


* @return 读取成功: STATUS_SUCCESS;读取失败:NTSTATUS error code


*/


__inline


NTSTATUS MyReadFile(IN HANDLE hFile,


                    IN PVOID pBuffer,


                    IN ULONG ulBufferSize,


                    OUT PULONG pulBytesRead)


{


    IO_STATUS_BLOCK    iosBlock;


    NTSTATUS        ntStatus = STATUS_UNSUCCESSFUL;




    if (hFile == NULL || pBuffer == NULL)


    {


        return ntStatus;


    }


    if( PASSIVE_LEVEL < KeGetCurrentIrql())


    {    


        DEBUG_ERROR(("All kernel file operating functions must running on PASSIVE_LEVEL\r\n"));




        return ntStatus;


    }




    *pulBytesRead = 0;




    ntStatus = ZwReadFile(hFile,


        NULL,


        NULL,


        NULL,


        &iosBlock,


        pBuffer,


        ulBufferSize,


        NULL,


        NULL);




    if (NT_SUCCESS(ntStatus))


    {


        //获取实际读取到的大小


        *pulBytesRead = (ULONG)iosBlock.Information;


    }


    else


    {


        DEBUG_ERROR(("[MyReadFile]ZwReadFile failed with:%08x\r\n", ntStatus));


    }




    return ntStatus;


}




/**


* 向文件写入内容


* @param hFile 文件句柄


* @param pBuffer 缓冲区


* @param ulBufferSize 缓冲区大小


* @param pulBytesWrite 实际写入的大小


* @return 读取成功: STATUS_SUCCESS;读取失败:NTSTATUS error code


*/


__inline


NTSTATUS MyWriteFile(IN HANDLE hFile,


                     IN PVOID pBuffer,


                     IN ULONG ulBufferSize,


                     OUT PULONG pulBytesWrite)


{


    IO_STATUS_BLOCK    iosBlock;


    NTSTATUS        ntStatus = STATUS_UNSUCCESSFUL;


    


    if (hFile == NULL || pBuffer == NULL)


    {


        return ntStatus;


    }




    // All kernel file operating functions must running on PASSIVE_LEVEL


    if (PASSIVE_LEVEL !=  KeGetCurrentIrql()) 


    {


        return ntStatus;


    }




    *pulBytesWrite = 0;




    ntStatus = ZwWriteFile(hFile,


        NULL,


        NULL,


        NULL,


        &iosBlock,


        pBuffer,


        ulBufferSize,


        NULL,


        NULL);




    if (NT_SUCCESS(ntStatus))


    {


        *pulBytesWrite = (ULONG)iosBlock.Information;


    }


    else


    {


        DEBUG_ERROR(("[MyWriteFile]ZwWriteFile failed with:%08x\r\n", ntStatus));


    }




    return ntStatus;


}




#endif
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: