DDK提供了文件读操作的内核函数,其函数声明如下:
NTSTATUS ZwWriteFile(
IN HANDLE FileHandle,
IN HANDLE Event,
IN PIO_APC_ROUTINE ApcRoutine,
IN PVOID ApcContext,
out PIO_STATUS_BLOCK IoStatusBlock,
IN PVOID Buffer,
IN ULONG Length,
IN PLARGE_INTEGER ByteOffset,
IN PULONG Key
);
// FileHandle: 文件打开的句柄。
// Event: 很少用到,一般设置为NULL。
// ApcRoutine: 很少用到,一般设置为NULL。
// ApcContext: 很少用到,一般设置为NULL。
// IoStatusBlock: 记录写操作的状态。其中IoStatusBlock.Infomation记录实际写了多少字节
// Buffer: 从这个缓冲区开始从文件里读。
// Length: 准备写多少字节。
// ByteOffset: 从文件的多少偏移地址开始写。
// Key: 很少用到,一般设置为NULL。
下面的代码演示了如何在驱动程序中读文件。如果是读取整个文件,需要知道文件的大小,该功能可以通过内核函数ZwWueryInformationFile来实现。
下面的代码演示了如何在驱动程序中读取文件。
#define BUFFER_SIZE 1024
OBJECT_ATTRIBUTES objectAttri;
IO_STATUS_BLOCK iostatus;
HANDLE hfile;
UNICODE_STRING logFileUnicodeStr;
// 初始化 UNICODE_STRING 字符串
RtlInitUnicodeString(&logFileUnicodeStr, L"\\?\\C:\\1.LOG");
// 或者写成 “\\Device\\HarddiskVolume1\\1.LOG”
// 初始化 objectAttri
InitializeObjectAttributes(&objectAttri,
&logFileUnicodeStr,
OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
// 创建文件
NTSTATUS ntStatus = ZwCreateFile(&hfile,
GENERIC_WRITE,
&objectAttri,
&iostatus,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ,
FILE_OPEN, // 即使存在该文件,也创建
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0
);
if (!NT_SUCCESS(ntStatus))
{
KdPrint(("The file is not exist\n"));
return;
}
FILE_STANDARD_INFORMATION fsi;
// 读取文件长度
ntStatus = ZwQueryInformationFile(hfile,
&iostatus,
&fsi,
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,
pBuffer,
(LONG)fsi.EndOfFile.QuadPart,
NULL, NULL);
KdPrint(("The program really read %d bytes\n", iostatus.Information));
// 关闭文件句柄
ZwClose(hfile);
// 释放缓冲区
ExFreePool(pBuffer);