Windows内核模式开发笔记_file_supersede_leehq的博客-程序员秘密

技术标签: file  编译器  开发(高级)  ddk  存储  windows  list  

* 通过 NTSTATUS 获得相应的字符串
    使用函数RtlNtStatusToDosError可以获得与NTSTATUS相对应的Windows错误码。

    微软网站上说用API函数 FormatMessage 可获得相应的字符串,但是在调用前必须先用 LoadLibrary 载入 "NTDLL.DLL"。
    文章链接 -
http://support.microsoft.com/kb/259693

 

* 内存操作
    尽量不要使用C运行时提供的内存操作函数,应该使用 RtlCopyMemory;RtlFillMemory;RtlZeroMemory 以便于程序移植。

 

* 字符串操作
    尽量不要使用C运行时提供的字符串操作函数,应该使用 RtlString{xxx};RtlUnicodeString{xxx} 系列安全字符串操作函数,以便于程序移植。
    在包含安全字符串操作的头文件 ntstrsafe.h 之前必须定义宏 NTSTRSAFE_LIB,以下是 ntstrsafe.h 里的原文:
        //
        // The following steps are *REQUIRED* if ntstrsafe.h is used for drivers on:
        //     Windows 2000
        //     Windows Millennium Edition
        //     Windows 98 Second Edition
        //     Windows 98
        //
        // 1. #define NTSTRSAFE_LIB before including this header file.
        // 2. Add ntstrsafe.lib to the TARGET_LIBS line in SOURCES
        //
        // Drivers running on XP and later can skip these steps to create a smaller
        // driver.
        //

 

* 卷上的文件系统路径
    用户模式下的文件系统路径必须在前面加上"\??\"才能被内核模式的程序识别,例如"\??\C:\file"。

 

* 操作文件
    用 Zw{xxx}File 系列函数可以实现类似用户模式的文件操作。

 

* 获得系统时间
    用 KeQuerySystemTime 获得从 1601-01-01 以来的时间计数,单位为100纳秒,时区为格林威治。
    用 ExSystemTimeToLocalTime 将格林威治时间值转换成本地时区时间值。
    用 RtlTimeToTimeFields 将时间值转换成 TIME_FIELDS 结构。

 

* 测试当前操作系统的版本信息
    使用 PsGetVersion 获得操作系统版本。
    最低兼容到Windows XP的程序应该使用 RtlGetVersion 获得操作系统版本。
    使用 RtlIsNtDdiVersionAvailable 获得设备驱动接口版本。

 

* 文件系统驱动处理相对路径
    处理IRP_MJ_CREATE时,如果IRP的FileObject使用的相对路径,可以通过FileObject的RelatedFileObject获得相对路径所在的目录信息。

 

* 链表操作
    Windows DDK提供了SINGLE_LIST_ENTRY结构和LIST_ENTRY结构来支持单向和双向的链表操作。

 

* 操作线程间的共享资源
    在用户模式下通常使用互斥对象来确保共享资源在同一时间下只能一个线程访问,其它要访问共享资源的线程则进入睡眠状态。
    在内核模式中虽然也有互斥对象,但是还提供了自旋锁。
    自旋锁和互斥对象的功能类似,但是它不会让等待的线程进入睡眠状态,而是让等待的线程一直在循环查询自旋锁的状态。
    所以当访问共享资源的过程占用时间很短时,应该使用自旋锁,这样可以降低系统开销。

    注意:获得自旋锁的所有权时,当前IRQL会变为DISPATCH_LEVEL,直到释放所有权为止。

 

* FILE_SUPERSEDE 和 FILE_OVERWRITE_IF 的区别
    ZwCreateFile 函数的 CreateDisposition 参数可以设置为 FILE_SUPERSEDE 或者 FILE_OVERWRITE_IF,似乎都是覆盖老文件,但还是有一些小区别的。
    FILE_SUPERSEDE - 先将老文件删除,在新建一个文件。
    FILE_OVERWRITE_IF - 不删除老文件,只是清空它的内容,其它属性保留。

 

* 线程操作
    使用 PsCreateSystemThread 创建线程。
    使用 PsGetCurrentThread 获得当前线程句柄。
    使用 KeDelayExecutionThread 让当前线程睡眠一段指定的时间。

 

* 内核模式里的几种互斥对象
    Mutex - 是标准的信号对象,支持所有等待信号相关的函数;可以在一个线程内递归获取所有权而不被阻塞;操作速度慢;所有者能够收到APC;所有者不能被换出内存。
    Fast Mutex - 不是标准的信号对象;不能被递归获取所有权;操作速度快;取得所有权后IRQL会变为APC_LEVEL直到释放所有权为止;从Windows 2000开始提供。
    Guarded Mutexes - 不是标准的信号对象;不能被递归获取所有权;操作速度更快;所有者不能够收到APC;从Windows Server 2003开始提供。

 

* 访问注册表
    所有注册表路径必须以"/REGISTRY"开头,可打开的根注册表键有"/REGISTRY/MACHINE"和"/REGISTRY/USERS",分别对应用户模式下的"HKEY_LOCAL_MACHINE"和"MACHINE HKEY_USERS"。
    用 Zw{xxx}Key 和 Zw{xxx}Value 系列函数可以实现类似用户模式的注册表操作。

 

* 用DDK工具编译时显示编译器警告信息

    使用DDK的build编译程序时默认情况下不会显示编译的警告信息,需要加上-w参数才行。

 

* 打开文件系统对象的特殊方式

    文件系统驱动接收到IRP请求IRP_MJ_CREATE时,如果IrpSp->Flags指定了SL_OPEN_TARGET_DIRECTORY,则表示并不是真的要打开指定的文件系统对象,而是要检查对象是否可以删除已经它所在的目录是否可以进行创建操作。 通常这样的请求会发生在重命名文件系统对象之前。

 

* 通过句柄获得对象信息

    通过函数ObReferenceObjectByHandle可以获得句柄引用的对象信息。

 

* IRQL

    IRQL(Interrupt ReQuest Level)表示代码运行的中断请求等级,Windows定义了0-31个IRQL,除了16个硬件中断,还虚拟了16个软件中断,IRQL越高代码运行的优先级也就越高。

    可以使用函数KeGetCurrentIrql、KeLowerIrql和KeRaiseIrql对IRQL进行相应的操作。

 

* 奇怪的IO控制码

    存储设备的驱动程序有时候会收到0x004D0008这类IO控制码,通过控制码的组成方式能够得出设备类型为0x4D,但是在ntddk.h里并没有发现定义为0x4D的设备类型。其实这是存储设备加载管理器的设备类型,打开mountmgr.h查看,可以发现如下宏定义:

    #define MOUNTDEVCONTROLTYPE  ((ULONG) 'M')

    这就是存储设备加载管理器的设备类型,字母'M'的ASCII码就是0x4D,这个文件里还定义了存储设备加载管理器的IO控制码。

 

* 获得一个内核对象的名称

    很多内核对象在创建时都指定了名称,例如驱动程序对象、设备对象和文件对象等,可以通过调用函数ObQueryNameString获得指定对象的完整名称。 

 

 

* 获得操作系统版本

    通过函数PsGetVersion可以获得操作系统版本。

 

* 获得当前进程的信息

    通过函数PsGetCurrentProcessId可以获得当前进程的ID,通过调用函数ZwQueryInformationProcess获得进程的详细信息,包括可执行文件的路径等。 


* 获得卷的设备名相应的MS-DOS名称

    通过调用函数RtlVolumeDeviceToDosName可以获得一个卷的MS-DOS名称。 


* 关于IRP_MJ_READ和IRP_MJ_WRITE的注意

    在这两种IRP的分派例程中,如果已经调用IoMarkIrpPending函数标记IRP,例程的返回值只能为STATUS_PENDING,绝对不能再调用IoCompleteRequest函数把IRP完成,也不能返回其它的状态码,否则系统会抛出异常MULTIPLE_IRP_COMPLETE_REQUESTS(0x00000044)。 


 

 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/leehq/article/details/3858766

智能推荐

LSPI 小车上山实例_小车上山问题_oni小涛的博客-程序员秘密

《Reinforcement Learning: State-of-the-Art》 第三章 Least-Squares Methods for Policy Iteration 第五节 举例说明最小二乘法对策略迭代的行为。将离线LSPI和在线乐观LSPI两种方法,应用于car-on-the-hill问题(Moore和Atkeson,1995),这是近似强化学习的经典benchmark。由...

Vijos p1165 火烧赤壁 离散化+单调栈_weixin_30535913的博客-程序员秘密

题目链接:https://vijos.org/p/1165题意:输入n(n <= 20,000)段线段的端点,问所有线段的长度总和为多少?input:3-1 15 112 9output:11思路:将左右端点分成一个一个的点,并且标记输入的id.即弄成一个pair;排序之后模拟加点,左端点直接入栈,右端点若是栈顶端点对应的右端点时,栈顶元素出栈,那这时是否...

【玩转cocos2d-x之一】V2.2.0版本开发环境配置_cocos2d 2.0 运行配置_Niteip的博客-程序员秘密

我的上一篇关于解决cocos2d添加项目模版的帖子,今天我在公司环境使用时,发现不行,我明白了那个方法的局限性。搜了一下,cocos2d-x 2.1.4以后,都用phthon建立项目,虽然不习惯,但是这个方便跨平台,现转一篇文章转自:http://blog.csdn.net/jackystudio/article/details/12419387现在cocos2d-x处在上

小白程序员该看什么书?书单推荐_0基础程序员适合看什么书_zhanglu_1024的博客-程序员秘密

前段时间,有位朋友的弟弟也想从事“程序开发“这份职业,托人问到了我,应该看些什么书籍? 很多新入门的小白同学都有这样的疑惑,统一做一篇推荐博文,希望可以帮助到有需要的人。 分类:首先还是需要分下类,如果你是类似于我朋友弟弟,非科班出身,那么你需要先学习一些必要的入门书籍夯实下基础。如果你是科班出身,或者目前正在就读相关专业,可以跳过第一段。 一、大体了解(非科班出身必读) 计算机概论:泛读即可。 ...

(五)springcloud从入门到放弃-Feign深入_放弃feign_扶苏l的博客-程序员秘密

Feign 的实战运用Feign 默认Client 的替换Feign 在默认情况下使用的是 JDK 原生的 URLConnection 发送 http 请求,没有连接池,但是每个地址会保持一个长连接,即利用 http 的 persistence Connection我们可以使用 Apache 的 HttpClient 替换掉 Feign 原生的 HttpClient,通过设置连接池,超时时...

使用subprocess.py报in __init__ restore_signals, start_new_session的错误_sir_chen的博客-程序员秘密

使用subprocess.py报in __init__ restore_signals, start_new_session的错误今天在运行Python代码的时候遇到subprocess.py报错:File "D:\code\video.py", line 76, in _parse_infos proc = sp.Popen(cmd, **popen_params)File "D:\Program Files\Python36\lib\subprocess.py", line 709

随便推点

大直播时代,P2P才是降低成本的必杀技 _weixin_33928137的博客-程序员秘密

在流媒体传输分发领域,CDN和P2P一直是经常被拿来进行对比和讨论的一大热点,虽然不少大型视频企业目前同时使用着CDN和P2P两套分发机制,但相对于CDN,很多人对于P2P技术知之甚少。整体来说,P2P技术一方面能够极大缓解CDN“中心化”的边缘节点服务器压力,提升CDN网络在...

数据泵导出碰到ORA-600(kcbz_check_objd_typ_3)错误_普通网友的博客-程序员秘密

客户的数据库崩溃,被强制打开后,使用数据泵导出出现ORA-600(kcbz_check_objd_typ_3)错误。以前碰到过一个ORA-600(kcbz...

虚拟机系统错误篇 - BusyBox v1.27.2 (ubuntu 1:1.27.2-2ubuntu3) built-in shell (ash)_IT B业生的博客-程序员秘密

1、错误内容BusyBox v1.27.2 (ubuntu 1:1.27.2-2ubuntu3) built-in shell (ash)Enter 'help ' for a list ofbuilt-in commands .2、错误分析BusyBox 是一个集成了最常用Linux命令和工具的软件,而以上报错提示:在 /dev/sda1 出现了文件系统的错误,需要用fsck进行手动修复。3、解决方法命令:# 修复文件系统错误(initramfs)fsck -y /

机器学习——特征工程之数据相关性_特征工程相关性分析_macan_dct的博客-程序员秘密

机器学习——特征工程之数据相关性前言图表相关性协方差和协方差矩阵代码实现相关系数1、皮尔逊相关系数( Pearson correlation coefficient)2、斯皮尔曼相关性系数、秩相关系数(spearman correlation coefficient)3、Kendall Rank(肯德尔等级)相关系数信息熵和互信息前言在样本属性很多的数据集中,一定会存在一些与标签关系不那么强的...

java-数据结构-哈夫曼编码(Huffman Coding)_怪我冷i的博客-程序员秘密

java-数据结构-哈夫曼编码概念哈夫曼编码(Huffman Coding),又称霍夫曼编码,是一种编码方式,哈夫曼编码是可变字长编码(VLC)的一种。Huffman于1952年提出一种编码方法,该方法完全依据字符出现概率来构造异字头的平均长度最短的码字,有时称之为最佳编码,一般就叫做Huffman编码(有时也称为霍夫曼编码)。代码package com.huffmancode;imp...

使用 docker-compose 部署多机 RabbitMQ 集群_yongxinz的博客-程序员秘密

本文介绍 RabbitMQ 集群的 Docker 化部署,最开始是想通过 DockerSwarm 方式来部署的,但是 RabbitMQ 节点加入集群时一直失败,在网上找了很多办法,始终没有解决这个问题,无奈只能放弃。所以最终采用配置 hosts 文件方式来保证节点之间的通信,下面来进行详细说明。部署环境系统:CentOS8两台服务器:10.1.1.1/10.1.1.2docker-compose 文件version: '3'services: rabbit1: containe

推荐文章

热门文章

相关标签