⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 重入问题创建shadow device object.txt

📁 文件系统驱动开发的文档资料(IFS DDK)
💻 TXT
📖 第 1 页 / 共 2 页
字号:
Pdx->Type = STANDARD; 
Pdx->FsDeviceObject = FileSysDevice; 
Pdx->AttachToDeviceObject = FileSysDevice; 
Pdx->[b]BuddyDeviceObject[/b] = ShadowDeviceObject; 

// 
// Finally, attach to the device. The second we're successfully attached, we may 
// start receiving IRPs targetted at the device we've hooked. 
// 
Pdx->AttachToDeviceObject = IoAttachDeviceToDeviceStack(DeviceObject, FileSysDevice); 
if (!Pdx->AttachToDeviceObject) 
{ 
// 
// Couldn' attach for some reason 
// 
KdPrint(("fdfilter.sys: Connect with Filesystem failed\n")); 

// 
// Derefence the object and get out 
// 
ObDereferenceObject(FileObject); 
ZwClose(FileHandle); 
IoDeleteDevice(ShadowDeviceObject); 
IoDeleteDevice(DeviceObject); 
return FALSE; 
} 

// 
// Make a new drive group for the device,l if it does not have one 
// already 
// 
KdPrint(("fdfilter.sys: Successfully connected to Filesystem device\n")); 

DeviceObject->Flags |= FileSysDevice->Flags & (DO_DIRECT_IO | DO_BUFFERED_IO); 
DeviceObject->Flags |= DO_POWER_PAGABLE; 
DeviceObject->DeviceType = FileSysDevice->DeviceType; 
DeviceObject->Characteristics = FileSysDevice->Characteristics; 

// 
// Clear the device's init flag as per NT DDK KB article on creating device 
// objects from a dispatch routine 
// 
ShadowDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; 
DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; 

// 
// Close the file and update the hooked drive list by entering a 
// pointer to the hook device object in it. 
// 
ObDereferenceObject(FileObject); 
ZwClose(FileHandle); 
return TRUE; 
} 

NTSTATUS 
DispatchCreate( 
IN PDEVICE_OBJECT DeviceObject, 
IN PIRP Irp 
) 
{ 
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; 
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); 

if (pdx->Type == SHADOW) 
{ 
// ShadowDevice 

// 调用过滤驱动的下一层驱动 

PDEVICE_EXTENSION BuddyPdx = (PDEVICE_EXTENSION) pdx->[b]BuddyDeviceObject[/b]->DeviceExtension; 
IoSkipCurrentIrpStatkLocation(Irp); 
return IoCallDriver([b]BuddyPdx[/b]->AttachToDeviceObject, Irp); 
} 
else if (pdx->Type == STANDARD) 
{ 
WCHAR wszFile[MAX_PATH] = {0}; 
// FilterDevice 
// 我们需要再次打开该文件,为了避免重入... 

GetFileNameFromFileObject(IrpSp->FileObject, wszFile); 
// 假设 wszFile 里面原来内容为 L"1.txt" 
// 修改为 L"\\Device\\FDFilterShadowA\\1.txt" 
// 然后... 

OBJECT_ATTRIBUTES oa; 
InitializeObjectAttributes(&oa, wszFile, ...); 

ZwCreateFile(..., &oa, ...); // 不会再有重入的问题了,:))) 
// 因为会进入ShadowDevice's DispatchCreate 

// ... 
} 
} 

=========================
22222222
===========================
为解决重入问题创建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;
}
==================
蓝屏是因为你的内存处理不对,或者没有判断pagefile
==============
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老大,请再帮我看看,我在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;
           }

再次谢谢了!!!
==================
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);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -