Visual Studio 2013开发 mini-filter driver step by step (5) - 读写文件

来源:互联网 发布:交通事故原因数据统计 编辑:程序博客网 时间:2024/05/16 00:33

在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一直等待下去。






0 0
原创粉丝点击