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

智能推荐

sci论文(以Elsevier为例) latex文件从小白到投稿_latex sci论文_weixin_44498793的博客-程序员秘密

前言:从未接触latex到排版一篇论文历程,其中在关于latex排版的一些问题网上的解决方法容易搜到并解决的不在过多赘述,对网上百度无果而自己踩过坑做个记录,也希望后人少踩坑。#1、Elsevier一般elservier旗下期刊都会有这一句话,推荐使用latex投稿。点开第一个链接是模板文件,下载下来。里面有三种模板文件,我认为就是三种参考文献格式不同-elsarticle-tem...

全国大学生数学建模竞赛(CUMCM)历年试题(查看超级方便)_数学建模竞赛历年真题_图灵猫的博客-程序员秘密

全国大学生数学建模竞赛(China Undergraduate Mathematical Contest in Modeling)是国家教委高教司和中国工业与应用数学学会共同主办的面向全国大学生的群众性科技活动,目的在于激励学生学习数学的积极性,提高学生建立数学模型和运用计算机技术解决实际问题的综合能力,鼓励广大学生踊跃参加课外科技活动,开拓知识面,培养 创造精神及合作意识,推动大学数学教学体系、教学内容和方法的改革。

如何使用http_request处理http请求_weixin_38169562的博客-程序员秘密

1 <?php 2 3 4 // 模拟 http 请求 5 function https_request($url,$data = null) 6 { 7 // php curl 发起get或者post请求 8 // curl 初始化 9 $curl = curl_init(); // curl 设置10 ...

C++设计模式——适配器模式(对象适配器、类适配器)_weixin_33795806的博客-程序员秘密

http://blog.jobbole.com/109381/?winzoom=1 前言 现在的笔记本都只存在USB接口,用来口,电脑上存在的是USB接口,两者如何通信呢?可以使用USB转串口线连接电脑和嵌入式设备,其中USB一端连接电脑、串口和外部设备进行通信。然而在一些嵌入式设备上(例如ARM9),通常使用串口和电脑进行通信。嵌入式设备上存在的是串一端连接嵌入式设...

【SLAM】gradslam(∇SLAM)开源:论文、代码全都有_风度78的博客-程序员秘密

内容提要:来自蒙特利尔、卡内基梅隆大学的团队,在 ICRA 2020 上发表的论文中所提出的∇SLAM,解决了当下 SLAM 系统普遍所面临的一个开放性问题。关键词:SLAM 室内 ...

【MFC】GDI如何释放资源_mfc selectobject释放_UniverseLin的博客-程序员秘密

转载博客链接:https://blog.csdn.net/lin_angle/article/details/6603572对开发中常见的内存泄露,GDI泄露进行检测一、GDI泄露检测方法:在软件测试阶段,可以通过procexp.exe 工具,或是通过任务管理器中选择GDI对象来查看软件GDI的对象是使用情况。注意点:Create出来的GDI对象,都要用DeleteObject来释放;Create出来的DC,都要用DeleteDC来释放,GetDC得出的DC,要用ReleaseDC来释放。以下是一

随便推点

Python网络爬虫实战项目代码大全_爬虫实战代码_xiaoxianerqq的博客-程序员秘密

转自 : http://blog.csdn.net/fanpeihua123/article/details/53582206Python学习思维脑图大全汇总打包 (密码:visk)WechatSogou [1]- 微信公众号爬虫。基于搜狗微信搜索的微信公众号爬虫接口,可以扩展成基于搜狗搜索的爬虫,返回结果是列表,每一项均是公众号具体信息字典。 DouBanSp

Android 以JSON格式存储和加载本地文件_android 加载本地目录 json_a987860319的博客-程序员秘密

本章主要讲把一个对象以json格式保存在沙盒中,然后又从沙盒中将json数据读取出来。每个应用的沙盒目录都是设备/data/data目录的子目录,且默认以应用包命名。例如,CriminalIntent应用的沙盒目录全路径为:/data/data/com.bignerdranch.android.criminalintent。Q:什么时候保存数据合适? 适用于移动应用的一个普遍规则是:尽可能频繁的

dubbo异常:Failed to check the status of the service . No provider available for the service 解决_dubbo failed to check the status of the service_厉兵秣码的博客-程序员秘密

服务消费者调用报Failed to check the status of the service . No provider available for the service 这个问题 ,dubboadmin上边看服务正常启动 ,报错信息如下:Exception in thread “main” org.springframework.beans.factory.BeanCreationE...

SQLyog:Error Code : 1583 Incorrect parameters in the call to native function ‘concat‘_mysql 1583_泡奶侠的博客-程序员秘密

SQLyog:Error Code : 1583 Incorrect parameters in the call to native function ‘concat‘

[email protected]注解用法详解_springboot valid_十八岁讨厌Java的博客-程序员秘密

Digits(integer,fraction)限制必须为一个小数,且整数部分的位数不能超过integer,小数部分的位数不能超过fraction。现在如果想要对User中的姓名和age做非空校验和长度校验,如果在接口中频繁使用if会增加很大的代码量,这个时候@Valid注解就派上了用场。@DecimalMin(value)限制必须为一个不小于指定值的数字,小数存在精度。@DecimalMax(value)限制必须为一个不大于指定值的数字,小数存在精度。@Null用在基本类型上;...

【玩转Excel】Oracle PLSQL处理生成XLSX文件_smt_xlsx_maker_pkg_samt007的博客-程序员秘密

INTRODUCTION介绍    之前发表了一个研究心得(当然是站在别人的肩膀上的),在Oracle中直接用PL/SQL解析并读取Excel的内容。很多人都感兴趣,按照我的写法也可以成功实现了。不过,有很多朋友提出了另外一个要求:读取Excel是可以了,那是否可以在Oracle数据库端直接生成Excel文件?二进制的文件。    开始我对这个问题是不怎么在意的。因为,在Oracle数

推荐文章

热门文章

相关标签