NTSTATUS NTAPI FinishDevPoUpIrp(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension) { NTSTATUS ntStatus; FreeBT_DbgPrint(3, ("FBTUSB: FinishDevPoUpIrp: Entered\n")); ntStatus = Irp->IoStatus.Status; if(Irp->PendingReturned) { IoMarkIrpPending(Irp); } if(!NT_SUCCESS(ntStatus)) { PoStartNextPowerIrp(Irp); FreeBT_DbgPrint(3, ("FBTUSB: FinishDevPoUpIrp::")); FreeBT_IoDecrement(DeviceExtension); return STATUS_SUCCESS; } SetDeviceFunctional(DeviceObject, Irp, DeviceExtension); FreeBT_DbgPrint(3, ("FBTUSB: FinishDevPoUpIrp: Leaving\n")); return STATUS_MORE_PROCESSING_REQUIRED; }
NTSTATUS NTAPI HandleSystemSetPower(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { NTSTATUS ntStatus; PDEVICE_EXTENSION deviceExtension; SYSTEM_POWER_STATE systemState; PIO_STACK_LOCATION irpStack; FreeBT_DbgPrint(3, ("FBTUSB: HandleSystemSetPower: Entered\n")); deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; irpStack = IoGetCurrentIrpStackLocation(Irp); systemState = irpStack->Parameters.Power.State.SystemState; FreeBT_DbgPrint(3, ("FBTUSB: HandleSystemSetPower: Set request for system power state S%X\n" "FBTUSB: HandleSystemSetPower: 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); FreeBT_DbgPrint(3, ("FBTUSB: HandleSystemSetPower: Leaving\n")); return STATUS_PENDING; }
NTSTATUS NTAPI FinishDevPoDnIrp(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension) { NTSTATUS ntStatus; POWER_STATE newState; PIO_STACK_LOCATION irpStack; FreeBT_DbgPrint(3, ("FBTUSB: FinishDevPoDnIrp: Entered\n")); ntStatus = Irp->IoStatus.Status; irpStack = IoGetCurrentIrpStackLocation(Irp); newState = irpStack->Parameters.Power.State; if (NT_SUCCESS(ntStatus) && irpStack->MinorFunction == IRP_MN_SET_POWER) { FreeBT_DbgPrint(3, ("FBTUSB: updating cache..\n")); DeviceExtension->DevPower = newState.DeviceState; PoSetPowerState(DeviceObject, DevicePowerState, newState); } PoStartNextPowerIrp(Irp); FreeBT_DbgPrint(3, ("FBTUSB: FinishDevPoDnIrp::")); FreeBT_IoDecrement(DeviceExtension); FreeBT_DbgPrint(3, ("FBTUSB: FinishDevPoDnIrp: Leaving\n")); return STATUS_SUCCESS; }
VOID NTAPI CancelQueued(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PDEVICE_EXTENSION deviceExtension; KIRQL oldIrql; FreeBT_DbgPrint(3, ("FBTUSB: CancelQueued: Entered\n")); deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; oldIrql = Irp->CancelIrql; // Release the cancel spin lock IoReleaseCancelSpinLock(Irp->CancelIrql); // Acquire the queue lock KeAcquireSpinLockAtDpcLevel(&deviceExtension->QueueLock); // Remove the cancelled Irp from queue and release the lock RemoveEntryList(&Irp->Tail.Overlay.ListEntry); KeReleaseSpinLock(&deviceExtension->QueueLock, oldIrql); // complete with STATUS_CANCELLED Irp->IoStatus.Status = STATUS_CANCELLED; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); FreeBT_DbgPrint(3, ("FBTUSB: CancelQueued: Leaving\n")); return; }
NTSTATUS NTAPI IssueWaitWake(IN PDEVICE_EXTENSION DeviceExtension) { POWER_STATE poState; NTSTATUS ntStatus; FreeBT_DbgPrint(3, ("FBTUSB: IssueWaitWake: Entered\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); } FreeBT_DbgPrint(3, ("FBTUSB: IssueWaitWake: Leaving\n")); return ntStatus; }
VOID NTAPI DevPoCompletionRoutine( IN PDEVICE_OBJECT DeviceObject, IN UCHAR MinorFunction, IN POWER_STATE PowerState, IN PVOID Context, IN PIO_STATUS_BLOCK IoStatus ) { PIRP sIrp; PDEVICE_EXTENSION deviceExtension; PPOWER_COMPLETION_CONTEXT powerContext; powerContext = (PPOWER_COMPLETION_CONTEXT) Context; sIrp = powerContext->SIrp; deviceExtension = (PDEVICE_EXTENSION) powerContext->DeviceObject->DeviceExtension; FreeBT_DbgPrint(3, ("FBTUSB: DevPoCompletionRoutine: Entered\n")); sIrp->IoStatus.Status = IoStatus->Status; PoStartNextPowerIrp(sIrp); sIrp->IoStatus.Information = 0; IoCompleteRequest(sIrp, IO_NO_INCREMENT); FreeBT_DbgPrint(3, ("FBTUSB: DevPoCompletionRoutine::")); FreeBT_IoDecrement(deviceExtension); ExFreePool(powerContext); FreeBT_DbgPrint(3, ("FBTUSB: DevPoCompletionRoutine: Leaving\n")); }
NTSTATUS NTAPI HandleSystemQueryPower(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { NTSTATUS ntStatus; PDEVICE_EXTENSION deviceExtension; SYSTEM_POWER_STATE systemState; PIO_STACK_LOCATION irpStack; FreeBT_DbgPrint(3, ("FBTUSB: HandleSystemQueryPower: Entered\n")); // initialize variables deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; irpStack = IoGetCurrentIrpStackLocation(Irp); systemState = irpStack->Parameters.Power.State.SystemState; FreeBT_DbgPrint(3, ("FBTUSB: HandleSystemQueryPower: Query for system power state S%X\n" "FBTUSB: HandleSystemQueryPower: Current system power state S%X\n", systemState - 1, deviceExtension->SysPower - 1)); // Fail a query for a power state incompatible with waking up the system if ((deviceExtension->WaitWakeEnable) && (systemState > deviceExtension->DeviceCapabilities.SystemWake)) { FreeBT_DbgPrint(1, ("FBTUSB: HandleSystemQueryPower: Query for an incompatible system power state\n")); PoStartNextPowerIrp(Irp); Irp->IoStatus.Status = ntStatus = STATUS_INVALID_DEVICE_STATE; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); FreeBT_DbgPrint(3, ("FBTUSB: HandleSystemQueryPower::")); FreeBT_IoDecrement(deviceExtension); return ntStatus; } // if querying for a lower S-state, issue a wait-wake if((systemState > deviceExtension->SysPower) && (deviceExtension->WaitWakeEnable)) { IssueWaitWake(deviceExtension); } IoCopyCurrentIrpStackLocationToNext(Irp); IoSetCompletionRoutine( Irp, (PIO_COMPLETION_ROUTINE)SysPoCompletionRoutine, deviceExtension, TRUE, TRUE, TRUE); ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp); FreeBT_DbgPrint(3, ("FBTUSB: HandleSystemQueryPower: Leaving\n")); return STATUS_PENDING; }
VOID NTAPI WaitWakeCallback( IN PDEVICE_OBJECT DeviceObject, IN UCHAR MinorFunction, IN POWER_STATE PowerState, IN PVOID Context, IN PIO_STATUS_BLOCK IoStatus) { NTSTATUS ntStatus; POWER_STATE powerState; PDEVICE_EXTENSION deviceExtension; FreeBT_DbgPrint(3, ("FBTUSB: WaitWakeCallback: Entered\n")); deviceExtension = (PDEVICE_EXTENSION) Context; InterlockedExchange(&deviceExtension->FlagWWOutstanding, 0); if(!NT_SUCCESS(IoStatus->Status)) { return; } // wake up the device if(deviceExtension->DevPower == PowerDeviceD0) { FreeBT_DbgPrint(3, ("FBTUSB: WaitWakeCallback: Device already powered up...\n")); return; } FreeBT_DbgPrint(3, ("FBTUSB: WaitWakeCallback::")); FreeBT_IoIncrement(deviceExtension); powerState.DeviceState = PowerDeviceD0; ntStatus = PoRequestPowerIrp(deviceExtension->PhysicalDeviceObject, IRP_MN_SET_POWER, powerState, (PREQUEST_POWER_COMPLETE) WWIrpCompletionFunc, deviceExtension, NULL); if(deviceExtension->WaitWakeEnable) { IssueWaitWake(deviceExtension); } FreeBT_DbgPrint(3, ("FBTUSB: WaitWakeCallback: Leaving\n")); return; }
NTSTATUS NTAPI HoldIoRequests(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { NTSTATUS ntStatus; PIO_WORKITEM item; PDEVICE_EXTENSION deviceExtension; PWORKER_THREAD_CONTEXT context; FreeBT_DbgPrint(3, ("FBTUSB: HoldIoRequests: Entered\n")); deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; deviceExtension->QueueState = HoldRequests; context = (PWORKER_THREAD_CONTEXT) ExAllocatePool(NonPagedPool, sizeof(WORKER_THREAD_CONTEXT)); if(context) { item = IoAllocateWorkItem(DeviceObject); context->Irp = Irp; context->DeviceObject = DeviceObject; context->WorkItem = item; if (item) { IoMarkIrpPending(Irp); IoQueueWorkItem(item, HoldIoRequestsWorkerRoutine, DelayedWorkQueue, context); ntStatus = STATUS_PENDING; } else { FreeBT_DbgPrint(3, ("FBTUSB: HoldIoRequests: Failed to allocate memory for workitem\n")); ExFreePool(context); ntStatus = STATUS_INSUFFICIENT_RESOURCES; } } else { FreeBT_DbgPrint(1, ("FBTUSB: HoldIoRequests: Failed to alloc memory for worker thread context\n")); ntStatus = STATUS_INSUFFICIENT_RESOURCES; } FreeBT_DbgPrint(3, ("FBTUSB: HoldIoRequests: Leaving\n")); return ntStatus; }
NTSTATUS NTAPI SetDeviceFunctional(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension) { KIRQL oldIrql; NTSTATUS ntStatus; POWER_STATE newState; PIO_STACK_LOCATION irpStack; DEVICE_POWER_STATE newDevState, oldDevState; ntStatus = Irp->IoStatus.Status; irpStack = IoGetCurrentIrpStackLocation(Irp); newState = irpStack->Parameters.Power.State; newDevState = newState.DeviceState; oldDevState = DeviceExtension->DevPower; FreeBT_DbgPrint(3, ("FBTUSB: SetDeviceFunctional: Entered\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) { 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); FreeBT_DbgPrint(3, ("FBTUSB: SetDeviceFunctional::")); FreeBT_IoDecrement(DeviceExtension); FreeBT_DbgPrint(3, ("FBTUSB: SetDeviceFunctional: Leaving\n")); return STATUS_SUCCESS; }
VOID NTAPI FreeBT_DriverUnload(IN PDRIVER_OBJECT DriverObject) { PUNICODE_STRING registryPath; FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DriverUnload: Entered\n")); registryPath = &Globals.FreeBT_RegistryPath; if(registryPath->Buffer) { ExFreePool(registryPath->Buffer); registryPath->Buffer = NULL; } FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DriverUnload: Leaving\n")); return; }
VOID NTAPI HoldIoRequestsWorkerRoutine(IN PDEVICE_OBJECT DeviceObject, IN PVOID Context) { PIRP irp; NTSTATUS ntStatus; PDEVICE_EXTENSION deviceExtension; PWORKER_THREAD_CONTEXT context; FreeBT_DbgPrint(3, ("FBTUSB: HoldIoRequestsWorkerRoutine: Entered\n")); deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; context = (PWORKER_THREAD_CONTEXT) Context; irp = (PIRP) context->Irp; // wait for I/O in progress to finish. // the stop event is signalled when the counter drops to 1. // invoke FreeBT_IoDecrement twice: once each for the S-Irp and D-Irp. FreeBT_DbgPrint(3, ("FBTUSB: HoldIoRequestsWorkerRoutine::")); FreeBT_IoDecrement(deviceExtension); FreeBT_DbgPrint(3, ("FBTUSB: HoldIoRequestsWorkerRoutine::")); FreeBT_IoDecrement(deviceExtension); KeWaitForSingleObject(&deviceExtension->StopEvent, Executive, KernelMode, FALSE, NULL); // Increment twice to restore the count FreeBT_DbgPrint(3, ("FBTUSB: HoldIoRequestsWorkerRoutine::")); FreeBT_IoIncrement(deviceExtension); FreeBT_DbgPrint(3, ("FBTUSB: HoldIoRequestsWorkerRoutine::")); FreeBT_IoIncrement(deviceExtension); // now send the Irp down IoCopyCurrentIrpStackLocationToNext(irp); IoSetCompletionRoutine( irp, (PIO_COMPLETION_ROUTINE) FinishDevPoDnIrp, deviceExtension, TRUE, TRUE, TRUE); ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, irp); if(!NT_SUCCESS(ntStatus)) { FreeBT_DbgPrint(1, ("FBTUSB: HoldIoRequestsWorkerRoutine: Lower driver fail a power Irp\n")); } IoFreeWorkItem(context->WorkItem); ExFreePool((PVOID)context); FreeBT_DbgPrint(3, ("FBTUSB: HoldIoRequestsWorkerRoutine: Leaving\n")); }
VOID NTAPI CancelWaitWake(IN PDEVICE_EXTENSION DeviceExtension) { PIRP Irp; FreeBT_DbgPrint(3, ("FBTUSB: CancelWaitWake: Entered\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); } } FreeBT_DbgPrint(3, ("FBTUSB: CancelWaitWake: Leaving\n")); }
NTSTATUS NTAPI QueueRequest(IN OUT PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp) { KIRQL oldIrql; NTSTATUS ntStatus; FreeBT_DbgPrint(3, ("FBTUSB: QueueRequests: Entered\n")); ntStatus = STATUS_PENDING; ASSERT(HoldRequests == DeviceExtension->QueueState); KeAcquireSpinLock(&DeviceExtension->QueueLock, &oldIrql); InsertTailList(&DeviceExtension->NewRequestsQueue, &Irp->Tail.Overlay.ListEntry); IoMarkIrpPending(Irp); IoSetCancelRoutine(Irp, CancelQueued); KeReleaseSpinLock(&DeviceExtension->QueueLock, oldIrql); FreeBT_DbgPrint(3, ("FBTUSB: QueueRequests: Leaving\n")); return ntStatus; }
NTSTATUS NTAPI SysPoCompletionRoutine(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension) { NTSTATUS ntStatus; PIO_STACK_LOCATION irpStack; ntStatus = Irp->IoStatus.Status; irpStack = IoGetCurrentIrpStackLocation(Irp); FreeBT_DbgPrint(3, ("FBTUSB: SysPoCompletionRoutine: Entered\n")); // lower drivers failed this Irp if(!NT_SUCCESS(ntStatus)) { PoStartNextPowerIrp(Irp); FreeBT_DbgPrint(3, ("FBTUSB: SysPoCompletionRoutine::")); FreeBT_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); FreeBT_DbgPrint(3, ("FBTUSB: SysPoCompletionRoutine: Leaving\n")); return STATUS_MORE_PROCESSING_REQUIRED; }
NTSTATUS NTAPI WaitWakeCompletionRoutine(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension) { FreeBT_DbgPrint(3, ("FBTUSB: WaitWakeCompletionRoutine: Entered\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; } FreeBT_DbgPrint(3, ("FBTUSB: WaitWakeCompletionRoutine: Leaving\n")); return STATUS_MORE_PROCESSING_REQUIRED; }
NTSTATUS NTAPI DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING UniRegistryPath) { NTSTATUS ntStatus; PUNICODE_STRING registryPath; registryPath = &Globals.FreeBT_RegistryPath; registryPath->MaximumLength = UniRegistryPath->Length + sizeof(UNICODE_NULL); registryPath->Length = UniRegistryPath->Length; registryPath->Buffer = (PWSTR) ExAllocatePool(PagedPool, registryPath->MaximumLength); if (!registryPath->Buffer) { FreeBT_DbgPrint(1, ("FBTUSB: Failed to allocate memory for registryPath\n")); ntStatus = STATUS_INSUFFICIENT_RESOURCES; goto DriverEntry_Exit; } RtlZeroMemory (registryPath->Buffer, registryPath->MaximumLength); RtlMoveMemory (registryPath->Buffer, UniRegistryPath->Buffer, UniRegistryPath->Length); ntStatus = STATUS_SUCCESS; // Initialize the driver object with this driver's entry points. DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = FreeBT_DispatchDevCtrl; DriverObject->MajorFunction[IRP_MJ_POWER] = FreeBT_DispatchPower; DriverObject->MajorFunction[IRP_MJ_PNP] = FreeBT_DispatchPnP; DriverObject->MajorFunction[IRP_MJ_CREATE] = FreeBT_DispatchCreate; DriverObject->MajorFunction[IRP_MJ_CLOSE] = FreeBT_DispatchClose; DriverObject->MajorFunction[IRP_MJ_CLEANUP] = FreeBT_DispatchClean; DriverObject->MajorFunction[IRP_MJ_READ] = FreeBT_DispatchRead; DriverObject->MajorFunction[IRP_MJ_WRITE] = FreeBT_DispatchWrite; #ifdef ENABLE_WMI DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = FreeBT_DispatchSysCtrl; #endif DriverObject->DriverUnload = FreeBT_DriverUnload; DriverObject->DriverExtension->AddDevice = (PDRIVER_ADD_DEVICE) FreeBT_AddDevice; DriverEntry_Exit: return ntStatus; }
NTSTATUS NTAPI FreeBT_QueryWmiRegInfo( IN PDEVICE_OBJECT DeviceObject, OUT ULONG *RegFlags, OUT PUNICODE_STRING InstanceName, OUT PUNICODE_STRING *RegistryPath, OUT PUNICODE_STRING MofResourceName, OUT PDEVICE_OBJECT *Pdo ) /*++ Routine Description: This routine is a callback into the driver to retrieve the list of guids or data blocks that the driver wants to register with WMI. This routine may not pend or block. Driver should NOT call WmiCompleteRequest. Arguments: DeviceObject is the device whose data block is being queried *RegFlags returns with a set of flags that describe the guids being registered for this device. If the device wants enable and disable collection callbacks before receiving queries for the registered guids then it should return the WMIREG_FLAG_EXPENSIVE flag. Also the returned flags may specify WMIREG_FLAG_INSTANCE_PDO in which case the instance name is determined from the PDO associated with the device object. Note that the PDO must have an associated devnode. If WMIREG_FLAG_INSTANCE_PDO is not set then Name must return a unique name for the device. InstanceName returns with the instance name for the guids if WMIREG_FLAG_INSTANCE_PDO is not set in the returned *RegFlags. The caller will call ExFreePool with the buffer returned. *RegistryPath returns with the registry path of the driver *MofResourceName returns with the name of the MOF resource attached to the binary file. If the driver does not have a mof resource attached then this can be returned as NULL. *Pdo returns with the device object for the PDO associated with this device if the WMIREG_FLAG_INSTANCE_PDO flag is returned in *RegFlags. Return Value: status --*/ { PDEVICE_EXTENSION deviceExtension; PAGED_CODE(); FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_QueryWmiRegInfo: Entered\n")); deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; *RegFlags = WMIREG_FLAG_INSTANCE_PDO; *RegistryPath = &Globals.FreeBT_RegistryPath; *Pdo = deviceExtension->PhysicalDeviceObject; RtlInitUnicodeString(MofResourceName, MOFRESOURCENAME); FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_QueryWmiRegInfo: Leaving\n")); return STATUS_SUCCESS; }
NTSTATUS NTAPI FreeBT_DispatchSysCtrl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PDEVICE_EXTENSION deviceExtension; SYSCTL_IRP_DISPOSITION disposition; NTSTATUS ntStatus; PIO_STACK_LOCATION irpStack; PAGED_CODE(); irpStack = IoGetCurrentIrpStackLocation (Irp); deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; FreeBT_DbgPrint(3, ("FBTUSB: ")); FreeBT_DbgPrint(3, (WMIMinorFunctionString(irpStack->MinorFunction))); if (Removed == deviceExtension->DeviceState) { ntStatus = STATUS_DELETE_PENDING; Irp->IoStatus.Status = ntStatus; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return ntStatus; } FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchSysCtrl::")); FreeBT_IoIncrement(deviceExtension); ntStatus = WmiSystemControl(&deviceExtension->WmiLibInfo, DeviceObject, Irp, &disposition); switch(disposition) { case IrpProcessed: { // This irp has been processed and may be completed or pending. break; } case IrpNotCompleted: { // This irp has not been completed, but has been fully processed. // we will complete it now IoCompleteRequest(Irp, IO_NO_INCREMENT); break; } case IrpForward: case IrpNotWmi: { // This irp is either not a WMI irp or is a WMI irp targeted // at a device lower in the stack. IoSkipCurrentIrpStackLocation (Irp); ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp); break; } default: { // We really should never get here, but if we do just forward.... ASSERT(FALSE); IoSkipCurrentIrpStackLocation (Irp); ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp); break; } } FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchSysCtrl::")); FreeBT_IoDecrement(deviceExtension); return ntStatus; }
NTSTATUS NTAPI FreeBT_SetWmiDataBlock( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN ULONG GuidIndex, IN ULONG InstanceIndex, IN ULONG BufferSize, IN PUCHAR Buffer ) /*++ Routine Description: This routine is a callback into the driver to set the contents of a data block. When the driver has finished filling the data block it must call WmiCompleteRequest to complete the irp. The driver can return STATUS_PENDING if the irp cannot be completed immediately. Arguments: DeviceObject is the device whose data block is being queried Irp is the Irp that makes this request GuidIndex is the index into the list of guids provided when the device registered InstanceIndex is the index that denotes which instance of the data block is being queried. BufferSize has the size of the data block passed Buffer has the new values for the data block --*/ { PDEVICE_EXTENSION deviceExtension; NTSTATUS ntStatus; ULONG info; PAGED_CODE(); FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_SetWmiDataBlock: Entered\n")); deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; info = 0; switch(GuidIndex) { case WMI_FREEBT_DRIVER_INFORMATION: if(BufferSize == sizeof(ULONG)) { DebugLevel = *(PULONG) Buffer; ntStatus = STATUS_SUCCESS; info = sizeof(ULONG); } else { ntStatus = STATUS_INFO_LENGTH_MISMATCH; } break; default: ntStatus = STATUS_WMI_GUID_NOT_FOUND; } ntStatus = WmiCompleteRequest(DeviceObject, Irp, ntStatus, info, IO_NO_INCREMENT); FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_SetWmiDataBlock: Leaving\n")); return ntStatus; }
NTSTATUS NTAPI HandleDeviceSetPower(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { KIRQL oldIrql; NTSTATUS ntStatus; POWER_STATE newState; PIO_STACK_LOCATION irpStack; PDEVICE_EXTENSION deviceExtension; DEVICE_POWER_STATE newDevState, oldDevState; FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower: Entered\n")); deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; irpStack = IoGetCurrentIrpStackLocation(Irp); oldDevState = deviceExtension->DevPower; newState = irpStack->Parameters.Power.State; newDevState = newState.DeviceState; FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower: Set request for device power state D%X\n" "FBTUSB: HandleDeviceSetPower: Current device power state D%X\n", newDevState - 1, deviceExtension->DevPower - 1)); if (newDevState < oldDevState) { FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower: Adding power to the device\n")); 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 FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower: 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); FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower::")); FreeBT_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 FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower: 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)) { FreeBT_DbgPrint(1, ("FBTUSB: HandleDeviceSetPower: Lower drivers failed a power Irp\n")); } } HandleDeviceSetPower_Exit: FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower: Leaving\n")); return STATUS_PENDING; }
VOID NTAPI SendDeviceIrp(IN PDEVICE_OBJECT DeviceObject, IN PIRP SIrp ) { NTSTATUS ntStatus; POWER_STATE powState; PDEVICE_EXTENSION deviceExtension; PIO_STACK_LOCATION irpStack; SYSTEM_POWER_STATE systemState; DEVICE_POWER_STATE devState; PPOWER_COMPLETION_CONTEXT powerContext; irpStack = IoGetCurrentIrpStackLocation(SIrp); systemState = irpStack->Parameters.Power.State.SystemState; deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; FreeBT_DbgPrint(3, ("FBTUSB: SendDeviceIrp: Entered\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) { FreeBT_DbgPrint(1, ("FBTUSB: SendDeviceIrp: 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); FreeBT_DbgPrint(3, ("FBTUSB: SendDeviceIrp::")); FreeBT_IoDecrement(deviceExtension); } FreeBT_DbgPrint(3, ("FBTUSB: SendDeviceIrp: Leaving\n")); }
NTSTATUS NTAPI HandleDeviceQueryPower(PDEVICE_OBJECT DeviceObject, PIRP Irp) { NTSTATUS ntStatus; PDEVICE_EXTENSION deviceExtension; PIO_STACK_LOCATION irpStack; DEVICE_POWER_STATE deviceState; FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceQueryPower: Entered\n")); deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; irpStack = IoGetCurrentIrpStackLocation(Irp); deviceState = irpStack->Parameters.Power.State.DeviceState; FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceQueryPower: Query for device power state D%X\n" "FBTUSB: HandleDeviceQueryPower: Current device power state D%X\n", deviceState - 1, deviceExtension->DevPower - 1)); if (deviceExtension->WaitWakeEnable && deviceState > deviceExtension->DeviceCapabilities.DeviceWake) { PoStartNextPowerIrp(Irp); Irp->IoStatus.Status = ntStatus = STATUS_INVALID_DEVICE_STATE; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceQueryPower::")); FreeBT_IoDecrement(deviceExtension); return ntStatus; } if (deviceState < deviceExtension->DevPower) { ntStatus = STATUS_SUCCESS; } else { ntStatus = HoldIoRequests(DeviceObject, Irp); if(STATUS_PENDING == ntStatus) { return ntStatus; } } // on error complete the Irp. // on success pass it to the lower layers PoStartNextPowerIrp(Irp); Irp->IoStatus.Status = ntStatus; Irp->IoStatus.Information = 0; if(!NT_SUCCESS(ntStatus)) { IoCompleteRequest(Irp, IO_NO_INCREMENT); } else { IoSkipCurrentIrpStackLocation(Irp); ntStatus=PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp); } FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceQueryPower::")); FreeBT_IoDecrement(deviceExtension); FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceQueryPower: Leaving\n")); return ntStatus; }
NTSTATUS NTAPI FreeBT_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 ) /*++ Routine Description: This routine is a callback into the driver to query for the contents of a data block. When the driver has finished filling the data block it must call WmiCompleteRequest to complete the irp. The driver can return STATUS_PENDING if the irp cannot be completed immediately. Arguments: DeviceObject is the device whose data block is being queried Irp is the Irp that makes this request GuidIndex is the index into the list of guids provided when the device registered InstanceIndex is the index that denotes which instance of the data block is being queried. InstanceCount is the number of instances expected to be returned for the data block. InstanceLengthArray is a pointer to an array of ULONG that returns the lengths of each instance of the data block. If this is NULL then there was not enough space in the output buffer to fulfill the request so the irp should be completed with the buffer needed. OutBufferSize has the maximum size available to write the data block. Buffer on return is filled with the returned data block Return Value: status --*/ { PDEVICE_EXTENSION deviceExtension; NTSTATUS ntStatus; ULONG size; WCHAR modelName[] = L"Aishverya\0\0"; USHORT modelNameLen; PAGED_CODE(); FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_QueryWmiDataBlock: Entered\n")); size = 0; modelNameLen = (wcslen(modelName) + 1) * sizeof(WCHAR); // Only ever registers 1 instance per guid ASSERT((InstanceIndex == 0) && (InstanceCount == 1)); deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; switch (GuidIndex) { case WMI_FREEBT_DRIVER_INFORMATION: size = sizeof(ULONG) + modelNameLen + sizeof(USHORT); if (OutBufferSize < size ) { FreeBT_DbgPrint(3, ("FBTUSB: OutBuffer too small\n")); ntStatus = STATUS_BUFFER_TOO_SMALL; break; } * (PULONG) Buffer = DebugLevel; Buffer += sizeof(ULONG); // put length of string ahead of string *((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; } ntStatus = WmiCompleteRequest(DeviceObject, Irp, ntStatus, size, IO_NO_INCREMENT); FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_QueryWmiDataBlock: Leaving\n")); return ntStatus; }
// AddDevice, called when an instance of our supported hardware is found // Returning anything other than NT_SUCCESS here causes the device to fail // to initialise NTSTATUS NTAPI FreeBT_AddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject) { NTSTATUS ntStatus; PDEVICE_OBJECT deviceObject; PDEVICE_EXTENSION deviceExtension; POWER_STATE state; KIRQL oldIrql; UNICODE_STRING uniDeviceName; WCHAR wszDeviceName[255]={0}; UNICODE_STRING uniDosDeviceName; LONG instanceNumber=0; FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_AddDevice: Entered\n")); deviceObject = NULL; swprintf(wszDeviceName, L"\\Device\\FbtUsb%02d", instanceNumber); RtlInitUnicodeString(&uniDeviceName, wszDeviceName); ntStatus=STATUS_OBJECT_NAME_COLLISION; while (instanceNumber<99 && !NT_SUCCESS(ntStatus)) { swprintf(wszDeviceName, L"\\Device\\FbtUsb%02d", instanceNumber); uniDeviceName.Length = wcslen(wszDeviceName) * sizeof(WCHAR); FreeBT_DbgPrint(1, ("FBTUSB: Attempting to create device %ws\n", wszDeviceName)); ntStatus = IoCreateDevice( DriverObject, // our driver object sizeof(DEVICE_EXTENSION), // extension size for us &uniDeviceName, // name for this device FILE_DEVICE_UNKNOWN, 0, // device characteristics FALSE, // Not exclusive &deviceObject); // Our device object if (!NT_SUCCESS(ntStatus)) instanceNumber++; } if (!NT_SUCCESS(ntStatus)) { FreeBT_DbgPrint(1, ("FBTUSB: Failed to create device object\n")); return ntStatus; } FreeBT_DbgPrint(1, ("FBTUSB: Created device %ws\n", wszDeviceName)); deviceExtension = (PDEVICE_EXTENSION) deviceObject->DeviceExtension; deviceExtension->FunctionalDeviceObject = deviceObject; deviceExtension->PhysicalDeviceObject = PhysicalDeviceObject; deviceObject->Flags |= DO_DIRECT_IO; swprintf(deviceExtension->wszDosDeviceName, L"\\DosDevices\\FbtUsb%02d", instanceNumber); RtlInitUnicodeString(&uniDosDeviceName, deviceExtension->wszDosDeviceName); ntStatus=IoCreateSymbolicLink(&uniDosDeviceName, &uniDeviceName); if (!NT_SUCCESS(ntStatus)) { FreeBT_DbgPrint(1, ("FBTUSB: Failed to create symbolic link %ws to %ws, status=0x%08x\n", deviceExtension->wszDosDeviceName, wszDeviceName, ntStatus)); IoDeleteDevice(deviceObject); return ntStatus; } FreeBT_DbgPrint(1, ("FBTUSB: Created symbolic link %ws\n", deviceExtension->wszDosDeviceName)); KeInitializeSpinLock(&deviceExtension->DevStateLock); INITIALIZE_PNP_STATE(deviceExtension); deviceExtension->OpenHandleCount = 0; // Initialize the selective suspend variables KeInitializeSpinLock(&deviceExtension->IdleReqStateLock); deviceExtension->IdleReqPend = 0; deviceExtension->PendingIdleIrp = NULL; // Hold requests until the device is started deviceExtension->QueueState = HoldRequests; // Initialize the queue and the queue spin lock InitializeListHead(&deviceExtension->NewRequestsQueue); KeInitializeSpinLock(&deviceExtension->QueueLock); // Initialize the remove event to not-signaled. KeInitializeEvent(&deviceExtension->RemoveEvent, SynchronizationEvent, FALSE); // Initialize the stop event to signaled. // This event is signaled when the OutstandingIO becomes 1 KeInitializeEvent(&deviceExtension->StopEvent, SynchronizationEvent, TRUE); // OutstandingIo count biased to 1. // Transition to 0 during remove device means IO is finished. // Transition to 1 means the device can be stopped deviceExtension->OutStandingIO = 1; KeInitializeSpinLock(&deviceExtension->IOCountLock); #ifdef ENABLE_WMI // Delegating to WMILIB ntStatus = FreeBT_WmiRegistration(deviceExtension); if (!NT_SUCCESS(ntStatus)) { FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_WmiRegistration failed with %X\n", ntStatus)); IoDeleteDevice(deviceObject); IoDeleteSymbolicLink(&uniDosDeviceName); return ntStatus; } #endif // Set the flags as underlying PDO if (PhysicalDeviceObject->Flags & DO_POWER_PAGABLE) { deviceObject->Flags |= DO_POWER_PAGABLE; } // Typically, the function driver for a device is its // power policy owner, although for some devices another // driver or system component may assume this role. // Set the initial power state of the device, if known, by calling // PoSetPowerState. deviceExtension->DevPower = PowerDeviceD0; deviceExtension->SysPower = PowerSystemWorking; state.DeviceState = PowerDeviceD0; PoSetPowerState(deviceObject, DevicePowerState, state); // attach our driver to device stack // The return value of IoAttachDeviceToDeviceStack is the top of the // attachment chain. This is where all the IRPs should be routed. deviceExtension->TopOfStackDeviceObject = IoAttachDeviceToDeviceStack(deviceObject, PhysicalDeviceObject); if (NULL == deviceExtension->TopOfStackDeviceObject) { #ifdef ENABLE_WMI FreeBT_WmiDeRegistration(deviceExtension); #endif IoDeleteDevice(deviceObject); IoDeleteSymbolicLink(&uniDosDeviceName); return STATUS_NO_SUCH_DEVICE; } // Register device interfaces ntStatus = IoRegisterDeviceInterface(deviceExtension->PhysicalDeviceObject, &GUID_CLASS_FREEBT_USB, NULL, &deviceExtension->InterfaceName); if (!NT_SUCCESS(ntStatus)) { #ifdef ENABLE_WMI FreeBT_WmiDeRegistration(deviceExtension); #endif IoDetachDevice(deviceExtension->TopOfStackDeviceObject); IoDeleteDevice(deviceObject); IoDeleteSymbolicLink(&uniDosDeviceName); return ntStatus; } if (IoIsWdmVersionAvailable(1, 0x20)) { deviceExtension->WdmVersion = WinXpOrBetter; } else if (IoIsWdmVersionAvailable(1, 0x10)) { deviceExtension->WdmVersion = Win2kOrBetter; } else if (IoIsWdmVersionAvailable(1, 0x5)) { deviceExtension->WdmVersion = WinMeOrBetter; } else if (IoIsWdmVersionAvailable(1, 0x0)) { deviceExtension->WdmVersion = Win98OrBetter; } deviceExtension->SSRegistryEnable = 0; deviceExtension->SSEnable = 0; // WinXP only: check the registry flag indicating whether // the device should selectively suspend when idle if (WinXpOrBetter == deviceExtension->WdmVersion) { FreeBT_GetRegistryDword(FREEBT_REGISTRY_PARAMETERS_PATH, L"BulkUsbEnable", (PULONG)(&deviceExtension->SSRegistryEnable)); if (deviceExtension->SSRegistryEnable) { // initialize DPC KeInitializeDpc(&deviceExtension->DeferredProcCall, DpcRoutine, deviceObject); // initialize the timer. // the DPC and the timer in conjunction, // monitor the state of the device to // selectively suspend the device. KeInitializeTimerEx(&deviceExtension->Timer, NotificationTimer); // Initialize the NoDpcWorkItemPendingEvent to signaled state. // This event is cleared when a Dpc is fired and signaled // on completion of the work-item. KeInitializeEvent(&deviceExtension->NoDpcWorkItemPendingEvent, NotificationEvent, TRUE); // Initialize the NoIdleReqPendEvent to ensure that the idle request // is indeed complete before we unload the drivers. KeInitializeEvent(&deviceExtension->NoIdleReqPendEvent, NotificationEvent, TRUE); } } // Initialize the NoIdleReqPendEvent to ensure that the idle request // is indeed complete before we unload the drivers. KeInitializeEvent(&deviceExtension->DelayEvent, NotificationEvent, FALSE); // Clear the DO_DEVICE_INITIALIZING flag. // Note: Do not clear this flag until the driver has set the // device power state and the power DO flags. deviceObject->Flags &= ~DO_DEVICE_INITIALIZING; InterlockedIncrement(&instanceNumber); FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_AddDevice: Leaving\n")); return ntStatus; }
// Handle power events NTSTATUS NTAPI FreeBT_DispatchPower(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { NTSTATUS ntStatus = STATUS_SUCCESS; PIO_STACK_LOCATION irpStack; //PUNICODE_STRING tagString; PDEVICE_EXTENSION deviceExtension; irpStack = IoGetCurrentIrpStackLocation(Irp); deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; // We don't queue power Irps, we'll only check if the // device was removed, otherwise we'll take appropriate // action and send it to the next lower driver. In general // drivers should not cause long delays while handling power // IRPs. If a driver cannot handle a power IRP in a brief time, // it should return STATUS_PENDING and queue all incoming // IRPs until the IRP completes. if (Removed == deviceExtension->DeviceState) { // Even if a driver fails the IRP, it must nevertheless call // PoStartNextPowerIrp to inform the Power Manager that it // is ready to handle another power IRP. PoStartNextPowerIrp(Irp); Irp->IoStatus.Status = ntStatus = STATUS_DELETE_PENDING; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return ntStatus; } if (NotStarted == deviceExtension->DeviceState) { // if the device is not started yet, pass it down PoStartNextPowerIrp(Irp); IoSkipCurrentIrpStackLocation(Irp); return PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp); } FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPower::")); FreeBT_IoIncrement(deviceExtension); switch(irpStack->MinorFunction) { case IRP_MN_SET_POWER: // The Power Manager sends this IRP for one of the // following reasons: // 1) To notify drivers of a change to the system power state. // 2) To change the power state of a device for which // the Power Manager is performing idle detection. // A driver sends IRP_MN_SET_POWER to change the power // state of its device if it's a power policy owner for the // device. FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPower: IRP_MN_SET_POWER\n")); IoMarkIrpPending(Irp); switch(irpStack->Parameters.Power.Type) { case SystemPowerState: HandleSystemSetPower(DeviceObject, Irp); ntStatus = STATUS_PENDING; break; case DevicePowerState: HandleDeviceSetPower(DeviceObject, Irp); ntStatus = STATUS_PENDING; break; } break; case IRP_MN_QUERY_POWER: // The Power Manager sends a power IRP with the minor // IRP code IRP_MN_QUERY_POWER to determine whether it // can safely change to the specified system power state // (S1-S5) and to allow drivers to prepare for such a change. // If a driver can put its device in the requested state, // it sets status to STATUS_SUCCESS and passes the IRP down. FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPower: IRP_MN_QUERY_POWER\n")); IoMarkIrpPending(Irp); switch(irpStack->Parameters.Power.Type) { case SystemPowerState: HandleSystemQueryPower(DeviceObject, Irp); ntStatus = STATUS_PENDING; break; case DevicePowerState: HandleDeviceQueryPower(DeviceObject, Irp); ntStatus = STATUS_PENDING; break; } break; case IRP_MN_WAIT_WAKE: // The minor power IRP code IRP_MN_WAIT_WAKE provides // for waking a device or waking the system. Drivers // of devices that can wake themselves or the system // send IRP_MN_WAIT_WAKE. The system sends IRP_MN_WAIT_WAKE // only to devices that always wake the system, such as // the power-on switch. FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPower: IRP_MN_WAIT_WAKE\n")); IoMarkIrpPending(Irp); IoCopyCurrentIrpStackLocationToNext(Irp); IoSetCompletionRoutine( Irp, (PIO_COMPLETION_ROUTINE)WaitWakeCompletionRoutine, deviceExtension, TRUE, TRUE, TRUE); PoStartNextPowerIrp(Irp); ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp); if(!NT_SUCCESS(ntStatus)) { FreeBT_DbgPrint(1, ("FBTUSB: Lower drivers failed the wait-wake Irp\n")); } ntStatus = STATUS_PENDING; // push back the count HERE and NOT in completion routine // a pending Wait Wake Irp should not impede stopping the device FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPower: IRP_MN_WAIT_WAKE::")); FreeBT_IoDecrement(deviceExtension); break; case IRP_MN_POWER_SEQUENCE: // A driver sends this IRP as an optimization to determine // whether its device actually entered a specific power state. // This IRP is optional. Power Manager cannot send this IRP. FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPower: IRP_MN_POWER_SEQUENCE\n")); default: PoStartNextPowerIrp(Irp); IoSkipCurrentIrpStackLocation(Irp); ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp); if(!NT_SUCCESS(ntStatus)) { FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_DispatchPower: Lower drivers failed this Irp\n")); } FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPower::")); FreeBT_IoDecrement(deviceExtension); break; } return ntStatus; }