驱动源码怎么ULONG转WCHAR或者matlab图像拼接源码两个UNICODE

小站会根据您的关注,为您发现更多,
看到喜欢的小站就马上关注吧!
下一站,你会遇见谁的梦想?
我们不是IT民工,我们只是在追求自己的梦想,我们是代码爱好者&&微博互粉@马超Terminal
Windows驱动开发技术详解__Windows内核函数
这篇文章主要复习Windows内核中字符串处理函数,文件读写函数,注册表读写函数。
内核模式下的字符串操作:
1.ASCII字符串和宽字符串
在应用程序中,往往使用两种字符:一种是char型字符串,负责记录ANSI字符集。它是指向一个char数组的指针,每个char型变量的大小为一个字节,字符串是以0标志结尾。还有一种是wchar_t型的宽字符,负责描述unicode字符集的字符串,他是一个指向wchar_t数组的指针,wchar_t字符串大小为两个字节字符串以0标志字符串结束。
ANSI字符串构造如下:
char * str1 = "abc";
UNICODE字符串的构造如下:&
wchar_t *str2 = L"abc";
2.ANSI_STRING字符串和UNICODE_STRING字符串
DDK鼓励程序员使用DDK自定义的字符串,这种数据格式定义如下:
typedef struct _STRING{ USHORT L USHORT MaximumL PCHAR B}STRING;typedef STRING ANSI_STRING;typedef PSTRING PANSI_STRING;typedef STRING OEM_STRING;typedef PSTRING POEM_STRING;
这个数据结构对ASCII字符串进行了封装:&
Length:字符串的长度
MaximumLength:整个字符串缓冲区的最大长度
Buffer:缓冲区的指针。
与ANSI_STRING相对应,DDK将宽字符封装成UNICODE_STRING数据结构:
typedef struct _UNICODE_STRING{ USHORT L USHORT MaximumL PWSTR B}UNICODE_STRING;
KdPrint函数提供了打印log方法ANSI_STRING ansiS//省去对ansiString初始化KdPrint("%Z\n",&ansiString);UNICODE_STRING uniS//省去对uniString的初始化KdPrint("%wZ\n",&uniString);
3.字符串的初始化与销毁
ANSI_STRIN字符串和UNICODE_STRING字符串使用前需要进行初始化。有两种办法构造这个数据结构。
(1)使用DDK提供的函数
初始化ANSI_STRING字符串:
VOID RtlInitAnsiString(
IN PANSI_STRING DestinationString,
IN PCSZ SourceString
);DestinationString:要初始化的ANSI_STRING字符串&
SourceString:字符串的内容
初始化UNICODE_STRING字符串:
RtlInitUnicodeString(
IN PUNICODE_STRING DestinationString,
IN PCWSTR SourceString );
DestinationString:要初始化的UNICODE_STRING字符串&
SourceString:字符串的内容
看下面一段代码:
//用RtlInitAnsiString初始化字符串 ANSI_STRING AnsiString1; CHAR * string1 = "hello"; //初始化ANSI_STRING字符串 RtlInitAnsiString(&AnsiString1,string1); KdPrint(("AnsiString1:%Z\n",&AnsiString1));//打印hello string1[0] = 'H'; string1[1] = 'E'; string1[2] = 'L'; string1[3] = 'L'; string1[4] = 'O'; //改变string1,AnsiString1同样会导致变化 KdPrint(("AnsiString1:%Z\n",&AnsiString1));//打印HELLO
(2)另一种方法是程序员自己申请内存,并初始化内存,当不用字符串时,需要回收字符串占用的内存&
//程序员自己初始化字符串#define
BUFFER_SIZE 1024 UNICODE_STRING UnicodeString1 = {0}; //设置缓冲区大小 UnicodeString1.MaximumLength = BUFFER_SIZE; //分配内存 UnicodeString1.Buffer = (PWSTR)ExAllocatePool(PagedPool,BUFFER_SIZE); WCHAR * wideString = L"hello"; //设置字符串长度,因为是宽字符,所以是字符长度的2倍 UnicodeString1.Length = 2*wcslen(wideString);
//保证缓冲区足够大,否则程序终止 ASSERT(UnicodeString1.MaximumLength &= UnicodeString1.Length); //内存拷贝 RtlCopyMemory(UnicodeString1.Buffer,wideString,UnicodeString1.Length); //设置字符长度 UnicodeString1.Length = 2*wcslen(wideString); KdPrint(("UnicodeString:%wZ\n",&UnicodeString1)); //清理内存 ExFreePool(UnicodeString1.Buffer); UnicodeString1.Buffer = NULL; UnicodeString1.Length = UnicodeString1.MaximumLength = 0;
4.字符串复制&
DDK提供了针对ANSI_STRING和UNICODE_STRING字符串的复制字符串命令,分别是:
ANSI_STRING:
VOID RtlCopyString(
IN PSTRING DestinationString,
IN PSTRING SourceString
&UNICODE_STRING:&
RtlCopyUnicodeString(
IN PUNICODE_STRING DestinationString,
IN PUNICODE_STRING SourceString
DestinationString:目的字符串&
SourceString:源字符串
请看如下代码:
//初始化Unicodestring1 UNICODE_STRING UnicodeString1; RtlInitUnicodeString(&UnicodeString1,L"Hello World"); //初始化UnicodeString2 UNICODE_STRING UnicodeString2={0}; UnicodeString2.Buffer = (PWSTR)ExAllocatePool(PagedPool,BUFFER_SIZE); UnicodeString2.MaximumLength = BUFFER_SIZE; //初始化Unicodestring2拷贝到UnicodeString1 RtlCopyUnicodeString(&UnicodeString2,&UnicodeString1); //分别显示UnicodeString1和UnicodeString2 KdPrint(("UnicodeString1:%wZ\n",&UnicodeString1)); KdPrint(("UnicodeString2:%wZ\n",&UnicodeString2)); //销毁UnicodeString2 //注意!!UnicodeString1不用销毁 RtlFreeUnicodeString(&UnicodeString2);
5.字符串的比较&
DDK提供了对ANSI_STRING和UNICODE_STRING字符串的相关字符串比较操作。
ANSI_STRING:
RtlCompareString(
IN PSTRING String1,
IN PSTRING String2,
BOOLEAN CaseInSensitive );UNICODE_STRING:&
RtlCompareUnicodeString(
IN PUNICODE_STRING String1,
IN PUNICODE_STRING String2,
BOOLEAN CaseInSensitive
);String1:要比较的第一个字符串&
String2:要比较的第二个字符串
CaseInSensitive:是否对大小写敏感
下面代码演示如何使用RtlCompareUnicodeString函数:
if (RtlEqualUnicodeString(&UnicodeString1,&UnicodeString2,TRUE)) {
KdPrint(("UnicodeString1 and UnicodeString2 are equal\n")); } else {
KdPrint(("UnicodeString1 and UnicodeString2 are NOT equal\n")); }
6.字符串转化成大写&
DDK提供了对ANSI_STRING和UNICODE_STRING字符串的相关字符串大小写转化的函数。
(1)ANSI_STRING字符串转化成大写
RtlUpperString(
PSTRING DestinationString,
PSTRING SourceString );
DestinationString:目的字符串&
SourceString:源字符串
(2)UNICODE_STRING字符串转化成大写
RtlUpcaseUnicodeString(
IN OUT PUNICODE_STRING DestinationString,
IN PCUNICODE_STRING SourceString,
IN BOOLEAN AllocateDestinationString
DestinationString:目的字符串&
SourceString:源字符串
AllocateDestinationString:是否为目的字符串分配内存
返回值:返回转换是否成功
DDK虽然提供了转化成大写的函数,但却没有提供转化成小写的函数。下面代码演示了如何使用RtlUpcaseUnicodeString函数:
//初始化UnicodeString1 UNICODE_STRING UnicodeString1; RtlInitUnicodeString(&UnicodeString1,L"Hello World");
//变化前 KdPrint(("UnicodeString1:%wZ\n",&UnicodeString1)); //变大写 RtlUpcaseUnicodeString(&UnicodeString1,&UnicodeString1,FALSE); //变化后 KdPrint(("UnicodeString1:%wZ\n",&UnicodeString1));
7.字符串与整形数字相互转换&
DDK提供了UNICODE_STRING字符串与整数相互转换的内核函数。
(1)将UNICODE_STRING字符串转换成整数
这个函数是RtlUnicodeStringToInteger,其声明是:
NTSTATUS RtlUnicodeStringToInteger(
IN PUNICODE_STRING String,
IN ULONG Base,
OUT PULONG Value
String:需要转换的字符串&
Base:转换的数的进制
Vlaue:需要转换的数字
返回值:指明是否转换成功
(2)将整数转换成UNICODE_STRING字符串
这个函数RtlIntegerToUnicodeString,其声明时:
NTSTATUS RtlIntegerToUnicodeString(
IN ULONG Value,
IN ULONG Base,
IN OUT PUNICODE_STRING String
Value:需要转换的数字&
Base:转换的数的进制
String:需要转换的字符串
返回值:是否转换成功
以下是字符串和数字之间的相互转换:
//字符串转换成数字 //初始化UnicodeString1 UNICODE_STRING UnicodeString1; RtlInitUnicodeString(&UnicodeString1,L"-100"); ULONG lN
NTSTATUS nStatus = RtlUnicodeStringToInteger(&UnicodeString1,10,&lNumber); if (NT_SUCCESS(nStatus)) {
KdPrint(("Convert to integer successfully\n")); } else {
KdPrint(("Convert to integer unsuccessfully\n")); } //数字转换成字符串 UNICODE_STRING UnicodeString2 = {0};
UnicodeString2.Buffer = (PWSTR)ExAllocatePool(PagedPool,BUFFER_SIZE);
UnicodeString2.MaximumLength = BUFFER_SIZE; nStatus = RtlIntegerToUnicodeString(200,10,&UnicodeString2);
if (NT_SUCCESS(nStatus))
KdPrint(("Conver to string successfully!\n"));
KdPrint(("Result: %wZ\n",&UnicodeString2));
KdPrint(("Convert to string unsuccessfully!\n")); } //销毁UnicodeString2 //注意!!UnicodeString1不用销毁 RtlFreeUnicodeString(&UnicodeString2);
ANSI_STRING字符串和UNICODE_STRING字符串相互转换&
DDK提供了ANSI_STRING字符串和UNICODE_STRING字符串相互转换的相关函数
(1)将UNICODE_STRING字符串转换为ANSI_STRING字符串
DDK提供了函数:RtlUnicodeStringToAnsiString,其声明是:
RtlUnicodeStringToAnsiString(
PANSI_STRING DestinationString,
PUNICODE_STRING SourceString,
BOOLEAN AllocateDestinationString
DestinationString:需要被转换的字符串&
SourceString:需要转换的源字符串
AllocateDestinationString:是否需要对被转换字符分配内存
返回值:指明是否分配成功
(2)将ANSI_STRING字符串转换为UNICODE_STRING字符串
DDK提供函数:RtlAnsiStringToUnicodeString,其声明:
NTSTATUS RtlAnsiStringToUnicodeString(
IN OUT PUNICODE_STRING DestinationString,
IN PANSI_STRING SourceString,
IN BOOLEAN AllocateDestinationString );
DestinationString:需要被转换的字符串
SourceString:需要转换的源字符串
AllocateDestinationString:是否需要对被转换字符分配内存
返回值:指明是否分配成功
&下面代码演示了ANSI_STRING和UNICODE_STRING之间是如何转换的:&
//将UNICODE_STRING字符串转换成ANSI_STRING字符串 //初始化UnicodeString1 UNICODE_STRING UnicodeString1; RtlInitUnicodeString(&UnicodeString1,L"Hello World"); ANSI_STRING AnsiString1; NTSTATUS nStatus = RtlUnicodeStringToAnsiString(&AnsiString1,&UnicodeString1,TRUE); if (NT_SUCCESS(nStatus)) {
KdPrint(("Conver successfully!\n"));
KdPrint(("Result:%Z\n",&AnsiString1)); } else {
KdPrint(("Conver unsuccessfully!\n")); } //销毁AnsiString1
RtlFreeAnsiString(&AnsiString1); //将ANSI_STRING字符串转换成UNICODE_STRING字符串 //初始化AnsiString2 ANSI_STRING AnsiString2; RtlInitAnsiString(&AnsiString2,"Hello World"); UNICODE_STRING UnicodeString2; nStatus = RtlAnsiStringToUnicodeString(&UnicodeString2,&AnsiString2,TRUE); if (NT_SUCCESS(nStatus)) {
KdPrint(("Conver succussfully!\n"));
KdPrint(("Result:%wZ\n",&UnicodeString2)); } else {
KdPrint(("Conver unsuccessfully!\n")); } //销毁UnicodeString2 RtlFreeUnicodeString(&UnicodeString2);
内核模式下的文件操作:&
1.文件的创建
对文件的创建或者打开都是通过ZwCreateFile实现的。和Windows API类似,这个内核函数返回一个文件句柄,文件的所有操作都是依靠这个句柄进行操作的。在操作完毕后,需要关闭这个句柄。
NTSTATUS ZwCreateFile(
OUT PHANDLE FileHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PLARGE_INTEGER AllocationSize OPTIONAL,
IN ULONG FileAttributes,
IN ULONG ShareAccess,
IN ULONG CreateDisposition,
IN ULONG CreateOptions,
IN PVOID EaBuffer OPTIONAL,
IN ULONG EaLength );
FileHanlde:返回打开文件的句柄&
DesireAccess:对打开文件操作的描述
ObjectAttributes:是OBJECT_ATTRIBUTES结构的地址,该结构包含要打开的文件名
IoStatuesBlock:指向一个IO_STATUS_BLOCK结构,该结构接收ZwCreateFile操作的结果状态
AllocateSize:是一个指针,指向一个64位整数,指定文件初始分配的大小
FileAttributes:0或FILE_ATTRIBUTES_NORMAL,指定新创建文件的属性
ShareAccess:FILE_OPEN_READ或0,指定文件的共享方式
CreateDisposition:FILE_OPEN或FILE_OVERWRITE_IF,表明当文件存在或不存在时应如何处理
CreateOptions:FILE_SYNCHRONOUS_IO_NONALERT,指定控制文件打开操作和句柄使用的附加标志位
EaBuffer:一个指针,指向可选的扩展属性区
EaLength:扩展属性区的长度
这个函数需要填写CreateDisposition参数。如果想打开文件,CreateDisposition参数设置成FILE_OPEN。如果想创建文件,CreateDisposition参数设置成FILE_OVERWRITE_IF。此时无论文件是否存在,都会创建新文件。
文件名的指定是通过设定第三个参数ObjectAttributes。这个参数是一个OBJECT_ATTRIBUTES结构。DDK提供对OBJECT_ATTRIBUTES结构初始化的宏InitializeObjectAttributes.
InitializeObjectAttributes(
OUT POBJECT_ATTRIBUTES InitializedAttributes,
IN PUNICODE_STRING ObjectName,
IN ULONG Attributes,
IN HANDLE RootDirectory,
IN PSECURITY_DESCRIPTOR SecurityDescriptor
InitializedAttributes:返回OBJECT_ATTRIBUTES结构&
ObjectName:对象名称,用UNICODE_STRING描述,这里设置的是文件名
Attributes:一般设置为OBJ_CASE_INSENSITIVE,对大小写敏感
后两个参数一般设置为NULL
下面代码演示如何在驱动程序中创建和打开文件
(1)创建文件
VOID CreateFileTest(){ OBJECT_ATTRIBUTES objectA IO_STATUS_BLOCK HANDLE UNICODE_STRING logFileUnicodeS //初始化UNICODE_STRING字符串 RtlInitUnicodeString(&logFileUnicodeString,
L"\\??\\C:\\1.log"); //初始化objectAtrributes InitializeObjectAttributes(&objectAtrributes,
&logFileUnicodeString,
OBJ_CASE_INSENSITIVE,
NULL); //创建文件 NTSTATUS ntStatus = ZwCreateFile(&hfile,
GENERIC_WRITE,
&objectAtrributes,
&iostatus,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ,
FILE_OPEN_IF,
FILE_SYNCHRONOUS_IO_NONALERT,
0); if (NT_SUCCESS(ntStatus)) {
KdPrint(("Create file successfully!\n")); } else {
KdPrint(("Create file unseccessfully!\n")); } //文件操作 //。。。。。。。。 //关闭文件句柄 ZwClose(hfile);}
(2)打开文件
#pragma INITCODEVOID OpenFileTest1(){ OBJECT_ATTRIBUTES objectA IO_STATUS_BLOCK HANDLE UNICODE_STRING logFileUnicodeS //初始化UNICODE_STRING字符串 RtlInitUnicodeString(&logFileUnicodeString,
L"\\??\\C:\\1.log"); //初始化objectAttributes InitializeObjectAttributes(&objectAttributes,
&logFileUnicodeString,
OBJ_CASE_INSENSITIVE,
NULL); //创建文件 NTSTATUS ntStatus = ZwCreateFile(&hfile,
GENERIC_READ,
&objectAttributes,
&iostatus,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_WRITE,
FILE_OPEN,
FILE_SYNCHRONOUS_IO_NONALERT,
0); if (NT_SUCCESS(ntStatus)) {
KdPrint(("Open file succssfully!\n")); } else {
KdPrint(("Open file unsuccssfully!\n")); } //文件操作 //。。。。 //关闭文件句柄 ZwClose(hfile);}
2.文件的打开
除了使用ZwCreateFile函数可以打开文件,DDK还提供了一个内核函数ZwOpenFile。ZwOpenFile内核函数的参数比ZwCreateFile的参数简化,方便程序员打开文件。
该函数声明如下:
ZwOpenFile(
OUT PHANDLE FileHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN ULONG ShareAccess,
IN ULONG OpenOptions
FileHandle:返回打开文件的句柄&
DesireAccess:打开的权限,一般设置为GENERIC_ALL
ObjectAttributes:OBJECT_ATTRIBUTES结构体
IoStatusBlock:指向一个结构体的指针,该结构体指明打开文件的状态
ShareAccess:共享的权限。可以是FILE_SYNCHRONOUS_IO_NONALERT
返回值:指明文件是否被成功打开
下面代码演示了如何使用ZwOpenFile打开文件:
OBJECT_ATTRIBUTES objectA IO_STATUS_BLOCK HANDLE UNICODE_STRING logFileUnicodeS //初始化UNICODE_STRING字符串 RtlInitUnicodeString(&logFileUnicodeString,
L"\\??\\C:\\1.log"); //初始化objectAttributes InitializeObjectAttributes(&objectAttributes,
&logFileUnicodeString,
OBJ_CASE_INSENSITIVE,
NULL); //创建文件
NTSTATUS ntStatus = ZwOpenFile(&hfile,
GENERIC_ALL,
&objectAttributes,
&iostatus,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_SYNCHRONOUS_IO_NONALERT); if (NT_SUCCESS(ntStatus)) {
KdPrint(("Create file successfully!\n")); } else
KdPrint(("Create file unsuccessfully!\n")); } //文件操作 //。。。。。。。。。。 //关闭文件句柄 ZwClose(hfile);
3.获取或修改文件的属性&
获取和修改文件属性,包括获取文件大小,获取或修改文件指针的位置,获取或修改文件名,获取或修改文件属性(只读信息,隐藏信息),获取或修改文件创建,修改日期等。DDK提供了内核函数ZwSetInformationFile和ZwQueryInformationFile函数来获取和修改文件属性。
ZwSetInformationFile(
IN HANDLE FileHandle,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PVOID FileInformation,
IN ULONG Length,
IN FILE_INFORMATION_CLASS FileInformationClass
NTSTATUS ZwQueryInformationFile(
IN HANDLE FileHandle,
OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID FileInformation,
IN ULONG Length,
IN FILE_INFORMATION_CLASS FileInformationClass
FileHandle:文件句柄IoStackBlock:返回设置状态
FileInformation:依据FileInformationClass不同而不同。作为输入信息
Length:FileInformation的长度
FileInformationClass:描述修改属性类型
下面代码演示如何使用ZwQueryInformationFile函数查询,修改文件属性
OBJECT_ATTRIBUTES objectA
IO_STATUS_BLOCK HANDLE
UNICODE_STRING logFileUnicodeS //初始化UNICODE_STRING字符串 RtlInitUnicodeString(&logFileUnicodeString,
L"\\??\\C:\\1.log"); //初始化objectAttributes InitializeObjectAttributes(&objectAttributes,
&logFileUnicodeString,
OBJ_CASE_INSENSITIVE,
NULL); //创建文件 NTSTATUS ntStatus = ZwCreateFile(&hfile,
GENERIC_READ,
&objectAttributes,
&iostatus,
FILE_ATTRIBUTE_NORMAL,
FILE_OPEN,
FILE_SYNCHRONOUS_IO_NONALERT,
0); if (NT_SUCCESS(ntStatus)) {
KdPrint(("open file successfully!\n")); } FILE_STANDARD_INFORMATION //读取文件长度 //读取文件长度 ntStatus = ZwQueryInformationFile(hfile,
&iostatus,
sizeof(FILE_STANDARD_INFORMATION),
FileStandardInformation); if (NT_SUCCESS(ntStatus)) {
KdPrint(("file length:%u\n",fsi.EndOfFile.QuadPart)); } //修改当前文件指针 FILE_POSITION_INFORMATION fpi.CurrentByteOffset.QuadPart = 100i64; ntStatus = ZwSetInformationFile(hfile,
&iostatus,
sizeof(FILE_POSITION_INFORMATION),
FilePositionInformation); if (NT_SUCCESS(ntStatus)) {
KdPrint(("update the file pointer successfully!\n")); } //关闭文件句柄 ZwClose(hfile);
4.文件的写操作&
DDK提供了文件写操作的内核函数,其声明如下:
NTSTATUS ZwWriteFile(
IN HANDLE FileHandle,
IN HANDLE Event OPTIONAL,
IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
IN PVOID ApcContext OPTIONAL,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PVOID Buffer,
IN ULONG Length,
IN PLARGE_INTEGER ByteOffset OPTIONAL,
IN PULONG Key OPTIONAL
FileHandle:文件打开句柄&
Event:很少用到,一般设置为NULL
ApcRountine:很少用到,一般设置为NULL
ApcContext:很少用到,一般设置为NULL
IoStackBlock:记录写操作的状态
Buffer:从这个缓冲区里开始写
Length:准备写多少字节
ByteOffset:从文件得多少偏移地址开始写
Key:很少用到,一般设置为NULL
下面代码演示如何进行文件写操作:
OBJECT_ATTRIBUTES objectA IO_STATUS_BLOCK HANDLE UNICODE_STRING logFileUnicodeS //初始化UNICODE_STRING字符串 RtlInitUnicodeString(&logFileUnicodeString,
L"\\??\\C:\\1.log"); //初始化objectAttributes InitializeObjectAttributes(&objectAttributes,
&logFileUnicodeString,
OBJ_CASE_INSENSITIVE,
NULL); //创建文件
NTSTATUS ntStatus = ZwCreateFile(&hfile,
GENERIC_WRITE,
&objectAttributes,
&iostatus,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_WRITE,
FILE_OPEN_IF,
FILE_SYNCHRONOUS_IO_NONALERT,
0);#define BUFFER_SIZE 1024 PUCHAR pBuffer = (PUCHAR)ExAllocatePool(PagedPool,BUFFER_SIZE); //构造要填充的数据 RtlFillMemory(pBuffer,BUFFER_SIZE,0xAA); KdPrint(("The program will write %d bytes\n",BUFFER_SIZE)); //写文件
ZwWriteFile(hfile,NULL,
NULL,NULL,&iostatus,pBuffer,
BUFFER_SIZE,NULL,NULL); KdPrint(("The program really wrote %d bytes\n",rmation)); //构造要填充的数据 RtlFillMemory(pBuffer,BUFFER_SIZE,0xBB);
KdPrint(("The program will append %d bytes\n",BUFFER_SIZE)); //追加数据 LARGE_INTEGER number.QuadPart = 1024i64;//设置文件指针 //对文件进行读写 ZwWriteFile(hfile,NULL,NULL,
NULL,&iostatus,pBuffer,
BUFFER_SIZE,&number,NULL); KdPrint(("The program really append %d bytes\n",rmation)); //关闭文件句柄 ZwClose(hfile); ExFreePool(pBuffer);
5文件的读操作:&
DDK提供了文件读操作的内核函数,其声明如下:
NTSTATUS ZwReadFile(
IN HANDLE FileHandle,
IN HANDLE Event OPTIONAL,
IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
IN PVOID ApcContext OPTIONAL,
OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID Buffer,
IN ULONG Length,
IN PLARGE_INTEGER ByteOffset OPTIONAL,
IN PULONG Key OPTIONAL );
下面代码演示如何在驱动程序中读文件:&
#pragma INITCODEVOID ReadFileTest(){ OBJECT_ATTRIBUTES objectA IO_STATUS_BLOCK HANDLE UNICODE_STRING logFileUnicodeS //初始化UNICODE_STRING字符串 RtlInitUnicodeString(&logFileUnicodeString,
L"\\??\\C:\\1.log"); //初始化objectAtrributes InitializeObjectAttributes(&objectAttributes,
&logFileUnicodeString,
OBJ_CASE_INSENSITIVE,
NULL); //创建文件 NTSTATUS ntStatus = ZwCreateFile(&hfile,
GENERIC_READ,
&objectAttributes,
&iostatus,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ,
FILE_OPEN,
FILE_SYNCHRONOUS_IO_NONALERT,
0); if (!NT_SUCCESS(ntStatus)) {
KdPrint(("The file is not exist!\n"));
} FILE_STANDARD_INFORMATION //读取文件长度 ntStatus = ZwQueryInformationFile(hfile,
&iostatus,
sizeof(FILE_STANDARD_INFORMATION),
FileStandardInformation); KdPrint(("The program want to read %d bytes\n",fsi.EndOfFile.QuadPart)); //为读取的文件分配缓冲区 PUCHAR pBuffer = (PUCHAR)ExAllocatePool(PagedPool,
(LONG)fsi.EndOfFile.QuadPart); //读取文件 ZwReadFile(hfile,NULL,
NULL,NULL,
&iostatus,
(LONG)fsi.EndOfFile.QuadPart,
NULL,NULL);
KdPrint(("The program really read %d bytes\n",rmation)); //关闭文件句柄 ZwClose(hfile); //释放缓冲区 ExFreePool(pBuffer);}
站长在关注在Unicode转换中,_T()与L到底怎么用,有什么区别?
[问题点数:0分]
在Unicode转换中,_T()与L到底怎么用,有什么区别?
[问题点数:0分]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
本帖子已过去太久远了,不再提供回复功能。

我要回帖

更多关于 全景视频拼接算法源码 的文章

 

随机推荐