驱动学习笔记2
来源:互联网 发布:奥尼尔06总决赛数据 编辑:程序博客网 时间:2024/06/06 23:16
1.文件操作
a)OBJECT_ATTRIBUTES
b)VOID InitializeObjectAttributes(
OUT POBJECT_ATTRIBUTES InitializedAttributes,
IN PUNICODE_STRING ObjectName, // 文件的路径 L”//??//C://a.dat”,//??//为设备链的路径
IN ULONG Attributes, // OBJ_CASE_INSENSITIVE| OBJ_KERNEL_HANDLE
IN HANDLE RootDirectory, // NULL
IN PSECURITY_DESCRIPTOR SecurityDescriptor); // 用于设置安全描述符,OBJ_KERNEL_HANDLE情况下可以不用设置此参数
c)创建文件
NTSTATUS ZwCreateFile(
OUT PHANDLE FileHandle, // 是一个句柄的指针
IN ACCESS_MASK DesiredAccess, // 申请的权限。
IN POBJECT_ATTRIBUTES ObjectAttribute,
OUT PIO_STATUS_BLOCK IoStatusBlock, // 返回值,status和information
IN PLARGE_INTEGER AllocationSize OPTIONAL, // NULL
IN ULONG FileAttributes, // FILE_ATTRIBUTE_NORMAL
IN ULONG ShareAccess, // 共享访问 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE
IN ULONG CreateDisposition, // 打开意图
IN ULONG createOptions, // FILE_ DIRECTORY_FILE,FILE_NON_DIRECTORY_FILE是否打开目录。 FILE_SYNCHRONOUS_IO_NONALERT同步操作,写文件阻塞,与SYNCHRONIZE联用。
IN PVOID EaBuffer OPTIONAL, // FILE_NO_INTERMEDIATE_BUFFERING 按磁盘扇区大小对齐
IN ULONG EaLength);
d)文件访问属性可用|组合
FILE_WRITE_DATA
FILE_READ_DATA
DELETE
FILE_WRITE_ATTRIBUTES
FILE_READ_ATTRIBUTES
GENERIC_READ - 常用的读权限组合
GENERIC_WRITE - 常用的写权限组合
GENERIC_ALL - 全部权限
SYNCHRONIZE - 同步打开文件
e)返回信息
FILE_CREATED:文件被成功的新建了。
FILE_OPENED: 文件被打开了。
FILE_OVERWRITTEN:文件被覆盖了。
FILE_SUPERSEDED: 文件被替代了。
FILE_EXISTS:文件已存在。(因而打开失败了)。
FILE_DOES_NOT_EXIST:文件不存在。(因而打开失败了)。
f)文件打开意图
FILE_CREATE:新建文件。如果文件已经存在,则这个请求失败。
FILE_OPEN:打开文件。如果文件不存在,则请求失败。
FILE_OPEN_IF:打开或新建。如果文件存在,则打开。如果不存在,则失败。
FILE_OVERWRITE:覆盖。如果文件存在,则打开并覆盖其内容。如果文件不存在,这个请求返回失败。
FILE_OVERWRITE_IF:新建或覆盖。如果要打开的文件已存在,则打开它,并覆盖其内存。如果不存在,则简单的新建新文件。
FILE_SUPERSEDE:新建或取代。如果要打开的文件已存在。则生成一个新文件替代之。如果不存在,则简单的生成新文件。
g)打开文件例子
// 要返回的文件句柄
HANDLE file_handle = NULL;
// 返回值
NTSTATUS status;
// 首先初始化含有文件路径的OBJECT_ATTRIBUTES
OBJECT_ATTRIBUTES object_attributes;
UNICODE_STRING ufile_name = RTL_CONST_STRING(L”//??//C://a.dat”);
InitializeObjectAttributes(
&object_attributes,
&ufile_name,
OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE,
NULL,
NULL);
// 以OPEN_IF方式打开文件。
status = ZwCreateFile(
&file_handle,
GENERIC_READ | GENERIC_WRITE,
&object_attributes,
&io_status,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ,
FILE_OPEN_IF,
FILE_NON_DIRECTORY_FILE |
FILE_RANDOM_ACCESS |
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0);
h)ZwClose(file_handle);
i)读文件/写文件
NTSTATUS ZwReadFile/ZwWriteFile(
IN HANDLE FileHandle,
IN HANDLE Event OPTIONAL, // 异步读写完成事件,同步读写时为NULL
IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, // 异步读写完成回调例程,同步读写时为NULL
IN PVOID ApcContext OPTIONAL,
OUT PIO_STATUS_BLOCK IoStatusBlock, // 返回结果状态
OUT PVOID Buffer, // 缓冲区
IN ULONG Length, // 描述缓冲区的长度,这个长度也就是试图读取文件的长度。
IN PLARGE_INTEGER ByteOffset OPTIONAL, // 要读取的文件的偏移量
IN PULONG Key OPTIONAL); // 读取文件时用的一种附加信息,一般不使用。设置NULL。
j)复制文件的例子
NTSTATUS MyCopyFile(
PUNICODE_STRING target_path,
PUNICODE_STRING source_path)
{
// 源和目标的文件句柄
HANDLE target = NULL,source = NULL;
// 用来拷贝的缓冲区
PVOID buffer = NULL;
LARGE_INTEGER offset = { 0 };
IO_STATUS_BLOCK io_status = { 0 };
do {
// 这里请用前一小节说到的例子打开target_path和source_path所对应的
// 句柄target和source,并为buffer分配一个页面也就是4k的内存。
… …
// 然后用一个循环来读取文件。每次从源文件中读取4k内容,然后往
// 目标文件中写入4k,直到拷贝结束为止。
while(1) {
length = 4*1024; // 每次读取4k。
// 读取旧文件。注意status。
status = ZwReadFile (
source,NULL,NULL,NULL,
&my_io_status,buffer, length,&offset,
NULL);
if(!NT_SUCCESS(status))
{
// 如果状态为STATUS_END_OF_FILE,则说明文件
// 的拷贝已经成功的结束了。
if(status == STATUS_END_OF_FILE)
status = STATUS_SUCCESS;
break;
}
// 获得实际读取到的长度。
length = IoStatus.Information;
// 现在读取了内容。读出的长度为length.那么我写入
// 的长度也应该是length。写入必须成功。如果失败,
// 则返回错误。
status = ZwWriteFile(
target,NULL,NULL,NULL,
&my_io_status,
buffer,length,&offset,
NULL);
if(!NT_SUCCESS(status))
break;
// offset移动,然后继续。直到出现STATUS_END_OF_FILE
// 的时候才结束。
offset.QuadPart += length;
}
} while(0);
// 在退出之前,释放资源,关闭所有的句柄。
if(target != NULL)
ZwClose(target);
if(source != NULL)
ZwClose(source);
if(buffer != NULL)
ExFreePool(buffer);
return STATUS_SUCCESS;
}
2.注册表操作
a)路径
应用程序和驱动程序很大的一个不同在于应用程序总是由某个“当前用户”启动的。因此可以直接读取HKEY_CLASSES_ROOT和HKEY_CURRENT_USER。而驱动程序和用户无关,所以直接去打开HKEY_CURRENT_USER也就不符合逻辑了
路径举例:
应用层L"//Registry//Machine//SOFTWARE//Microsoft//Windows NT//CurrentVersion"
驱动层"HKEY_LOCAL_MACHINE//SOFTWARE//Microsoft//Windows NT//CurrentVersion"
b)创建,打开注册表项
NTSTATUS ZwOpenKey/ZwCreateKey(
OUT PHANDLE KeyHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes
);
KEY_QUERY_VALUE:读取键下的值。
KEY_SET_VALUE:设置键下的值。
KEY_CREATE_SUB_KEY:生成子键。
KEY_ENUMERATE_SUB_KEYS:枚举子键。
KEY_READ:通用读权限组合
KEY_WRITE:通用写权限组合
KEY_ALL_ACCESS:通用写权限组合
c)读
NTSTATUS ZwQueryValueKey(
IN HANDLE KeyHandle,
IN PUNICODE_STRING ValueName, // 要读取的值的名字
IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, // KeyValuePartialInformation
OUT PVOID KeyValueInformation,
IN ULONG Length, // 用户传入的输出空间KeyValueInformation的长度
OUT PULONG ResultLength // 返回实际需要的长度
);
KeyValueInformationClass:本次查询所需要查询的信息类型。这有如下的三种可能。
KeyValueBasicInformation:获得基础信息,包含值名和类型。
KeyValueFullInformation:获得完整信息。包含值名、类型和值的数据。
KeyValuePartialInformation:获得局部信息。包含类型和值数据。
KeyValueInformation
typedef struct _KEY_VALUE_PARTIAL_INFORMATION {
ULONG TitleIndex; // 请忽略这个成员
ULONG Type; // 常见数据类型 REG_BINARY:十六进制数据。REG_DWORD:四字节整数。REG_SZ:以空结束的Unicode字符串。
ULONG DataLength; // 数据长度
UCHAR Data[1]; // 可变长度的数据
}KEY_VALUE_PARTIAL_INFORMATION,*PKEY_VALUE_PARTIAL_INFORMATIO;
读取未知长度的键值时,最好反复尝试数据长度,而不是给一个足够大的长度。
d)读取例程
// 要读取的值的名字
UNICODE_STRING my_key_name =
RTL_CONSTANT_STRING(L”SystemRoot”);
// 用来试探大小的key_infor
KEY_VALUE_PARTIAL_INFORMATION key_infor;
// 最后实际用到的key_infor指针。内存分配在堆中
PKEY_VALUE_PARTIAL_INFORMATION ac_key_infor;
ULONG ac_length;
……
// 前面已经打开了句柄my_key,下面如此来读取值:
status = ZwQueryValueKey(
my_key,
&my_key_name,
KeyValuePartialInformation,
&key_infor,
sizeof(KEY_VALUE_PARTIAL_INFORMATION),
&ac_length);
if(!NT_SUCCESS(status) &&
status != STATUS_BUFFER_OVERFLOW &&
status != STATUS_BUFFER_TOO_SMALL)
{
// 错误处理
…
}
// 如果没失败,那么分配足够的空间,再次读取
ac_key_infor = (PKEY_VALUE_PARTIAL_INFORMATION)
ExAllocatePoolWithTag(NonpagedPool,ac_length ,MEM_TAG);
if(ac_key_infor == NULL)
{
stauts = STATUS_INSUFFICIENT_RESOURCES;
// 错误处理
…
}
status = ZwQueryValueKey(
my_key,
&my_key_name,
KeyValuePartialInformation,
ac_key_infor,
ac_length,
&ac_length);
// 到此为止,如果status为STATUS_SUCCESS,则要读取的数据已经
// 在ac_key_infor->Data中。请利用前面学到的知识,转换为
// UNICODE_STRING
……
d)写
NTSTATUS ZwSetValueKey(
IN HANDLE KeyHandle,
IN PUNICODE_STRING ValueName,
IN ULONG TitleIndex OPTIONAL,
IN ULONG Type,
IN PVOID Data,
IN ULONG DataSize
);
如果该Value已经存在,那么其值会被这次写入覆盖。如果不存在,则会新建一个。
- 驱动学习笔记2
- lcd驱动学习笔记2
- 驱动开发学习笔记2
- 领域驱动设计学习笔记(2)
- linux字符设备驱动学习笔记2
- Linux 驱动学习笔记2 -- Timer
- asoc 音频驱动学习笔记2
- Linux 驱动学习笔记2 -- Timer
- Linux驱动学习笔记(2)
- Asio驱动开发学习笔记(2)
- 驱动学习笔记bosch
- 驱动开发学习笔记
- NDIS驱动学习笔记
- 驱动学习笔记1
- 驱动学习笔记1
- 驱动学习笔记3
- NDIS驱动学习笔记
- Linux 驱动学习笔记
- SQL Server优化二
- windows 下使用 wx-config
- vdfs收到
- Linux 上安装 WikidPad
- C#和Access中的取模运算
- 驱动学习笔记2
- 改变窗口大小位置
- 从零开始做3D地图编辑器(七)(基于QT与OGRE)
- Sicily 1031 Campus(Dijkstra[邻接表+优先队列优化])
- 这些道理不懂,你注定就是穷打工的命
- 中国软件的出路
- oracle 开发设计一些规范经验
- C++ Programming: Static Code Analysis and the New Language Standard C++0x
- 如何阅读passthru?