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
// ApcContext: 很少用到,一般设置为NULL
// ApcRoutine: 很少用到,一般设置为NULL
// IoStatusBlock: 记录写操作的状态。其中 IoStatusBlock.Infomation 记录实际写了多少字节。
// Buffer: 从这个缓冲区开始往文件里写。
// Length: 准备写多少字节。
// ByteOffset:从文件的多少偏移地址开始写。
// Key: 很少用到,一般设置为NULL。
下面的代码演示了如何对文件进行写操作。(为了使代码简化和阅读更加方便,这里省略了对写操作是否成功的判断)
#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\\hARDDISKvOLUME\\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_WRITE,
FILE_OPEN_IF, // 打开文件,如果不存在则返回错误
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0
);
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 ready wrote %d bytes\n", iostatus.Information));
// 构造要填充的数据
RtlFillMemory(pBuffer, BUFFER_SIZE, 0xBB);
KdPrint(("The program will apped %d bytes\n", BUFFER_SIZE));
// 追加数据
LARGE_INTEGER number;
number.QuadPart = 1024i64; //这事文件指针
// 对文件进行附加写
ZwWriteFile(hfile, NULL, NULL, NULL, &iostatus, pBuffer, BUFFER_SIZE, &number, NULL);
KdPrint(("The program ready appeded %d bytes\n", iostatus.Information));
// 关闭文件句柄
ZwClose(hfile);