【驱动开发】Windows内核驱动中操作文件

一. 在驱动中使用文件

在Windows执行体中,通过文件对象来代表文件,该文件对象是一种由对象管理器管理的执行体对象。例如:目录也是由文件对象代表的。

内核组件通过对象名来引用文件,即在文件的全路径前面加\DosDevices。(在Windows 2000及后续操作系统中,\??等同于\DosDevices)。例如,文件C:\WINDOWS\example.txt的对象名为\DosDevices\C:\WINDOWS\example.txt。你需要用对象名来打开文件以获取句柄。

对象名在下面会讲述。

使用文件步骤:

  1. 打开文件返回文件句柄。

  2. 调用合适的ZwXxxFile 函数以完成对文件的操作。

  3. 调用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. 调用IoCreateFileZwCreateFile, 或者 ZwOpenFile,传递上面定义的结构体变量,成功就会返回执行该文件的句柄。

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

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

四. 使用文件句柄操作文件

    下表列出了驱动中常用的利用文件句柄操作文件的函数

操作

函数

读文件

ZwReadFile

写文件

ZwWriteFile

读文件属性

ZwQueryInformationFile

设置文件属性

ZwSetInformationFile

 

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

 

[cpp]  view plain copy print ?
  1. /** @file  
  2. *Copyright(C):     Information Technology Co Ltd., All rights reserved. 
  3. *@n 
  4. *@n 文件:            MyKFile.h 
  5. *@n 功能:            处理内核文件的操作 
  6. *@n 作者:            aurain([email protected]) 2009-12-31 
  7. */  
  8. #ifndef __MYKFILE_H__  
  9. #define __MYKFILE_H__  
  10.   
  11. #include "debug.h"  
  12.   
  13. /** 
  14. * 创建或打开文件 
  15. * @param lpFileHandle 返回打开的文件句柄指针 
  16. * @param usFileName 需要打开的文件路径,使用对象路径,如\\??\\c:\test.txt 
  17. * @param dwDesiredAccess 申请权限,可以用|(或)组合以下操作 
  18. 写文件内容-FILE_WRITE_DATA,设置文件属性-FILE_WRITE_ATTRIBUTES,通用写-GENERIC_WRITE 
  19. 读文件内容-FILE_READ_DATA,设置文件属性-FILE_READE_ATTRIBUTES,通用写-GENERIC_READ 
  20. 删除文件-DELETE 
  21. 全部权限-GENERIC_ALL 
  22. 同步打开文件-SYNCHRONIZE 
  23. * @param dwShareAccess 共享方式(是指本代码打开这个文件时,允许别的代码同时打开这个文件所具有的权限 
  24. 可以用|(或)组合以下操作 
  25. 共享读-FILE_SHARE_READ 
  26. 共享写-FILE_SHARE_WRITE 
  27. 共享删除-FILE_SHARE_DELETE 
  28. * @param dwCreateDisposition 创建或打开文件的目的 
  29. 新建文件-FILE_CREATE 
  30. 打开文件-FILE_OPEN 
  31. 打开或新建-FILE_OPEN_IF 
  32. 覆盖-FILE_OVERWRITE 
  33. 新建或覆盖-FILE_OVERWRITE_IF 
  34. 新建或取代-FILE_SUPERSEDE 
  35. * @param dwCreateOptions 打开文件时选项设置 
  36. 一般用FILE_NOT_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT 
  37. * @return 读取成功: STATUS_SUCCESS;读取失败:NTSTATUS error code 
  38. */  
  39. __inline  
  40. NTSTATUS MyCreateFile(OUT PHANDLE lpFileHandle,  
  41.                       IN PUNICODE_STRING usFileName,  
  42.                       IN ULONG dwDesiredAccess,  
  43.                       IN ULONG dwShareAccess,  
  44.                       IN ULONG dwCreateDisposition,  
  45.                       IN ULONG dwCreateOptions)  
  46. {  
  47.     NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;  
  48.     OBJECT_ATTRIBUTES oaName;  
  49.     IO_STATUS_BLOCK iosBlock;  
  50.     if (lpFileHandle != NULL && usFileName != NULL && usFileName->Buffer != NULL)  
  51.     {  
  52.         if (PASSIVE_LEVEL != KeGetCurrentIrql())   
  53.         {  
  54.             return ntStatus;  
  55.         }  
  56.         InitializeObjectAttributes(&oaName,  
  57.             usFileName,  
  58.             OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,  
  59.             NULL,  
  60.             NULL);  
  61.         ntStatus = ZwCreateFile(lpFileHandle,  
  62.             dwDesiredAccess,  
  63.             &oaName,  
  64.             &iosBlock,  
  65.             NULL,  
  66.             FILE_ATTRIBUTE_NORMAL,  
  67.             dwShareAccess,  
  68.             dwCreateDisposition,  
  69.             dwCreateOptions,  
  70.             NULL,  
  71.             0);  
  72.         if (!NT_SUCCESS(ntStatus))  
  73.         {      
  74.             DEBUG_ERROR(("[MyCreateFile]ZwCreateFile(%ws)failed with error:%08x\r\n", usFileName->Buffer, ntStatus));      
  75.             return ntStatus;  
  76.         }  
  77.     }  
  78.     return ntStatus;  
  79. }  
  80.   
  81.   
  82.   
  83. /** 
  84. * 关闭打开的文件句柄 
  85. * @param hFile 文件句柄 
  86. * @return 读取成功: STATUS_SUCCESS;读取失败:NTSTATUS error code 
  87. */  
  88. __inline  
  89. NTSTATUS MyCloseFile(IN HANDLE hFile)  
  90. {  
  91.     return ZwClose(hFile);  
  92. }  
  93.   
  94. /** 
  95. * 读取文件内容 
  96. * @param hFile 文件句柄 
  97. * @param pBuffer 缓冲区 
  98. * @param ulBufferSize 缓冲区大小 
  99. * @param pulBytesRead 实际读取的大小 
  100. * @return 读取成功: STATUS_SUCCESS;读取失败:NTSTATUS error code 
  101. */  
  102. __inline  
  103. NTSTATUS MyReadFile(IN HANDLE hFile,  
  104.                     IN PVOID pBuffer,  
  105.                     IN ULONG ulBufferSize,  
  106.                     OUT PULONG pulBytesRead)  
  107. {  
  108.     IO_STATUS_BLOCK    iosBlock;  
  109.     NTSTATUS        ntStatus = STATUS_UNSUCCESSFUL;  
  110.   
  111.     if (hFile == NULL || pBuffer == NULL)  
  112.     {  
  113.         return ntStatus;  
  114.     }  
  115.     if( PASSIVE_LEVEL < KeGetCurrentIrql())  
  116.     {      
  117.         DEBUG_ERROR(("All kernel file operating functions must running on PASSIVE_LEVEL\r\n"));  
  118.   
  119.         return ntStatus;  
  120.     }  
  121.   
  122.     *pulBytesRead = 0;  
  123.   
  124.     ntStatus = ZwReadFile(hFile,  
  125.         NULL,  
  126.         NULL,  
  127.         NULL,  
  128.         &iosBlock,  
  129.         pBuffer,  
  130.         ulBufferSize,  
  131.         NULL,  
  132.         NULL);  
  133.   
  134.     if (NT_SUCCESS(ntStatus))  
  135.     {  
  136.         //获取实际读取到的大小  
  137.         *pulBytesRead = (ULONG)iosBlock.Information;  
  138.     }  
  139.     else  
  140.     {  
  141.         DEBUG_ERROR(("[MyReadFile]ZwReadFile failed with:%08x\r\n", ntStatus));  
  142.     }  
  143.   
  144.     return ntStatus;  
  145. }  
  146.   
  147. /** 
  148. * 向文件写入内容 
  149. * @param hFile 文件句柄 
  150. * @param pBuffer 缓冲区 
  151. * @param ulBufferSize 缓冲区大小 
  152. * @param pulBytesWrite 实际写入的大小 
  153. * @return 读取成功: STATUS_SUCCESS;读取失败:NTSTATUS error code 
  154. */  
  155. __inline  
  156. NTSTATUS MyWriteFile(IN HANDLE hFile,  
  157.                      IN PVOID pBuffer,  
  158.                      IN ULONG ulBufferSize,  
  159.                      OUT PULONG pulBytesWrite)  
  160. {  
  161.     IO_STATUS_BLOCK    iosBlock;  
  162.     NTSTATUS        ntStatus = STATUS_UNSUCCESSFUL;  
  163.       
  164.     if (hFile == NULL || pBuffer == NULL)  
  165.     {  
  166.         return ntStatus;  
  167.     }  
  168.   
  169.     // All kernel file operating functions must running on PASSIVE_LEVEL  
  170.     if (PASSIVE_LEVEL !=  KeGetCurrentIrql())   
  171.     {  
  172.         return ntStatus;  
  173.     }  
  174.   
  175.     *pulBytesWrite = 0;  
  176.   
  177.     ntStatus = ZwWriteFile(hFile,  
  178.         NULL,  
  179.         NULL,  
  180.         NULL,  
  181.         &iosBlock,  
  182.         pBuffer,  
  183.         ulBufferSize,  
  184.         NULL,  
  185.         NULL);  
  186.   
  187.     if (NT_SUCCESS(ntStatus))  
  188.     {  
  189.         *pulBytesWrite = (ULONG)iosBlock.Information;  
  190.     }  
  191.     else  
  192.     {  
  193.         DEBUG_ERROR(("[MyWriteFile]ZwWriteFile failed with:%08x\r\n", ntStatus));  
  194.     }  
  195.   
  196.     return ntStatus;  
  197. }  
  198.   
  199. #endif  

你可能感兴趣的:(【驱动开发】Windows内核驱动中操作文件)