NTSTATUS WaitWakeCompletionRoutine( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension ) /*++ Routine Description: This is the IoSet completion routine for the wait wake irp. Arguments: DeviceObject - pointer to device object Irp - I/O request packet DeviceExtension - pointer to device extension Return Value: NT status value --*/ { BulkUsb_DbgPrint(3, ("WaitWakeCompletionRoutine - begins\n")); if(Irp->PendingReturned) { IoMarkIrpPending(Irp); } // // Nullify the WaitWakeIrp pointer-the Irp is released // as part of the completion process. If it's already NULL, // avoid race with the CancelWaitWake routine. // if(InterlockedExchangePointer(&DeviceExtension->WaitWakeIrp, NULL)) { PoStartNextPowerIrp(Irp); return STATUS_SUCCESS; } // // CancelWaitWake has run. // If FlagWWCancel != 0, complete the Irp. // If FlagWWCancel == 0, CancelWaitWake completes it. // if(InterlockedExchange(&DeviceExtension->FlagWWCancel, 1)) { PoStartNextPowerIrp(Irp); return STATUS_CANCELLED; } BulkUsb_DbgPrint(3, ("WaitWakeCompletionRoutine - ends\n")); return STATUS_MORE_PROCESSING_REQUIRED; }
VOID CancelSelectSuspend(IN PTDeviceExtension DeviceExtension) { PIRP irp; KIRQL oldIrql; irp = NULL; BulkUsb_DbgPrint(3, ("file bulkdev: CancelSelectSuspend - begins\n")); KeAcquireSpinLock(&DeviceExtension->IdleReqStateLock, &oldIrql); if(!CanDeviceSuspend(DeviceExtension)) { BulkUsb_DbgPrint(3, ("file bulkdev: Device is not idle\n")); irp = (PIRP)InterlockedExchangePointer(&DeviceExtension->PendingIdleIrp, NULL); } KeReleaseSpinLock(&DeviceExtension->IdleReqStateLock, oldIrql); if(irp) { IoCancelIrp(irp); if(0 == InterlockedDecrement(&DeviceExtension->FreeIdleIrpCount)) { BulkUsb_DbgPrint(3, ("file bulkdev: CancelSelectSuspend frees the irp\n")); IoFreeIrp(irp); KeSetEvent(&DeviceExtension->NoIdleReqPendEvent, IO_NO_INCREMENT, FALSE); } } BulkUsb_DbgPrint(3, ("file bulkdev: CancelSelectSuspend - ends\n")); return; }
NTSTATUS HandleSystemSetPower( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) /*++ Routine Description: This routine services irps of minor type IRP_MN_SET_POWER for the system power state Arguments: DeviceObject - pointer to device object Irp - I/O request packet sent by the power manager Return Value: NT status value: --*/ { NTSTATUS ntStatus; PDEVICE_EXTENSION deviceExtension; SYSTEM_POWER_STATE systemState; PIO_STACK_LOCATION irpStack; BulkUsb_DbgPrint(3, ("HandleSystemSetPower - begins\n")); // // initialize variables // deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; irpStack = IoGetCurrentIrpStackLocation(Irp); systemState = irpStack->Parameters.Power.State.SystemState; BulkUsb_DbgPrint(3, ("Set request for system power state S%X\n" "Current system power state S%X\n", systemState - 1, deviceExtension->SysPower - 1)); IoCopyCurrentIrpStackLocationToNext(Irp); IoSetCompletionRoutine( Irp, (PIO_COMPLETION_ROUTINE)SysPoCompletionRoutine, deviceExtension, TRUE, TRUE, TRUE); ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp); BulkUsb_DbgPrint(3, ("HandleSystemSetPower - ends\n")); return STATUS_PENDING; }
NTSTATUS FinishDevPoDnIrp( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension ) /*++ Routine Description: This routine is the completion routine for device power DOWN irp. Arguments: DeviceObject - pointer to device object Irp - I/O request packet DeviceExtension - pointer to device extension Return Value: NT status value --*/ { NTSTATUS ntStatus; POWER_STATE newState; PIO_STACK_LOCATION irpStack; // // initialize variables // ntStatus = Irp->IoStatus.Status; irpStack = IoGetCurrentIrpStackLocation(Irp); newState = irpStack->Parameters.Power.State; BulkUsb_DbgPrint(3, ("FinishDevPoDnIrp - begins\n")); if(NT_SUCCESS(ntStatus) && irpStack->MinorFunction == IRP_MN_SET_POWER) { // // update the cache; // BulkUsb_DbgPrint(3, ("updating cache..\n")); DeviceExtension->DevPower = newState.DeviceState; PoSetPowerState(DeviceObject, DevicePowerState, newState); } PoStartNextPowerIrp(Irp); BulkUsb_DbgPrint(3, ("FinishDevPoDnIrp::")); BulkUsb_IoDecrement(DeviceExtension); BulkUsb_DbgPrint(3, ("FinishDevPoDnIrp - ends\n")); return STATUS_SUCCESS; }
NTSTATUS FinishDevPoUpIrp( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension ) /*++ Routine Description: completion routine for the device power UP irp with minor function IRP_MN_SET_POWER. Arguments: DeviceObject - pointer to device object Irp - I/O request packet DeviceExtension - pointer to device extension Return Value: NT status value --*/ { NTSTATUS ntStatus; // // initialize variables // ntStatus = Irp->IoStatus.Status; BulkUsb_DbgPrint(3, ("FinishDevPoUpIrp - begins\n")); if(Irp->PendingReturned) { IoMarkIrpPending(Irp); } if(!NT_SUCCESS(ntStatus)) { PoStartNextPowerIrp(Irp); BulkUsb_DbgPrint(3, ("FinishDevPoUpIrp::")); BulkUsb_IoDecrement(DeviceExtension); return STATUS_SUCCESS; } SetDeviceFunctional(DeviceObject, Irp, DeviceExtension); BulkUsb_DbgPrint(3, ("FinishDevPoUpIrp - ends\n")); return STATUS_MORE_PROCESSING_REQUIRED; }
NTSTATUS IssueWaitWake( IN PDEVICE_EXTENSION DeviceExtension ) /*++ Routine Description: This routine will PoRequest a WAIT WAKE irp for the device Arguments: DeviceExtension - pointer to device extension Return Value: NT status value. --*/ { POWER_STATE poState; NTSTATUS ntStatus; BulkUsb_DbgPrint(3, ("IssueWaitWake - begins\n")); if(InterlockedExchange(&DeviceExtension->FlagWWOutstanding, 1)) { return STATUS_DEVICE_BUSY; } InterlockedExchange(&DeviceExtension->FlagWWCancel, 0); // // lowest state from which this Irp will wake the system // poState.SystemState = DeviceExtension->DeviceCapabilities.SystemWake; ntStatus = PoRequestPowerIrp(DeviceExtension->PhysicalDeviceObject, IRP_MN_WAIT_WAKE, poState, (PREQUEST_POWER_COMPLETE) WaitWakeCallback, DeviceExtension, &DeviceExtension->WaitWakeIrp); if(!NT_SUCCESS(ntStatus)) { InterlockedExchange(&DeviceExtension->FlagWWOutstanding, 0); } BulkUsb_DbgPrint(3, ("IssueWaitWake - ends\n")); return ntStatus; }
NTSTATUS QueueRequest( IN OUT PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp ) /*++ Routine Description: Queue the Irp in the device queue Arguments: DeviceExtension - pointer to device extension Irp - I/O request packet. Return Value: NT status value --*/ { KIRQL oldIrql; NTSTATUS ntStatus; // // initialize variables // ntStatus = STATUS_PENDING; BulkUsb_DbgPrint(3, ("QueueRequests - begins\n")); ASSERT(HoldRequests == DeviceExtension->QueueState); KeAcquireSpinLock(&DeviceExtension->QueueLock, &oldIrql); InsertTailList(&DeviceExtension->NewRequestsQueue, &Irp->Tail.Overlay.ListEntry); IoMarkIrpPending(Irp); // // Set the cancel routine // IoSetCancelRoutine(Irp, CancelQueued); KeReleaseSpinLock(&DeviceExtension->QueueLock, oldIrql); BulkUsb_DbgPrint(3, ("QueueRequests - ends\n")); return ntStatus; }
NTSTATUS BulkUsb_DispatchSysCtrl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PTDeviceExtension deviceExtension; SYSCTL_IRP_DISPOSITION disposition; NTSTATUS ntStatus; PIO_STACK_LOCATION irpStack; PAGED_CODE(); irpStack = IoGetCurrentIrpStackLocation (Irp); deviceExtension = (PTDeviceExtension) DeviceObject->DeviceExtension; if(REMOVED == deviceExtension->DeviceState) { ntStatus = STATUS_DELETE_PENDING; Irp->IoStatus.Status = ntStatus; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return ntStatus; } BulkUsb_DbgPrint(3, ("file bulkwmi: BulkUsb_DispatchSysCtrl::\n")); BulkUsb_IoIncrement(deviceExtension); ntStatus = WmiSystemControl(&deviceExtension->WmiLibInfo, DeviceObject, Irp, &disposition); switch(disposition) { case IrpProcessed: break; case IrpNotCompleted: IoCompleteRequest(Irp, IO_NO_INCREMENT); break; case IrpForward: case IrpNotWmi: IoSkipCurrentIrpStackLocation (Irp); ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp); break; default: IoSkipCurrentIrpStackLocation (Irp); ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp); break; } BulkUsb_DbgPrint(3, ("file bulkwmi: BulkUsb_DispatchSysCtrl::\n")); BulkUsb_IoDecrement(deviceExtension); return ntStatus; }
static VOID IdleNotificationCallback(IN PTDeviceExtension DeviceExtension) { NTSTATUS ntStatus; POWER_STATE powerState; KEVENT irpCompletionEvent; PTIrpCompletionContext irpContext; BulkUsb_DbgPrint(3, ("file bulkdev: IdleNotificationCallback - process\n")); if(DeviceExtension->DeviceState != WORKING) return; if(DeviceExtension->WaitWakeEnable) IssueWaitWake(DeviceExtension); irpContext = (PTIrpCompletionContext)ExAllocatePool(NonPagedPool, sizeof(TIrpCompletionContext)); if(!irpContext) { BulkUsb_DbgPrint(1, ("file bulkdev: Failed to alloc memory for irpContext\n")); //ntStatus = STATUS_INSUFFICIENT_RESOURCES; return; } BulkUsb_DbgPrint(3, ("file bulkdev: IdleNotificationCallback::")); BulkUsb_IoIncrement(DeviceExtension); powerState.DeviceState = DeviceExtension->PowerDownLevel; KeInitializeEvent(&irpCompletionEvent, NotificationEvent, FALSE); irpContext->DeviceExtension = DeviceExtension; irpContext->Event = &irpCompletionEvent; ntStatus = PoRequestPowerIrp( DeviceExtension->PhysicalDeviceObject, IRP_MN_SET_POWER, powerState, (PREQUEST_POWER_COMPLETE) PoIrpCompletionFunc, irpContext, NULL); if(STATUS_PENDING == ntStatus) { BulkUsb_DbgPrint(3, ("file bulkdev: IdleNotificationCallback::" "waiting for the power irp to complete\n")); KeWaitForSingleObject(&irpCompletionEvent, Executive, KernelMode, FALSE, NULL); } ExFreePool(irpContext); BulkUsb_DbgPrint(3, ("file bulkdev: IdleNotificationCallback - ends\n")); }
NTSTATUS BulkUsb_QueryWmiDataBlock(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN ULONG GuidIndex, IN ULONG InstanceIndex, IN ULONG InstanceCount, IN OUT PULONG InstanceLengthArray, IN ULONG OutBufferSize, OUT PUCHAR Buffer) { PTDeviceExtension deviceExtension; NTSTATUS ntStatus; ULONG size; WCHAR modelName[] = L"Aishverya\0\0"; USHORT modelNameLen; PAGED_CODE(); BulkUsb_DbgPrint(3, ("file bulkwmi: BulkUsb_QueryWmiDataBlock - begins\n")); size = 0; modelNameLen = (wcslen(modelName) + 1) * sizeof(WCHAR); ASSERT((InstanceIndex == 0) && (InstanceCount == 1)); deviceExtension = (PTDeviceExtension) DeviceObject->DeviceExtension; switch (GuidIndex) { case WMI_BULKUSB_DRIVER_INFORMATION: size = sizeof(ULONG) + modelNameLen + sizeof(USHORT); if (OutBufferSize < size ) { BulkUsb_DbgPrint(3, ("file bulkwmi: OutBuffer too small\n")); ntStatus = STATUS_BUFFER_TOO_SMALL; break; } * (PULONG) Buffer = DebugLevel; Buffer += sizeof(ULONG); *((PUSHORT)Buffer) = modelNameLen; Buffer = (PUCHAR)Buffer + sizeof(USHORT); RtlCopyBytes((PVOID)Buffer, (PVOID)modelName, modelNameLen); *InstanceLengthArray = size ; ntStatus = STATUS_SUCCESS; break; default: ntStatus = STATUS_WMI_GUID_NOT_FOUND; break; } ntStatus = WmiCompleteRequest(DeviceObject, Irp, ntStatus, size, IO_NO_INCREMENT); BulkUsb_DbgPrint(3, ("file bulkwmi: BulkUsb_QueryWmiDataBlock - ends\n")); return ntStatus; }
static NTSTATUS BulkUsb_QueryWmiRegInfo(IN PDEVICE_OBJECT DeviceObject, OUT ULONG *RegFlags, OUT PUNICODE_STRING InstanceName, OUT PUNICODE_STRING *RegistryPath, OUT PUNICODE_STRING MofResourceName, OUT PDEVICE_OBJECT *Pdo) { PTDeviceExtension deviceExtension; PAGED_CODE(); BulkUsb_DbgPrint(3, ("file bulkwmi: BulkUsb_QueryWmiRegInfo - begins\n")); deviceExtension = DeviceObject->DeviceExtension; *RegFlags = WMIREG_FLAG_INSTANCE_PDO; *RegistryPath = &gUsbdContext.BulkUsb_RegistryPath; *Pdo = deviceExtension->PhysicalDeviceObject; RtlInitUnicodeString(MofResourceName, MOFRESOURCENAME); BulkUsb_DbgPrint(3, ("file bulkwmi: BulkUsb_QueryWmiRegInfo - ends\n")); return STATUS_SUCCESS; }
NTSTATUS BulkUsb_ResetDevice(IN PDEVICE_OBJECT DeviceObject) { NTSTATUS ntStatus; ULONG portStatus; BulkUsb_DbgPrint(3, ("file bulkdev: BulkUsb_ResetDevice - begins\n")); ntStatus = BulkUsb_GetPortStatus(DeviceObject, &portStatus); if((NT_SUCCESS(ntStatus)) && (!(portStatus & USBD_PORT_ENABLED)) && (portStatus & USBD_PORT_CONNECTED)) { ntStatus = BulkUsb_ResetParentPort(DeviceObject); } BulkUsb_DbgPrint(3, ("file bulkdev: BulkUsb_ResetDevice - ends\n")); return ntStatus; }
//============================================ static NTSTATUS BulkUsb_GetPortStatus(IN PDEVICE_OBJECT DeviceObject, IN OUT PULONG PortStatus) { NTSTATUS ntStatus; KEVENT event; PIRP irp; IO_STATUS_BLOCK ioStatus; PIO_STACK_LOCATION nextStack; PTDeviceExtension deviceExtension; deviceExtension = (PTDeviceExtension) DeviceObject->DeviceExtension; *PortStatus = 0; BulkUsb_DbgPrint(3, ("file bulkdev: BulkUsb_GetPortStatus - begins\n")); KeInitializeEvent(&event, NotificationEvent, FALSE); irp = IoBuildDeviceIoControlRequest( IOCTL_INTERNAL_USB_GET_PORT_STATUS, deviceExtension->TopOfStackDeviceObject, NULL, 0, NULL, 0, TRUE, &event, &ioStatus); if(NULL == irp) { BulkUsb_DbgPrint(1, ("file bulkdev: memory alloc for irp failed\n")); return STATUS_INSUFFICIENT_RESOURCES; } nextStack = IoGetNextIrpStackLocation(irp); ASSERT(nextStack != NULL); nextStack->Parameters.Others.Argument1 = PortStatus; ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, irp); if(STATUS_PENDING == ntStatus) { KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL); } else ioStatus.Status = ntStatus; ntStatus = ioStatus.Status; BulkUsb_DbgPrint(3, ("file bulkdev: BulkUsb_GetPortStatus - ends\n")); return ntStatus; }
NTSTATUS BulkUsb_SetWmiDataItem(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN ULONG GuidIndex, IN ULONG InstanceIndex, IN ULONG DataItemId, IN ULONG BufferSize, IN PUCHAR Buffer) { PTDeviceExtension deviceExtension; NTSTATUS ntStatus; ULONG info; PAGED_CODE(); BulkUsb_DbgPrint(3, ("file bulkwmi: BulkUsb_SetWmiDataItem - begins\n")); deviceExtension = (PTDeviceExtension) DeviceObject->DeviceExtension; info = 0; switch(GuidIndex) { case WMI_BULKUSB_DRIVER_INFORMATION: if(DataItemId == 1) { if(BufferSize == sizeof(ULONG)) { DebugLevel = *((PULONG)Buffer); ntStatus = STATUS_SUCCESS; info = sizeof(ULONG); } else ntStatus = STATUS_INFO_LENGTH_MISMATCH; } else ntStatus = STATUS_WMI_READ_ONLY; break; default: ntStatus = STATUS_WMI_GUID_NOT_FOUND; break; } ntStatus = WmiCompleteRequest(DeviceObject, Irp, ntStatus, info, IO_NO_INCREMENT); BulkUsb_DbgPrint(3, ("file bulkwmi: BulkUsb_SetWmiDataItem - ends\n")); return ntStatus; }
VOID CancelWaitWake( IN PDEVICE_EXTENSION DeviceExtension ) /*++ Routine Description: This routine cancels the Wait Wake request. Arguments: DeviceExtension - pointer to the device extension Return Value: None. --*/ { PIRP Irp; BulkUsb_DbgPrint(3, ("CancelWaitWake - begins\n")); Irp = (PIRP) InterlockedExchangePointer(&DeviceExtension->WaitWakeIrp, NULL); if(Irp) { IoCancelIrp(Irp); if(InterlockedExchange(&DeviceExtension->FlagWWCancel, 1)) { PoStartNextPowerIrp(Irp); Irp->IoStatus.Status = STATUS_CANCELLED; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); } } BulkUsb_DbgPrint(3, ("CancelWaitWake - ends\n")); }
VOID PoIrpCompletionFunc( IN PDEVICE_OBJECT DeviceObject, IN UCHAR MinorFunction, IN POWER_STATE PowerState, IN PVOID Context, IN PIO_STATUS_BLOCK IoStatus ) /*++ Routine Description: Completion routine for power irp PoRequested in IdleNotificationCallback. Arguments: DeviceObject - pointer to device object MinorFunciton - minor function for the irp. PowerState - irp power state Context - context passed to the completion function IoStatus - status block. Return Value: None --*/ { PIRP_COMPLETION_CONTEXT irpContext; // // initialize variables // if(Context) { irpContext = (PIRP_COMPLETION_CONTEXT) Context; } // // all we do is set the event and decrement the count // if(irpContext) { KeSetEvent(irpContext->Event, 0, FALSE); BulkUsb_DbgPrint(3, ("PoIrpCompletionFunc::")); BulkUsb_IoDecrement(irpContext->DeviceExtension); ExFreePool(irpContext); } return; }
static VOID PoIrpAsyncCompletionFunc(IN PDEVICE_OBJECT DeviceObject, IN UCHAR MinorFunction, IN POWER_STATE PowerState, IN PVOID Context, IN PIO_STATUS_BLOCK IoStatus) { PTDeviceExtension DeviceExtension; DeviceExtension = (PTDeviceExtension) Context; if(DeviceExtension) { BulkUsb_DbgPrint(3, ("file bulkdev: PoIrpAsyncCompletionFunc::")); BulkUsb_IoDecrement(DeviceExtension); } }
NTSTATUS BulkUsb_ResetDevice( IN PDEVICE_OBJECT DeviceObject ) /*++ Routine Description: This routine invokes BulkUsb_ResetParentPort to reset the device Arguments: DeviceObject - pointer to device object Return Value: NT status value --*/ { NTSTATUS ntStatus; ULONG portStatus; BulkUsb_DbgPrint(3, ("BulkUsb_ResetDevice - begins\n")); ntStatus = BulkUsb_GetPortStatus(DeviceObject, &portStatus); if((NT_SUCCESS(ntStatus)) && (!(portStatus & USBD_PORT_ENABLED)) && (portStatus & USBD_PORT_CONNECTED)) { ntStatus = BulkUsb_ResetParentPort(DeviceObject); } BulkUsb_DbgPrint(3, ("BulkUsb_ResetDevice - ends\n")); return ntStatus; }
NTSTATUS BulkUsb_DispatchClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { NTSTATUS ntStatus; PFILE_OBJECT fileObject; PTDeviceExtension deviceExtension; PIO_STACK_LOCATION irpStack; PTPipeContext pipeContext; PUSBD_PIPE_INFORMATION pipeInformation; PAGED_CODE(); irpStack = IoGetCurrentIrpStackLocation(Irp); fileObject = irpStack->FileObject; pipeContext = NULL; pipeInformation = NULL; deviceExtension = (PTDeviceExtension) DeviceObject->DeviceExtension; BulkUsb_DbgPrint(3, ("file bulkdev: BulkUsb_DispatchClose - begins\n")); if(fileObject && fileObject->FsContext) { pipeInformation = fileObject->FsContext; if(0 != fileObject->FileName.Length) { pipeContext = BulkUsb_PipeWithName(DeviceObject, &fileObject->FileName); } if(pipeContext && pipeContext->PipeOpen) pipeContext->PipeOpen = FALSE; } ntStatus = STATUS_SUCCESS; Irp->IoStatus.Status = ntStatus; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); InterlockedDecrement(&deviceExtension->OpenHandleCount); BulkUsb_DbgPrint(3, ("file bulkdev: BulkUsb_DispatchClose - ends\n")); return ntStatus; }
static VOID PoIrpCompletionFunc(IN PDEVICE_OBJECT DeviceObject, IN UCHAR MinorFunction, IN POWER_STATE PowerState, IN PVOID Context, IN PIO_STATUS_BLOCK IoStatus) { PTIrpCompletionContext irpContext; //irpContext = NULL; //if(Context) irpContext = (PTIrpCompletionContext) Context; if(irpContext) { KeSetEvent(irpContext->Event, 0, FALSE); BulkUsb_DbgPrint(3, ("file bulkdev: PoIrpCompletionFunc::")); BulkUsb_IoDecrement(irpContext->DeviceExtension); ExFreePool(irpContext); } }
VOID PoIrpAsyncCompletionFunc( IN PDEVICE_OBJECT DeviceObject, IN UCHAR MinorFunction, IN POWER_STATE PowerState, IN PVOID Context, IN PIO_STATUS_BLOCK IoStatus ) /*++ Routine Description: Completion routine for power irp PoRequested in IdleNotification RequestComplete routine. Arguments: DeviceObject - pointer to device object MinorFunciton - minor function for the irp. PowerState - irp power state Context - context passed to the completion function IoStatus - status block. Return Value: None --*/ { PDEVICE_EXTENSION DeviceExtension; // // initialize variables // DeviceExtension = (PDEVICE_EXTENSION) Context; // // all we do is decrement the count // BulkUsb_DbgPrint(3, ("PoIrpAsyncCompletionFunc::")); BulkUsb_IoDecrement(DeviceExtension); return; }
VOID SendDeviceIrp( IN PDEVICE_OBJECT DeviceObject, IN PIRP SIrp ) /*++ Routine Description: This routine is invoked from the completion routine of the system power irp. This routine will PoRequest a device power irp. The system irp is passed as a context to the the device power irp. Arguments: DeviceObject - pointer to device object SIrp - system power irp. Return Value: None --*/ { NTSTATUS ntStatus; POWER_STATE powState; PDEVICE_EXTENSION deviceExtension; PIO_STACK_LOCATION irpStack; SYSTEM_POWER_STATE systemState; DEVICE_POWER_STATE devState; PPOWER_COMPLETION_CONTEXT powerContext; // // initialize variables // irpStack = IoGetCurrentIrpStackLocation(SIrp); systemState = irpStack->Parameters.Power.State.SystemState; deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; BulkUsb_DbgPrint(3, ("SendDeviceIrp - begins\n")); // // Read out the D-IRP out of the S->D mapping array captured in QueryCap's. // we can choose deeper sleep states than our mapping but never choose // lighter ones. // devState = deviceExtension->DeviceCapabilities.DeviceState[systemState]; powState.DeviceState = devState; powerContext = (PPOWER_COMPLETION_CONTEXT) ExAllocatePool(NonPagedPool, sizeof(POWER_COMPLETION_CONTEXT)); if(!powerContext) { BulkUsb_DbgPrint(1, ("Failed to alloc memory for powerContext\n")); ntStatus = STATUS_INSUFFICIENT_RESOURCES; } else { powerContext->DeviceObject = DeviceObject; powerContext->SIrp = SIrp; // // in win2k PoRequestPowerIrp can take fdo or pdo. // ntStatus = PoRequestPowerIrp( deviceExtension->PhysicalDeviceObject, irpStack->MinorFunction, powState, (PREQUEST_POWER_COMPLETE)DevPoCompletionRoutine, powerContext, NULL); } if(!NT_SUCCESS(ntStatus)) { if(powerContext) { ExFreePool(powerContext); } PoStartNextPowerIrp(SIrp); SIrp->IoStatus.Status = ntStatus; SIrp->IoStatus.Information = 0; IoCompleteRequest(SIrp, IO_NO_INCREMENT); BulkUsb_DbgPrint(3, ("SendDeviceIrp::")); BulkUsb_IoDecrement(deviceExtension); } BulkUsb_DbgPrint(3, ("SendDeviceIrp - ends\n")); }
NTSTATUS HandleDeviceSetPower( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) /*++ Routine Description: This routine services irps of minor type IRP_MN_SET_POWER for the device power state Arguments: DeviceObject - pointer to device object Irp - I/O request packet sent by the power manager Return Value: NT status value --*/ { KIRQL oldIrql; NTSTATUS ntStatus; POWER_STATE newState; PIO_STACK_LOCATION irpStack; PDEVICE_EXTENSION deviceExtension; DEVICE_POWER_STATE newDevState, oldDevState; BulkUsb_DbgPrint(3, ("HandleDeviceSetPower - begins\n")); // // initialize variables // deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; irpStack = IoGetCurrentIrpStackLocation(Irp); oldDevState = deviceExtension->DevPower; newState = irpStack->Parameters.Power.State; newDevState = newState.DeviceState; BulkUsb_DbgPrint(3, ("Set request for device power state D%X\n" "Current device power state D%X\n", newDevState - 1, deviceExtension->DevPower - 1)); if(newDevState < oldDevState) { // // adding power // BulkUsb_DbgPrint(3, ("Adding power to the device\n")); // // send the power IRP to the next driver in the stack // IoCopyCurrentIrpStackLocationToNext(Irp); IoSetCompletionRoutine( Irp, (PIO_COMPLETION_ROUTINE)FinishDevPoUpIrp, deviceExtension, TRUE, TRUE, TRUE); ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp); } else { // // newDevState >= oldDevState // // hold I/O if transition from D0 -> DX (X = 1, 2, 3) // if transition from D1 or D2 to deeper sleep states, // I/O queue is already on hold. // if(PowerDeviceD0 == oldDevState && newDevState > oldDevState) { // // D0 -> DX transition // BulkUsb_DbgPrint(3, ("Removing power from the device\n")); ntStatus = HoldIoRequests(DeviceObject, Irp); if(!NT_SUCCESS(ntStatus)) { PoStartNextPowerIrp(Irp); Irp->IoStatus.Status = ntStatus; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); BulkUsb_DbgPrint(3, ("HandleDeviceSetPower::")); BulkUsb_IoDecrement(deviceExtension); return ntStatus; } else { goto HandleDeviceSetPower_Exit; } } else if(PowerDeviceD0 == oldDevState && PowerDeviceD0 == newDevState) { // // D0 -> D0 // unblock the queue which may have been blocked processing // query irp // BulkUsb_DbgPrint(3, ("A SetD0 request\n")); KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql); deviceExtension->QueueState = AllowRequests; KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql); ProcessQueuedRequests(deviceExtension); } IoCopyCurrentIrpStackLocationToNext(Irp); IoSetCompletionRoutine( Irp, (PIO_COMPLETION_ROUTINE) FinishDevPoDnIrp, deviceExtension, TRUE, TRUE, TRUE); ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp); if(!NT_SUCCESS(ntStatus)) { BulkUsb_DbgPrint(1, ("Lower drivers failed a power Irp\n")); } } HandleDeviceSetPower_Exit: BulkUsb_DbgPrint(3, ("HandleDeviceSetPower - ends\n")); return STATUS_PENDING; }
NTSTATUS SysPoCompletionRoutine( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension ) /*++ Routine Description: This is the completion routine for the system power irps of minor function types IRP_MN_QUERY_POWER and IRP_MN_SET_POWER. This completion routine sends the corresponding device power irp and returns STATUS_MORE_PROCESSING_REQUIRED. The system irp is passed as a context to the device power irp completion routine and is completed in the device power irp completion routine. Arguments: DeviceObject - pointer to device object Irp - I/O request packet DeviceExtension - pointer to device extension Return Value: NT status value --*/ { NTSTATUS ntStatus; PIO_STACK_LOCATION irpStack; // // initialize variables // ntStatus = Irp->IoStatus.Status; irpStack = IoGetCurrentIrpStackLocation(Irp); BulkUsb_DbgPrint(3, ("SysPoCompletionRoutine - begins\n")); // // lower drivers failed this Irp // if(!NT_SUCCESS(ntStatus)) { PoStartNextPowerIrp(Irp); BulkUsb_DbgPrint(3, ("SysPoCompletionRoutine::")); BulkUsb_IoDecrement(DeviceExtension); return STATUS_SUCCESS; } // // ..otherwise update the cached system power state (IRP_MN_SET_POWER) // if(irpStack->MinorFunction == IRP_MN_SET_POWER) { DeviceExtension->SysPower = irpStack->Parameters.Power.State.SystemState; } // // queue device irp and return STATUS_MORE_PROCESSING_REQUIRED // SendDeviceIrp(DeviceObject, Irp); BulkUsb_DbgPrint(3, ("SysPoCompletionRoutine - ends\n")); return STATUS_MORE_PROCESSING_REQUIRED; }
//==================== NTSTATUS BulkUsb_DispatchDevCtrl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { ULONG code; PVOID ioBuffer; ULONG inputBufferLength; ULONG outputBufferLength; ULONG info; NTSTATUS ntStatus; PTDeviceExtension deviceExtension; PIO_STACK_LOCATION irpStack; info = 0; irpStack = IoGetCurrentIrpStackLocation(Irp); code = irpStack->Parameters.DeviceIoControl.IoControlCode; deviceExtension = (PTDeviceExtension) DeviceObject->DeviceExtension; ioBuffer = Irp->AssociatedIrp.SystemBuffer; inputBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength; outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength; if(deviceExtension->DeviceState != WORKING) { BulkUsb_DbgPrint(1, ("file bulkdev: Invalid device state\n")); Irp->IoStatus.Status = ntStatus = STATUS_INVALID_DEVICE_STATE; Irp->IoStatus.Information = info; IoCompleteRequest(Irp, IO_NO_INCREMENT); return ntStatus; } BulkUsb_DbgPrint(3, ("file bulkdev: BulkUsb_DispatchDevCtrl::")); BulkUsb_IoIncrement(deviceExtension); BulkUsb_DbgPrint(3, ("file bulkdev: Waiting on the IdleReqPendEvent\n")); if(deviceExtension->SSEnable) { KeWaitForSingleObject(&deviceExtension->NoIdleReqPendEvent, Executive, KernelMode, FALSE, NULL); } switch(code) { case IOCTL_BULKUSB_RESET_PIPE: { PFILE_OBJECT fileObject; PUSBD_PIPE_INFORMATION pipe; pipe = NULL; fileObject = irpStack->FileObject; if(fileObject == NULL) { ntStatus = STATUS_INVALID_PARAMETER; break; } pipe = (PUSBD_PIPE_INFORMATION) fileObject->FsContext; if(pipe == NULL) ntStatus = STATUS_INVALID_PARAMETER; else ntStatus = BulkUsb_ResetPipe(DeviceObject, pipe); break; } case IOCTL_BULKUSB_GET_CONFIG_DESCRIPTOR: { ULONG length; if(deviceExtension->UsbConfigurationDescriptor) { length = deviceExtension->UsbConfigurationDescriptor->wTotalLength; if(outputBufferLength >= length) { RtlCopyMemory(ioBuffer, deviceExtension->UsbConfigurationDescriptor, length); info = length; ntStatus = STATUS_SUCCESS; } else ntStatus = STATUS_BUFFER_TOO_SMALL; } else ntStatus = STATUS_UNSUCCESSFUL; break; } case IOCTL_BULKUSB_RESET_DEVICE: ntStatus = BulkUsb_ResetDevice(DeviceObject); break; default : ntStatus = STATUS_INVALID_DEVICE_REQUEST; break; } Irp->IoStatus.Status = ntStatus; Irp->IoStatus.Information = info; IoCompleteRequest(Irp, IO_NO_INCREMENT); BulkUsb_DbgPrint(3, ("file bulkdev: BulkUsb_DispatchDevCtrl::")); BulkUsb_IoDecrement(deviceExtension); return ntStatus; }
static NTSTATUS IdleNotificationRequestComplete(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PTDeviceExtension DeviceExtension) { NTSTATUS ntStatus; POWER_STATE powerState; KIRQL oldIrql; LARGE_INTEGER dueTime; PIRP idleIrp; PUSB_IDLE_CALLBACK_INFO idleCallbackInfo; BulkUsb_DbgPrint(3, ("file bulkdev: IdleNotificationRequestCompete - begins\n")); idleIrp = NULL; ntStatus = Irp->IoStatus.Status; if(!NT_SUCCESS(ntStatus) && ntStatus != STATUS_NOT_SUPPORTED) { BulkUsb_DbgPrint(1, ("file bulkdev: Idle irp completes with error::")); switch(ntStatus) { case STATUS_INVALID_DEVICE_REQUEST: BulkUsb_DbgPrint(1, ("file bulkdev: STATUS_INVALID_DEVICE_REQUEST\n")); break; case STATUS_CANCELLED: BulkUsb_DbgPrint(1, ("file bulkdev: STATUS_CANCELLED\n")); break; case STATUS_POWER_STATE_INVALID: BulkUsb_DbgPrint(1, ("file bulkdev: STATUS_POWER_STATE_INVALID\n")); goto IdleNotificationRequestComplete_Exit; case STATUS_DEVICE_BUSY: BulkUsb_DbgPrint(1, ("file bulkdev: STATUS_DEVICE_BUSY\n")); break; default: BulkUsb_DbgPrint(1, ("file bulkdev: default: status = %X\n", ntStatus)); break; } if(PowerDeviceD0 != DeviceExtension->DevPower) { BulkUsb_DbgPrint(3, ("file bulkdev: IdleNotificationRequestComplete::")); BulkUsb_IoIncrement(DeviceExtension); powerState.DeviceState = PowerDeviceD0; ntStatus = PoRequestPowerIrp( DeviceExtension->PhysicalDeviceObject, IRP_MN_SET_POWER, powerState, (PREQUEST_POWER_COMPLETE) PoIrpAsyncCompletionFunc, DeviceExtension, NULL); if(!NT_SUCCESS(ntStatus)) { BulkUsb_DbgPrint(1, ("file bulkdev: PoRequestPowerIrp failed\n")); } } } IdleNotificationRequestComplete_Exit: KeAcquireSpinLock(&DeviceExtension->IdleReqStateLock, &oldIrql); idleCallbackInfo = DeviceExtension->IdleCallbackInfo; DeviceExtension->IdleCallbackInfo = NULL; idleIrp = (PIRP) InterlockedExchangePointer(&DeviceExtension->PendingIdleIrp, NULL); InterlockedExchange(&DeviceExtension->IdleReqPend, 0); KeReleaseSpinLock(&DeviceExtension->IdleReqStateLock, oldIrql); if(idleCallbackInfo) { ExFreePool(idleCallbackInfo); } if(idleIrp) { BulkUsb_DbgPrint(3, ("file bulkdev: completion routine has a valid irp and frees it\n")); IoFreeIrp(Irp); KeSetEvent(&DeviceExtension->NoIdleReqPendEvent, IO_NO_INCREMENT, FALSE); } else { if(0 == InterlockedDecrement(&DeviceExtension->FreeIdleIrpCount)) { BulkUsb_DbgPrint(3, ("file bulkdev: completion routine frees the irp\n")); IoFreeIrp(Irp); KeSetEvent(&DeviceExtension->NoIdleReqPendEvent, IO_NO_INCREMENT, FALSE); } } if(DeviceExtension->SSEnable) { BulkUsb_DbgPrint(3, ("file bulkdev: Set the timer to fire DPCs\n")); dueTime.QuadPart = -10000 * IDLE_INTERVAL; // 5000 ms KeSetTimerEx(&DeviceExtension->Timer, dueTime, IDLE_INTERVAL, // 5000 ms &DeviceExtension->DeferredProcCall); BulkUsb_DbgPrint(3, ("file bulkdev: IdleNotificationRequestCompete - ends\n")); } return STATUS_MORE_PROCESSING_REQUIRED; }
NTSTATUS BulkUsb_DispatchCreate(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { ULONG i; NTSTATUS ntStatus; PFILE_OBJECT fileObject; PTDeviceExtension deviceExtension; PIO_STACK_LOCATION irpStack; PTPipeContext pipeContext; PUSBD_INTERFACE_INFORMATION Interface; PAGED_CODE(); BulkUsb_DbgPrint(3, ("file bulkdev: BulkUsb_DispatchCreate - begins\n")); irpStack = IoGetCurrentIrpStackLocation(Irp); fileObject = irpStack->FileObject; deviceExtension = (PTDeviceExtension) DeviceObject->DeviceExtension; if(deviceExtension->DeviceState != WORKING) { ntStatus = STATUS_INVALID_DEVICE_STATE; goto BulkUsb_DispatchCreate_Exit; } if(deviceExtension->UsbInterface) Interface = deviceExtension->UsbInterface; else { BulkUsb_DbgPrint(1, ("file bulkdev: UsbInterface not found\n")); ntStatus = STATUS_INVALID_DEVICE_STATE; goto BulkUsb_DispatchCreate_Exit; } if(fileObject) fileObject->FsContext = NULL; else { ntStatus = STATUS_INVALID_PARAMETER; goto BulkUsb_DispatchCreate_Exit; } if(0 == fileObject->FileName.Length) { ntStatus = STATUS_SUCCESS; InterlockedIncrement(&deviceExtension->OpenHandleCount); if(deviceExtension->SSEnable) { CancelSelectSuspend(deviceExtension); } goto BulkUsb_DispatchCreate_Exit; } pipeContext = BulkUsb_PipeWithName(DeviceObject, &fileObject->FileName); if(pipeContext == NULL) { ntStatus = STATUS_INVALID_PARAMETER; goto BulkUsb_DispatchCreate_Exit; } ntStatus = STATUS_INVALID_PARAMETER; for(i = 0; i < Interface->NumberOfPipes; i++) { if(pipeContext == &deviceExtension->PipeContext[i]) { BulkUsb_DbgPrint(3, ("file bulkdev: open pipe %d\n", i)); fileObject->FsContext = &Interface->Pipes[i]; ASSERT(fileObject->FsContext); pipeContext->PipeOpen = TRUE; ntStatus = STATUS_SUCCESS; InterlockedIncrement(&deviceExtension->OpenHandleCount); if(deviceExtension->SSEnable) { CancelSelectSuspend(deviceExtension); } } } BulkUsb_DispatchCreate_Exit: Irp->IoStatus.Status = ntStatus; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); BulkUsb_DbgPrint(3, ("file bulkdev: BulkUsb_DispatchCreate - ends\n")); return ntStatus; }
VOID DevPoCompletionRoutine( IN PDEVICE_OBJECT DeviceObject, IN UCHAR MinorFunction, IN POWER_STATE PowerState, IN PVOID Context, IN PIO_STATUS_BLOCK IoStatus ) /*++ Routine Description: This is the PoRequest - completion routine for the device power irp. This routine is responsible for completing the system power irp, received as a context. Arguments: DeviceObject - pointer to device object MinorFunction - minor function of the irp. PowerState - power state of the irp. Context - context passed to the completion routine. IoStatus - status of the device power irp. Return Value: None --*/ { PIRP sIrp; PDEVICE_EXTENSION deviceExtension; PPOWER_COMPLETION_CONTEXT powerContext; // // initialize variables // powerContext = (PPOWER_COMPLETION_CONTEXT) Context; sIrp = powerContext->SIrp; deviceExtension = powerContext->DeviceObject->DeviceExtension; BulkUsb_DbgPrint(3, ("DevPoCompletionRoutine - begins\n")); // // copy the D-Irp status into S-Irp // sIrp->IoStatus.Status = IoStatus->Status; // // complete the system Irp // PoStartNextPowerIrp(sIrp); sIrp->IoStatus.Information = 0; IoCompleteRequest(sIrp, IO_NO_INCREMENT); // // cleanup // BulkUsb_DbgPrint(3, ("DevPoCompletionRoutine::")); BulkUsb_IoDecrement(deviceExtension); ExFreePool(powerContext); BulkUsb_DbgPrint(3, ("DevPoCompletionRoutine - ends\n")); }
NTSTATUS SetDeviceFunctional( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension ) /*++ Routine Description: This routine processes queue of pending irps. Arguments: DeviceObject - pointer to device object Irp - I/O request packet DeviceExtension - pointer to device extension Return Value: NT status value --*/ { KIRQL oldIrql; NTSTATUS ntStatus; POWER_STATE newState; PIO_STACK_LOCATION irpStack; DEVICE_POWER_STATE newDevState, oldDevState; // // initialize variables // ntStatus = Irp->IoStatus.Status; irpStack = IoGetCurrentIrpStackLocation(Irp); newState = irpStack->Parameters.Power.State; newDevState = newState.DeviceState; oldDevState = DeviceExtension->DevPower; BulkUsb_DbgPrint(3, ("SetDeviceFunctional - begins\n")); // // update the cached state // DeviceExtension->DevPower = newDevState; // // restore appropriate amount of state to our h/w // this driver does not implement partial context // save/restore. // PoSetPowerState(DeviceObject, DevicePowerState, newState); if(PowerDeviceD0 == newDevState) { // // empty existing queue of all pending irps. // KeAcquireSpinLock(&DeviceExtension->DevStateLock, &oldIrql); DeviceExtension->QueueState = AllowRequests; KeReleaseSpinLock(&DeviceExtension->DevStateLock, oldIrql); ProcessQueuedRequests(DeviceExtension); } PoStartNextPowerIrp(Irp); Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); BulkUsb_DbgPrint(3, ("SetDeviceFunctional::")); BulkUsb_IoDecrement(DeviceExtension); BulkUsb_DbgPrint(3, ("SetDeviceFunctional - ends\n")); return STATUS_SUCCESS; }
NTSTATUS SubmitIdleRequestIrp(IN PTDeviceExtension DeviceExtension) { PIRP irp; NTSTATUS ntStatus; KIRQL oldIrql; PUSB_IDLE_CALLBACK_INFO idleCallbackInfo; PIO_STACK_LOCATION nextStack; irp = NULL; idleCallbackInfo = NULL; BulkUsb_DbgPrint(3, ("file bulkdev: SubmitIdleRequest - process\n")); ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); if(PowerDeviceD0 != DeviceExtension->DevPower) { // ntStatus = STATUS_POWER_STATE_INVALID; // goto SubmitIdleRequestIrp_Exit; return STATUS_POWER_STATE_INVALID; } KeAcquireSpinLock(&DeviceExtension->IdleReqStateLock, &oldIrql); if(InterlockedExchange(&DeviceExtension->IdleReqPend, 1)) { BulkUsb_DbgPrint(1, ("file bulkdev: Idle request pending..\n")); KeReleaseSpinLock(&DeviceExtension->IdleReqStateLock, oldIrql); // ntStatus = STATUS_DEVICE_BUSY; // goto SubmitIdleRequestIrp_Exit; return STATUS_DEVICE_BUSY; } KeClearEvent(&DeviceExtension->NoIdleReqPendEvent); idleCallbackInfo = ExAllocatePool(NonPagedPool, sizeof(struct _USB_IDLE_CALLBACK_INFO)); if(idleCallbackInfo) { idleCallbackInfo->IdleCallback = IdleNotificationCallback; idleCallbackInfo->IdleContext = (PVOID)DeviceExtension; ASSERT(DeviceExtension->IdleCallbackInfo == NULL); DeviceExtension->IdleCallbackInfo = idleCallbackInfo; irp = IoAllocateIrp(DeviceExtension->TopOfStackDeviceObject->StackSize, FALSE); if(irp == NULL) { BulkUsb_DbgPrint(1, ("file bulkdev: cannot build idle request irp\n")); KeSetEvent(&DeviceExtension->NoIdleReqPendEvent, IO_NO_INCREMENT, FALSE); InterlockedExchange(&DeviceExtension->IdleReqPend, 0); KeReleaseSpinLock(&DeviceExtension->IdleReqStateLock, oldIrql); ExFreePool(idleCallbackInfo); // ntStatus = STATUS_INSUFFICIENT_RESOURCES; // goto SubmitIdleRequestIrp_Exit; return STATUS_INSUFFICIENT_RESOURCES; } nextStack = IoGetNextIrpStackLocation(irp); nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; nextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION; nextStack->Parameters.DeviceIoControl.Type3InputBuffer = idleCallbackInfo; nextStack->Parameters.DeviceIoControl.InputBufferLength = sizeof(struct _USB_IDLE_CALLBACK_INFO); IoSetCompletionRoutine(irp, IdleNotificationRequestComplete, DeviceExtension, TRUE, TRUE, TRUE); DeviceExtension->PendingIdleIrp = irp; DeviceExtension->FreeIdleIrpCount = 2; KeReleaseSpinLock(&DeviceExtension->IdleReqStateLock, oldIrql); if(!CanDeviceSuspend(DeviceExtension) || PowerDeviceD0 != DeviceExtension->DevPower) { BulkUsb_DbgPrint(1, ("file bulkdev: Device is not idle\n")); KeAcquireSpinLock(&DeviceExtension->IdleReqStateLock, &oldIrql); DeviceExtension->IdleCallbackInfo = NULL; DeviceExtension->PendingIdleIrp = NULL; KeSetEvent(&DeviceExtension->NoIdleReqPendEvent, IO_NO_INCREMENT, FALSE); InterlockedExchange(&DeviceExtension->IdleReqPend, 0); KeReleaseSpinLock(&DeviceExtension->IdleReqStateLock, oldIrql); if(idleCallbackInfo) { ExFreePool(idleCallbackInfo); } if(irp) { IoFreeIrp(irp); } // ntStatus = STATUS_UNSUCCESSFUL; // goto SubmitIdleRequestIrp_Exit; return STATUS_UNSUCCESSFUL; } BulkUsb_DbgPrint(3, ("file bulkdev: Cancel the timers\n")); KeCancelTimer(&DeviceExtension->Timer); ntStatus = IoCallDriver(DeviceExtension->TopOfStackDeviceObject, irp); if(!NT_SUCCESS(ntStatus)) { // BulkUsb_DbgPrint(1, ("file bulkdev: IoCallDriver failed\n")); // goto SubmitIdleRequestIrp_Exit; return ntStatus; } } else { BulkUsb_DbgPrint(1, ("file bulkdev: Memory allocation for idleCallbackInfo failed\n")); KeSetEvent(&DeviceExtension->NoIdleReqPendEvent, IO_NO_INCREMENT, FALSE); InterlockedExchange(&DeviceExtension->IdleReqPend, 0); KeReleaseSpinLock(&DeviceExtension->IdleReqStateLock, oldIrql); ntStatus = STATUS_INSUFFICIENT_RESOURCES; } //SubmitIdleRequestIrp_Exit: BulkUsb_DbgPrint(3, ("file bulkdev: SubmitIdleRequest - ends\n")); return ntStatus; }