static DECLSPEC_NOINLINE NTSTATUS PdoRemoveDevice( IN PXENFILT_PDO Pdo, IN PIRP Irp ) { PXENFILT_FDO Fdo = __PdoGetFdo(Pdo); POWER_STATE PowerState; NTSTATUS status; status = IoAcquireRemoveLock(&Pdo->Dx->RemoveLock, Irp); if (!NT_SUCCESS(status)) goto fail1; if (__PdoGetDevicePowerState(Pdo) != PowerDeviceD0) goto done; __PdoSetDevicePowerState(Pdo, PowerDeviceD3); __PdoSetSystemPowerState(Pdo, PowerSystemShutdown); PowerState.DeviceState = PowerDeviceD3; PoSetPowerState(Pdo->Dx->DeviceObject, DevicePowerState, PowerState); done: if (__PdoIsMissing(Pdo)) { __PdoSetDevicePnpState(Pdo, Deleted); IoReleaseRemoveLockAndWait(&Pdo->Dx->RemoveLock, Irp); } else { __PdoSetDevicePnpState(Pdo, Enumerated); IoReleaseRemoveLock(&Pdo->Dx->RemoveLock, Irp); } status = PdoForwardIrpSynchronously(Pdo, Irp); IoCompleteRequest(Irp, IO_NO_INCREMENT); if (__PdoIsMissing(Pdo)) { FdoAcquireMutex(Fdo); PdoDestroy(Pdo); FdoReleaseMutex(Fdo); } return status; fail1: Irp->IoStatus.Status = status; IoCompleteRequest(Irp, IO_NO_INCREMENT); return status; }
NTSTATUS VBoxDrvAddDevice(IN PDRIVER_OBJECT Driver, IN PDEVICE_OBJECT PDO) { NTSTATUS rc; PDEVICE_OBJECT pDO, pDOParent; PVBOXMOUSE_DEVEXT pDevExt; PAGED_CODE(); LOGF_ENTER(); rc = IoCreateDevice(Driver, sizeof(VBOXMOUSE_DEVEXT), NULL, FILE_DEVICE_MOUSE, 0, FALSE, &pDO); if (!NT_SUCCESS(rc)) { WARN(("IoCreateDevice failed with %#x", rc)); return rc; } pDevExt = (PVBOXMOUSE_DEVEXT) pDO->DeviceExtension; RtlZeroMemory(pDevExt, sizeof(VBOXMOUSE_DEVEXT)); IoInitializeRemoveLock(&pDevExt->RemoveLock, VBOXUSB_RLTAG, 1, 100); rc = IoAcquireRemoveLock(&pDevExt->RemoveLock, pDevExt); if (!NT_SUCCESS(rc)) { WARN(("IoAcquireRemoveLock failed with %#x", rc)); IoDeleteDevice(pDO); return rc; } pDOParent = IoAttachDeviceToDeviceStack(pDO, PDO); if (!pDOParent) { IoReleaseRemoveLockAndWait(&pDevExt->RemoveLock, pDevExt); WARN(("IoAttachDeviceToDeviceStack failed")); IoDeleteDevice(pDO); return STATUS_DEVICE_NOT_CONNECTED; } pDevExt->pdoMain = PDO; pDevExt->pdoSelf = pDO; pDevExt->pdoParent = pDOParent; VBoxDeviceAdded(pDevExt); pDO->Flags |= (DO_BUFFERED_IO | DO_POWER_PAGABLE); pDO->Flags &= ~DO_DEVICE_INITIALIZING; LOGF_LEAVE(); return rc; }
static NTSTATUS DispatchPnp (PDEVICE_OBJECT DeviceObject, PIRP Irp, VolumeFilterExtension *Extension, PIO_STACK_LOCATION irpSp) { NTSTATUS status; status = IoAcquireRemoveLock (&Extension->Queue.RemoveLock, Irp); if (!NT_SUCCESS (status)) return TCCompleteIrp (Irp, status, 0); switch (irpSp->MinorFunction) { case IRP_MN_START_DEVICE: Dump ("IRP_MN_START_DEVICE volume pdo=%p\n", Extension->Pdo); return PassFilteredIrp (Extension->LowerDeviceObject, Irp, OnStartDeviceCompleted, Extension); case IRP_MN_DEVICE_USAGE_NOTIFICATION: { PDEVICE_OBJECT attachedDevice = IoGetAttachedDeviceReference (DeviceObject); if (attachedDevice == DeviceObject || (attachedDevice->Flags & DO_POWER_PAGABLE)) DeviceObject->Flags |= DO_POWER_PAGABLE; ObDereferenceObject (attachedDevice); } return PassFilteredIrp (Extension->LowerDeviceObject, Irp, OnDeviceUsageNotificationCompleted, Extension); case IRP_MN_REMOVE_DEVICE: Dump ("IRP_MN_REMOVE_DEVICE volume pdo=%p\n", Extension->Pdo); IoReleaseRemoveLockAndWait (&Extension->Queue.RemoveLock, Irp); status = PassIrp (Extension->LowerDeviceObject, Irp); IoDetachDevice (Extension->LowerDeviceObject); IoDeleteDevice (DeviceObject); return status; default: status = PassIrp (Extension->LowerDeviceObject, Irp); IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp); } return status; }
NTSTATUS VBoxIrpPnP(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PIO_STACK_LOCATION pStack; PVBOXMOUSE_DEVEXT pDevExt; NTSTATUS rc; LOGF_ENTER(); pStack = IoGetCurrentIrpStackLocation(Irp); pDevExt = (PVBOXMOUSE_DEVEXT) DeviceObject->DeviceExtension; switch (pStack->MinorFunction) { case IRP_MN_REMOVE_DEVICE: { LOGF(("IRP_MN_REMOVE_DEVICE")); IoReleaseRemoveLockAndWait(&pDevExt->RemoveLock, pDevExt); VBoxDeviceRemoved(pDevExt); Irp->IoStatus.Status = STATUS_SUCCESS; rc = VBoxIrpPassthrough(DeviceObject, Irp); IoDetachDevice(pDevExt->pdoParent); IoDeleteDevice(DeviceObject); break; } default: { rc = VBoxIrpPassthrough(DeviceObject, Irp); break; } } if (!NT_SUCCESS(rc) && rc != STATUS_NOT_SUPPORTED) { WARN(("rc=%#x", rc)); } LOGF_LEAVE(); return rc; }
VOID USBPcapDeleteRootHubControlDevice(IN PDEVICE_OBJECT controlDevice) { UNICODE_STRING symbolicLinkName; PWCHAR symbolicNameBuffer[MAX_SYMBOLIC_LEN]; USHORT id; PDEVICE_EXTENSION pDevExt; NTSTATUS status; pDevExt = ((PDEVICE_EXTENSION)controlDevice->DeviceExtension); ASSERT(pDevExt->deviceMagic == USBPCAP_MAGIC_CONTROL); id = pDevExt->context.control.id; symbolicLinkName.Length = 0; symbolicLinkName.MaximumLength = MAX_SYMBOLIC_LEN; symbolicLinkName.Buffer = (PWSTR)symbolicNameBuffer; status = RtlUnicodeStringPrintf(&symbolicLinkName, SYMBOLIC_PREFIX L"%hu", id); IoAcquireRemoveLock(&pDevExt->removeLock, NULL); IoReleaseRemoveLockAndWait(&pDevExt->removeLock, NULL); IoReleaseRemoveLock(pDevExt->parentRemoveLock, NULL); ASSERT(NT_SUCCESS(status)); if (NT_SUCCESS(status)) { IoDeleteSymbolicLink(&symbolicLinkName); IoDeleteDevice(controlDevice); } else { /* Very bad */ KdPrint(("Failed to init symbolic link name\n")); pDevExt->context.control.pRootHubObject = NULL; } }
NTSTATUS DkHubFltPnP(PDEVICE_EXTENSION pDevExt, PIO_STACK_LOCATION pStack, PIRP pIrp) { NTSTATUS ntStat = STATUS_SUCCESS; ntStat = IoAcquireRemoveLock(&pDevExt->removeLock, (PVOID) pIrp); if (!NT_SUCCESS(ntStat)) { DkDbgVal("Error lock!", ntStat); DkCompleteRequest(pIrp, ntStat, 0); return ntStat; } switch (pStack->MinorFunction) { case IRP_MN_START_DEVICE: DkDbgStr("IRP_MN_START_DEVICE"); ntStat = DkForwardAndWait(pDevExt->pNextDevObj, pIrp); IoCompleteRequest(pIrp, IO_NO_INCREMENT); IoReleaseRemoveLock(&pDevExt->removeLock, (PVOID) pIrp); return ntStat; case IRP_MN_REMOVE_DEVICE: { PUSBPCAP_DEVICE_DATA pDeviceData = pDevExt->context.usb.pDeviceData; DkDbgStr("IRP_MN_REMOVE_DEVICE"); IoSkipCurrentIrpStackLocation(pIrp); ntStat = IoCallDriver(pDevExt->pNextDevObj, pIrp); if (pDeviceData != NULL && pDeviceData->pRootData != NULL && pDeviceData->pRootData->controlDevice != NULL) { USBPcapDeleteRootHubControlDevice(pDeviceData->pRootData->controlDevice); } IoReleaseRemoveLockAndWait(&pDevExt->removeLock, (PVOID) pIrp); DkDetachAndDeleteHubFilt(pDevExt); return ntStat; } case IRP_MN_QUERY_DEVICE_RELATIONS: DkDbgStr("IRP_MN_QUERY_DEVICE_RELATIONS"); ntStat = DkHubFltPnpHandleQryDevRels(pDevExt, pStack, pIrp); IoReleaseRemoveLock(&pDevExt->removeLock, (PVOID) pIrp); return ntStat; default: DkDbgVal("", pStack->MinorFunction); break; } IoSkipCurrentIrpStackLocation(pIrp); ntStat = IoCallDriver(pDevExt->pNextDevObj, pIrp); IoReleaseRemoveLock(&pDevExt->removeLock, (PVOID) pIrp); return ntStat; }
NTSTATUS DkTgtPnP(PDEVICE_EXTENSION pDevExt, PIO_STACK_LOCATION pStack, PIRP pIrp) { NTSTATUS ntStat = STATUS_SUCCESS; PUSBPCAP_DEVICE_DATA pDeviceData = pDevExt->context.usb.pDeviceData; ntStat = IoAcquireRemoveLock(&pDevExt->removeLock, (PVOID) pIrp); if (!NT_SUCCESS(ntStat)) { DkDbgVal("Error lock!", ntStat); DkCompleteRequest(pIrp, ntStat, 0); return ntStat; } switch (pStack->MinorFunction) { case IRP_MN_START_DEVICE: /* IRP_MN_START_DEVICE is sent at PASSIVE_LEVEL */ DkDbgStr("IRP_MN_START_DEVICE"); ntStat = DkForwardAndWait(pDevExt->pNextDevObj, pIrp); IoCompleteRequest(pIrp, IO_NO_INCREMENT); if (NT_SUCCESS(USBPcapGetDeviceUSBInfo(pDevExt))) { DkDbgVal("Started device", pDeviceData->deviceAddress); } else { DkDbgStr("Failed to get info of started device"); } IoReleaseRemoveLock(&pDevExt->removeLock, (PVOID) pIrp); return ntStat; case IRP_MN_QUERY_DEVICE_RELATIONS: /* Keep track of, and create child devices only for hubs. * Do not create child filters for composite devices. */ if (pDeviceData->isHub == TRUE) { DkDbgStr("IRP_MN_QUERY_DEVICE_RELATIONS"); ntStat = DkHubFltPnpHandleQryDevRels(pDevExt, pStack, pIrp); IoReleaseRemoveLock(&pDevExt->removeLock, (PVOID) pIrp); return ntStat; } else { break; } case IRP_MN_REMOVE_DEVICE: DkDbgStr("IRP_MN_REMOVE_DEVICE"); IoSkipCurrentIrpStackLocation(pIrp); ntStat = IoCallDriver(pDevExt->pNextDevObj, pIrp); IoReleaseRemoveLockAndWait(&pDevExt->removeLock, (PVOID) pIrp); DkDetachAndDeleteTgt(pDevExt); return ntStat; default: DkDbgVal("", pStack->MinorFunction); break; } IoSkipCurrentIrpStackLocation(pIrp); ntStat = IoCallDriver(pDevExt->pNextDevObj, pIrp); IoReleaseRemoveLock(&pDevExt->removeLock, (PVOID) pIrp); return ntStat; }
//======================================================================================== // Function: DispatchPnp // Purpose: // Return Value: // NT status code //======================================================================================== NTSTATUS DispatchPnp ( IN PDEVICE_OBJECT fido, // fido - pointer to a device object. IN PIRP irp // Irp - pointer to an I/O Request Packet. ) { PDEVICE_EXTENSION dx; PIO_STACK_LOCATION irpStack; NTSTATUS ntStatus = STATUS_SUCCESS; PAGED_CODE(); dx = (PDEVICE_EXTENSION)fido->DeviceExtension; irpStack = IoGetCurrentIrpStackLocation(irp); //acquire remove lock ntStatus = IoAcquireRemoveLock(&dx->rmLock, irp); if (!NT_SUCCESS(ntStatus)) { //complete irp if cannot acquire remove lock irp->IoStatus.Status=ntStatus; irp->IoStatus.Information=0; IoCompleteRequest(irp, IO_NO_INCREMENT); return ntStatus; } PnPMinorFunctionString(irpStack->MinorFunction); switch (irpStack->MinorFunction) { case IRP_MN_START_DEVICE: //The device is starting. //We cannot touch the device (send it any non pnp irps) until a //start device has been passed down to the lower drivers. IoCopyCurrentIrpStackLocationToNext(irp); IoSetCompletionRoutine(irp, (PIO_COMPLETION_ROUTINE)CompletionRoutineStartDevice, NULL, TRUE, TRUE, TRUE); return IoCallDriver(dx->lowerdo, irp); case IRP_MN_REMOVE_DEVICE: IoSkipCurrentIrpStackLocation(irp); ntStatus = IoCallDriver(dx->lowerdo, irp); IoReleaseRemoveLockAndWait(&dx->rmLock, irp); SET_NEW_PNP_STATE(dx, Deleted); IoDetachDevice(dx->lowerdo); IoDeleteDevice(fido); return ntStatus; case IRP_MN_QUERY_STOP_DEVICE: SET_NEW_PNP_STATE(dx, StopPending); break; case IRP_MN_CANCEL_STOP_DEVICE: //Check to see whether you have received cancel-stop //without first receiving a query-stop. This could happen if someone //above us fails a query-stop and passes down the subsequent //cancel-stop. if(dx->DevicePnPState == StopPending) { //We did receive a query-stop, so restore. RESTORE_PREVIOUS_PNP_STATE(dx); } //We must not fail this IRP. break; case IRP_MN_STOP_DEVICE: SET_NEW_PNP_STATE(dx, Stopped); break; case IRP_MN_QUERY_REMOVE_DEVICE: SET_NEW_PNP_STATE(dx, RemovePending); break; case IRP_MN_SURPRISE_REMOVAL: SET_NEW_PNP_STATE(dx, SurpriseRemovePending); break; case IRP_MN_CANCEL_REMOVE_DEVICE: //Check to see whether you have received cancel-remove //without first receiving a query-remove. This could happen if //someone above us fails a query-remove and passes down the //subsequent cancel-remove. if(dx->DevicePnPState == RemovePending) { //We did receive a query-remove, so restore. RESTORE_PREVIOUS_PNP_STATE(dx); } //We must not fail this IRP. break; case IRP_MN_DEVICE_USAGE_NOTIFICATION: //On the way down, pagable might become set. Mimic the driver //above us. If no one is above us, just set pagable. if ((fido->AttachedDevice == NULL) || (fido->AttachedDevice->Flags & DO_POWER_PAGABLE)) { fido->Flags |= DO_POWER_PAGABLE; } IoCopyCurrentIrpStackLocationToNext(irp); IoSetCompletionRoutine(irp, CompletionRoutineDevUsgNotify, NULL, TRUE, TRUE, TRUE); return IoCallDriver(dx->lowerdo, irp); default: break; } IoSkipCurrentIrpStackLocation(irp); ntStatus = IoCallDriver(dx->lowerdo, irp); IoReleaseRemoveLock(&dx->rmLock, irp); return ntStatus; }
// IRP_MJ_CREATE/IRP_MJ_CLOSE处理函数 NTSTATUS DispatchCreateClose( __in PDEVICE_OBJECT DeviceObject, __in PIRP Irp ) { PIO_STACK_LOCATION irpStack; NTSTATUS status; PFILE_CONTEXT fileContext; UNREFERENCED_PARAMETER(DeviceObject); PAGED_CODE(); irpStack = IoGetCurrentIrpStackLocation(Irp); ASSERT(irpStack->FileObject != NULL); switch (irpStack->MajorFunction) { case IRP_MJ_CREATE: { DebugPrint(("IRP_MJ_CREATE\n")); fileContext = (PFILE_CONTEXT)ExAllocatePoolWithQuotaTag( NonPagedPool, sizeof(FILE_CONTEXT), TAG); if (NULL == fileContext) { status = STATUS_INSUFFICIENT_RESOURCES; break; } IoInitializeRemoveLock(&fileContext->FileRundownLock, TAG, 0, 0); ASSERT(irpStack->FileObject->FsContext == NULL); irpStack->FileObject->FsContext = (PVOID) fileContext; status = STATUS_SUCCESS; break; } case IRP_MJ_CLOSE: { DebugPrint(("IRP_MJ_CLOSE\n")); fileContext = irpStack->FileObject->FsContext; IoAcquireRemoveLock(&fileContext->FileRundownLock, 0); IoReleaseRemoveLockAndWait(&fileContext->FileRundownLock, 0); ExFreePoolWithTag(fileContext, TAG); status = STATUS_SUCCESS; break; } default: ASSERT(FALSE); // should never hit this status = STATUS_NOT_IMPLEMENTED; break; } Irp->IoStatus.Status = status; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return status; }
NTSTATUS FPFilterDispatchPnp( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp); NTSTATUS status; PDEVICE_EXTENSION pDevExt = DeviceObject->DeviceExtension; BOOLEAN lockHeld; KdPrint(("LPCFILTER: FPFilterDispatchPnp: Device %X Irp %X\n", DeviceObject, Irp)); // // Acquire the remove lock so that device will not be removed while // processing this irp. // status = IoAcquireRemoveLock(&pDevExt->RemoveLock, Irp); if (!NT_SUCCESS(status)) { KdPrint(("LPCFILTER: FPFilterDispatchPnp: Remove lock failed PNP Irp type [%#02x]\n", irpSp->MinorFunction)); Irp->IoStatus.Information = 0; Irp->IoStatus.Status = status; IoCompleteRequest(Irp, IO_NO_INCREMENT); return status; } lockHeld = TRUE; switch(irpSp->MinorFunction) { case IRP_MN_QUERY_INTERFACE: { KdPrint(("LPCFILTER: FPFilterDispatchPnp: Schedule completion for QUERY_INTERFACE\n")); status = FPFilterForwardIrpSynchronous(DeviceObject, Irp); status = Irp->IoStatus.Status; IoCompleteRequest(Irp,IO_NO_INCREMENT); break; } case IRP_MN_QUERY_CAPABILITIES: { KdPrint(("LPCFILTER: FPFilterDispatchPnp: Sending on QUERY_CAPABILITIES\n")); status = FPFilterSendToNextDriver(DeviceObject, Irp); break; } case IRP_MN_START_DEVICE: { KdPrint(("LPCFILTER: FPFilterDispatchPnp: Sending on START_DEVICE\n")); status = FPFilterSendToNextDriver(DeviceObject, Irp); break; } case IRP_MN_STOP_DEVICE: { KdPrint(("LPCFILTER: FPFilterDispatchPnp: Sending on STOP_DEVICE\n")); status = FPFilterSendToNextDriver(DeviceObject, Irp); // if this filter device is the one with an associated control device then stop the thread and tidy up if(pDevExt->pOtherExt != NULL) { pDevExt->pOtherExt->ThreadGo = FALSE; // wait for the thread to end if(pDevExt->pOtherExt->DispatcherThreadObject) { KeWaitForSingleObject(pDevExt->pOtherExt->DispatcherThreadObject, Executive, KernelMode, FALSE, NULL); ObDereferenceObject(pDevExt->pOtherExt->DispatcherThreadObject); pDevExt->pOtherExt->DispatcherThreadObject = NULL; } if(pDevExt->pOtherExt->pStats) { ExFreePool(pDevExt->pOtherExt->pStats); pDevExt->pOtherExt->pStats = NULL; pDevExt->pOtherExt->StatsDataSize = 0; } if(pDevExt->pOtherExt->pPCTData) { ExFreePool(pDevExt->pOtherExt->pPCTData); pDevExt->pOtherExt->pPCTData = NULL; } if(pDevExt->pOtherExt->pPSSData) { ExFreePool(pDevExt->pOtherExt->pPSSData); pDevExt->pOtherExt->pPSSData = NULL; } if(pDevExt->pOtherExt->pChildEnumData) { ExFreePool(pDevExt->pOtherExt->pChildEnumData); pDevExt->pOtherExt->pChildEnumData = NULL; } if(pDevExt->pOtherExt->pCPUDB) { ExFreePool(pDevExt->pOtherExt->pCPUDB); pDevExt->pOtherExt->pCPUDB = NULL; } pDevExt->pOtherExt->IsDataObtained = FALSE; } break; } case IRP_MN_REMOVE_DEVICE: { // // Delete our device object(s) // KdPrint(( "FPFilterDispatchPnp: Sending on REMOVE_DEVICE\n")); status = FPFilterSendToNextDriver(DeviceObject, Irp); IoReleaseRemoveLockAndWait(&pDevExt->RemoveLock, Irp); IoDetachDevice(pDevExt->TargetDeviceObject); // if this filter device is the one with an associated control device then tidy up // stop the thread and delete that too device too if(pDevExt->pOtherExt != NULL) { pDevExt->pOtherExt->ThreadGo = FALSE; // wait for the thread to end if(pDevExt->pOtherExt->DispatcherThreadObject) { KeWaitForSingleObject(pDevExt->pOtherExt->DispatcherThreadObject, Executive, KernelMode, FALSE, NULL); ObDereferenceObject(pDevExt->pOtherExt->DispatcherThreadObject); pDevExt->pOtherExt->DispatcherThreadObject = NULL; } if(pDevExt->pOtherExt->pStats) { ExFreePool(pDevExt->pOtherExt->pStats); pDevExt->pOtherExt->pStats = NULL; pDevExt->pOtherExt->StatsDataSize = 0; } if(pDevExt->pOtherExt->pPCTData) { ExFreePool(pDevExt->pOtherExt->pPCTData); pDevExt->pOtherExt->pPCTData = NULL; } if(pDevExt->pOtherExt->pPSSData) { ExFreePool(pDevExt->pOtherExt->pPSSData); pDevExt->pOtherExt->pPSSData = NULL; } if(pDevExt->pOtherExt->pChildEnumData) { ExFreePool(pDevExt->pOtherExt->pChildEnumData); pDevExt->pOtherExt->pChildEnumData = NULL; } if(pDevExt->pOtherExt->pCPUDB) { ExFreePool(pDevExt->pOtherExt->pCPUDB); pDevExt->pOtherExt->pCPUDB = NULL; } IoDeleteSymbolicLink(&pDevExt->pOtherExt->linkName); IoDeleteDevice(pDevExt->pOtherExt->DeviceObject); gCtlDevNum = 0; } IoDeleteDevice(pDevExt->DeviceObject); lockHeld = FALSE; break; } case IRP_MN_DEVICE_USAGE_NOTIFICATION: { KdPrint(("LPCFILTER: FPFilterDispatchPnp: Sending on DEVICE_USAGE_NOTIFICATION\n")); status = FPFilterSendToNextDriver(DeviceObject, Irp); break; } default: { KdPrint(("LPCFILTER: FPFilterDispatchPnp: Forwarding irp\n")); status = FPFilterSendToNextDriver(DeviceObject, Irp); } } if (lockHeld) { IoReleaseRemoveLock(&pDevExt->RemoveLock, Irp); } return status; }
NTSTATUS mvolRemoveDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { NTSTATUS status; PVOLUME_EXTENSION VolumeExtension = DeviceObject->DeviceExtension; // we should call acuire removelock before pass down irp. // if acuire-removelock fail, we should return fail(STATUS_DELETE_PENDING). if (KeGetCurrentIrql() <= DISPATCH_LEVEL) { status = IoAcquireRemoveLock(&VolumeExtension->RemoveLock, NULL); if(!NT_SUCCESS(status)) { Irp->IoStatus.Status = status; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return status; } } status = mvolRunIrpSynchronous(DeviceObject, Irp); if (!NT_SUCCESS(status)) { WDRBD_ERROR("cannot remove device, status=0x%x\n", status); } IoReleaseRemoveLockAndWait(&VolumeExtension->RemoveLock, NULL); //wait remove lock IoDetachDevice(VolumeExtension->TargetDeviceObject); IoDeleteDevice(DeviceObject); #ifdef MULTI_WRITE_HOOKER_THREADS { int i = 0; for (i = 0; i < 5; i++) { if (deviceExtension->WorkThreadInfo[i].Active) { mvolTerminateThread(&deviceExtension->WorkThreadInfo); WDRBD_TRACE("[%ws]: WorkThread Terminate Completely\n", deviceExtension->PhysicalDeviceName); } } } #else if (VolumeExtension->WorkThreadInfo.Active) { mvolTerminateThread(&VolumeExtension->WorkThreadInfo); WDRBD_TRACE("[%ws]: WorkThread Terminate Completely\n", VolumeExtension->PhysicalDeviceName); } #endif if (VolumeExtension->dev) { struct drbd_device *device = minor_to_device(VolumeExtension->VolIndex); if (device) { // DRBD-UPGRADE: if primary, check umount first? maybe umounted already? struct drbd_resource *resource = device->resource; int ret; // DW-876: The function 'drbd_adm_down_from_engine' performs down operation with specified resource, it does clean up all it needs(including disconnecting connections..) // It should be called per resource. Do not call with the resource which is already down. ret = drbd_adm_down_from_engine(resource); if (ret != NO_ERROR) { WDRBD_ERROR("drbd_adm_down_from_engine failed. ret=%d\n", ret); // EVENTLOG! // error ignored. } } } FreeUnicodeString(&VolumeExtension->MountPoint); FreeUnicodeString(&VolumeExtension->VolumeGuid); MVOL_LOCK(); mvolDeleteDeviceList(VolumeExtension); MVOL_UNLOCK(); Irp->IoStatus.Status = status; IoCompleteRequest(Irp, IO_NO_INCREMENT); return status; }
NTSTATUS FilterDispatchPnp ( PDEVICE_OBJECT DeviceObject, PIRP Irp ) /*++ Routine Description: The plug and play dispatch routines. Most of these the driver will completely ignore. In all cases it must pass on the IRP to the lower driver. Arguments: DeviceObject - pointer to a device object. Irp - pointer to an I/O Request Packet. Return Value: NT status code --*/ { PDEVICE_EXTENSION deviceExtension; PIO_STACK_LOCATION irpStack; NTSTATUS status; KEVENT event; PAGED_CODE(); deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; irpStack = IoGetCurrentIrpStackLocation(Irp); DebugPrint(("FilterDO %s IRP:0x%p \n", PnPMinorFunctionString(irpStack->MinorFunction), Irp)); status = IoAcquireRemoveLock (&deviceExtension->RemoveLock, Irp); if (!NT_SUCCESS (status)) { Irp->IoStatus.Status = status; IoCompleteRequest (Irp, IO_NO_INCREMENT); return status; } switch (irpStack->MinorFunction) { case IRP_MN_START_DEVICE: // // The device is starting. // We cannot touch the device (send it any non pnp irps) until a // start device has been passed down to the lower drivers. // KeInitializeEvent(&event, NotificationEvent, FALSE); IoCopyCurrentIrpStackLocationToNext(Irp); IoSetCompletionRoutine(Irp, FilterStartCompletionRoutine, &event, TRUE, TRUE, TRUE); status = IoCallDriver(deviceExtension->NextLowerDriver, Irp); // // Wait for lower drivers to be done with the Irp. Important thing to // note here is when you allocate memory for an event in the stack // you must do a KernelMode wait instead of UserMode to prevent // the stack from getting paged out. // if (status == STATUS_PENDING) { KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL); status = Irp->IoStatus.Status; } if (NT_SUCCESS (status)) { // // As we are successfully now back, we will // first set our state to Started. // SET_NEW_PNP_STATE(deviceExtension, Started); // // On the way up inherit FILE_REMOVABLE_MEDIA during Start. // This characteristic is available only after the driver stack is started!. // if (deviceExtension->NextLowerDriver->Characteristics & FILE_REMOVABLE_MEDIA) { DeviceObject->Characteristics |= FILE_REMOVABLE_MEDIA; } #ifdef IOCTL_INTERFACE // // If the PreviousPnPState is stopped then we are being stopped temporarily // and restarted for resource rebalance. // if (Stopped != deviceExtension->PreviousPnPState) { // // Device is started for the first time. // FilterCreateControlObject(DeviceObject); } #endif } Irp->IoStatus.Status = status; IoCompleteRequest (Irp, IO_NO_INCREMENT); IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp); return status; case IRP_MN_REMOVE_DEVICE: // // Wait for all outstanding requests to complete // DebugPrint(("Waiting for outstanding requests\n")); IoReleaseRemoveLockAndWait(&deviceExtension->RemoveLock, Irp); IoSkipCurrentIrpStackLocation(Irp); status = IoCallDriver(deviceExtension->NextLowerDriver, Irp); SET_NEW_PNP_STATE(deviceExtension, Deleted); #ifdef IOCTL_INTERFACE FilterDeleteControlObject(); #endif IoDetachDevice(deviceExtension->NextLowerDriver); IoDeleteDevice(DeviceObject); return status; case IRP_MN_QUERY_STOP_DEVICE: SET_NEW_PNP_STATE(deviceExtension, StopPending); status = STATUS_SUCCESS; break; case IRP_MN_CANCEL_STOP_DEVICE: // // Check to see whether you have received cancel-stop // without first receiving a query-stop. This could happen if someone // above us fails a query-stop and passes down the subsequent // cancel-stop. // if (StopPending == deviceExtension->DevicePnPState) { // // We did receive a query-stop, so restore. // RESTORE_PREVIOUS_PNP_STATE(deviceExtension); } status = STATUS_SUCCESS; // We must not fail this IRP. break; case IRP_MN_STOP_DEVICE: SET_NEW_PNP_STATE(deviceExtension, Stopped); status = STATUS_SUCCESS; break; case IRP_MN_QUERY_REMOVE_DEVICE: SET_NEW_PNP_STATE(deviceExtension, RemovePending); status = STATUS_SUCCESS; break; case IRP_MN_SURPRISE_REMOVAL: SET_NEW_PNP_STATE(deviceExtension, SurpriseRemovePending); status = STATUS_SUCCESS; break; case IRP_MN_CANCEL_REMOVE_DEVICE: // // Check to see whether you have received cancel-remove // without first receiving a query-remove. This could happen if // someone above us fails a query-remove and passes down the // subsequent cancel-remove. // if (RemovePending == deviceExtension->DevicePnPState) { // // We did receive a query-remove, so restore. // RESTORE_PREVIOUS_PNP_STATE(deviceExtension); } status = STATUS_SUCCESS; // We must not fail this IRP. break; case IRP_MN_DEVICE_USAGE_NOTIFICATION: // // On the way down, pagable might become set. Mimic the driver // above us. If no one is above us, just set pagable. // #pragma prefast(suppress:__WARNING_INACCESSIBLE_MEMBER) if ((DeviceObject->AttachedDevice == NULL) || (DeviceObject->AttachedDevice->Flags & DO_POWER_PAGABLE)) { DeviceObject->Flags |= DO_POWER_PAGABLE; } IoCopyCurrentIrpStackLocationToNext(Irp); IoSetCompletionRoutine( Irp, FilterDeviceUsageNotificationCompletionRoutine, NULL, TRUE, TRUE, TRUE ); return IoCallDriver(deviceExtension->NextLowerDriver, Irp); default: // // If you don't handle any IRP you must leave the // status as is. // status = Irp->IoStatus.Status; break; } // // Pass the IRP down and forget it. // Irp->IoStatus.Status = status; IoSkipCurrentIrpStackLocation (Irp); status = IoCallDriver (deviceExtension->NextLowerDriver, Irp); IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp); return status; }
NTSTATUS DispatchPnp(IN PDEVICE_OBJECT fido, IN PIRP Irp) { // DispatchPnp PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp); ULONG fcn = stack->MinorFunction; NTSTATUS status; PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fido->DeviceExtension; status = IoAcquireRemoveLock(&pdx->RemoveLock, Irp); if (!NT_SUCCESS(status)) return CompleteRequest(Irp, status, 0); #if DBG static char* pnpname[] = { "IRP_MN_START_DEVICE", "IRP_MN_QUERY_REMOVE_DEVICE", "IRP_MN_REMOVE_DEVICE", "IRP_MN_CANCEL_REMOVE_DEVICE", "IRP_MN_STOP_DEVICE", "IRP_MN_QUERY_STOP_DEVICE", "IRP_MN_CANCEL_STOP_DEVICE", "IRP_MN_QUERY_DEVICE_RELATIONS", "IRP_MN_QUERY_INTERFACE", "IRP_MN_QUERY_CAPABILITIES", "IRP_MN_QUERY_RESOURCES", "IRP_MN_QUERY_RESOURCE_REQUIREMENTS", "IRP_MN_QUERY_DEVICE_TEXT", "IRP_MN_FILTER_RESOURCE_REQUIREMENTS", "", "IRP_MN_READ_CONFIG", "IRP_MN_WRITE_CONFIG", "IRP_MN_EJECT", "IRP_MN_SET_LOCK", "IRP_MN_QUERY_ID", "IRP_MN_QUERY_PNP_DEVICE_STATE", "IRP_MN_QUERY_BUS_INFORMATION", "IRP_MN_DEVICE_USAGE_NOTIFICATION", "IRP_MN_SURPRISE_REMOVAL", "IRP_MN_QUERY_LEGACY_BUS_INFORMATION", }; if (fcn < arraysize(pnpname)) KdPrint((DRIVERNAME " - IRP_MJ_PNP (%s)\n", pnpname[fcn])); else KdPrint((DRIVERNAME " - IRP_MJ_PNP (%2.2X)\n", fcn)); #endif // DBG // Handle usage notification specially in order to track power pageable // flag correctly. We need to avoid allowing a non-pageable handler to be // layered on top of a pageable handler. if (fcn == IRP_MN_DEVICE_USAGE_NOTIFICATION) { // usage notification if (!fido->AttachedDevice || (fido->AttachedDevice->Flags & DO_POWER_PAGABLE)) fido->Flags |= DO_POWER_PAGABLE; IoCopyCurrentIrpStackLocationToNext(Irp); IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE) UsageNotificationCompletionRoutine, (PVOID) pdx, TRUE, TRUE, TRUE); return IoCallDriver(pdx->LowerDeviceObject, Irp); } // usage notification // Handle start device specially in order to correctly inherit // FILE_REMOVABLE_MEDIA if (fcn == IRP_MN_START_DEVICE) { // device start IoCopyCurrentIrpStackLocationToNext(Irp); IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE) StartDeviceCompletionRoutine, (PVOID) pdx, TRUE, TRUE, TRUE); return IoCallDriver(pdx->LowerDeviceObject, Irp); } // device start // Handle remove device specially in order to cleanup device stack if (fcn == IRP_MN_REMOVE_DEVICE) { // remove device IoSkipCurrentIrpStackLocation(Irp); status = IoCallDriver(pdx->LowerDeviceObject, Irp); IoReleaseRemoveLockAndWait(&pdx->RemoveLock, Irp); RemoveDevice(fido); return status; } // remove device // Simply forward any other type of PnP request IoSkipCurrentIrpStackLocation(Irp); status = IoCallDriver(pdx->LowerDeviceObject, Irp); IoReleaseRemoveLock(&pdx->RemoveLock, Irp); return status; } // DispatchPnp
NTSTATUS CsampCleanup( __in PDEVICE_OBJECT DeviceObject, __in PIRP Irp ) /*++ Routine Description: This dispatch routine is called when the last handle (in the whole system) to a file object is closed. In other words, the open handle count for the file object goes to 0. A driver that holds pending IRPs internally must implement a routine for IRP_MJ_CLEANUP. When the routine is called, the driver should cancel all the pending IRPs that belong to the file object identified by the IRP_MJ_CLEANUP call. In other words, it should cancel all the IRPs that have the same file-object pointer as the one supplied in the current I/O stack location of the IRP for the IRP_MJ_CLEANUP call. Of course, IRPs belonging to other file objects should not be canceled. Also, if an outstanding IRP is completed immediately, the driver does not have to cancel it. Arguments: DeviceObject -- pointer to the device object Irp -- pointer to the requesing Irp Return Value: STATUS_SUCCESS -- if the poll succeeded, --*/ { PDEVICE_EXTENSION devExtension; PIRP pendingIrp; PIO_STACK_LOCATION irpStack; PFILE_CONTEXT fileContext; NTSTATUS status; CSAMP_KDPRINT(("CsampCleanupIrp enter\n")); devExtension = DeviceObject->DeviceExtension; irpStack = IoGetCurrentIrpStackLocation(Irp); ASSERT(irpStack->FileObject != NULL); fileContext = irpStack->FileObject->FsContext; // // This acquire cannot fail because you cannot get more than one // cleanup for the same handle. // status = IoAcquireRemoveLock(&fileContext->FileRundownLock, Irp); ASSERT(NT_SUCCESS(status)); // // Wait for all the threads that are currently dispatching to exit and // prevent any threads dispatching I/O on the same handle beyond this point. // IoReleaseRemoveLockAndWait(&fileContext->FileRundownLock, Irp); pendingIrp = IoCsqRemoveNextIrp(&devExtension->CancelSafeQueue, irpStack->FileObject); while(pendingIrp) { // // Cancel the IRP // pendingIrp->IoStatus.Information = 0; pendingIrp->IoStatus.Status = STATUS_CANCELLED; CSAMP_KDPRINT(("Cleanup cancelled irp\n")); IoCompleteRequest(pendingIrp, IO_NO_INCREMENT); pendingIrp = IoCsqRemoveNextIrp(&devExtension->CancelSafeQueue, irpStack->FileObject); } // // Finally complete the cleanup IRP // Irp->IoStatus.Information = 0; Irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(Irp, IO_NO_INCREMENT); CSAMP_KDPRINT(("CsampCleanupIrp exit\n")); return STATUS_SUCCESS; }
static NTSTATUS NTAPI V4vDispatchPnP(PDEVICE_OBJECT fdo, PIRP irp) { NTSTATUS status = STATUS_SUCCESS; PIO_STACK_LOCATION isl = IoGetCurrentIrpStackLocation(irp); PXENV4V_EXTENSION pde = V4vGetDeviceExtension(fdo); KEVENT kev; TraceVerbose(("====> '%s'.\n", __FUNCTION__)); TraceVerbose((" =PnP= 0x%x\n", isl->MinorFunction)); status = IoAcquireRemoveLock(&pde->removeLock, irp); if (!NT_SUCCESS(status)) { TraceError(("failed to acquire IO lock - error: 0x%x\n", status)); return V4vSimpleCompleteIrp(irp, status); } switch (isl->MinorFunction) { case IRP_MN_START_DEVICE: KeInitializeEvent(&kev, NotificationEvent, FALSE); // Send the start down and wait for it to complete IoCopyCurrentIrpStackLocationToNext(irp); IoSetCompletionRoutine(irp, V4vStartDeviceIoCompletion, &kev, TRUE, TRUE, TRUE); status = IoCallDriver(pde->ldo, irp); if (status == STATUS_PENDING) { // Wait for everything underneath us to complete TraceVerbose(("Device start waiting for lower device.\n")); KeWaitForSingleObject(&kev, Executive, KernelMode, FALSE, NULL); TraceVerbose(("Device start wait finished.\n")); } status = irp->IoStatus.Status; if (!NT_SUCCESS(status)) { TraceError(("Failed to start lower drivers: %x.\n", status)); IoCompleteRequest(irp, IO_NO_INCREMENT); break; } status = STATUS_SUCCESS; // Connect our interrupt (ec). status = V4vInitializeEventChannel(fdo); if (NT_SUCCESS(status)) { InterlockedExchange(&pde->state, XENV4V_DEV_STARTED); } else { TraceError(("failed to initialize event channel - error: 0x%x\n", status)); } irp->IoStatus.Status = status; IoCompleteRequest(irp, IO_NO_INCREMENT); break; case IRP_MN_STOP_DEVICE: // Stop our device's IO processing V4vStopDevice(fdo, pde); // Pass it down irp->IoStatus.Status = STATUS_SUCCESS; IoSkipCurrentIrpStackLocation(irp); status = IoCallDriver(pde->ldo, irp); break; case IRP_MN_REMOVE_DEVICE: // Stop our device's IO processing V4vStopDevice(fdo, pde); // Cleanup anything here that locks for IO IoReleaseRemoveLockAndWait(&pde->removeLock, irp); // Pass it down first IoSkipCurrentIrpStackLocation(irp); status = IoCallDriver(pde->ldo, irp); // Then detach and cleanup our device xenbus_change_state(XBT_NIL, pde->frontendPath, "state", XENBUS_STATE_CLOSED); IoDetachDevice(pde->ldo); ExDeleteNPagedLookasideList(&pde->destLookasideList); XmFreeMemory(pde->frontendPath); IoDeleteSymbolicLink(&pde->symbolicLink); IoDeleteDevice(fdo); InterlockedAnd(&g_deviceCreated, 0); return status; default: // Pass it down TraceVerbose(("IRP_MJ_PNP MinorFunction %d passed down\n", isl->MinorFunction)); IoSkipCurrentIrpStackLocation(irp); status = IoCallDriver(pde->ldo, irp); }; // Everybody but REMOVE IoReleaseRemoveLock(&pde->removeLock, irp); TraceVerbose(("<==== '%s'.\n", __FUNCTION__)); return status; }