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 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; }
// 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; }
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; }