阅读:2445回复:8
为解决重入问题创建shadow device object的代码,启动就蓝屏,请各位指点!
开发环境win2000,在sfilter的基础上修改,启动时就蓝屏。水平很菜,请高手纠正并请不要laugh at me。
根据OSR资料以及tooflat老大翻译的资料,想通过在SfMountCompletion中创建shadow device object来解决调用Zwxxx函数的重入问题(这样处理的话,以后在对文件进行操作时就不用自己创建IRP,我认为比较方便)。由于IoCreateDevice只能在<DISPATCH_LEVEL级别下运行,所以将创建的任务放到system worker thread中运行。 typedef struct _WORKER_CONTEXT { PDEVICE_OBJECT FilterDeviceObject;//attach到volume上的device object KEVENT Event;//用于同步 } WORKER_CONTEXT, *PWORKER_CONTEXT;//sfCreateSecondDevice的参数 在SfMountCompletion中,在创建了一个filter device object并attach到设备栈顶部以后,将sfCreateSecondDevice放到system worker thread中: MyworkContext.FilterDeviceObject = fsfDeviceObject; KeInitializeEvent(&MyworkContext.Event, NotificationEvent, FALSE); ExInitializeWorkItem(&MyWorkItem, sfCreateSecondDevice, &MyworkContext); ExQueueWorkItem(&MyWorkItem, CriticalWorkQueue); KeWaitForSingleObject(&MyworkContext.Event, Executive, KernelMode, FALSE, NULL);//等待sfCreateSecondDevice中的任务完成 VOID sfCreateSecondDevice(IN OUT PWORKER_CONTEXT WorkContext) { PDEVICE_OBJECT DeviceObject1 = WorkContext->FilterDeviceObject; PDEVICE_OBJECT DeviceObject2; PDEVICE_EXTENSION Device1Extension; PDEVICE_EXTENSION Device2Extension; UNICODE_STRING Temp;//name of second device object NTSTATUS status; WCHAR Prefix[10] = {L'\0'}; Prefix[0] = L'M'; Prefix[1] = L'y'; Prefix[2] = L'D'; Prefix[3] = L'e'; Prefix[4] = L'v'; Prefix[5] = L'i'; Prefix[6] = L'c'; Prefix[7] = L'e'; Prefix[8] = MyDeviceSerialNo; RtlInitUnicodeString(&Temp, Prefix); status = IoCreateDevice( FsDriverObject, sizeof( DEVICE_EXTENSION ), &Temp, FILE_DEVICE_DISK_FILE_SYSTEM, 0, FALSE, &DeviceObject2 ); Device2Extension = DeviceObject2->DeviceExtension; Device2Extension->RelatedDeviceObject = DeviceObject1; Device2Extension->IsSecondDevice = TRUE; Device2Extension->Size = sizeof( DEVICE_EXTENSION ); Device2Extension->FileSystemDeviceObject = NULL; Device2Extension->RealDeviceObject = NULL; Device2Extension->Attached = FALSE; Device2Extension->Type = SFILTER_DEVICE_TYPE; DeviceObject2->Flags &= ~DO_DEVICE_INITIALIZING; Device1Extension = DeviceObject1->DeviceExtension; Device1Extension->RelatedDeviceObject = DeviceObject2; Device1Extension->IsSecondDevice = FALSE; MyDeviceSerialNo = MyDeviceSerialNo + 1;//全局变量(其实最好用driverletter代替) KeSetEvent(&(WorkContext->Event), IO_NO_INCREMENT, FALSE); return; } |
|
最新喜欢:![]() |
沙发#
发布于:2005-06-26 20:51
蓝屏是因为你的内存处理不对,或者没有判断pagefile
|
|
|
板凳#
发布于:2005-06-26 20:53
|
|
|
地板#
发布于:2005-06-26 20:54
|
|
|
地下室#
发布于:2005-06-26 23:20
谢谢znsoft的回复,我先仔细看看tooflat发布的code再说。。。
|
|
5楼#
发布于:2005-06-28 15:04
谢谢znsoft老大的帮助,现在可以区分开由于调用ZwCreateFile引起的重入了,其实主要是犯了个低级错误,在创建shadow device object的时候名字搞错了,没加上 \Device\ 前缀:)
不过还是有几个问题请znsoft老大有时间的话解答一下, 1、你说“你在shdow object 进入它自己的dispatch时,需要修改fileobj下的realdevice. devicobject 为实际的设备才行.”,但是我没有这样做好象也可以啊,我在创建device object时将 DeviceExtension->Type设为自己定义的SHADOW_DEVICE_TYPE,进入sfCreate的时候只判断这个不就可以区别开了吗? 2、好象用创建shadow device object的方法只能对付Create的重入,因为在Zw系列函数中,只有ZwCreateFile参数中使用路径,其他函数都使用调用ZwCreateFile得到的file handle,而在调用ZwCreateFile发生重入后,已经将shadow device object换成了filter device object,所以在调用其他函数进行读/写/设置信息/询问信息 时都无法区别开。 是不是在进行读/写/设置信息/询问信息 时只能自己构造IRP? 3、在U盘插入时创建了一个shadow device object,那么如何在拔出U盘后找到并删除它? 谢谢znsoft老大!!! |
|
6楼#
发布于:2005-06-28 15:57
1. 你在ntfs下测试一下,这时会挂起。
2. 这种方法就是解决creatfile的,解决了打开就行了。其它的可以想别的办法解决。 一般在读写时很少会导致重入,没有打开的常见。 3. 你可以在unmount中删除。 |
|
|
7楼#
发布于:2005-06-29 11:29
znsoft老大,请再帮我看看,我在read或write中调用ZwWriteFile为什么总是失败?这个函数没几个参数啊,应该不会错吧,是不是还是重入问题?是不是还是要自己构造IRP?谢谢!!!
TempBuffer = ExAllocatePool(NonPagedPool, 100); for(i = 0; i<100; i++) { ((PUCHAR) TempBuffer) = '9'; }//自己随便弄一个Buffer来写进去 RtlInitUnicodeString(&ObjectName, L"\\Device\\MyDeviceD\\temp.txt"); //MyDeviceD是自己定义的shadow device object,防止Create重入 InitializeObjectAttributes(&ObjectAttributes, &ObjectName, OBJ_KERNEL_HANDLE, NULL, NULL ); Status = ZwCreateFile(&FileHandle, GENERIC_READ | GENERIC_WRITE, &ObjectAttributes, &IoStatus, NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN_IF, 0, NULL, 0 );//Create是成功的 if (!NT_SUCCESS(Status)) { return Status; } Status = ZwWriteFile(FileHandle, NULL, NULL, NULL, &IoStatus, TempBuffer, 100, NULL, NULL );//write不知道怎么,就是fail ZwClose(FileHandle); ExFreePool(TempBuffer); if (!NT_SUCCESS(Status)) { return Status; } 再次谢谢了!!! |
|
8楼#
发布于:2005-06-30 17:17
znsoft老大帮忙啊!
我前面回的帖子用了ZwWriteFile总是失败,不知道什么原因。现在想改用自己构造IRP的方法来写文件(在write dispatch routine中),代码如下,请帮忙看看: RtlInitUnicodeString(&ObjectName, L"\\Device\\MyDeviceD\\temp.txt"); InitializeObjectAttributes(&ObjectAttributes, &ObjectName, OBJ_KERNEL_HANDLE, NULL, NULL ); Status = ZwCreateFile(&FileHandle, GENERIC_READ | GENERIC_WRITE, &ObjectAttributes, &IoStatus, NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN_IF, 0, NULL, 0 ); if (!NT_SUCCESS(Status)));//Create是成功的 { return Status; } KeInitializeEvent(&WriteEvent, NotificationEvent, FALSE); WriteIrp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE, DevExt->FileSystemDeviceObject, OldBuffer,//从IRP中获得的buffer地址 Length,//从IRP中获得的数据长度 NULL, &WriteEvent, &IoStatus);//这里总是重启 if(WriteIrp == NULL) { ZwClose(FileHandle); return Status; } Status = ObReferenceObjectByHandle(FileHandle, 0, NULL, KernelMode, WriteFileObject, NULL); WriteIrp->RequestorMode = ExGetPreviousMode(); WriteIrp->Tail.Overlay.OriginalFileObject = WriteFileObject; WriteStack = IoGetNextIrpStackLocation(WriteIrp); WriteStack->FileObject = WriteFileObject; Status = IoCallDriver(DevExt->FileSystemDeviceObject, WriteIrp); if (!NT_SUCCESS(Status)) { IoFreeIrp(WriteIrp); ZwClose(FileHandle); return Status; } KeWaitForSingleObject(&WriteEvent, Executive, KernelMode, FALSE, NULL); KeClearEvent(&WriteEvent); IoFreeIrp(WriteIrp); ZwClose(FileHandle); |
|