lydzyw
驱动牛犊
驱动牛犊
  • 注册日期2004-06-28
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分257分
  • 威望40点
  • 贡献值0点
  • 好评度28点
  • 原创分0分
  • 专家分0分
阅读:2445回复:8

为解决重入问题创建shadow device object的代码,启动就蓝屏,请各位指点!

楼主#
更多 发布于:2005-06-26 20:45
  开发环境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;
}

最新喜欢:

lovehhylovehh...
znsoft
管理员
管理员
  • 注册日期2001-03-23
  • 最后登录2023-10-25
  • 粉丝300
  • 关注6
  • 积分910分
  • 威望14796点
  • 贡献值7点
  • 好评度2410点
  • 原创分5分
  • 专家分100分
  • 社区居民
  • 最爱沙发
  • 社区明星
沙发#
发布于:2005-06-26 20:51
蓝屏是因为你的内存处理不对,或者没有判断pagefile
http://www.zndev.com 免费源码交换网 ----------------------------- 软件创造价值,驱动提供力量! 淡泊以明志,宁静以致远。 ---------------------------------- 勤用搜索,多查资料,先搜再问。
znsoft
管理员
管理员
  • 注册日期2001-03-23
  • 最后登录2023-10-25
  • 粉丝300
  • 关注6
  • 积分910分
  • 威望14796点
  • 贡献值7点
  • 好评度2410点
  • 原创分5分
  • 专家分100分
  • 社区居民
  • 最爱沙发
  • 社区明星
板凳#
发布于:2005-06-26 20:53
http://www.zndev.com 免费源码交换网 ----------------------------- 软件创造价值,驱动提供力量! 淡泊以明志,宁静以致远。 ---------------------------------- 勤用搜索,多查资料,先搜再问。
znsoft
管理员
管理员
  • 注册日期2001-03-23
  • 最后登录2023-10-25
  • 粉丝300
  • 关注6
  • 积分910分
  • 威望14796点
  • 贡献值7点
  • 好评度2410点
  • 原创分5分
  • 专家分100分
  • 社区居民
  • 最爱沙发
  • 社区明星
地板#
发布于:2005-06-26 20:54
http://www.zndev.com 免费源码交换网 ----------------------------- 软件创造价值,驱动提供力量! 淡泊以明志,宁静以致远。 ---------------------------------- 勤用搜索,多查资料,先搜再问。
lydzyw
驱动牛犊
驱动牛犊
  • 注册日期2004-06-28
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分257分
  • 威望40点
  • 贡献值0点
  • 好评度28点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2005-06-26 23:20
谢谢znsoft的回复,我先仔细看看tooflat发布的code再说。。。
lydzyw
驱动牛犊
驱动牛犊
  • 注册日期2004-06-28
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分257分
  • 威望40点
  • 贡献值0点
  • 好评度28点
  • 原创分0分
  • 专家分0分
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老大!!!
znsoft
管理员
管理员
  • 注册日期2001-03-23
  • 最后登录2023-10-25
  • 粉丝300
  • 关注6
  • 积分910分
  • 威望14796点
  • 贡献值7点
  • 好评度2410点
  • 原创分5分
  • 专家分100分
  • 社区居民
  • 最爱沙发
  • 社区明星
6楼#
发布于:2005-06-28 15:57
1. 你在ntfs下测试一下,这时会挂起。
2. 这种方法就是解决creatfile的,解决了打开就行了。其它的可以想别的办法解决。 一般在读写时很少会导致重入,没有打开的常见。
3. 你可以在unmount中删除。
http://www.zndev.com 免费源码交换网 ----------------------------- 软件创造价值,驱动提供力量! 淡泊以明志,宁静以致远。 ---------------------------------- 勤用搜索,多查资料,先搜再问。
lydzyw
驱动牛犊
驱动牛犊
  • 注册日期2004-06-28
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分257分
  • 威望40点
  • 贡献值0点
  • 好评度28点
  • 原创分0分
  • 专家分0分
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;
              }

再次谢谢了!!!
lydzyw
驱动牛犊
驱动牛犊
  • 注册日期2004-06-28
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分257分
  • 威望40点
  • 贡献值0点
  • 好评度28点
  • 原创分0分
  • 专家分0分
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);
游客

返回顶部