|
|
对文件的读写操作一直是我们需要熟练掌握的内容,在ring3我们可以使用CreateFile、ReadFile、WriteFile等API,在ring0同样很相似,不过函数变成了ZwCreateFile、ZwReadFile、ZwWriteFile等函数。
在“【驱动笔记1】第一个驱动程序”一文中我们曾经用到过ZwCreateFile,并且成功使用它创建了一个新文件,但那个文件里面什么内容也没有。本节我们就对那个程序进行扩充,实现一个MyCopyFile函数,通过文件的读写来复制文件。
下面的代码来自楚狂人的《Windows驱动编程基础教程》,我把它前面省略的文件打开和缓冲区分配过程都补充完整了,下面是该函数的完整代码。
BOOLEAN
MyCopyFile(
IN PUNICODE_STRING ustrDestFile,
IN PUNICODE_STRING ustrSrcFile
)
{
HANDLE hSrcFile, hDestFile;
PVOID buffer = NULL;
ULONG length = 0;
LARGE_INTEGER offset = {0};
IO_STATUS_BLOCK Io_Status_Block = {0};
OBJECT_ATTRIBUTES obj_attrib;
NTSTATUS status;
BOOLEAN bRet = FALSE;
do
{
// 打开源文件
InitializeObjectAttributes( &obj_attrib,
ustrSrcFile,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
NULL);
status = ZwCreateFile( &hSrcFile,
GENERIC_READ,
&obj_attrib,
&Io_Status_Block,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ,
FILE_OPEN,
FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0 );
if (!NT_SUCCESS(status))
{
bRet = FALSE;
goto END;
}
// 打开目标文件
InitializeObjectAttributes( &obj_attrib,
ustrDestFile,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
NULL);
status = ZwCreateFile( &hDestFile,
GENERIC_WRITE,
&obj_attrib,
&Io_Status_Block,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ,
FILE_OPEN_IF,
FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0 );
if (!NT_SUCCESS(status))
{
bRet = FALSE;
goto END;
}
// 为buffer分配4KB空间
buffer = ExAllocatePool(NonPagedPool, 1024 * 4);
if (buffer == NULL)
{
bRet = FALSE;
goto END;
}
// 复制文件
while (1)
{
length = 4 * 1024;
// 读取源文件
status = ZwReadFile(hSrcFile,
NULL,
NULL,
NULL,
&Io_Status_Block,
buffer,
length,
&offset,
NULL);
if (!NT_SUCCESS(status))
{
// 如果状态为STATUS_END_OF_FILE,说明文件已经读取到末尾
if (status == STATUS_END_OF_FILE)
{
bRet = TRUE;
goto END;
}
}
// 获得实际读取的长度
length = Io_Status_Block.Information;
// 写入到目标文件
status = ZwWriteFile( hDestFile,
NULL,
NULL,
NULL,
&Io_Status_Block,
buffer,
length,
&offset,
NULL);
if (!NT_SUCCESS(status))
{
bRet = FALSE;
goto END;
}
// 移动文件指针
offset.QuadPart += length;
}
} while (0);
END:
if (hSrcFile)
{
ZwClose(hSrcFile);
}
if (hDestFile)
{
ZwClose(hDestFile);
}
if (buffer = NULL)
{
ExFreePool(buffer);
}
return bRet;
}
在DriverEntry中调用该函数的测试代码如下所示:
// 测试函数
RtlInitUnicodeString(&ustrSrcFile, L"\\??\\C:\\windows\\notepad.exe");
RtlInitUnicodeString(&ustrDestFile, L"\\??\\C:\\notepad.exe");
if(MyCopyFile(&ustrDestFile, &ustrSrcFile))
{
KdPrint(("[ReadFileTest] CopyFile Success!"));
}
else
{
KdPrint(("[ReadFileTest] CopyFile Error!"));
} |
|