コード例 #1
0
ファイル: bulkwmi.c プロジェクト: stormbay/DragonVer1.0
NTSTATUS BulkUsb_DispatchSysCtrl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
    PTDeviceExtension       deviceExtension;
    SYSCTL_IRP_DISPOSITION  disposition;
    NTSTATUS                ntStatus;
    PIO_STACK_LOCATION      irpStack;
    
    PAGED_CODE();
    irpStack = IoGetCurrentIrpStackLocation (Irp);
    deviceExtension = (PTDeviceExtension) DeviceObject->DeviceExtension;
    if(REMOVED == deviceExtension->DeviceState) 
	{
        ntStatus = STATUS_DELETE_PENDING;
        Irp->IoStatus.Status = ntStatus;
        Irp->IoStatus.Information = 0;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        return ntStatus;
    }

	BulkUsb_DbgPrint(3, ("file bulkwmi: BulkUsb_DispatchSysCtrl::\n"));
    BulkUsb_IoIncrement(deviceExtension);
    ntStatus = WmiSystemControl(&deviceExtension->WmiLibInfo, 
                                DeviceObject, 
                                Irp,
                                &disposition);

    switch(disposition) 
	{
        case IrpProcessed: 
            break;
        
        case IrpNotCompleted:
            IoCompleteRequest(Irp, IO_NO_INCREMENT);                
            break;
      
        case IrpForward:
        case IrpNotWmi:
            IoSkipCurrentIrpStackLocation (Irp);
            ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
            break;
                                    
        default:
            IoSkipCurrentIrpStackLocation (Irp);
            ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
            break;
    }
    BulkUsb_DbgPrint(3, ("file bulkwmi: BulkUsb_DispatchSysCtrl::\n"));
    BulkUsb_IoDecrement(deviceExtension);

    return ntStatus;
}
コード例 #2
0
ファイル: bulkdev.c プロジェクト: stormbay/DragonVer1.0
static VOID IdleNotificationCallback(IN PTDeviceExtension DeviceExtension)
{
	NTSTATUS                ntStatus;
	POWER_STATE             powerState;
	KEVENT                  irpCompletionEvent;
	PTIrpCompletionContext	irpContext;

	BulkUsb_DbgPrint(3, ("file bulkdev: IdleNotificationCallback - process\n"));
	if(DeviceExtension->DeviceState != WORKING) 
		return;

	if(DeviceExtension->WaitWakeEnable) 
		IssueWaitWake(DeviceExtension);
	irpContext = (PTIrpCompletionContext)ExAllocatePool(NonPagedPool, sizeof(TIrpCompletionContext));
	if(!irpContext) 
	{
		BulkUsb_DbgPrint(1, ("file bulkdev: Failed to alloc memory for irpContext\n"));
		//ntStatus = STATUS_INSUFFICIENT_RESOURCES;
		return;
	}
	BulkUsb_DbgPrint(3, ("file bulkdev: IdleNotificationCallback::"));
	BulkUsb_IoIncrement(DeviceExtension);
	powerState.DeviceState = DeviceExtension->PowerDownLevel;
	KeInitializeEvent(&irpCompletionEvent, NotificationEvent, FALSE);
	irpContext->DeviceExtension = DeviceExtension;
	irpContext->Event = &irpCompletionEvent;
	ntStatus = PoRequestPowerIrp(
				DeviceExtension->PhysicalDeviceObject, 
				IRP_MN_SET_POWER, 
				powerState, 
				(PREQUEST_POWER_COMPLETE) PoIrpCompletionFunc,
				irpContext, 
				NULL);

	if(STATUS_PENDING == ntStatus) 
	{
		BulkUsb_DbgPrint(3, ("file bulkdev: IdleNotificationCallback::"
						"waiting for the power irp to complete\n"));
		KeWaitForSingleObject(&irpCompletionEvent,
					Executive,
					KernelMode,
					FALSE,
					NULL);
	}
	ExFreePool(irpContext);
	BulkUsb_DbgPrint(3, ("file bulkdev: IdleNotificationCallback - ends\n"));
}
コード例 #3
0
ファイル: bulkdev.c プロジェクト: stormbay/DragonVer1.0
//====================
NTSTATUS BulkUsb_DispatchDevCtrl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
    ULONG              code;
    PVOID              ioBuffer;
    ULONG              inputBufferLength;
    ULONG              outputBufferLength;
    ULONG              info;
    NTSTATUS           ntStatus;
    PTDeviceExtension  deviceExtension;
    PIO_STACK_LOCATION irpStack;

    info = 0;
    irpStack = IoGetCurrentIrpStackLocation(Irp);
    code = irpStack->Parameters.DeviceIoControl.IoControlCode;
    deviceExtension = (PTDeviceExtension) DeviceObject->DeviceExtension;
    ioBuffer           = Irp->AssociatedIrp.SystemBuffer;
    inputBufferLength  = irpStack->Parameters.DeviceIoControl.InputBufferLength;
    outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
    if(deviceExtension->DeviceState != WORKING) 
	{
        BulkUsb_DbgPrint(1, ("file bulkdev: Invalid device state\n"));
        Irp->IoStatus.Status = ntStatus = STATUS_INVALID_DEVICE_STATE;
        Irp->IoStatus.Information = info;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        return ntStatus;
    }
    BulkUsb_DbgPrint(3, ("file bulkdev: BulkUsb_DispatchDevCtrl::"));
    BulkUsb_IoIncrement(deviceExtension);
    BulkUsb_DbgPrint(3, ("file bulkdev: Waiting on the IdleReqPendEvent\n"));
    
    if(deviceExtension->SSEnable) 
	{
        KeWaitForSingleObject(&deviceExtension->NoIdleReqPendEvent, 
                              Executive, 
                              KernelMode, 
                              FALSE, 
                              NULL);
    }

    switch(code) 
	{
    case IOCTL_BULKUSB_RESET_PIPE:
    {
        PFILE_OBJECT           fileObject;
        PUSBD_PIPE_INFORMATION pipe;

        pipe = NULL;
        fileObject = irpStack->FileObject;
        if(fileObject == NULL) 
		{
            ntStatus = STATUS_INVALID_PARAMETER;
            break;
        }

        pipe = (PUSBD_PIPE_INFORMATION) fileObject->FsContext;
        if(pipe == NULL) 
            ntStatus = STATUS_INVALID_PARAMETER;
        else 
            ntStatus = BulkUsb_ResetPipe(DeviceObject, pipe);
        break;
    }

    case IOCTL_BULKUSB_GET_CONFIG_DESCRIPTOR:
    {
        ULONG length;

        if(deviceExtension->UsbConfigurationDescriptor) 
		{
            length = deviceExtension->UsbConfigurationDescriptor->wTotalLength;
            if(outputBufferLength >= length) 
			{
                RtlCopyMemory(ioBuffer, deviceExtension->UsbConfigurationDescriptor, length);
                info = length;
                ntStatus = STATUS_SUCCESS;
            }
            else 
                ntStatus = STATUS_BUFFER_TOO_SMALL;
        }
        else 
            ntStatus = STATUS_UNSUCCESSFUL;
        break;
    }

    case IOCTL_BULKUSB_RESET_DEVICE:
        ntStatus = BulkUsb_ResetDevice(DeviceObject);
        break;

    default :
        ntStatus = STATUS_INVALID_DEVICE_REQUEST;
        break;
    }

    Irp->IoStatus.Status = ntStatus;
    Irp->IoStatus.Information = info;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    BulkUsb_DbgPrint(3, ("file bulkdev: BulkUsb_DispatchDevCtrl::"));
    BulkUsb_IoDecrement(deviceExtension);
    return ntStatus;
}
コード例 #4
0
ファイル: bulkdev.c プロジェクト: stormbay/DragonVer1.0
static NTSTATUS IdleNotificationRequestComplete(IN PDEVICE_OBJECT DeviceObject,
												IN PIRP Irp, IN PTDeviceExtension DeviceExtension)
{
	NTSTATUS                ntStatus;
	POWER_STATE             powerState;
	KIRQL                   oldIrql;
	LARGE_INTEGER           dueTime;
	PIRP                    idleIrp;
	PUSB_IDLE_CALLBACK_INFO idleCallbackInfo;

	BulkUsb_DbgPrint(3, ("file bulkdev: IdleNotificationRequestCompete - begins\n"));
	idleIrp = NULL;
	ntStatus = Irp->IoStatus.Status;
	if(!NT_SUCCESS(ntStatus) && ntStatus != STATUS_NOT_SUPPORTED) 
	{
		BulkUsb_DbgPrint(1, ("file bulkdev: Idle irp completes with error::"));
		switch(ntStatus) 
		{
		case STATUS_INVALID_DEVICE_REQUEST:
			BulkUsb_DbgPrint(1, ("file bulkdev: STATUS_INVALID_DEVICE_REQUEST\n"));
			break;

		case STATUS_CANCELLED:
			BulkUsb_DbgPrint(1, ("file bulkdev: STATUS_CANCELLED\n"));
			break;

		case STATUS_POWER_STATE_INVALID:
			BulkUsb_DbgPrint(1, ("file bulkdev: STATUS_POWER_STATE_INVALID\n"));
			goto IdleNotificationRequestComplete_Exit;

		case STATUS_DEVICE_BUSY:
			BulkUsb_DbgPrint(1, ("file bulkdev: STATUS_DEVICE_BUSY\n"));
			break;

		default:
			BulkUsb_DbgPrint(1, ("file bulkdev: default: status = %X\n", ntStatus));
			break;
		}

		if(PowerDeviceD0 != DeviceExtension->DevPower) 
		{
			BulkUsb_DbgPrint(3, ("file bulkdev: IdleNotificationRequestComplete::"));
			BulkUsb_IoIncrement(DeviceExtension);
			powerState.DeviceState = PowerDeviceD0;
			ntStatus = PoRequestPowerIrp(
						DeviceExtension->PhysicalDeviceObject, 
						IRP_MN_SET_POWER, 
						powerState, 
						(PREQUEST_POWER_COMPLETE) PoIrpAsyncCompletionFunc, 
						DeviceExtension, 
						NULL);

			if(!NT_SUCCESS(ntStatus)) 
			{
				BulkUsb_DbgPrint(1, ("file bulkdev: PoRequestPowerIrp failed\n"));
			}
		}
	}

IdleNotificationRequestComplete_Exit:

	KeAcquireSpinLock(&DeviceExtension->IdleReqStateLock, &oldIrql);
	idleCallbackInfo = DeviceExtension->IdleCallbackInfo;
	DeviceExtension->IdleCallbackInfo = NULL;
	idleIrp = (PIRP) InterlockedExchangePointer(&DeviceExtension->PendingIdleIrp, NULL);
	InterlockedExchange(&DeviceExtension->IdleReqPend, 0);
	KeReleaseSpinLock(&DeviceExtension->IdleReqStateLock, oldIrql);
	if(idleCallbackInfo) 
	{
		ExFreePool(idleCallbackInfo);
	}
	if(idleIrp) 
	{
		BulkUsb_DbgPrint(3, ("file bulkdev: completion routine has a valid irp and frees it\n"));
		IoFreeIrp(Irp);
		KeSetEvent(&DeviceExtension->NoIdleReqPendEvent, IO_NO_INCREMENT, FALSE);
	}
	else 
	{
		if(0 == InterlockedDecrement(&DeviceExtension->FreeIdleIrpCount)) 
		{
			BulkUsb_DbgPrint(3, ("file bulkdev: completion routine frees the irp\n"));
			IoFreeIrp(Irp);
			KeSetEvent(&DeviceExtension->NoIdleReqPendEvent, IO_NO_INCREMENT, FALSE);
		}
	}
	if(DeviceExtension->SSEnable) 
	{
		BulkUsb_DbgPrint(3, ("file bulkdev: Set the timer to fire DPCs\n"));
		dueTime.QuadPart = -10000 * IDLE_INTERVAL;               // 5000 ms
		KeSetTimerEx(&DeviceExtension->Timer, 
			dueTime,
			IDLE_INTERVAL,                              // 5000 ms
			&DeviceExtension->DeferredProcCall);

		BulkUsb_DbgPrint(3, ("file bulkdev: IdleNotificationRequestCompete - ends\n"));
	}
	return STATUS_MORE_PROCESSING_REQUIRED;
}
コード例 #5
0
ファイル: bulkpwr.c プロジェクト: caidongyun/libs
NTSTATUS
BulkUsb_DispatchPower(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )
/*++
 
Routine Description:

    The power dispatch routine.

Arguments:

    DeviceObject - pointer to a device object.

    Irp - pointer to an I/O Request Packet.

Return Value:

    NT status code

--*/
{
    NTSTATUS           ntStatus;
    PIO_STACK_LOCATION irpStack;
    PUNICODE_STRING    tagString;
    PDEVICE_EXTENSION  deviceExtension;
	
    //
    // initialize the variables
    //
	
    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);
    }

    BulkUsb_DbgPrint(3, ("BulkUsb_DispatchPower::"));
    BulkUsb_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.
        //

        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.
        //

        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.
        //

        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)) {

            BulkUsb_DbgPrint(1, ("Lower drivers failed the wait-wake Irp"));
        }

        ntStatus = STATUS_PENDING;

        //
        // push back the count HERE and NOT in completion routine
        // a pending Wait Wake Irp should not impede stopping the device
        //

        BulkUsb_DbgPrint(3, ("IRP_MN_WAIT_WAKE::"));
        BulkUsb_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.
        //

    default:

        PoStartNextPowerIrp(Irp);

        IoSkipCurrentIrpStackLocation(Irp);

        ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);

        if(!NT_SUCCESS(ntStatus)) {

            BulkUsb_DbgPrint(1, ("Lower drivers failed this Irp"));
        }
        
        BulkUsb_DbgPrint(3, ("BulkUsb_DispatchPower::"));
        BulkUsb_IoDecrement(deviceExtension);

        break;
    }

    return ntStatus;
}
コード例 #6
0
ファイル: bulkpwr.c プロジェクト: caidongyun/libs
VOID
WaitWakeCallback( 
    IN PDEVICE_OBJECT DeviceObject,
    IN UCHAR MinorFunction,
    IN POWER_STATE PowerState,
    IN PVOID Context,
    IN PIO_STATUS_BLOCK IoStatus
    )
/*++
 
Routine Description:

    This is the PoRequest completion routine for the wait wake irp.

Arguments:

    DeviceObject - pointer to device object
    MinorFunction - irp minor function
    PowerState - power state of the irp.
    Context - context passed to the completion routine.
    IoStatus - status block.

Return Value:

    None

--*/
{
    NTSTATUS               ntStatus;
    POWER_STATE            powerState;
    PDEVICE_EXTENSION      deviceExtension;

    BulkUsb_DbgPrint(3, ("WaitWakeCallback - begins\n"));

    deviceExtension = (PDEVICE_EXTENSION) Context;

    InterlockedExchange(&deviceExtension->FlagWWOutstanding, 0);

    if(!NT_SUCCESS(IoStatus->Status)) {

        return;
    }

    //
    // wake up the device
    //

    if(deviceExtension->DevPower == PowerDeviceD0) {

        BulkUsb_DbgPrint(3, ("device already powered up...\n"));

        return;
    }

    BulkUsb_DbgPrint(3, ("WaitWakeCallback::"));
    BulkUsb_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);
    }

    BulkUsb_DbgPrint(3, ("WaitWakeCallback - ends\n"));

    return;
}
コード例 #7
0
ファイル: bulkpwr.c プロジェクト: caidongyun/libs
VOID
HoldIoRequestsWorkerRoutine(
    IN PDEVICE_OBJECT DeviceObject,
    IN PVOID          Context
    )
/*++
 
Routine Description:

    This routine waits for the I/O in progress to finish and then
    sends the device power irp (query/set) down the stack.

Arguments:

    DeviceObject - pointer to device object
    Context - context passed to the work-item.

Return Value:

    None

--*/
{
    PIRP                   irp;
    NTSTATUS               ntStatus;
    PDEVICE_EXTENSION      deviceExtension;
    PWORKER_THREAD_CONTEXT context;

    BulkUsb_DbgPrint(3, ("HoldIoRequestsWorkerRoutine - begins\n"));

    //
    // initialize variables
    //
    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 BulkUsb_IoDecrement twice: once each for the S-Irp and D-Irp.
    //
    BulkUsb_DbgPrint(3, ("HoldIoRequestsWorkerRoutine::"));
    BulkUsb_IoDecrement(deviceExtension);
    BulkUsb_DbgPrint(3, ("HoldIoRequestsWorkerRoutine::"));
    BulkUsb_IoDecrement(deviceExtension);

    KeWaitForSingleObject(&deviceExtension->StopEvent, Executive,
                          KernelMode, FALSE, NULL);

    //
    // Increment twice to restore the count
    //
    BulkUsb_DbgPrint(3, ("HoldIoRequestsWorkerRoutine::"));
    BulkUsb_IoIncrement(deviceExtension);
    BulkUsb_DbgPrint(3, ("HoldIoRequestsWorkerRoutine::"));
    BulkUsb_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)) {

        BulkUsb_DbgPrint(1, ("Lower driver fail a power Irp\n"));
    }

    IoFreeWorkItem(context->WorkItem);
    ExFreePool((PVOID)context);

    BulkUsb_DbgPrint(3, ("HoldIoRequestsWorkerRoutine - ends\n"));

}
コード例 #8
0
ファイル: bulkdev.c プロジェクト: caidongyun/libs
VOID
IdleNotificationCallback(
    IN PDEVICE_EXTENSION DeviceExtension
    )
/*++
 
Routine Description:

  "A pointer to a callback function in your driver is passed down the stack with
   this IOCTL, and it is this callback function that is called by USBHUB when it
   safe for your device to power down."

  "When the callback in your driver is called, all you really need to do is to
   to first ensure that a WaitWake Irp has been submitted for your device, if 
   remote wake is possible for your device and then request a SetD2 (or DeviceWake)"

Arguments:

    DeviceExtension - pointer to device extension

Return Value:

    NT status value

--*/
{
    NTSTATUS                ntStatus;
    POWER_STATE             powerState;
    KEVENT                  irpCompletionEvent;
    PIRP_COMPLETION_CONTEXT irpContext;

    BulkUsb_DbgPrint(3, ("IdleNotificationCallback - begins\n"));

    //
    // Dont idle, if the device was just disconnected or being stopped
    // i.e. return for the following DeviceState(s)
    // NotStarted, Stopped, PendingStop, PendingRemove, SurpriseRemoved, Removed
    //

    if(DeviceExtension->DeviceState != Working) {

        return;
    }

    //
    // If there is not already a WW IRP pending, submit one now
    //
    if(DeviceExtension->WaitWakeEnable) {

        IssueWaitWake(DeviceExtension);
    }


    //
    // power down the device
    //

    irpContext = (PIRP_COMPLETION_CONTEXT) 
                 ExAllocatePool(NonPagedPool,
                                sizeof(IRP_COMPLETION_CONTEXT));

    if(!irpContext) {

        BulkUsb_DbgPrint(1, ("Failed to alloc memory for irpContext\n"));
        ntStatus = STATUS_INSUFFICIENT_RESOURCES;
    }
    else {

        //
        // increment the count. In the HoldIoRequestWorkerRoutine, the
        // count is decremented twice (one for the system Irp and the 
        // other for the device Irp. An increment here compensates for 
        // the sytem irp..The decrement corresponding to this increment 
        // is in the completion function
        //

        BulkUsb_DbgPrint(3, ("IdleNotificationCallback::"));
        BulkUsb_IoIncrement(DeviceExtension);

        powerState.DeviceState = DeviceExtension->PowerDownLevel;

        KeInitializeEvent(&irpCompletionEvent, NotificationEvent, FALSE);

        irpContext->DeviceExtension = DeviceExtension;
        irpContext->Event = &irpCompletionEvent;

        ntStatus = PoRequestPowerIrp(
                          DeviceExtension->PhysicalDeviceObject, 
                          IRP_MN_SET_POWER, 
                          powerState, 
                          (PREQUEST_POWER_COMPLETE) PoIrpCompletionFunc,
                          irpContext, 
                          NULL);

        if(STATUS_PENDING == ntStatus) {

            BulkUsb_DbgPrint(3, ("IdleNotificationCallback::"
                           "waiting for the power irp to complete\n"));

            KeWaitForSingleObject(&irpCompletionEvent,
                                  Executive,
                                  KernelMode,
                                  FALSE,
                                  NULL);
        }
    }
    
    if(!NT_SUCCESS(ntStatus)) {

        if(irpContext) {

            ExFreePool(irpContext);
        }
    }

    BulkUsb_DbgPrint(3, ("IdleNotificationCallback - ends\n"));
}
コード例 #9
0
ファイル: bulkdev.c プロジェクト: caidongyun/libs
NTSTATUS
BulkUsb_DispatchDevCtrl(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )
/*++
 
Routine Description:

    Dispatch routine for IRP_MJ_DEVICE_CONTROL

Arguments:

    DeviceObject - pointer to device object
    Irp - I/O request packet

Return Value:

    NT status value

--*/
{
    ULONG              code;
    PVOID              ioBuffer;
    ULONG              inputBufferLength;
    ULONG              outputBufferLength;
    ULONG              info;
    NTSTATUS           ntStatus;
    PDEVICE_EXTENSION  deviceExtension;
    PIO_STACK_LOCATION irpStack;

    //
    // initialize variables
    //
    info = 0;
    irpStack = IoGetCurrentIrpStackLocation(Irp);
    code = irpStack->Parameters.DeviceIoControl.IoControlCode;
    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;

    ioBuffer           = Irp->AssociatedIrp.SystemBuffer;
    inputBufferLength  = irpStack->Parameters.DeviceIoControl.InputBufferLength;
    outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;

    if(deviceExtension->DeviceState != Working) {

        BulkUsb_DbgPrint(1, ("Invalid device state\n"));

        Irp->IoStatus.Status = ntStatus = STATUS_INVALID_DEVICE_STATE;
        Irp->IoStatus.Information = info;

        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        return ntStatus;
    }

    BulkUsb_DbgPrint(3, ("BulkUsb_DispatchDevCtrl::"));
    BulkUsb_IoIncrement(deviceExtension);

    //
    // It is true that the client driver cancelled the selective suspend
    // request in the dispatch routine for create.
    // But there is no guarantee that it has indeed been completed.
    // so wait on the NoIdleReqPendEvent and proceed only if this event
    // is signalled.
    //
    BulkUsb_DbgPrint(3, ("Waiting on the IdleReqPendEvent\n"));
    
    //
    // make sure that the selective suspend request has been completed.
    //

    if(deviceExtension->SSEnable) {

        KeWaitForSingleObject(&deviceExtension->NoIdleReqPendEvent, 
                              Executive, 
                              KernelMode, 
                              FALSE, 
                              NULL);
    }

    switch(code) {

    case IOCTL_BULKUSB_RESET_PIPE:
    {
        PFILE_OBJECT           fileObject;
        PUSBD_PIPE_INFORMATION pipe;

        pipe = NULL;
        fileObject = NULL;

        //
        // FileObject is the address of the kernel file object to
        // which the IRP is directed. Drivers use the FileObject
        // to correlate IRPs in a queue.
        //
        fileObject = irpStack->FileObject;

        if(fileObject == NULL) {

            ntStatus = STATUS_INVALID_PARAMETER;

            break;
        }

        pipe = (PUSBD_PIPE_INFORMATION) fileObject->FsContext;

        if(pipe == NULL) {

            ntStatus = STATUS_INVALID_PARAMETER;
        }
        else {
            
            ntStatus = BulkUsb_ResetPipe(DeviceObject, pipe);
        }

        break;
    }

    case IOCTL_BULKUSB_GET_CONFIG_DESCRIPTOR:
    {
        ULONG length;

        if(deviceExtension->UsbConfigurationDescriptor) {

            length = deviceExtension->UsbConfigurationDescriptor->wTotalLength;

            if(outputBufferLength >= length) {

                RtlCopyMemory(ioBuffer,
                              deviceExtension->UsbConfigurationDescriptor,
                              length);

                info = length;

                ntStatus = STATUS_SUCCESS;
            }
            else {
                
                ntStatus = STATUS_BUFFER_TOO_SMALL;
            }
        }
        else {
            
            ntStatus = STATUS_UNSUCCESSFUL;
        }

        break;
    }

    case IOCTL_BULKUSB_RESET_DEVICE:
        
        ntStatus = BulkUsb_ResetDevice(DeviceObject);

        break;

    default :

        ntStatus = STATUS_INVALID_DEVICE_REQUEST;

        break;
    }

    Irp->IoStatus.Status = ntStatus;
    Irp->IoStatus.Information = info;

    IoCompleteRequest(Irp, IO_NO_INCREMENT);

    BulkUsb_DbgPrint(3, ("BulkUsb_DispatchDevCtrl::"));
    BulkUsb_IoDecrement(deviceExtension);

    return ntStatus;
}
コード例 #10
0
ファイル: bulkdev.c プロジェクト: caidongyun/libs
NTSTATUS
IdleNotificationRequestComplete(
    IN PDEVICE_OBJECT    DeviceObject,
    IN PIRP              Irp,
    IN PDEVICE_EXTENSION DeviceExtension
    )
/*++
 
Routine Description:

  Completion routine for idle notification irp

Arguments:

    DeviceObject - pointer to device object
    Irp - I/O request packet
    DeviceExtension - pointer to device extension

Return Value:

    NT status value

--*/
{
    NTSTATUS                ntStatus;
    POWER_STATE             powerState;
    KIRQL                   oldIrql;
    LARGE_INTEGER           dueTime;
    PIRP                    idleIrp;
    PUSB_IDLE_CALLBACK_INFO idleCallbackInfo;

    BulkUsb_DbgPrint(3, ("IdleNotificationRequestCompete - begins\n"));

    idleIrp = NULL;

    //
    // check the Irp status
    //

    ntStatus = Irp->IoStatus.Status;

    if(!NT_SUCCESS(ntStatus) && ntStatus != STATUS_NOT_SUPPORTED) {

        BulkUsb_DbgPrint(1, ("Idle irp completes with error::"));

        switch(ntStatus) {
            
        case STATUS_INVALID_DEVICE_REQUEST:

            BulkUsb_DbgPrint(1, ("STATUS_INVALID_DEVICE_REQUEST\n"));

            break;

        case STATUS_CANCELLED:

            BulkUsb_DbgPrint(1, ("STATUS_CANCELLED\n"));

            break;

        case STATUS_POWER_STATE_INVALID:

            BulkUsb_DbgPrint(1, ("STATUS_POWER_STATE_INVALID\n"));

            goto IdleNotificationRequestComplete_Exit;

        case STATUS_DEVICE_BUSY:

            BulkUsb_DbgPrint(1, ("STATUS_DEVICE_BUSY\n"));

            break;

        default:

            BulkUsb_DbgPrint(1, ("default: status = %X\n", ntStatus));

            break;
        }

        //
        // if in error, issue a SetD0
        //

        BulkUsb_DbgPrint(3, ("IdleNotificationRequestComplete::"));
        BulkUsb_IoIncrement(DeviceExtension);

        powerState.DeviceState = PowerDeviceD0;

        ntStatus = PoRequestPowerIrp(
                          DeviceExtension->PhysicalDeviceObject, 
                          IRP_MN_SET_POWER, 
                          powerState, 
                          (PREQUEST_POWER_COMPLETE) PoIrpAsyncCompletionFunc, 
                          DeviceExtension, 
                          NULL);

        if(!NT_SUCCESS(ntStatus)) {
    
            BulkUsb_DbgPrint(1, ("PoRequestPowerIrp failed\n"));
        }

    }

IdleNotificationRequestComplete_Exit:

    KeAcquireSpinLock(&DeviceExtension->IdleReqStateLock, &oldIrql);

    idleCallbackInfo = DeviceExtension->IdleCallbackInfo;

    DeviceExtension->IdleCallbackInfo = NULL;

    idleIrp = (PIRP) InterlockedExchangePointer(
                                        &DeviceExtension->PendingIdleIrp,
                                        NULL);

    InterlockedExchange(&DeviceExtension->IdleReqPend, 0);

    KeReleaseSpinLock(&DeviceExtension->IdleReqStateLock, oldIrql);

    if(idleCallbackInfo) {

        ExFreePool(idleCallbackInfo);
    }

    //
    // since the irp was created using IoAllocateIrp, 
    // the Irp needs to be freed using IoFreeIrp.
    // Also return STATUS_MORE_PROCESSING_REQUIRED so that 
    // the kernel does not reference this in the near future.
    //

    if(idleIrp) {

        BulkUsb_DbgPrint(3, ("completion routine has a valid irp and frees it\n"));
        IoFreeIrp(Irp);
        KeSetEvent(&DeviceExtension->NoIdleReqPendEvent,
                   IO_NO_INCREMENT,
                   FALSE);
    }
    else {

        //
        // The CancelSelectiveSuspend routine has grabbed the Irp from the device 
        // extension. Now the last one to decrement the FreeIdleIrpCount should
        // free the irp.
        //
        if(0 == InterlockedDecrement(&DeviceExtension->FreeIdleIrpCount)) {

            BulkUsb_DbgPrint(3, ("completion routine frees the irp\n"));
            IoFreeIrp(Irp);

            KeSetEvent(&DeviceExtension->NoIdleReqPendEvent,
                       IO_NO_INCREMENT,
                       FALSE);
        }
    }

    if(DeviceExtension->SSEnable) {

        BulkUsb_DbgPrint(3, ("Set the timer to fire DPCs\n"));

        dueTime.QuadPart = -10000 * IDLE_INTERVAL;               // 5000 ms

        KeSetTimerEx(&DeviceExtension->Timer, 
                     dueTime,
                     IDLE_INTERVAL,                              // 5000 ms
                     &DeviceExtension->DeferredProcCall);

        BulkUsb_DbgPrint(3, ("IdleNotificationRequestCompete - ends\n"));
    }

    return STATUS_MORE_PROCESSING_REQUIRED;
}