4.1文件的读写(实现内核文件复制功能)

ZwCreateFile -> ZwReadFile/ZwWriteFile (读文件/写文件)

读文件:

ZwReadFile(

//ZwCreateFile得到的文件句柄,如果是内核句柄,这创建文件和读取文件并不需要在同一个进程,是通用的.

_In_ HANDLE FileHandle,

//事件,用户异步完成读时,这里填 NULL

_In_opt_ HANDLE Event,

//回调例程,用于异步完成读时.这里填 NULL

_In_opt_ PIO_APC_ROUTINE ApcRoutine,

_In_opt_ PVOID ApcContext,

//返回结果状态

_Out_ PIO_STATUS_BLOCK IoStatusBlock,

//缓冲区,当读文件成功,内容会被保存在这个缓冲区中

_Out_writes_bytes_(Length) PVOID Buffer,

//描述缓冲区的长度,也是试图读取文件的长度

_In_ ULONG Length,

//要读取内容在文件中的偏移,一般不要设置为 NULL,文件句柄不一定支持直接读取当前的偏移

_In_opt_ PLARGE_INTEGER ByteOffset,

//读取文件时的附加信息,一般不使用,设置为 NULL

_In_opt_ PULONG Key

);

函数执行成功后返回 STATUS_SUCCESS .只要读取到字符,不管是否符合指定长度都返回成功,即使试图读取长度超过文件长度.

电子书教材没有写出完整的代码,简直了.最终实现复制文件的完整代码如下,原始文件是1.txt,目标文件是2.txt:

#include

VOID DriverUnload(PDRIVER_OBJECT driver){

}

NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path){

//设置读取到文件保存数据的缓冲区

PVOID Buffer = ExAllocatePoolWithTag(NonPagedPool, 4*1024, 2333);

//返回状态 读写共用

IO_STATUS_BLOCK iostatus = { 0 };

//保存读取文件的偏移,以便下次从这里读取

LARGE_INTEGER offset = { 0 };

//实际读取的长度

ULONG length = 0;

//这个变量是全部函数返回共用的

NTSTATUS status;

//创建文件,oldfile newfile 先打开两个文件..

HANDLE yuanwenjian = NULL;

HANDLE mubiaowenjian = NULL;

//初始化

OBJECT_ATTRIBUTES old_object_attributes;

UNICODE_STRING old_ufile_name = RTL_CONSTANT_STRING(L"\\??\\C:\\1.txt");//使用对象路径

InitializeObjectAttributes(&old_object_attributes, &old_ufile_name, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);

//初始化

OBJECT_ATTRIBUTES new_object_attributes;

UNICODE_STRING new_ufile_name = RTL_CONSTANT_STRING(L"\\??\\C:\\2.txt");//使用对象路径

InitializeObjectAttributes(&new_object_attributes, &new_ufile_name, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);

//保存打开文件的返回状态

IO_STATUS_BLOCK oldstatus;

IO_STATUS_BLOCK newstatus;

status = ZwCreateFile(

&yuanwenjian,

GENERIC_READ | GENERIC_WRITE,

&old_object_attributes,

&oldstatus,

NULL,

FILE_ATTRIBUTE_NORMAL,

FILE_SHARE_READ,

FILE_OPEN_IF,

FILE_NON_DIRECTORY_FILE | FILE_RANDOM_ACCESS | FILE_SYNCHRONOUS_IO_NONALERT,

NULL,

0

);

status = ZwCreateFile(

&mubiaowenjian,

GENERIC_READ | GENERIC_WRITE,

&new_object_attributes,

&newstatus,

NULL,

FILE_ATTRIBUTE_NORMAL,

FILE_SHARE_READ,

FILE_OPEN_IF,

FILE_NON_DIRECTORY_FILE | FILE_RANDOM_ACCESS | FILE_SYNCHRONOUS_IO_NONALERT,

NULL,

0

);

//复制文件

while (1){

length = 4 * 1024;

status = ZwReadFile(yuanwenjian, NULL, NULL, NULL, &iostatus, Buffer, length, &offset, NULL);

if (!NT_SUCCESS(status)){

//如果状态为 STATUS_END_OF_FILE 说明拷贝完成

if (status == STATUS_END_OF_FILE){

status = STATUS_SUCCESS;

}

break;

}

//得到实际读取到的长度

length = (ULONG)iostatus.Information;

status = ZwWriteFile(mubiaowenjian, NULL, NULL, NULL, &iostatus, Buffer, length, &offset, NULL);

if (!NT_SUCCESS(status)){

break;

}

//设置新的偏移

offset.QuadPart += length;

}

//释放资源,关闭句柄

if (yuanwenjian != NULL){ ZwClose(yuanwenjian); }

if (mubiaowenjian != NULL){ ZwClose(mubiaowenjian); }

if (Buffer != NULL){ ExFreePool(Buffer); }

DbgPrint("misaka: finished\r\n");

driver->DriverUnload = DriverUnload;

return STATUS_SUCCESS;

}

你可能感兴趣的:(4.1文件的读写(实现内核文件复制功能))