Example #1
0
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;

}
Example #2
0
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;

}
Example #3
0
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;

}
Example #4
0
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;

}
Example #5
0
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;

}
Example #6
0
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"));

}
Example #7
0
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;

}
Example #8
0
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;

}
Example #9
0
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;

}
Example #10
0
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;

}
Example #11
0
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;

}
Example #12
0
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"));

}
Example #13
0
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"));

}
Example #14
0
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;

}
Example #15
0
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;

}
Example #16
0
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;

}
Example #17
0
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;

}
Example #18
0
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;

}
Example #19
0
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;

}
Example #20
0
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;

}
Example #21
0
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;

}
Example #22
0
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"));

}
Example #23
0
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;

}
Example #24
0
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;

}
Example #25
0
// 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;

}
Example #26
0
// 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;

}