Visual Studio 2013开发 mini-filter driver step by step (5) - 读写文件
在kernel中讀寫文件要比在應用層麻煩一些,但是基本思路大體上還是一致的。
在內核中,也有很多相關的讀寫文件的API,本文只對
FltCreateFileEx
FltReadFile
FltWriteFile
進行簡單說明。
這三個API和應用層的API CreateFileEx,ReadFile和WriteFile相對應。其作用分別是打開文件,從文件中讀取數據和將數據寫入文件。下面這個函數實現了文件拷貝操作,即將FullFileName的文件內容拷貝到FullFileName2中。
NTSTATUS ReadFileTest(INPUNICODE_STRINGFullFileName,INPUNICODE_STRINGFullFileName2)
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
PVOID buffer = NULL;
ULONG total_len = 0;
ULONG readbytes = 0;
ULONG byteswritten = 0;
HANDLE FileHandle = NULL;
PFILE_OBJECT FileObject = NULL;
HANDLE FileHandle2 = NULL;
PFILE_OBJECT FileObject2 = NULL;
OBJECT_ATTRIBUTES ObjectAttributes;
OBJECT_ATTRIBUTES ObjectAttributes2;
IO_STATUS_BLOCK IoStatus;
PFLT_VOLUME Volume = NULL;
PFLT_INSTANCE Instance = NULL;
buffer = ExAllocatePoolWithTag(PagedPool, 4096,'ssmf');
InitializeObjectAttributes(
&ObjectAttributes,
FullFileName,
OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
InitializeObjectAttributes(
&ObjectAttributes2,
FullFileName2,
OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
status = FltCreateFileEx(
gFilterHandle,
NULL,
&FileHandle,
&FileObject,
GENERIC_READ,
&ObjectAttributes,
&IoStatus,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
FILE_OPEN,
FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_ALERT | FILE_SEQUENTIAL_ONLY | FILE_COMPLETE_IF_OPLOCKED,
NULL,
0,
IO_NO_PARAMETER_CHECKING
);
status = FltCreateFileEx(
gFilterHandle,
NULL,
&FileHandle2,
&FileObject2,
GENERIC_READ|GENERIC_WRITE,
&ObjectAttributes2,
&IoStatus,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
FILE_OVERWRITE_IF,
FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_ALERT | FILE_SEQUENTIAL_ONLY | FILE_COMPLETE_IF_OPLOCKED,
NULL,
0,
IO_NO_PARAMETER_CHECKING
);
PT_DBG_PRINT(PTDBG_TRACE_ROUTINES, ("SSMF:Open the file status is status=%08x\n",status));
if (FileObject)
{
//read the file
//get the volume
status = FltGetVolumeFromFileObject(gFilterHandle, FileObject, &Volume);
if (NT_SUCCESS(status))
{
status = FltGetVolumeInstanceFromName(
gFilterHandle,
Volume,
NULL,
&Instance
);
if (NT_SUCCESS(status))
{
while (STATUS_END_OF_FILE != FltReadFile(Instance, FileObject, NULL, 4096,
buffer,FLTFL_IO_OPERATION_NON_CACHED, &readbytes, NULL,NULL))
{
total_len += readbytes;
PT_DBG_PRINT(PTDBG_TRACE_ROUTINES, ("SSMF:Read length is %u,total len is %u\n", readbytes, total_len));
FltWriteFile(Instance, FileObject2,NULL, readbytes, buffer, FLTFL_IO_OPERATION_NON_CACHED, &byteswritten, NULL,NULL);
}
}
if (Volume)
{
FltObjectDereference(Volume);
}
if (Instance)
{
FltObjectDereference(Instance);
}
}
}
if (FileObject)
{
FltClose(FileHandle);
ObDereferenceObject(FileObject);
}
if (FileObject2)
{
FltClose(FileHandle2);
ObDereferenceObject(FileObject2);
}
if (buffer != NULL)
{
ExFreePoolWithTag(buffer,'ssmf');
}
return status;
}
寫這段代碼的時候發生了一個小插曲,當我準備用sc stop ssmf來停止ssmf的時候,居然hung住了,我想肯定是我的代碼有問題,果斷按下ctrl+scroll鍵兩次,讓系統藍屏,產生dump文件。
最后分析dump文件,果然是ssmf不能退出,如下圖所示。
原因是在某種情況下沒有打開FullfileName1,但是打開了FullfileName2,但是FileObject沒有關閉,導致driver在unload的時候要等所有的run-down對象的引用計數都為0,但是針對FileObject2,沒有調用
ObDereferenceObject(FileObject2);
則使系統調用ExfWaitForRundownProtectionRelease一直等待下去。
總結
以上是生活随笔為你收集整理的Visual Studio 2013开发 mini-filter driver step by step (5) - 读写文件的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Visual Studio 2013开发
- 下一篇: Visual Studio 2013开发