Windows内核驱动中操作文件 (转)
原文链接:http://www.cppblog.com/aurain/archive/2009/12/31/104563.html
一.在驱动中使用文件
在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,传递上面定义的结构体变量,成功就会返回执行该文件的句柄。
注:驱动一般用ZwCreateFile和ZwOpenFile,IoCreateFile很少使用
当调用ZwCreateFile,ZwOpenFile或IoCreateFile时,Windows执行体创建一个代表该文件的新的文件对象,并返回一个指向该对象的句柄。文件对象一直存在,知道你关闭了所有指向它的文件句柄。
四.使用文件句柄操作文件
下表列出了驱动中常用的利用文件句柄操作文件的函数
|
操作 |
函数 |
|
读文件 |
ZwReadFile |
|
写文件 |
ZwWriteFile |
|
读文件熟悉 |
ZwQueryInformationFile |
|
设置文件熟悉 |
ZwSetInformationFile |
五.驱动中使用文件代码示例
1 /**/ 2 /** 3 @file *Copyright(C): 4 Information Technology Co Ltd., All rights reserved. 5 *@n 6 *@n 文件: MyKFile.h 7 *@n 功能: 处理内核文件的操作 8 *@n 作者: aurain(zhangqiushui@gmail.com) 2009-12-31 9 */ 10 #ifndef __MYKFILE_H__ 11 define __MYKFILE_H__ 12 13 #include "debug.h" 14 15 /**/ 16 /** * 创建或打开文件 17 * @param lpFileHandle 返回打开的文件句柄指针 18 * @param usFileName 需要打开的文件路径,使用对象路径,如\\??\\c:\test.txt 19 * @param dwDesiredAccess 申请权限,可以用|(或)组合以下操作 20 写文件内容-FILE_WRITE_DATA, 21 设置文件属性-FILE_WRITE_ATTRIBUTES,通用写-GENERIC_WRITE 读文件内容-FILE_READ_DATA, 22 设置文件属性-FILE_READE_ATTRIBUTES,通用写-GENERIC_READ 删除文件-DELETE 全部权限-GENERIC_ALL 同步打开文件-SYNCHRONIZE 23 * @param dwShareAccess 共享方式(是指本代码打开这个文件时,允许别的代码同时打开这个文件所具有的权限 可以用|(或)组合以下操作 24 共享读-FILE_SHARE_READ 25 共享写-FILE_SHARE_WRITE 26 共享删除-FILE_SHARE_DELETE 27 * @param dwCreateDisposition 创建或打开文件的目的 28 新建文件-FILE_CREATE 29 打开文件-FILE_OPEN 30 打开或新建-FILE_OPEN_IF 31 覆盖-FILE_OVERWRITE 32 新建或覆盖-FILE_OVERWRITE_IF 33 新建或取代-FILE_SUPERSEDE 34 * @param dwCreateOptions 打开文件时选项设置 一般用FILE_NOT_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT 35 36 * @return 读取成功: STATUS_SUCCESS;读取失败:NTSTATUS error code */ 37 38 __inline NTSTATUS MyCreateFile(OUT PHANDLE lpFileHandle, 39 IN PUNICODE_STRING usFileName, 40 IN ULONG dwDesiredAccess, 41 IN ULONG dwShareAccess, 42 IN ULONG dwCreateDisposition, 43 IN ULONG dwCreateOptions) { 44 45 NTSTATUS ntStatus = STATUS_UNSUCCESSFUL; 46 OBJECT_ATTRIBUTES oaName; 47 IO_STATUS_BLOCK iosBlock; 48 if (lpFileHandle != NULL && usFileName != NULL && usFileName->Buffer != NULL){ 49 if (PASSIVE_LEVEL != KeGetCurrentIrql()) { 50 return ntStatus; 51 } 52 InitializeObjectAttributes(&oaName,usFileName,OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL,NULL); 53 ntStatus = ZwCreateFile(lpFileHandle,dwDesiredAccess,&oaName,&iosBlock,NULL,FILE_ATTRIBUTE_NORMAL,dwShareAccess,dwCreateDisposition,dwCreateOptions,NULL,0); 54 if (!NT_SUCCESS(ntStatus)) { 55 DEBUG_ERROR(("[MyCreateFile]ZwCreateFile(%ws)failed with error:%08x\r\n", usFileName->Buffer, ntStatus)); 56 return ntStatus; 57 } 58 } 59 return ntStatus; 60 } 61 62 63 /**/ 64 /** * 关闭打开的文件句柄 65 * @param hFile 文件句柄 66 * @return 读取成功: STATUS_SUCCESS;读取失败:NTSTATUS error code 67 */ 68 69 __inline NTSTATUS MyCloseFile(IN HANDLE hFile) { 70 return ZwClose(hFile); 71 } 72 73 /**/ 74 75 /** * 读取文件内容 76 * @param hFile 文件句柄 77 * @param pBuffer 缓冲区 78 * @param ulBufferSize 缓冲区大小 79 * @param pulBytesRead 实际读取的大小 80 * @return 读取成功: STATUS_SUCCESS;读取失败:NTSTATUS error code 81 */ 82 83 __inline NTSTATUS MyReadFile(IN HANDLE hFile,IN PVOID pBuffer,IN ULONG ulBufferSize,OUT PULONG pulBytesRead) { 84 IO_STATUS_BLOCK iosBlock;NTSTATUSntStatus = STATUS_UNSUCCESSFUL; 85 if (hFile == NULL || pBuffer == NULL){ 86 return ntStatus; 87 } 88 if( PASSIVE_LEVEL < KeGetCurrentIrql()){ 89 DEBUG_ERROR(("All kernel file operating functions must running on PASSIVE_LEVEL\r\n")); 90 return ntStatus; 91 } 92 *pulBytesRead = 0; 93 ntStatus = ZwReadFile(hFile, NULL, NULL, NULL, &iosBlock, pBuffer, ulBufferSize, NULL, NULL); 94 if (NT_SUCCESS(ntStatus)){ 95 //获取实际读取到的大小 96 *pulBytesRead = (ULONG)iosBlock.Information; 97 }else{ 98 DEBUG_ERROR(("[MyReadFile]ZwReadFile failed with:%08x\r\n", ntStatus)); 99 } 100 return ntStatus; 101 } 102 103 /**/ 104 /** * 向文件写入内容 105 * @param hFile 文件句柄 106 * @param pBuffer 缓冲区 107 * @param ulBufferSize 缓冲区大小 108 * @param pulBytesWrite 实际写入的大小 109 * @return 读取成功: STATUS_SUCCESS;读取失败:NTSTATUS error code 110 */ 111 __inline NTSTATUS MyWriteFile(IN HANDLE hFile, IN PVOID pBuffer, IN ULONG ulBufferSize, OUT PULONG pulBytesWrite) { 112 IO_STATUS_BLOCK iosBlock;NTSTATUSntStatus = STATUS_UNSUCCESSFUL; 113 if (hFile == NULL || pBuffer == NULL){ 114 return ntStatus; 115 } 116 // All kernel file operating functions must running on PASSIVE_LEVEL 117 if (PASSIVE_LEVEL != KeGetCurrentIrql()) { 118 return ntStatus; 119 } 120 *pulBytesWrite = 0; 121 ntStatus = ZwWriteFile(hFile, NULL, NULL, NULL, &iosBlock, pBuffer, ulBufferSize, NULL, NULL); 122 if (NT_SUCCESS(ntStatus)){ 123 *pulBytesWrite = (ULONG)iosBlock.Information; 124 }else{ 125 DEBUG_ERROR(("[MyWriteFile]ZwWriteFile failed with:%08x\r\n", ntStatus)); 126 } 127 return ntStatus; 128 } 129 #endif
每天进步一点点,有时间先装修空间哈

浙公网安备 33010602011771号