一. 在驱动中使用文件

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

Windows内核驱动中操作文件相关推荐

  1. linux 内核驱动中对文件的读写

    转载地址 http://www.360doc.com/content/12/1224/10/3478092_255969804.shtml 有时候需要在Linux kernel--大多是在需要调试的驱 ...

  2. linux内核驱动中对文件的读写 【转】

    本文转载自:http://blog.chinaunix.net/uid-13059007-id-5766941.html 有时候需要在Linux kernel--大多是在需要调试的驱动程序--中读写文 ...

  3. 在linux内核中操作文件的方法--使用get_fs()和set_fs(KERNEL_DS)

    在linux内核中操作文件的方法--使用get_fs()和set_fs(KERNEL_DS) #include <linux/kernel.h> #include <linux/mo ...

  4. 【梅哥的Ring0湿润插入教程】第一课Windows内核/驱动编程概述及应用、商业驱动保护软件原理分析...

    [梅哥的Ring0湿润插入教程] Email:mlkui@163.com 转载请注明出处,谢绝喷子记者等,如引起各类不适请自觉滚J8蛋! 第一课Windows内核/驱动编程概述及应用. 商业驱动保护软 ...

  5. 九七的Windows内核驱动开发 WIN10-2004+VS2019+WDK驱动开发环境安装及配置

    WIN10-2004+VS2019+WDK驱动开发环境安装及配置 一.定义介绍   本节介绍如何在Windows10系统(2004版本,操作步骤中有如何查看版本)中安装VS2019及WDK开发包,并进 ...

  6. 如何在Windows资源管理器中自定义文件夹背景和图标

    We've covered a lot of Windows tweaks over the years, and today we're going to show you how to custo ...

  7. 在Python中操作文件之truncate()方法的使用教程

    在Python中操作文件之truncate()方法的使用教程 这篇文章主要介绍了在Python中操作文件之truncate()方法的使用教程,是Python入门学习中的基础知识,需要的朋友可以参考下 ...

  8. python中seek函数的用法_在Python中操作文件之seek()方法的使用教程

    seek()方法在偏移设定该文件的当前位置.参数是可选的,默认为0,这意味着绝对的文件定位,它的值如果是1,这意味着寻求相对于当前位置,2表示相对于文件的末尾. 没有返回值.需要注意的是,如果该文件被 ...

  9. python文件处理seek()方法的参数是,在Python中操作文件之seek()方法的使用教程

    在Python中操作文件之seek()方法的使用教程 seek()方法在偏移设定该文件的当前位置.参数是可选的,默认为0,这意味着绝对的文件定位,它的值如果是1,这意味着寻求相对于当前位置,2表示相对 ...

最新文章

  1. 伸缩门遥控器c语言程序,急求求c++编程高手,求50的阶乘,要求结果是精确的整数,打印在屏幕上。...
  2. (chap8 确认访问用户身份的认证) 基于表单认证
  3. Python 之字典常用方法
  4. 续说零拷贝(Zero-Copy) - DMA技术
  5. 非阻塞IO与异步IO
  6. fps测试网页_对话斗鱼云游戏负责人:做强网页端,近3成为新增用户
  7. [No0000111]java9环境变量配置bat
  8. 计算机应用基础形考作业3Excel部分,计算机应用基础形考3,Excel部分
  9. 在读博士生 2 年实现 Nature、Science 双发,他来自这所高校!
  10. ERROR streaming.StreamExecution:createConsumer(ConsumerStrategy.scala:63)
  11. Java多线程学习九:如何正确关闭线程池?shutdown 和 shutdownNow 的区别
  12. python映射的主要特点_30 个 Python 语言的特点技巧
  13. iOS 越狱手机 ikeymonitor 插件检测
  14. android videoview截屏,android VideoView截屏黑屏解决方法
  15. android转移数据到苹果手机号码,苹果电话号码怎么转到新手机(简单教你两招轻松搞定)...
  16. 放大电路中反馈及类型的判断
  17. 知网摘要作者信息爬取和搜狗微信、搜狗新闻的爬虫
  18. 《国富论》阅读笔记05
  19. bootstrap冻结表头功能实现
  20. 静态条件下三轴加速度求角度的算法

热门文章

  1. JavaScript是如何工作的:与WebAssembly比较及其使用场景
  2. 进程、线程和上下文切换
  3. 美国中央情报局CIA正通过开发人工智能项目,收集与检索社交媒体情报
  4. 【转】strlen源码
  5. Android Studio-设置鼠标悬停显示方法声明
  6. 优化SqlServer--数据压缩
  7. mysql asyn 示例
  8. Android之使用Jsoup抓取网络数据
  9. WCF Data Service文章列表
  10. C#类方法中使用数组参数params关键字的作用