NTSTATUS SpPagingPathNotificationCompletion( IN PDEVICE_OBJECT DeviceObject, IN PIRP LowerIrp, IN PDEVICE_OBJECT Fdo ) { PIRP upperIrp = LowerIrp->AssociatedIrp.MasterIrp; PIO_STACK_LOCATION lowerStack = IoGetCurrentIrpStackLocation(LowerIrp); PIO_STACK_LOCATION upperStack = IoGetCurrentIrpStackLocation(upperIrp); PDEVICE_OBJECT pdo = upperStack->DeviceObject; PADAPTER_EXTENSION lowerExtension; PLOGICAL_UNIT_EXTENSION upperExtension; ASSERT(Fdo != NULL); ASSERT(pdo != NULL); DebugPrint((1, "Completion - IRP_MN_DEVICE_USAGE_NOTIFICATION: Completion of " "paging notification irp %#p sent due to irp %#p\n", LowerIrp, upperIrp)); lowerExtension = (PADAPTER_EXTENSION) Fdo->DeviceExtension; upperExtension = (PLOGICAL_UNIT_EXTENSION) pdo->DeviceExtension; ASSERT_FDO(lowerExtension->DeviceObject); ASSERT_PDO(upperExtension->DeviceObject); DebugPrint((1, "Completion - IRP_MN_DEVICE_USAGE_NOTIFICATION: irp status %#08lx\n", LowerIrp->IoStatus.Status)); if(NT_SUCCESS(LowerIrp->IoStatus.Status)) { PUCHAR typeName = "INSERT TYPE HERE"; PULONG lowerCount; PULONG upperCount; // // The parameters have already been erased from the lower irp stack // location - use the parameters from the upper once since they're // just a copy. // switch(upperStack->Parameters.UsageNotification.Type) { case DeviceUsageTypePaging: { lowerCount = &(lowerExtension->CommonExtension.PagingPathCount); upperCount = &(upperExtension->CommonExtension.PagingPathCount); typeName = "PagingPathCount"; break; } case DeviceUsageTypeHibernation: { lowerCount = &(lowerExtension->CommonExtension.HibernatePathCount); upperCount = &(upperExtension->CommonExtension.HibernatePathCount); typeName = "HibernatePathCount"; break; } case DeviceUsageTypeDumpFile: { lowerCount = &(lowerExtension->CommonExtension.DumpPathCount); upperCount = &(upperExtension->CommonExtension.DumpPathCount); typeName = "DumpPathCount"; break; } default: { typeName = "unknown type"; lowerCount = upperCount = NULL; break; } } if(lowerCount != NULL) { IoAdjustPagingPathCount( lowerCount, upperStack->Parameters.UsageNotification.InPath ); DebugPrint((1, "Completion - IRP_MN_DEVICE_USAGE_NOTIFICATION: " "Fdo %s count - %d\n", typeName, *lowerCount)); IoInvalidateDeviceState(lowerExtension->LowerPdo); } if(upperCount != NULL) { IoAdjustPagingPathCount( upperCount, upperStack->Parameters.UsageNotification.InPath ); DebugPrint((1, "Completion - IRP_MN_DEVICE_USAGE_NOTIFICATION: " "Pdo %s count - %d\n", typeName, *upperCount)); IoInvalidateDeviceState(upperExtension->DeviceObject); } } upperIrp->IoStatus = LowerIrp->IoStatus; SpReleaseRemoveLock(lowerExtension->CommonExtension.DeviceObject, LowerIrp); SpReleaseRemoveLock(upperExtension->CommonExtension.DeviceObject, upperIrp); IoMarkIrpPending(upperIrp); SpCompleteRequest(upperExtension->CommonExtension.DeviceObject, upperIrp, NULL, IO_NO_INCREMENT); IoFreeIrp(LowerIrp); return STATUS_MORE_PROCESSING_REQUIRED; }
NTSTATUS BlkMovDispatchPnp( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp); NTSTATUS status; PDEVICE_EXTENSION deviceExtension; PAGED_CODE(); switch(irpSp->MinorFunction) { case IRP_MN_START_DEVICE: // // Call the Start Routine handler to schedule a completion routine // status = BlkMovStartDevice(DeviceObject, Irp); break; /*case IRP_MN_REMOVE_DEVICE: { // // Call the Remove Routine handler to schedule a completion routine // status = BlkMovRemoveDevice(DeviceObject, Irp); break; }*/ case IRP_MN_DEVICE_USAGE_NOTIFICATION: { PIO_STACK_LOCATION irpStack; ULONG count; BOOLEAN setPagable; DbgPrint("BlkMovDispatchPnp: Processing DEVICE_USAGE_NOTIFICATION\n"); irpStack = IoGetCurrentIrpStackLocation(Irp); if (irpStack->Parameters.UsageNotification.Type != DeviceUsageTypePaging) { status = BlkMovSendToNextDriver(DeviceObject, Irp); break; // out of case statement } deviceExtension = DeviceObject->DeviceExtension; // // wait on the paging path event // status = KeWaitForSingleObject(&deviceExtension->PagingPathCountEvent, Executive, KernelMode, FALSE, NULL); // // if removing last paging device, need to set DO_POWER_PAGABLE // bit here, and possible re-set it below on failure. // setPagable = FALSE; if (!irpStack->Parameters.UsageNotification.InPath && deviceExtension->PagingPathCount == 1 ) { // // removing the last paging file // must have DO_POWER_PAGABLE bits set // if (DeviceObject->Flags & DO_POWER_INRUSH) { DbgPrint("BlkMovDispatchPnp: last paging file " "removed but DO_POWER_INRUSH set, so not " "setting PAGABLE bit " "for DO %p\n", DeviceObject); } else { DbgPrint("BlkMovDispatchPnp: Setting PAGABLE " "bit for DO %p\n", DeviceObject); DeviceObject->Flags |= DO_POWER_PAGABLE; setPagable = TRUE; } } // // send the irp synchronously // status = BlkMovForwardIrpSynchronous(DeviceObject, Irp); // // now deal with the failure and success cases. // note that we are not allowed to fail the irp // once it is sent to the lower drivers. // if (NT_SUCCESS(status)) { IoAdjustPagingPathCount( &deviceExtension->PagingPathCount, irpStack->Parameters.UsageNotification.InPath); if (irpStack->Parameters.UsageNotification.InPath) { if (deviceExtension->PagingPathCount == 1) { // // first paging file addition // DeviceObject->Flags &= ~DO_POWER_PAGABLE; } } } else { // // cleanup the changes done above // if (setPagable == TRUE) { DeviceObject->Flags &= ~DO_POWER_PAGABLE; setPagable = FALSE; } } // // set the event so the next one can occur. // KeSetEvent(&deviceExtension->PagingPathCountEvent, IO_NO_INCREMENT, FALSE); // // and complete the irp // IoCompleteRequest(Irp, IO_NO_INCREMENT); return status; break; } case IRP_MN_REMOVE_DEVICE: return BlkMovSendToNextDriver(DeviceObject, Irp); case IRP_MN_STOP_DEVICE: return BlkMovSendToNextDriver(DeviceObject, Irp); default: // // Simply forward all other Irps // return BlkMovSendToNextDriver(DeviceObject, Irp); } return status; } // end BlkMovDispatchPnp()
NTSTATUS YtDispatchFilterPnP( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp); NTSTATUS status; PDEVICE_EXTENSION deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; //DebugPrint(("YtDispatchPnp: Device %X Irp %X\n", DeviceObject, Irp)); switch(irpSp->MinorFunction) { case IRP_MN_REMOVE_DEVICE: DebugPrint(("YtDispatchFilterPnP: Schedule completion for REMOVE_DEVICE.\n")); status = YtRemoveDevice(DeviceObject, Irp); return status; case IRP_MN_START_DEVICE: DebugPrint(("YtDispatchFilterPnP: Schedule completion for START_DEVICE.\n")); status = YtStartDevice(DeviceObject, Irp); return status; case IRP_MN_STOP_DEVICE: DebugPrint(("YtDispatchFilterPnP: Schedule completion for STOP_DEVICE.\n")); status = YtStopDevice(DeviceObject, Irp); return status; case IRP_MN_DEVICE_USAGE_NOTIFICATION: PIO_STACK_LOCATION irpStack; ULONG count; BOOLEAN setPagable; DebugPrint(("YtDispatchFilterPnP: Processing DEVICE_USAGE_NOTIFICATION\n")); irpStack = IoGetCurrentIrpStackLocation(Irp); if (irpStack->Parameters.UsageNotification.Type != DeviceUsageTypePaging) { status = YtSendToNextDriver(DeviceObject, Irp); return status; } deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; // wait on the paging path event status = KeWaitForSingleObject( &deviceExtension->PagingPathCountEvent, Executive, KernelMode, FALSE, NULL ); // if removing last paging device, need to set DO_POWER_PAGABLE // bit here, and possible re-set it below on failure. setPagable = FALSE; if (!irpStack->Parameters.UsageNotification.InPath && deviceExtension->PagingPathCount == 1 ) { // removing the last paging file // must have DO_POWER_PAGABLE bits set if (DeviceObject->Flags & DO_POWER_INRUSH) { DebugPrint(("YtDispatchFilterPnP: last paging file " "removed but DO_POWER_INRUSH set, so not " "setting PAGABLE bit " "for DO %p\n", DeviceObject)); } else { DebugPrint(("YtDispatchFilterPnP: Setting PAGABLE " "bit for DO %p\n", DeviceObject)); DeviceObject->Flags |= DO_POWER_PAGABLE; setPagable = TRUE; } } //send the irp synchronously status = YtForwardIrpSynchronous(DeviceObject, Irp); //now deal with the failure and success cases. //note that we are not allowed to fail the irp //once it is sent to the lower drivers. if (NT_SUCCESS(status)) { IoAdjustPagingPathCount( &deviceExtension->PagingPathCount, irpStack->Parameters.UsageNotification.InPath ); if (irpStack->Parameters.UsageNotification.InPath) { if (deviceExtension->PagingPathCount == 1) { DebugPrint(("YtDispatchFilterPnP: Clearing PAGABLE bit " "for DO %p\n", DeviceObject)); DeviceObject->Flags &= ~DO_POWER_PAGABLE; } } } else { // // cleanup the changes done above // if (setPagable == TRUE) { DeviceObject->Flags &= ~DO_POWER_PAGABLE; setPagable = FALSE; } } // // set the event so the next one can occur. // KeSetEvent(&deviceExtension->PagingPathCountEvent, IO_NO_INCREMENT, FALSE); // // and complete the irp // IoCompleteRequest(Irp, IO_NO_INCREMENT); return status; } //DebugPrint(("YtDispatchPnp: Forwarding irp...\n")); //Forward all other Irps status = YtSendToNextDriver(DeviceObject, Irp); return status; }
NTSTATUS DF_DispatchPnp(PDEVICE_OBJECT DeviceObject, PIRP Irp) { NTSTATUS status; PDF_DEVICE_EXTENSION DevExt; PIO_STACK_LOCATION IrpSp; // For handling paging requests. BOOLEAN setPageable; BOOLEAN bAddPageFile; PAGED_CODE(); IrpSp = IoGetCurrentIrpStackLocation(Irp); DevExt = (PDF_DEVICE_EXTENSION)DeviceObject->DeviceExtension; switch(IrpSp->MinorFunction) { case IRP_MN_START_DEVICE: DBG_PRINT(DBG_TRACE_OPS, ("%s: Start Device...\n", __FUNCTION__)); status = Irp->IoStatus.Status; DevExt->CurrentPnpState = IRP_MN_START_DEVICE; break; case IRP_MN_DEVICE_USAGE_NOTIFICATION : setPageable = FALSE; bAddPageFile = IrpSp->Parameters.UsageNotification.InPath; DBG_PRINT(DBG_TRACE_OPS, ("%s: Paging file request...\n", __FUNCTION__)); if (IrpSp->Parameters.UsageNotification.Type == DeviceUsageTypePaging) // Indicated it will create or delete a paging file. { if(bAddPageFile && !DevExt->CurrentPnpState) { status = STATUS_DEVICE_NOT_READY; break; } // Waiting other paging requests. KeWaitForSingleObject(&DevExt->PagingCountEvent, Executive, KernelMode, FALSE, NULL); // Removing last paging device. if (!bAddPageFile && DevExt->PagingCount == 1 ) { // The last paging file is no longer active. // Set the DO_POWER_PAGABLE bit before // forwarding the paging request down the // stack. if (!(DeviceObject->Flags & DO_POWER_INRUSH)) { DeviceObject->Flags |= DO_POWER_PAGABLE; setPageable = TRUE; } } // Waiting lower device complete. IoForwardIrpSynchronously(DevExt->LowerDeviceObject, Irp); if (NT_SUCCESS(Irp->IoStatus.Status)) { IoAdjustPagingPathCount(&DevExt->PagingCount, bAddPageFile); if (bAddPageFile && DevExt->PagingCount == 1) { // Once the lower device objects have succeeded the addition of the paging // file, it is illegal to fail the request. It is also the time to clear // the Filter DO's DO_POWER_PAGABLE flag. DeviceObject->Flags &= ~DO_POWER_PAGABLE; } } else { if (setPageable == TRUE) { DeviceObject->Flags &= ~DO_POWER_PAGABLE; setPageable = FALSE; } } KeSetEvent(&DevExt->PagingCountEvent, IO_NO_INCREMENT, FALSE); status = Irp->IoStatus.Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); return status; } break; case IRP_MN_REMOVE_DEVICE: DBG_PRINT(DBG_TRACE_OPS, ("%s: Removing Device...\n", __FUNCTION__)); IoForwardIrpSynchronously(DevExt->LowerDeviceObject, Irp); status = Irp->IoStatus.Status; if (NT_SUCCESS(status)) { DBG_PRINT(DBG_TRACE_OPS, ("%d-%d: Stopping Device...\n", DevExt->DiskNumber, DevExt->PartitionNumber)); StopDevice(DeviceObject); DBG_PRINT(DBG_TRACE_OPS, ("%d-%d: Device Stopped.\n", DevExt->DiskNumber, DevExt->PartitionNumber)); } IoCompleteRequest(Irp, IO_NO_INCREMENT); return status; } IoSkipCurrentIrpStackLocation(Irp); return IoCallDriver(DevExt->LowerDeviceObject, Irp); }
NTSTATUS DPDispatchPnp( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { //用来指向过滤设备的设备扩展的指针 PDP_FILTER_DEV_EXTENSION DevExt = DeviceObject->DeviceExtension; //返回值 NTSTATUS ntStatus = STATUS_SUCCESS; //用来指向irp stack的指针 PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation(Irp); switch(irpsp->MinorFunction) { case IRP_MN_REMOVE_DEVICE: //如果是PnP manager发过来的移除设备的irp,将进入这里 { //这里主要做一些清理工作 if (DevExt->ThreadTermFlag != TRUE && NULL != DevExt->ThreadHandle) { //如果线程还在运行的话需要停止它,这里通过设置线程停止运行的标志并且发送事件信息,让线程自己终止运行 DevExt->ThreadTermFlag = TRUE; KeSetEvent( &DevExt->ReqEvent, (KPRIORITY) 0, FALSE ); //等待线程结束 KeWaitForSingleObject( DevExt->ThreadHandle, Executive, KernelMode, FALSE, NULL ); //解除引用线程对象 ObDereferenceObject(DevExt->ThreadHandle); } if (NULL != DevExt->Bitmap) { //如果还有位图,就释放 DPBitmapFree(DevExt->Bitmap); } if (NULL != DevExt->LowerDevObj) { //如果存在着下层设备,就先去掉挂接 IoDetachDevice(DevExt->LowerDevObj); } if (NULL != DevExt->FltDevObj) { //如果存在过滤设备,就要删除它 IoDeleteDevice(DevExt->FltDevObj); } break; } //这个是PnP 管理器用来询问设备能否支持特殊文件的irp,作为卷的过滤驱动,我们必须处理 case IRP_MN_DEVICE_USAGE_NOTIFICATION: { BOOLEAN setPagable; //如果是询问是否支持休眠文件和dump文件,则直接下发给下层设备去处理 if (irpsp->Parameters.UsageNotification.Type != DeviceUsageTypePaging) { ntStatus = DPSendToNextDriver( DevExt->LowerDevObj, Irp); return ntStatus; } //这里等一下分页计数事件 ntStatus = KeWaitForSingleObject( &DevExt->PagingPathCountEvent, Executive, KernelMode, FALSE, NULL); //setPagable初始化为假,是没有设置过DO_POWER_PAGABLE的意思 setPagable = FALSE; if (!irpsp->Parameters.UsageNotification.InPath && DevExt->PagingPathCount == 1 ) { //如果是PnP manager通知我们将要删去分页文件,且我们目前只剩下最后一个分页文件的时候会进入这里 if (DeviceObject->Flags & DO_POWER_INRUSH) {} else { //到这里说明没有分页文件在这个设备上了,需要设置DO_POWER_PAGABLE这一位了 DeviceObject->Flags |= DO_POWER_PAGABLE; setPagable = TRUE; } } //到这里肯定是关于分页文件的是否可建立查询,或者是删除的通知,我们交给下层设备去做。这里需要用同步的方式给下层设备,也就是说要等待下层设备的返回 ntStatus = DPForwardIrpSync(DevExt->LowerDevObj,Irp); if (NT_SUCCESS(ntStatus)) { //如果发给下层设备的请求成功了,说明下层设备支持这个操作,会执行到这里 //在成功的条件下我们来改变我们自己的计数值,这样就能记录我们现在这个设备上到底有多少个分页文件 IoAdjustPagingPathCount( &DevExt->PagingPathCount, irpsp->Parameters.UsageNotification.InPath); if (irpsp->Parameters.UsageNotification.InPath) { if (DevExt->PagingPathCount == 1) { //如果这个请求是一个建立分页文件的查询请求,并且下层设备支持这个请求,而且这是第一个在这个设备上的分页文件,那么我们需要清除DO_POWER_PAGABLE位 DeviceObject->Flags &= ~DO_POWER_PAGABLE; } } } else { //到这里说明给下层设备发请求失败了,下层设备不支持这个请求,这时候我们需要把之前做过的操作还原 if (setPagable == TRUE) { //根据setPagable变量的值来判断我们之前是否做过对DO_POWER_PAGABLE的设置,如果有的话就清楚这个设置 DeviceObject->Flags &= ~DO_POWER_PAGABLE; setPagable = FALSE; } } //设置分页计数事件 KeSetEvent( &DevExt->PagingPathCountEvent, IO_NO_INCREMENT, FALSE ); //到这里我们就可以完成这个irp请求了 IoCompleteRequest(Irp, IO_NO_INCREMENT); return ntStatus; } default: break; } return DPSendToNextDriver( DevExt->LowerDevObj, Irp); }