Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

803 lines
21 KiB

  1. /*++
  2. Copyright (c) 1997-1999 Microsoft Corporation, All Rights Reserved
  3. Module Name:
  4. ptdrvpnp.c
  5. Abstract:
  6. This module contains general PnP code for the RDP remote port driver.
  7. Environment:
  8. Kernel mode.
  9. Revision History:
  10. 02/12/99 - Initial Revision based on pnpi8042 driver
  11. --*/
  12. #include <precomp.h>
  13. #pragma hdrstop
  14. #include "ptdrvcom.h"
  15. #ifdef ALLOC_PRAGMA
  16. #pragma alloc_text(PAGE, PtAddDevice)
  17. #pragma alloc_text(PAGE, PtManuallyRemoveDevice)
  18. #pragma alloc_text(PAGE, PtPnP)
  19. //#pragma alloc_text(PAGE, PtPower)
  20. #pragma alloc_text(PAGE, PtSendIrpSynchronously)
  21. #endif
  22. NTSTATUS
  23. PtAddDevice (
  24. IN PDRIVER_OBJECT Driver,
  25. IN PDEVICE_OBJECT PDO
  26. )
  27. /*++
  28. Routine Description:
  29. Adds a device to the stack and sets up the appropriate flags and
  30. device extension for the newly created device.
  31. Arguments:
  32. Driver - The driver object
  33. PDO - the device that we are attaching ourselves on top of
  34. Return Value:
  35. NTSTATUS result code.
  36. --*/
  37. {
  38. PCOMMON_DATA commonData;
  39. IO_ERROR_LOG_PACKET errorLogEntry;
  40. PDEVICE_OBJECT device;
  41. NTSTATUS status = STATUS_SUCCESS;
  42. ULONG maxSize;
  43. UNICODE_STRING fullRDPName;
  44. UNICODE_STRING baseRDPName;
  45. UNICODE_STRING deviceNameSuffix;
  46. PAGED_CODE();
  47. Print(DBG_PNP_TRACE, ("enter Add Device: %ld \n", Globals.ulDeviceNumber));
  48. //
  49. // Initialize the various unicode structures for forming the device name.
  50. //
  51. if (Globals.ulDeviceNumber == 0)
  52. RtlInitUnicodeString(&fullRDPName, RDP_CONSOLE_BASE_NAME0);
  53. else
  54. RtlInitUnicodeString(&fullRDPName, RDP_CONSOLE_BASE_NAME1);
  55. maxSize = sizeof(PORT_KEYBOARD_EXTENSION) > sizeof(PORT_MOUSE_EXTENSION) ?
  56. sizeof(PORT_KEYBOARD_EXTENSION) :
  57. sizeof(PORT_MOUSE_EXTENSION);
  58. status = IoCreateDevice(Driver, // driver
  59. maxSize, // size of extension
  60. &fullRDPName, // device name
  61. FILE_DEVICE_8042_PORT, // device type ?? unknown at this time!!!
  62. 0, // device characteristics
  63. FALSE, // exclusive
  64. &device // new device
  65. );
  66. if (!NT_SUCCESS(status)) {
  67. Print(DBG_SS_TRACE, ("Add Device failed! (0x%x) \n", status));
  68. return status;
  69. }
  70. Globals.ulDeviceNumber++;
  71. RtlZeroMemory(device->DeviceExtension, maxSize);
  72. //
  73. // Set up the device type
  74. //
  75. *((ULONG *)(device->DeviceExtension)) = DEV_TYPE_PORT;
  76. commonData = GET_COMMON_DATA(device->DeviceExtension);
  77. RtlInitUnicodeString(&commonData->DeviceName, fullRDPName.Buffer);
  78. commonData->TopOfStack = IoAttachDeviceToDeviceStack(device, PDO);
  79. ASSERT(commonData->TopOfStack);
  80. commonData->Self = device;
  81. commonData->PDO = PDO;
  82. device->Flags |= DO_BUFFERED_IO;
  83. device->Flags &= ~DO_DEVICE_INITIALIZING;
  84. Print(DBG_PNP_TRACE, ("Add Device (0x%x)\n", status));
  85. return status;
  86. }
  87. NTSTATUS
  88. PtSendIrpSynchronously (
  89. IN PDEVICE_OBJECT DeviceObject,
  90. IN PIRP Irp
  91. )
  92. /*++
  93. Routine Description:
  94. Generic routine to send an irp DeviceObject and wait for its return up the
  95. device stack.
  96. Arguments:
  97. DeviceObject - The device object to which we want to send the Irp
  98. Irp - The Irp we want to send
  99. Return Value:
  100. return code from the Irp
  101. --*/
  102. {
  103. KEVENT event;
  104. NTSTATUS status;
  105. PAGED_CODE();
  106. KeInitializeEvent(&event,
  107. SynchronizationEvent,
  108. FALSE
  109. );
  110. IoCopyCurrentIrpStackLocationToNext(Irp);
  111. IoSetCompletionRoutine(Irp,
  112. PtPnPComplete,
  113. &event,
  114. TRUE,
  115. TRUE,
  116. TRUE
  117. );
  118. status = IoCallDriver(DeviceObject, Irp);
  119. //
  120. // Wait for lower drivers to be done with the Irp
  121. //
  122. if (status == STATUS_PENDING) {
  123. KeWaitForSingleObject(&event,
  124. Executive,
  125. KernelMode,
  126. FALSE,
  127. NULL
  128. );
  129. status = Irp->IoStatus.Status;
  130. }
  131. return status;
  132. }
  133. NTSTATUS
  134. PtPnPComplete (
  135. IN PDEVICE_OBJECT DeviceObject,
  136. IN PIRP Irp,
  137. IN PKEVENT Event
  138. )
  139. /*++
  140. Routine Description:
  141. Completion routine for all PnP IRPs
  142. Arguments:
  143. DeviceObject - Pointer to the DeviceObject
  144. Irp - Pointer to the request packet
  145. Event - The event to set once processing is complete
  146. Return Value:
  147. STATUS_SUCCESSFUL if successful,
  148. an valid NTSTATUS error code otherwise
  149. --*/
  150. {
  151. PIO_STACK_LOCATION stack;
  152. NTSTATUS status;
  153. UNREFERENCED_PARAMETER (DeviceObject);
  154. status = STATUS_SUCCESS;
  155. stack = IoGetCurrentIrpStackLocation(Irp);
  156. if (Irp->PendingReturned) {
  157. IoMarkIrpPending(Irp);
  158. }
  159. KeSetEvent(Event, 0, FALSE);
  160. return STATUS_MORE_PROCESSING_REQUIRED;
  161. }
  162. NTSTATUS
  163. PtPnP (
  164. IN PDEVICE_OBJECT DeviceObject,
  165. IN PIRP Irp
  166. )
  167. /*++
  168. Routine Description:
  169. This is the dispatch routine for PnP requests
  170. Arguments:
  171. DeviceObject - Pointer to the device object
  172. Irp - Pointer to the request packet
  173. Return Value:
  174. STATUS_SUCCESSFUL if successful,
  175. an valid NTSTATUS error code otherwise
  176. --*/
  177. {
  178. PPORT_KEYBOARD_EXTENSION kbExtension;
  179. PPORT_MOUSE_EXTENSION mouseExtension;
  180. PCOMMON_DATA commonData;
  181. PIO_STACK_LOCATION stack;
  182. NTSTATUS status = STATUS_SUCCESS;
  183. KIRQL oldIrql;
  184. PAGED_CODE();
  185. commonData = GET_COMMON_DATA(DeviceObject->DeviceExtension);
  186. stack = IoGetCurrentIrpStackLocation(Irp);
  187. Print(DBG_PNP_TRACE,
  188. ("PtPnP (%s), enter (min func=0x%x)\n",
  189. commonData->IsKeyboard ? "kb" : "mou",
  190. (ULONG) stack->MinorFunction
  191. ));
  192. switch (stack->MinorFunction) {
  193. case IRP_MN_START_DEVICE:
  194. //
  195. // The device is starting.
  196. //
  197. // We cannot touch the device (send it any non pnp irps) until a
  198. // start device has been passed down to the lower drivers.
  199. //
  200. status = PtSendIrpSynchronously(commonData->TopOfStack, Irp);
  201. if (NT_SUCCESS(status) && NT_SUCCESS(Irp->IoStatus.Status)) {
  202. //
  203. // As we are successfully now back from our start device
  204. // we can do work.
  205. ExAcquireFastMutexUnsafe(&Globals.DispatchMutex);
  206. if (commonData->Started) {
  207. Print(DBG_PNP_ERROR,
  208. ("received 1+ starts on %s\n",
  209. commonData->IsKeyboard ? "kb" : "mouse"
  210. ));
  211. }
  212. else {
  213. //
  214. // commonData->IsKeyboard is set during
  215. // IOCTL_INTERNAL_KEYBOARD_CONNECT to TRUE and
  216. // IOCTL_INTERNAL_MOUSE_CONNECT to FALSE
  217. //
  218. if (commonData->IsKeyboard) {
  219. status = PtKeyboardStartDevice(
  220. (PPORT_KEYBOARD_EXTENSION) DeviceObject->DeviceExtension,
  221. stack->Parameters.StartDevice.AllocatedResourcesTranslated
  222. );
  223. }
  224. else {
  225. status = PtMouseStartDevice(
  226. (PPORT_MOUSE_EXTENSION) DeviceObject->DeviceExtension,
  227. stack->Parameters.StartDevice.AllocatedResourcesTranslated
  228. );
  229. }
  230. if (NT_SUCCESS(status)) {
  231. commonData->Started = TRUE;
  232. }
  233. }
  234. ExReleaseFastMutexUnsafe(&Globals.DispatchMutex);
  235. }
  236. //
  237. // We must now complete the IRP, since we stopped it in the
  238. // completetion routine with MORE_PROCESSING_REQUIRED.
  239. //
  240. Irp->IoStatus.Status = status;
  241. Irp->IoStatus.Information = 0;
  242. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  243. break;
  244. case IRP_MN_QUERY_PNP_DEVICE_STATE:
  245. status = PtSendIrpSynchronously(commonData->TopOfStack, Irp);
  246. //
  247. // If the lower filter does not support this Irp, this is
  248. // OK, we can ignore this error
  249. //
  250. if (status == STATUS_NOT_SUPPORTED ||
  251. status == STATUS_INVALID_DEVICE_REQUEST) {
  252. status = STATUS_SUCCESS;
  253. }
  254. //
  255. // do stuff here...
  256. //
  257. if (NT_SUCCESS(status)) {
  258. if (commonData->ManuallyRemoved &&
  259. !(commonData->IsKeyboard ? KEYBOARD_PRESENT():MOUSE_PRESENT())) {
  260. commonData->Started = FALSE;
  261. (PNP_DEVICE_STATE) Irp->IoStatus.Information |=
  262. (PNP_DEVICE_REMOVED | PNP_DEVICE_DONT_DISPLAY_IN_UI);
  263. }
  264. //
  265. // In all cases this device must be disableable
  266. //
  267. (PNP_DEVICE_STATE) Irp->IoStatus.Information &= ~PNP_DEVICE_NOT_DISABLEABLE;
  268. //
  269. // Don't show it in the device manager
  270. //
  271. (PNP_DEVICE_STATE) Irp->IoStatus.Information |= PNP_DEVICE_DONT_DISPLAY_IN_UI;
  272. } else {
  273. Print(DBG_PNP_ERROR,
  274. ("error pending query pnp device state event (0x%x)\n",
  275. status
  276. ));
  277. }
  278. //
  279. // Irp->IoStatus.Information will contain the new i/o resource
  280. // requirements list so leave it alone
  281. //
  282. Irp->IoStatus.Status = status;
  283. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  284. break;
  285. //
  286. // Don't let either of the requests succeed, otherwise the kb/mouse
  287. // might be rendered useless.
  288. //
  289. // NOTE: this behavior is particular to i8042prt. Any other driver,
  290. // especially any other keyboard or port driver, should
  291. // succeed the query remove or stop. i8042prt has this different
  292. // behavior because of the shared I/O ports but independent interrupts.
  293. //
  294. // FURTHERMORE, if you allow the query to succeed, it should be sent
  295. // down the stack (see sermouse.sys for an example of how to do this)
  296. //
  297. case IRP_MN_QUERY_REMOVE_DEVICE:
  298. case IRP_MN_QUERY_STOP_DEVICE:
  299. status = (commonData->ManuallyRemoved ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
  300. Irp->IoStatus.Status = status;
  301. Irp->IoStatus.Information = 0;
  302. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  303. break;
  304. //
  305. // PnP rules dictate we send the IRP down to the PDO first
  306. //
  307. case IRP_MN_CANCEL_REMOVE_DEVICE:
  308. case IRP_MN_CANCEL_STOP_DEVICE:
  309. status = PtSendIrpSynchronously(commonData->TopOfStack, Irp);
  310. //
  311. // If the lower filter does not support this Irp, this is
  312. // OK, we can ignore this error
  313. //
  314. if (status == STATUS_NOT_SUPPORTED ||
  315. status == STATUS_INVALID_DEVICE_REQUEST) {
  316. status = STATUS_SUCCESS;
  317. }
  318. Irp->IoStatus.Status = status;
  319. Irp->IoStatus.Information = 0;
  320. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  321. break;
  322. case IRP_MN_REMOVE_DEVICE:
  323. Print(DBG_PNP_TRACE, ("remove device\n"));
  324. if (commonData->Started && !commonData->ManuallyRemoved) {
  325. //
  326. // This should never happen. The only way we can get a remove is if
  327. // a start has failed.
  328. //
  329. // NOTE: Again, this should never happen for i8042prt, but any
  330. // other input port driver should allow itself to be removed
  331. // (see sermouse.sys on how to do this correctly)
  332. //
  333. Print(DBG_PNP_ERROR, ("Cannot remove a started device!!!\n"));
  334. ASSERT(FALSE);
  335. }
  336. if (commonData->Initialized) {
  337. IoWMIRegistrationControl(commonData->Self,
  338. WMIREG_ACTION_DEREGISTER
  339. );
  340. }
  341. ExAcquireFastMutexUnsafe(&Globals.DispatchMutex);
  342. if (commonData->IsKeyboard) {
  343. PtKeyboardRemoveDevice(DeviceObject);
  344. }
  345. ExReleaseFastMutexUnsafe(&Globals.DispatchMutex);
  346. //
  347. // Nothing has been allocated or connected
  348. //
  349. IoSkipCurrentIrpStackLocation(Irp);
  350. IoCallDriver(commonData->TopOfStack, Irp);
  351. IoDetachDevice(commonData->TopOfStack);
  352. IoDeleteDevice(DeviceObject);
  353. status = STATUS_SUCCESS;
  354. break;
  355. case IRP_MN_STOP_DEVICE:
  356. case IRP_MN_QUERY_DEVICE_RELATIONS:
  357. case IRP_MN_QUERY_INTERFACE:
  358. case IRP_MN_QUERY_CAPABILITIES:
  359. case IRP_MN_QUERY_DEVICE_TEXT:
  360. case IRP_MN_QUERY_RESOURCES:
  361. case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
  362. case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
  363. case IRP_MN_READ_CONFIG:
  364. case IRP_MN_WRITE_CONFIG:
  365. case IRP_MN_EJECT:
  366. case IRP_MN_SET_LOCK:
  367. case IRP_MN_QUERY_ID:
  368. default:
  369. //
  370. // Here the driver below i8042prt might modify the behavior of these IRPS
  371. // Please see PlugPlay documentation for use of these IRPs.
  372. //
  373. IoSkipCurrentIrpStackLocation(Irp);
  374. status = IoCallDriver(commonData->TopOfStack, Irp);
  375. break;
  376. }
  377. Print(DBG_PNP_TRACE,
  378. ("PtPnP (%s) exit (status=0x%x)\n",
  379. commonData->IsKeyboard ? "kb" : "mou",
  380. status
  381. ));
  382. return status;
  383. }
  384. LONG
  385. PtManuallyRemoveDevice(
  386. PCOMMON_DATA CommonData
  387. )
  388. /*++
  389. Routine Description:
  390. Invalidates CommonData->PDO's device state and sets the manually removed
  391. flag
  392. Arguments:
  393. CommonData - represent either the keyboard or mouse
  394. Return Value:
  395. new device count for that particular type of device
  396. --*/
  397. {
  398. LONG deviceCount;
  399. PAGED_CODE();
  400. if (CommonData->IsKeyboard) {
  401. deviceCount = InterlockedDecrement(&Globals.AddedKeyboards);
  402. if (deviceCount < 1) {
  403. Print(DBG_PNP_INFO, ("clear kb (manually remove)\n"));
  404. CLEAR_KEYBOARD_PRESENT();
  405. }
  406. } else {
  407. deviceCount = InterlockedDecrement(&Globals.AddedMice);
  408. if (deviceCount < 1) {
  409. Print(DBG_PNP_INFO, ("clear mou (manually remove)\n"));
  410. CLEAR_MOUSE_PRESENT();
  411. }
  412. }
  413. CommonData->ManuallyRemoved = TRUE;
  414. IoInvalidateDeviceState(CommonData->PDO);
  415. return deviceCount;
  416. }
  417. NTSTATUS
  418. PtPower (
  419. IN PDEVICE_OBJECT DeviceObject,
  420. IN PIRP Irp
  421. )
  422. /*++
  423. Routine Description:
  424. This is the dispatch routine for power requests.
  425. Arguments:
  426. DeviceObject - Pointer to the device object.
  427. Irp - Pointer to the request packet.
  428. Return Value:
  429. STATUS_SUCCESSFUL if successful,
  430. an valid NTSTATUS error code otherwise
  431. --*/
  432. {
  433. PCOMMON_DATA commonData;
  434. PIO_STACK_LOCATION stack;
  435. NTSTATUS status = STATUS_SUCCESS;
  436. //PAGED_CODE();
  437. commonData = GET_COMMON_DATA(DeviceObject->DeviceExtension);
  438. stack = IoGetCurrentIrpStackLocation(Irp);
  439. Print(DBG_POWER_TRACE,
  440. ("Power (%s), enter\n",
  441. commonData->IsKeyboard ? "keyboard" :
  442. "mouse"
  443. ));
  444. switch(stack->MinorFunction) {
  445. case IRP_MN_WAIT_WAKE:
  446. Print(DBG_POWER_NOISE, ("Got IRP_MN_WAIT_WAKE\n" ));
  447. break;
  448. case IRP_MN_POWER_SEQUENCE:
  449. Print(DBG_POWER_NOISE, ("Got IRP_MN_POWER_SEQUENCE\n" ));
  450. break;
  451. case IRP_MN_SET_POWER:
  452. Print(DBG_POWER_NOISE, ("Got IRP_MN_SET_POWER\n" ));
  453. //
  454. // Don't handle anything but DevicePowerState changes
  455. //
  456. if (stack->Parameters.Power.Type != DevicePowerState) {
  457. Print(DBG_POWER_TRACE, ("not a device power irp\n"));
  458. break;
  459. }
  460. //
  461. // Check for no change in state, and if none, do nothing
  462. //
  463. if (stack->Parameters.Power.State.DeviceState ==
  464. commonData->PowerState) {
  465. Print(DBG_POWER_INFO,
  466. ("no change in state (PowerDeviceD%d)\n",
  467. commonData->PowerState-1
  468. ));
  469. break;
  470. }
  471. switch (stack->Parameters.Power.State.DeviceState) {
  472. case PowerDeviceD0:
  473. Print(DBG_POWER_TRACE, ("Powering up to PowerDeviceD0\n"));
  474. commonData->IsKeyboard ? KEYBOARD_POWERED_UP_STARTED()
  475. : MOUSE_POWERED_UP_STARTED();
  476. IoCopyCurrentIrpStackLocationToNext(Irp);
  477. IoSetCompletionRoutine(Irp,
  478. PtPowerUpToD0Complete,
  479. NULL,
  480. TRUE, // on success
  481. TRUE, // on error
  482. TRUE // on cancel
  483. );
  484. //
  485. // PoStartNextPowerIrp() gets called when the irp gets completed
  486. //
  487. IoMarkIrpPending(Irp);
  488. PoCallDriver(commonData->TopOfStack, Irp);
  489. return STATUS_PENDING;
  490. case PowerDeviceD1:
  491. case PowerDeviceD2:
  492. case PowerDeviceD3:
  493. Print(DBG_POWER_TRACE,
  494. ("Powering down to PowerDeviceD%d\n",
  495. stack->Parameters.Power.State.DeviceState-1
  496. ));
  497. PoSetPowerState(DeviceObject,
  498. stack->Parameters.Power.Type,
  499. stack->Parameters.Power.State
  500. );
  501. commonData->PowerState = stack->Parameters.Power.State.DeviceState;
  502. commonData->ShutdownType = stack->Parameters.Power.ShutdownType;
  503. //
  504. // For what we are doing, we don't need a completion routine
  505. // since we don't race on the power requests.
  506. //
  507. Irp->IoStatus.Status = STATUS_SUCCESS;
  508. IoCopyCurrentIrpStackLocationToNext(Irp); // skip ?
  509. PoStartNextPowerIrp(Irp);
  510. return PoCallDriver(commonData->TopOfStack, Irp);
  511. default:
  512. Print(DBG_POWER_INFO, ("unknown state\n"));
  513. break;
  514. }
  515. break;
  516. case IRP_MN_QUERY_POWER:
  517. Print(DBG_POWER_NOISE, ("Got IRP_MN_QUERY_POWER\n" ));
  518. break;
  519. default:
  520. Print(DBG_POWER_NOISE,
  521. ("Got unhandled minor function (%d)\n",
  522. stack->MinorFunction
  523. ));
  524. break;
  525. }
  526. Print(DBG_POWER_TRACE, ("Power, exit\n"));
  527. PoStartNextPowerIrp(Irp);
  528. IoSkipCurrentIrpStackLocation(Irp);
  529. return PoCallDriver(commonData->TopOfStack, Irp);
  530. }
  531. NTSTATUS
  532. PtPowerUpToD0Complete(
  533. IN PDEVICE_OBJECT DeviceObject,
  534. IN PIRP Irp,
  535. IN PVOID Context
  536. )
  537. /*++
  538. Routine Description:
  539. Reinitializes the i8042 haardware after any type of hibernation/sleep.
  540. Arguments:
  541. DeviceObject - Pointer to the device object
  542. Irp - Pointer to the request
  543. Context - Context passed in from the funciton that set the completion
  544. routine. UNUSED.
  545. Return Value:
  546. STATUS_SUCCESSFUL if successful,
  547. an valid NTSTATUS error code otherwise
  548. --*/
  549. {
  550. NTSTATUS status;
  551. PCOMMON_DATA commonData;
  552. PIO_STACK_LOCATION stack;
  553. KIRQL irql;
  554. UNREFERENCED_PARAMETER(Context);
  555. commonData = GET_COMMON_DATA(DeviceObject->DeviceExtension);
  556. Print(DBG_POWER_TRACE,
  557. ("PowerUpToD0Complete (%s), Enter\n",
  558. commonData->IsKeyboard ? "kb" : "mouse"
  559. ));
  560. KeAcquireSpinLock(&Globals.ControllerData->PowerUpSpinLock, &irql);
  561. if (NT_SUCCESS(Irp->IoStatus.Status)) {
  562. commonData->IsKeyboard ? KEYBOARD_POWERED_UP_SUCCESSFULLY()
  563. : MOUSE_POWERED_UP_SUCCESSFULLY();
  564. status = STATUS_MORE_PROCESSING_REQUIRED;
  565. }
  566. else {
  567. commonData->IsKeyboard ? KEYBOARD_POWERED_UP_FAILED()
  568. : MOUSE_POWERED_UP_FAILED();
  569. status = Irp->IoStatus.Status;
  570. #if DBG
  571. if (commonData->IsKeyboard) {
  572. ASSERT(MOUSE_POWERED_UP_FAILED());
  573. }
  574. else {
  575. ASSERT(KEYBOARD_POWERED_UP_FAILED());
  576. }
  577. #endif // DBG
  578. }
  579. KeReleaseSpinLock(&Globals.ControllerData->PowerUpSpinLock, irql);
  580. if (NT_SUCCESS(status)) {
  581. Print(DBG_SS_NOISE, ("reinit, status == 0x%x\n", status));
  582. stack = IoGetCurrentIrpStackLocation(Irp);
  583. ASSERT(stack->Parameters.Power.State.DeviceState == PowerDeviceD0);
  584. commonData->PowerState = stack->Parameters.Power.State.DeviceState;
  585. commonData->ShutdownType = PowerActionNone;
  586. PoSetPowerState(commonData->Self,
  587. stack->Parameters.Power.Type,
  588. stack->Parameters.Power.State
  589. );
  590. }
  591. //
  592. // Complete the irp
  593. //
  594. Irp->IoStatus.Status = status;
  595. Irp->IoStatus.Information = 0;
  596. PoStartNextPowerIrp(Irp);
  597. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  598. //
  599. // Reset PoweredDevices so that we can keep track of the powered device
  600. // the next time the machine is power managed off.
  601. //
  602. CLEAR_POWERUP_FLAGS();
  603. return status;
  604. }