//----------------------------------------------------------------------------------------------
//	SendAndWaitPowerRequest
//----------------------------------------------------------------------------------------------
NTSTATUS SendAndWaitPowerRequest(
	 IN PDEVICE_OBJECT	DeviceObject
	,IN PIRP			Irp )
{
	//	変数宣言
	NTSTATUS	Status;
	KEVENT		WaitEvent;

	//	下位ドライバに I/O 要求を発行する
	KeInitializeEvent( &WaitEvent, NotificationEvent, FALSE );
	PoStartNextPowerIrp( Irp );
	IoCopyCurrentIrpStackLocationToNext( Irp );
	IoSetCompletionRoutine(
		 Irp
		,(PIO_COMPLETION_ROUTINE)IoCompletionRoutine
		,(PVOID)&WaitEvent
		,TRUE
		,TRUE
		,TRUE );
#if (NTDDI_VERSION < NTDDI_LONGHORN)
	Status	= PoCallDriver( GET_NEXT_DEVICE_OBJECT( DeviceObject ), Irp );
#else
	Status	= IoCallDriver( GET_NEXT_DEVICE_OBJECT( DeviceObject ), Irp );
#endif

	//	下位ドライバの処理が完了するまで待機する
	if( Status == STATUS_PENDING )
	{
		KeWaitForSingleObject( &WaitEvent, Executive, KernelMode, FALSE, NULL );
		Status	= Irp->IoStatus.Status;
	}

	return( Status );
}
//----------------------------------------------------------------------------------------------
//	SendPowerRequest
//----------------------------------------------------------------------------------------------
NTSTATUS SendPowerRequest(
	 IN PDEVICE_OBJECT	DeviceObject
	,IN PIRP			Irp )
{
	//	下位ドライバに I/O 要求を発行する
	PoStartNextPowerIrp( Irp );
	IoSkipCurrentIrpStackLocation( Irp );
#if (NTDDI_VERSION < NTDDI_LONGHORN)
	return( PoCallDriver( GET_NEXT_DEVICE_OBJECT( DeviceObject ), Irp ) );
#else
	return( IoCallDriver( GET_NEXT_DEVICE_OBJECT( DeviceObject ), Irp ) );
#endif
}
Exemplo n.º 3
0
NTSTATUS
HidKmdfPowerPassThrough(
    __in PDEVICE_OBJECT DeviceObject,
    __in PIRP Irp
    )
/*++

Routine Description:

    Pass through routine for power IRPs .

Arguments:

   DeviceObject - pointer to a device object.

   Irp - pointer to an I/O Request Packet.

Return Value:

      NT status code

--*/
{
    //
    // Must start the next power irp before skipping to the next stack location
    //
    PoStartNextPowerIrp(Irp);

    //
    // Copy current stack to next instead of skipping. We do this to preserve 
    // current stack information provided by hidclass driver to the minidriver
    //
    IoCopyCurrentIrpStackLocationToNext(Irp);
    return PoCallDriver(GET_NEXT_DEVICE_OBJECT(DeviceObject), Irp);
}
Exemplo n.º 4
0
NTSTATUS EXTERNAL
HbtnAddDevice(
    __in PDRIVER_OBJECT DrvObj,
    __in PDEVICE_OBJECT DevObj
    )
{
    NTSTATUS            status = STATUS_SUCCESS;
    PDEVICE_EXTENSION   devext = NULL;

    PAGED_CODE ();
    TEnter(Func,("(DrvObj=%p,DevObj=%p)\n", DrvObj, DevObj));
    
    UNREFERENCED_PARAMETER(DrvObj);

    devext = GET_MINIDRIVER_DEVICE_EXTENSION(DevObj);
    RtlZeroMemory(devext, sizeof(*devext));
    devext->self = DevObj;
    devext->LowerDevObj = GET_NEXT_DEVICE_OBJECT(DevObj);
    IoInitializeRemoveLock(&devext->RemoveLock, HBTN_POOL_TAG, 0, 10);
    KeInitializeSpinLock(&devext->QueueLock);
    KeInitializeSpinLock(&devext->DataLock);
    InitializeListHead(&devext->PendingIrpList);
    IoCsqInitialize(&devext->IrpQueue, HbtnInsertIrp, HbtnRemoveIrp, 
        HbtnPeekNextIrp, HbtnAcquireLock, HbtnReleaseLock, HbtnCompleteCancelledIrp);

    status = OemAddDevice(devext);
    if (NT_SUCCESS(status))
    {
        DevObj->Flags &= ~DO_DEVICE_INITIALIZING;
        DevObj->Flags |= DO_POWER_PAGABLE;
    }

    TExit(Func,("=%x\n", status));
    return status;
}       //HbtnAddDevice
Exemplo n.º 5
0
NTSTATUS
HidUmdfPowerPassThrough(
    _In_ PDEVICE_OBJECT DeviceObject,
    _Inout_ PIRP Irp
    )
/*++

Routine Description:

    Pass through routine for power IRPs .

Arguments:

   DeviceObject - pointer to a device object.

   Irp - pointer to an I/O Request Packet.

Return Value:

      NT status code

--*/
{
    PoStartNextPowerIrp(Irp);
    IoCopyCurrentIrpStackLocationToNext(Irp);
    return PoCallDriver(GET_NEXT_DEVICE_OBJECT(DeviceObject), Irp);
}
Exemplo n.º 6
0
NTSTATUS
HidUmdfPassThrough(
    _In_ PDEVICE_OBJECT DeviceObject,
    _Inout_ PIRP Irp
    )
/*++

Routine Description:

    Pass through routine for all the IRPs except power.

Arguments:

   DeviceObject - pointer to a device object.

   Irp - pointer to an I/O Request Packet.

Return Value:

      NT status code

--*/
{
    PIO_STACK_LOCATION irpStack;

    irpStack = IoGetCurrentIrpStackLocation(Irp);

    IoCopyCurrentIrpStackLocationToNext(Irp);
    return IoCallDriver(GET_NEXT_DEVICE_OBJECT(DeviceObject), Irp);
}
//----------------------------------------------------------------------------------------------
//	SendRequest
//----------------------------------------------------------------------------------------------
NTSTATUS SendRequest(
	 IN PDEVICE_OBJECT	DeviceObject
	,IN PIRP			Irp )
{
	//	下位ドライバに I/O 要求を発行する
	IoSkipCurrentIrpStackLocation( Irp );
	return( IoCallDriver( GET_NEXT_DEVICE_OBJECT( DeviceObject ), Irp ) );
}
Exemplo n.º 8
0
NTSTATUS PPJoy_Power (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
 PDEVICE_EXTENSION  DeviceExtension;
 NTSTATUS           ntStatus;
 POWER_STATE		PowerState;
 POWER_STATE_TYPE	PowerType;
 PIO_STACK_LOCATION	Stack;

 PAGED_CODE ();

 PPJOY_DBGPRINT (FILE_POWER | PPJOY_FENTRY, ("Enter PPJoy_Power(DeviceObject=0x%p,Irp=0x%p)",DeviceObject,Irp) );

 DeviceExtension = GET_MINIDRIVER_DEVICE_EXTENSION (DeviceObject);

 ntStatus= PPJoy_EnterRequest (DeviceExtension);
 if (NT_SUCCESS(ntStatus))
 {
  Stack= IoGetCurrentIrpStackLocation (Irp);
  PowerType= Stack->Parameters.Power.Type;
  PowerState= Stack->Parameters.Power.State;

  if ((Stack->MinorFunction==IRP_MN_SET_POWER)&&
	  (PowerType==DevicePowerState)&&
	  (PowerState.DeviceState==PowerDeviceD0))
  {
   PPJOY_DBGPRINT (FILE_POWER|PPJOY_BABBLE, ("We got a device D0 power state request for our device. Set parallel port mode again") );

   /* Set the parallel port mode. */
   PPJoy_InitPortAndInterface (DeviceObject);
  }
 
  /* Must be called before IoSkipCurrentIrpStackLocation, else bugcheck */
  PoStartNextPowerIrp (Irp);
  /* Prepare IRP stack for next driver */
  IoSkipCurrentIrpStackLocation (Irp);

  /* We call PoCallDriver since this is a Power IRP */
  ntStatus=  PoCallDriver (GET_NEXT_DEVICE_OBJECT (DeviceObject),Irp);
 }
 else
 {
  /* Must be called even when the device is removed */
  PoStartNextPowerIrp (Irp);

  Irp->IoStatus.Information= 0;
  Irp->IoStatus.Status= ntStatus;
  IoCompleteRequest (Irp,IO_NO_INCREMENT);
 }

 PPJoy_LeaveRequest	(DeviceExtension);

 PPJOY_EXITPROC (FILE_POWER|PPJOY_FEXIT, "PPJOY_Power",ntStatus);
 return ntStatus;
}
//----------------------------------------------------------------------------------------------
//	AddDevice
//----------------------------------------------------------------------------------------------
NTSTATUS AddDevice(
	 IN PDRIVER_OBJECT	DriverObject
	,IN PDEVICE_OBJECT	DeviceObject )
{
	//	変数宣言
	PDEVICE_EXTENSION	DeviceExtension	= GET_MINIDRIVER_DEVICE_EXTENSION( DeviceObject );
	UCHAR				ThreadId;

	//	デバイス エクステンションの内容を初期化する
	RtlZeroMemory( DeviceExtension, sizeof( DEVICE_EXTENSION ) );

	//	I/O 要求制御
	DeviceExtension->DriverState	= Enable;
	DeviceExtension->DeviceState	= Disable;
	DeviceExtension->ReferenceCount	= 1;
	KeInitializeEvent( &DeviceExtension->ReferenceEnd, NotificationEvent, FALSE );

	//	ワーカ スレッド
	DeviceExtension->ThreadStateIo	= Disable;
	for( ThreadId = 0; ThreadId < ControllerCount; ThreadId ++ )
	{
		KeInitializeEvent(
			 &DeviceExtension->ThreadExitingIn[ThreadId]
			,SynchronizationEvent
			,FALSE );
		KeInitializeEvent(
			 &DeviceExtension->ThreadExitingOut[ThreadId]
			,SynchronizationEvent
			,FALSE );
	}

	//	IRP
	DeviceExtension->ThreadStateIdc	= Disable;
	KeInitializeEvent( &DeviceExtension->ThreadExitingIdc, SynchronizationEvent, FALSE );
	KeInitializeSpinLock( &DeviceExtension->LockIrp );

	//	USB
	DeviceExtension->NextDeviceObject	= GET_NEXT_DEVICE_OBJECT( DeviceObject );

	//	レポート
	KeInitializeSpinLock( &DeviceExtension->LockReport );

	//	デバイス エクステンションの初期化完了を通知する
	DeviceObject->Flags	&= ~DO_DEVICE_INITIALIZING;

	return( STATUS_SUCCESS );
}
Exemplo n.º 10
0
NTSTATUS PPJoy_Ctl_CreateClose (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
 NTSTATUS			ntStatus;
 PDEVICE_EXTENSION	DeviceExtension;
 int				Count;


 PAGED_CODE ();

 /* If it is not for one of our control devices - pass on to HID.sys */
 if (GET_NEXT_DEVICE_OBJECT(DeviceObject))
 {
  PPJOY_DBGPRINT (FILE_PPORTJOY|PPJOY_HIDHACK, ("Not a control device - passing request on to HID.sys (PPJoy_Ctl_CreateClose)") );
  return HIDMajorFunctions[IoGetCurrentIrpStackLocation(Irp)->MajorFunction](DeviceObject,Irp);
 }

 PPJOY_DBGPRINT (FILE_PPORTJOY|PPJOY_FENTRY, ("PPJoy_Ctl_CreateClose(DeviceObject=0x%p,Irp=0x%p)",DeviceObject,Irp) );

 DeviceExtension= GET_MINIDRIVER_DEVICE_EXTENSION (DeviceObject);

 ntStatus= PPJoy_EnterRequest (DeviceExtension);
 if (!NT_SUCCESS(ntStatus))
  goto Exit;


 switch(IoGetCurrentIrpStackLocation(Irp)->MajorFunction)
 {
  case IRP_MJ_CREATE:
		DeviceExtension->OpenCount++;
		PPJOY_DBGPRINT (FILE_PPORTJOY|PPJOY_BABBLE, ("PPJoy_CreateClose:IRP_MJ_CREATE - open count %d",DeviceExtension->OpenCount) );
		Irp->IoStatus.Information= 0;
		break;

  case IRP_MJ_CLOSE:
		if (DeviceExtension->OpenCount)
		 DeviceExtension->OpenCount--;
		PPJOY_DBGPRINT (FILE_PPORTJOY|PPJOY_BABBLE, ("PPJoy_CreateClose:IRP_MJ_CLOSE - open count %d",DeviceExtension->OpenCount) );
		if ((!(DeviceExtension->OpenCount))&&(DeviceExtension->Config.JoyType==IF_IOCTL))
		{
		 /* Last open handle the Virtual stick closed. Reset device to idle state */
		 PPJOY_DBGPRINT (FILE_PPORTJOY|PPJOY_BABBLE2, ("PPJoy_CreateClose: reseting virtual joystick position") );
         RtlZeroMemory (&(DeviceExtension->RawInput),sizeof(DeviceExtension->RawInput));
         for (Count=0;Count<MAX_ANALOG_RAW;Count++)
          DeviceExtension->RawInput.Analog[Count]= (PPJOY_AXIS_MIN+PPJOY_AXIS_MAX)/2;	/* Centre */
		}
		Irp->IoStatus.Information= 0;
		break;

  default:
		PPJOY_DBGPRINT (FILE_PPORTJOY|PPJOY_WARN, ("PPJoy_CreateClose:Not handled IrpStack->MajorFunction 0x%x",IoGetCurrentIrpStackLocation(Irp)->MajorFunction) );
		ntStatus= STATUS_INVALID_PARAMETER;
		break;
 }

Exit:
 /* Set the return status for operation in the IRP */
 Irp->IoStatus.Status= ntStatus;
 PPJoy_LeaveRequest	(DeviceExtension);

 /* Complete the IRP */
 IoCompleteRequest (Irp,IO_NO_INCREMENT);

 PPJOY_EXITPROC (FILE_PPORTJOY | PPJOY_FEXIT_STATUSOK, "PPJoy_Ctl_CreateClose", ntStatus);
 return ntStatus;
}
Exemplo n.º 11
0
NTSTATUS
HidUmdfPnp(
    _In_ PDEVICE_OBJECT DeviceObject,
    _Inout_ PIRP Irp
    )
/*++

Routine Description:

    Pass through routine for all the IRPs except power.

Arguments:

   DeviceObject - pointer to a device object.

   Irp - pointer to an I/O Request Packet.

Return Value:

      NT status code

--*/
{
    NTSTATUS status;
    BUS_QUERY_ID_TYPE queryIdType;
    PIO_STACK_LOCATION  currStack;

    PAGED_CODE();

    currStack = IoGetCurrentIrpStackLocation(Irp);

    //
    // Copy current stack to next instead of skipping to preserve 
    // current stack information provided by hidclass driver to the minidriver
    //
    IoCopyCurrentIrpStackLocationToNext(Irp);

    switch (currStack->MinorFunction) {
    case IRP_MN_QUERY_ID: 
        //
        // Handle Query ID. HIDClass only sends QueryDeviceId and QueryHardwareIDs
        // to minidriver. Root enumerated minidriver needs special handling.
        //
        queryIdType = currStack->Parameters.QueryId.IdType;
        switch (queryIdType) {
        case BusQueryDeviceID:
        case BusQueryHardwareIDs:
            status = HandleQueryId(DeviceObject, Irp);
            return status;
        default:
            break;
        }
 
        break;


    default:
        break;
    }
   
    return IoCallDriver(GET_NEXT_DEVICE_OBJECT(DeviceObject), Irp);
}
Exemplo n.º 12
0
NTSTATUS
HidUmdfInternalIoctlWorker(
    _In_ PDEVICE_OBJECT DeviceObject,
    _Inout_ PIRP Irp
    )
/*++

Routine Description:

    IOCTL handler.


Arguments:

   DeviceObject - pointer to a device object.

   Irp - pointer to an I/O Request Packet.

Return Value:

      NT status code

--*/
{
    PIO_STACK_LOCATION currStack, nextStack;
    ULONG ioctlCode, newIoctlCode;
    BOOLEAN setCompletionRoutine = FALSE;
    NTSTATUS status = STATUS_SUCCESS;
    BOOLEAN modeChanged = FALSE;
    PULONG temp = NULL;
    
    currStack = IoGetCurrentIrpStackLocation(Irp);

    //
    // Copy current stack to next instead of skipping. We do this to preserve 
    // current stack information provided by hidclass driver to the minidriver
    //
    IoCopyCurrentIrpStackLocationToNext(Irp);

    //
    // HIDclass uses INTERNAL_IOCTL but since UMDF doesn't yet have support for
    // internal IOCTLS we change the IOCTL type to DEVICE_CONTROL for next stack
    // so that UMDF stack can handle it as normal IOCTL.
    // Note that user mode apps cannot open a handle to minidriver since 
    // HIDClass doesn't allow that (it own's minidriver's dispatch table),
    // and therefore they can't send these IOCTLs to UMDF minidriver by calling 
    // win32 API.
    //
    nextStack = IoGetNextIrpStackLocation(Irp);
    nextStack->MajorFunction = IRP_MJ_DEVICE_CONTROL;

    //
    // Some IOCTLs are not of type METHOD_NEITHER and are forwarded by 
    // HIDClass to minidriver. We modify those IOCTLs to use METHOD_NEITHER
    // and send it down to UMDF driver.
    //
    ioctlCode = nextStack->Parameters.DeviceIoControl.IoControlCode;

    newIoctlCode = ioctlCode;
    
    switch(ioctlCode) {
    case IOCTL_HID_GET_DEVICE_DESCRIPTOR:           // METHOD_NEITHER, KM
    case IOCTL_HID_GET_REPORT_DESCRIPTOR:           // METHOD_NEITHER, KM
    case IOCTL_HID_READ_REPORT:                     // METHOD_NEITHER, KM
    case IOCTL_HID_ACTIVATE_DEVICE:                 // METHOD_NEITHER, KM
    case IOCTL_HID_DEACTIVATE_DEVICE:               // METHOD_NEITHER, KM
    case IOCTL_HID_GET_DEVICE_ATTRIBUTES:           // METHOD_NEITHER, KM
    case IOCTL_HID_SEND_IDLE_NOTIFICATION_REQUEST:  // METHOD_NEITHER, KM
        //
        // Nothing to do. These IOCTLs have been listed for completeness.
        //
        break;
    case IOCTL_HID_WRITE_REPORT:                    // METHOD_NEITHER, KM
    case IOCTL_HID_SET_FEATURE:                     // METHOD_IN_DIRECT, KM/UM
    case IOCTL_HID_GET_FEATURE:                     // METHOD_OUT_DIRECT, KM/UM
    case IOCTL_HID_GET_INPUT_REPORT:                // METHOD_OUT_DIRECT, KM/UM
    case IOCTL_HID_SET_OUTPUT_REPORT:               // METHOD_IN_DIRECT, KM/UM
        //
        // These IOCTLs use HID_XFER_PACKET. They need their buffer location 
        // updated. See comments in function for IOCTL specific updates.
        //
        status = UpdateBufferLocationAndIoctl(Irp, &newIoctlCode);
        if (!NT_SUCCESS(status)) {
            KdPrint(("HidUmdf: Ioctl %s failed status 0x%x\n", 
                DbgHidInternalIoctlString(ioctlCode), status));
            Irp->IoStatus.Status = status;
            IoCompleteRequest(Irp, IO_NO_INCREMENT);
            return status;
        }

        //
        // set completion routine
        //
        setCompletionRoutine = TRUE;
        break;

    case IOCTL_GET_PHYSICAL_DESCRIPTOR:             // METHOD_OUT_DIRECT, KM/UM 
        //
        // These IOCTLs are not METHOD_NEITHER but hidclass places buffers at
        // locations that are standard locations for METHOD_NEITHER 
        // (Type3InputBuffer and Irp->UserBuffer), so we modify the IOCTL type
        // to use METHOD_NEITHER so that UMDF can provide the buffers from 
        // standard METHOD_NEITHER buffer locations.
        // 
        newIoctlCode = IOCTL_UMDF_GET_PHYSICAL_DESCRIPTOR;
        break;

    case IOCTL_HID_GET_STRING:                      // METHOD_NEITHER, KM     
        //
        // This is a METHOD_NEITHER IOCTL. Hidclass places an input
        // ULONG value, and not a buffer, at Type3inputBuffer location. 
        // We store the input value in Irp->AssocatedIrp.SystemBuffer location
        // and store pointer to Irp->AssocatedIrp.SystemBuffer at 
        // Type3InputBuffer so that lower driver can access it as input buffer. 
        // 

        //
        // swap current SystemBuffer content with Type3inputBuffer
        //
        temp = Irp->AssociatedIrp.SystemBuffer;
        Irp->AssociatedIrp.SystemBuffer = 
            currStack->Parameters.DeviceIoControl.Type3InputBuffer;
        currStack->Parameters.DeviceIoControl.Type3InputBuffer = temp;

        //
        // store the address of SystemBuffer in next stack's Type3InputBuffer
        // and set buffer size
        //
        nextStack->Parameters.DeviceIoControl.Type3InputBuffer = 
            &Irp->AssociatedIrp.SystemBuffer;
        nextStack->Parameters.DeviceIoControl.InputBufferLength = sizeof(ULONG);

        setCompletionRoutine = TRUE;
        break;
    
    case IOCTL_HID_GET_INDEXED_STRING:              // METHOD_OUT_DIRECT, KM/UM
        //
        // This is a METHOD_OUT_DIRECT IOCTL however hidclass places buffer/value
        // in a mix of locations (Type3InputBuffer for input instead of 
        // Irp->AssociatedIrp.SystemBuffer and Irp->MdlAddress for output). 
        // Also, the input is not a buffer but a ULONG value.
        // 
        // We store the address of next stack's Type3InputBuffer that contains 
        // the input value at Irp->AssiciatedIrp.SystemBuffer 
        // (standard location for METHOD_OUT_DIRECT), and keep the output buffer
        // location (Irp->UserBuffer) unchanged  since it's already at standard
        // location. The input buffer location is reverted back to original in 
        // completion routine.
        // 

        //
        // store SystemBuffer in curr stack's Type3inputBuffer so we 
        // can get it back in completion routine.
        //
        currStack->Parameters.DeviceIoControl.Type3InputBuffer = 
            Irp->AssociatedIrp.SystemBuffer;

        //
        // store the address of next stack's Type3InputBuffer in  SystemBuffer
        // and set buffer size.
        //
        Irp->AssociatedIrp.SystemBuffer = 
            &nextStack->Parameters.DeviceIoControl.Type3InputBuffer;
        nextStack->Parameters.DeviceIoControl.InputBufferLength = sizeof(ULONG);

        setCompletionRoutine = TRUE;
        break;

    default:
        NT_ASSERTMSG("Unexpected IOCTL", FALSE);
        break;
    }

    //
    // update ioctl code for next stack location
    //
    nextStack->Parameters.DeviceIoControl.IoControlCode = newIoctlCode;

    if (Irp->RequestorMode == UserMode) {
        Irp->RequestorMode = KernelMode;
        setCompletionRoutine = TRUE;
        modeChanged = TRUE;
    }

    if (setCompletionRoutine) {
        IoSetCompletionRoutine(Irp,
                       UserIoctlCompletion,
                       (modeChanged ? (PVOID)Irp : NULL),  // context
                       TRUE,                       
                       TRUE,
                       TRUE );
    }

    return IoCallDriver(GET_NEXT_DEVICE_OBJECT(DeviceObject), Irp);
}
Exemplo n.º 13
0
NTSTATUS PPJoy_Ctl_Power (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
 NTSTATUS           ntStatus;
 POWER_STATE		PowerState;
 POWER_STATE_TYPE	PowerType;
 PIO_STACK_LOCATION	Stack;
 PDEVICE_EXTENSION	DeviceExtension;

 PAGED_CODE ();

 /* If it is not for one of our control devices - pass on to HID.sys */
 if (GET_NEXT_DEVICE_OBJECT(DeviceObject))
 {
  PPJOY_DBGPRINT (FILE_POWER|PPJOY_HIDHACK, ("Not a control device - passing request on to HID.sys (PPJoy_Ctl_Power)") );
  return HIDMajorFunctions[IoGetCurrentIrpStackLocation(Irp)->MajorFunction](DeviceObject,Irp);
 }

 PPJOY_DBGPRINT (FILE_POWER | PPJOY_FENTRY, ("Enter PPJoy_Ctl_Power(DeviceObject=0x%p,Irp=0x%p)",DeviceObject,Irp) );

 DeviceExtension = GET_MINIDRIVER_DEVICE_EXTENSION (DeviceObject);

 ntStatus= PPJoy_EnterRequest (DeviceExtension);
 if (NT_SUCCESS(ntStatus))
 {
  Stack= IoGetCurrentIrpStackLocation (Irp);
  PowerType= Stack->Parameters.Power.Type;
  PowerState= Stack->Parameters.Power.State;
  PPJOY_DBGPRINT (FILE_POWER|PPJOY_BABBLE, ("Received Power IRP %s",PowerMinorFunctionString(Stack->MinorFunction)) );

  switch (Stack->MinorFunction)
  {
   case IRP_MN_SET_POWER:
		PPJOY_DBGPRINT (FILE_POWER|PPJOY_BABBLE, ("Request to set %s state to %s",					\
					((PowerType==SystemPowerState)?"System":"Device"),								\
                     ((PowerType==SystemPowerState)?DbgSystemPowerString(PowerState.SystemState):	\
					 DbgDevicePowerString(PowerState.DeviceState))) );

		if ((PowerType==DevicePowerState)||(PowerType==SystemPowerState))
         ntStatus= STATUS_SUCCESS;
		break;

   case IRP_MN_QUERY_POWER:
		ntStatus= STATUS_SUCCESS;
		break;

   case IRP_MN_WAIT_WAKE:
   case IRP_MN_POWER_SEQUENCE:
   default:
		ntStatus= STATUS_NOT_SUPPORTED;
        break;
  }
 }

 /* Must be before IoCompleteRequest(), else bugcheck! */
 PoStartNextPowerIrp (Irp);

 /* We are the lowest level driver for this device, complete IRP */
 if (ntStatus!=STATUS_NOT_SUPPORTED)
  Irp->IoStatus.Status= ntStatus;
 IoCompleteRequest (Irp,IO_NO_INCREMENT);
 
 PPJoy_LeaveRequest	(DeviceExtension);

 PPJOY_EXITPROC (FILE_POWER|PPJOY_FEXIT, "PPJOY_Ctl_Power",ntStatus);
 return ntStatus;
}