Windows内核编程基础篇之文件读/写操作

      打开文件后,最重要是的操作在是对文件的读/写。读写的方法是对称的知识参数输入与输出方向不同。读取文件内容一般用ZwReadFile,写文件一般用ZwWriteFile

       先看看 ZwReadFile 结构吧:

NTSTATUS ZwReadFile(
  _In_     HANDLE           FileHandle,
  _In_opt_ HANDLE           Event,
  _In_opt_ PIO_APC_ROUTINE  ApcRoutine,
  _In_opt_ PVOID            ApcContext,
  _Out_    PIO_STATUS_BLOCK IoStatusBlock,
  _Out_    PVOID            Buffer,
  _In_     ULONG            Length,
  _In_opt_ PLARGE_INTEGER   ByteOffset,
  _In_opt_ PULONG           Key
);
       参数解释:

FileHandle:是ZwCreateFile成功后所得到的FileHandle。若是内核句柄,ZwReadFile和ZwCreateFile并不需要在同一个进程中。句柄是个进程通用的。

Event          :  一个事件,用于异步完成读时。设置为NULL 即可。

ApcRoutine :回调例程,用于异步完成读时,设置为 NULL即可。

IoStatusBlock  :返回结构状态,同ZwCreateFile中的同名参数。

Buffer        :缓冲区。如果读文件的内容成功,则分内容被读到这个缓冲区里。

Length       :描述缓冲区的长度。这个长度也就是试图读取文件的长度。

ByteOffset   : 要读取的文件的偏移量,也就是要读取的内容在文件中的位置,一般不要设置为NULL文件句柄不一定支持直接读取当前偏移量。

Key         : 读取文件时使用的一种附加信息,一般不用,设置为NULL即可。

    ZwReadFile 的返回值: 调用成功,则返回STATUS_SUCCESSS。只要读取到的任意多个字节,返回值都是STATUS_SUCCESS。及时试图读取的长度超出了文件本来的大小。但是如果仅是读取文件长度之外的部分,则返回的是:STATUS_END_OF_FILE。

    ZwWriteFile 参数与ZwReadFile完全相同。

    说了这么多,看看代码,简单的实现了文件的拷贝。

NTSTATUS CopyFile(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 
	{
		//---这里就开始 获取 源文件 和目标路径句柄,并为 buffer分配一个页面。然后就是循环读取文件,再写入文件。
		while (1)
		{
			///--每次读取4KB
			length = 4 * 1024;
			//---
			status = ZwReadFile(
				source,
				NULL,
				NULL,
				NULL,
				&my_io_status,
				buffer,
				length,
				&offset,
				NULL);

			if (!NT_SUCCESS(status))
			{
				//---若状态为STATUS_END_OF_FILE,则文件的拷贝结束。
				if (STATUS_END_OF_FILE == status)
				{
					status = STATUS_SUCCESS;
				}
				break;
			}
			//---得到文件被读取到的长度
			length = IoStatus.Information;
			//---下面开始写文件
			status = ZwWriteFile(
							target,
							NULL,
							NULL,
							NULL,
							&my_io_status,
							buffer,
							length,
							&offset,
							NULL);
			if (!NT_SUCCESS(status))
			{
				break;
			}
			///----继续,直到出现 STATUS_END_OF_FILE的时候结束
			offset.QuadPart += length;
		}
	} while (0);

	//---释放资源,关闭句柄
	if (NULL !=target)
	{ 
		ZwClose(target);
	}
	if (NULL != source)
	{
		ZwClose(source);
	}
	if (NULL != buffer)
	{
		ExFreePool(buffer);
	}

	return STATUS_SUCCESS;
}
    

你可能感兴趣的:(Windows内核编程,文件读写操作)