Leaked source code of windows server 2003
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.

766 lines
21 KiB

  1. /*++
  2. Copyright (c) 1997-1998 Microsoft Corporation
  3. Module Name:
  4. apmpnp.c
  5. Abstract:
  6. This module contains contains the plugplay calls
  7. needed to make ntapm.sys work.
  8. Author:
  9. Bryan Willman
  10. Kenneth D. Ray
  11. Doron J. Holan
  12. Environment:
  13. kernel mode only
  14. Notes:
  15. Revision History:
  16. --*/
  17. #include <wdm.h>
  18. #include "ntapmp.h"
  19. #include "ntapmdbg.h"
  20. #include "ntapm.h"
  21. //#include "stdio.h"
  22. //
  23. // Globals
  24. //
  25. PDEVICE_OBJECT NtApm_ApmBatteryPdo = NULL;
  26. #ifdef ALLOC_PRAGMA
  27. #pragma alloc_text (PAGE, NtApm_AddDevice)
  28. #pragma alloc_text (PAGE, NtApm_PnP)
  29. #pragma alloc_text (PAGE, NtApm_FDO_PnP)
  30. #pragma alloc_text (PAGE, NtApm_PDO_PnP)
  31. #pragma alloc_text (PAGE, NtApm_Power)
  32. #pragma alloc_text (PAGE, NtApm_FDO_Power)
  33. #pragma alloc_text (PAGE, NtApm_PDO_Power)
  34. #pragma alloc_text (PAGE, NtApm_CreatePdo)
  35. #pragma alloc_text (PAGE, NtApm_InitializePdo)
  36. #endif
  37. NTSTATUS
  38. NtApm_AddDevice(
  39. IN PDRIVER_OBJECT DriverObject,
  40. IN PDEVICE_OBJECT BusPhysicalDeviceObject
  41. )
  42. /*++
  43. Routine Description.
  44. A bus has been found. Attach our FDO to it.
  45. Allocate any required resources. Set things up. And be prepared for the
  46. first ``start device.''
  47. Arguments:
  48. BusDeviceObject - Device object representing the bus. That to which we
  49. attach a new FDO.
  50. DriverObject - This very self referenced driver.
  51. --*/
  52. {
  53. NTSTATUS status;
  54. PDEVICE_OBJECT deviceObject;
  55. PFDO_DEVICE_DATA deviceData;
  56. UNICODE_STRING deviceNameUni;
  57. PWCHAR deviceName;
  58. ULONG nameLength;
  59. PAGED_CODE ();
  60. DrDebug(PNP_INFO, ("ntapm Add Device: 0x%x\n", BusPhysicalDeviceObject));
  61. status = IoCreateDevice (
  62. DriverObject, // our driver object
  63. sizeof (FDO_DEVICE_DATA), // device object extension size
  64. NULL, // FDOs do not have names
  65. FILE_DEVICE_BUS_EXTENDER,
  66. 0, // No special characteristics
  67. TRUE, // our FDO is exclusive
  68. &deviceObject); // The device object created
  69. if (!NT_SUCCESS (status)) {
  70. return status;
  71. }
  72. deviceData = (PFDO_DEVICE_DATA) deviceObject->DeviceExtension;
  73. RtlFillMemory (deviceData, sizeof (FDO_DEVICE_DATA), 0);
  74. deviceData->IsFDO = TRUE;
  75. deviceData->Self = deviceObject;
  76. deviceData->UnderlyingPDO = BusPhysicalDeviceObject;
  77. //
  78. // Attach our filter driver to the device stack.
  79. // the return value of IoAttachDeviceToDeviceStack is the top of the
  80. // attachment chain. This is where all the IRPs should be routed.
  81. //
  82. // Our filter will send IRPs to the top of the stack and use the PDO
  83. // for all PlugPlay functions.
  84. //
  85. deviceData->TopOfStack = IoAttachDeviceToDeviceStack (
  86. deviceObject,
  87. BusPhysicalDeviceObject
  88. );
  89. if (!deviceData->TopOfStack) {
  90. IoDeleteDevice(deviceObject);
  91. return STATUS_UNSUCCESSFUL;
  92. }
  93. status = ApmAddHelper();
  94. if (!NT_SUCCESS(status)) {
  95. IoDetachDevice(deviceData->TopOfStack);
  96. IoDeleteDevice(deviceObject);
  97. }
  98. deviceObject->Flags |= DO_POWER_PAGABLE;
  99. deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  100. return status;
  101. }
  102. NTSTATUS
  103. NtApm_FDO_PnPComplete (
  104. IN PDEVICE_OBJECT DeviceObject,
  105. IN PIRP Pirp,
  106. IN PVOID Context
  107. );
  108. NTSTATUS
  109. NtApm_PnP (
  110. IN PDEVICE_OBJECT DeviceObject,
  111. IN PIRP Irp
  112. )
  113. /*++
  114. Routine Description:
  115. Answer the plithera of Irp Major PnP IRPS.
  116. --*/
  117. {
  118. PIO_STACK_LOCATION irpStack;
  119. NTSTATUS status;
  120. PCOMMON_DEVICE_DATA commonData;
  121. KIRQL oldIrq;
  122. PAGED_CODE ();
  123. status = STATUS_SUCCESS;
  124. irpStack = IoGetCurrentIrpStackLocation (Irp);
  125. ASSERT (IRP_MJ_PNP == irpStack->MajorFunction);
  126. commonData = (PCOMMON_DEVICE_DATA) DeviceObject->DeviceExtension;
  127. if (commonData->IsFDO) {
  128. DrDebug(PNP_INFO, ("ntapm PNP: Functional DO: %x IRP: %x\n", DeviceObject, Irp));
  129. status = NtApm_FDO_PnP (
  130. DeviceObject,
  131. Irp,
  132. irpStack,
  133. (PFDO_DEVICE_DATA) commonData);
  134. } else {
  135. DrDebug(PNP_INFO, ("ntapm: PNP: Physical DO: %x IRP: %x\n", DeviceObject, Irp));
  136. status = NtApm_PDO_PnP (
  137. DeviceObject,
  138. Irp,
  139. irpStack,
  140. (PPDO_DEVICE_DATA) commonData);
  141. }
  142. return status;
  143. }
  144. NTSTATUS
  145. NtApm_FDO_PnP (
  146. IN PDEVICE_OBJECT DeviceObject,
  147. IN PIRP Irp,
  148. IN PIO_STACK_LOCATION IrpStack,
  149. IN PFDO_DEVICE_DATA DeviceData
  150. )
  151. /*++
  152. Routine Description:
  153. Handle requests from the PlugPlay system for the BUS itself
  154. NB: the various Minor functions of the PlugPlay system will not be
  155. overlapped and do not have to be reentrant
  156. --*/
  157. {
  158. NTSTATUS status;
  159. KIRQL irql;
  160. KEVENT event;
  161. ULONG length;
  162. ULONG i;
  163. PLIST_ENTRY entry;
  164. PPDO_DEVICE_DATA pdoData;
  165. PDEVICE_RELATIONS relations;
  166. PIO_STACK_LOCATION stack;
  167. ULONG battresult;
  168. PAGED_CODE ();
  169. stack = IoGetCurrentIrpStackLocation (Irp);
  170. switch (IrpStack->MinorFunction) {
  171. case IRP_MN_START_DEVICE:
  172. //
  173. // BEFORE you are allowed to ``touch'' the device object to which
  174. // the FDO is attached (that send an irp from the bus to the Device
  175. // object to which the bus is attached). You must first pass down
  176. // the start IRP. It might not be powered on, or able to access or
  177. // something.
  178. //
  179. DrDebug(PNP_INFO, ("ntapm: Start Device\n"));
  180. KeInitializeEvent (&event, NotificationEvent, FALSE);
  181. IoCopyCurrentIrpStackLocationToNext (Irp);
  182. IoSetCompletionRoutine (Irp,
  183. NtApm_FDO_PnPComplete,
  184. &event,
  185. TRUE,
  186. TRUE,
  187. TRUE);
  188. status = IoCallDriver (DeviceData->TopOfStack, Irp);
  189. if (STATUS_PENDING == status) {
  190. // wait for it...
  191. status = KeWaitForSingleObject (&event,
  192. Executive,
  193. KernelMode,
  194. FALSE, // Not allertable
  195. NULL); // No timeout structure
  196. ASSERT (STATUS_SUCCESS == status);
  197. status = Irp->IoStatus.Status;
  198. }
  199. //
  200. // We must now complete the IRP, since we stopped it in the
  201. // completetion routine with MORE_PROCESSING_REQUIRED.
  202. //
  203. break;
  204. case IRP_MN_QUERY_DEVICE_RELATIONS:
  205. if (IrpStack->Parameters.QueryDeviceRelations.Type != BusRelations) {
  206. //
  207. // We don't support this
  208. //
  209. goto NtApm_FDO_PNP_DEFAULT;
  210. }
  211. //
  212. // In theory, APM should be fired up by now.
  213. // So call off into it to see if there is any sign
  214. // of a battery on the box. If there is NOT, don't
  215. // export the PDOs for the battery objects
  216. //
  217. battresult = DoApmReportBatteryStatus();
  218. if (battresult & NTAPM_NO_SYS_BATT) {
  219. //
  220. // it appears that the machine does not have
  221. // a battery. so don't export battery driver PDOs.
  222. //
  223. Irp->IoStatus.Status = STATUS_SUCCESS;
  224. IoSkipCurrentIrpStackLocation(Irp);
  225. return IoCallDriver(DeviceData->TopOfStack, Irp);
  226. }
  227. DrDebug(PNP_INFO, ("ntapm: Query Relations "));
  228. //
  229. // create PDO for apm battery
  230. //
  231. if (NtApm_ApmBatteryPdo == NULL) {
  232. status = NtApm_CreatePdo(
  233. DeviceData,
  234. NTAPM_PDO_NAME_APM_BATTERY,
  235. &NtApm_ApmBatteryPdo
  236. );
  237. if (!NT_SUCCESS(status)) {
  238. goto NtApm_DONE;
  239. }
  240. }
  241. NtApm_InitializePdo(NtApm_ApmBatteryPdo, DeviceData, NTAPM_ID_APM_BATTERY);
  242. //
  243. // Tell PNP about our two child PDOs.
  244. //
  245. i = (Irp->IoStatus.Information == 0) ? 0 :
  246. ((PDEVICE_RELATIONS) Irp->IoStatus.Information)->Count;
  247. //
  248. // above should be count of PDOs
  249. // make a new structure and our PDO to the end
  250. //
  251. //
  252. // Need to allocate a new relations structure and add our
  253. // PDOs to it.
  254. //
  255. length = sizeof(DEVICE_RELATIONS) + ((i + 1) * sizeof (PDEVICE_OBJECT));
  256. relations = (PDEVICE_RELATIONS) ExAllocatePool (NonPagedPool, length);
  257. if (relations == NULL) {
  258. status = STATUS_INSUFFICIENT_RESOURCES;
  259. goto NtApm_DONE;
  260. }
  261. //
  262. // Copy in the device objects so far
  263. //
  264. if (i) {
  265. RtlCopyMemory (
  266. relations->Objects,
  267. ((PDEVICE_RELATIONS) Irp->IoStatus.Information)->Objects,
  268. i * sizeof (PDEVICE_OBJECT));
  269. }
  270. relations->Count = i + 1;
  271. //
  272. // add the apm battery PDO to the list
  273. //
  274. ObReferenceObject(NtApm_ApmBatteryPdo);
  275. relations->Objects[i] = NtApm_ApmBatteryPdo;
  276. //
  277. // Replace the relations structure in the IRP with the new
  278. // one.
  279. //
  280. if (Irp->IoStatus.Information != 0) {
  281. ExFreePool ((PVOID) Irp->IoStatus.Information);
  282. }
  283. Irp->IoStatus.Information = (ULONG) relations;
  284. //
  285. // Set up and pass the IRP further down the stack
  286. //
  287. Irp->IoStatus.Status = STATUS_SUCCESS;
  288. IoSkipCurrentIrpStackLocation (Irp);
  289. status = IoCallDriver (DeviceData->TopOfStack, Irp);
  290. return status;
  291. break;
  292. case IRP_MN_QUERY_STOP_DEVICE:
  293. case IRP_MN_STOP_DEVICE:
  294. case IRP_MN_REMOVE_DEVICE:
  295. case IRP_MN_QUERY_REMOVE_DEVICE:
  296. status = STATUS_UNSUCCESSFUL;
  297. break;
  298. case IRP_MN_CANCEL_REMOVE_DEVICE:
  299. case IRP_MN_CANCEL_STOP_DEVICE:
  300. Irp->IoStatus.Status = STATUS_SUCCESS; // we're lying, it's more like noop
  301. IoSkipCurrentIrpStackLocation(Irp);
  302. return IoCallDriver (DeviceData->TopOfStack, Irp);
  303. break;
  304. NtApm_FDO_PNP_DEFAULT:
  305. default:
  306. //
  307. // In the default case we merely call the next driver since
  308. // we don't know what to do.
  309. //
  310. IoSkipCurrentIrpStackLocation (Irp);
  311. return IoCallDriver (DeviceData->TopOfStack, Irp);
  312. }
  313. NtApm_DONE:
  314. Irp->IoStatus.Status = status;
  315. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  316. return status;
  317. }
  318. NTSTATUS
  319. NtApm_FDO_PnPComplete (
  320. IN PDEVICE_OBJECT DeviceObject,
  321. IN PIRP Irp,
  322. IN PVOID Context
  323. )
  324. /*++
  325. Routine Description:
  326. A completion routine for use when calling the lower device objects to
  327. which our bus (FDO) is attached.
  328. --*/
  329. {
  330. UNREFERENCED_PARAMETER (DeviceObject);
  331. UNREFERENCED_PARAMETER (Irp);
  332. KeSetEvent ((PKEVENT) Context, 1, FALSE);
  333. // No special priority
  334. // No Wait
  335. return STATUS_MORE_PROCESSING_REQUIRED; // Keep this IRP
  336. }
  337. NTSTATUS
  338. NtApm_PDO_PnP (
  339. IN PDEVICE_OBJECT DeviceObject,
  340. IN PIRP Irp,
  341. IN PIO_STACK_LOCATION IrpStack,
  342. IN PPDO_DEVICE_DATA DeviceData
  343. )
  344. /*++
  345. Routine Description:
  346. Handle requests from the PlugPlay system for the devices on the BUS
  347. --*/
  348. {
  349. PDEVICE_CAPABILITIES deviceCapabilities;
  350. ULONG information;
  351. PWCHAR buffer, buffer2;
  352. ULONG length, length2, i, j;
  353. NTSTATUS status;
  354. KIRQL oldIrq;
  355. PDEVICE_RELATIONS relations;
  356. PAGED_CODE ();
  357. status = Irp->IoStatus.Status;
  358. //
  359. // NB: since we are a bus enumerator, we have no one to whom we could
  360. // defer these irps. Therefore we do not pass them down but merely
  361. // return them.
  362. //
  363. switch (IrpStack->MinorFunction) {
  364. case IRP_MN_QUERY_CAPABILITIES:
  365. DrDebug(PNP_INFO, ("ntapm: Query Caps \n"));
  366. //
  367. // Get the packet.
  368. //
  369. deviceCapabilities = IrpStack->Parameters.DeviceCapabilities.Capabilities;
  370. deviceCapabilities->UniqueID = FALSE;
  371. status = STATUS_SUCCESS;
  372. break;
  373. case IRP_MN_QUERY_ID:
  374. // Query the IDs of the device
  375. DrDebug(PNP_INFO, ("ntapm: QueryID: 0x%x\n", IrpStack->Parameters.QueryId.IdType));
  376. switch (IrpStack->Parameters.QueryId.IdType) {
  377. case BusQueryDeviceID:
  378. // this can be the same as the hardware ids (which requires a multi
  379. // sz) ... we are just allocating more than enough memory
  380. case BusQueryHardwareIDs:
  381. // return a multi WCHAR (null terminated) string (null terminated)
  382. // array for use in matching hardare ids in inf files;
  383. //
  384. buffer = DeviceData->HardwareIDs;
  385. while (*(buffer++)) {
  386. while (*(buffer++)) {
  387. ;
  388. }
  389. }
  390. length = (buffer - DeviceData->HardwareIDs) * sizeof (WCHAR);
  391. buffer = ExAllocatePool (PagedPool, length);
  392. if (buffer) {
  393. RtlCopyMemory (buffer, DeviceData->HardwareIDs, length);
  394. Irp->IoStatus.Information = (ULONG) buffer;
  395. status = STATUS_SUCCESS;
  396. } else {
  397. status = STATUS_INSUFFICIENT_RESOURCES;
  398. }
  399. break;
  400. case BusQueryInstanceID:
  401. //
  402. // Build an instance ID. This is what PnP uses to tell if it has
  403. // seen this thing before or not.
  404. //
  405. //
  406. // return 0000 for all devices and have the flag set to not unique
  407. //
  408. length = APM_INSTANCE_IDS_LENGTH * sizeof(WCHAR);
  409. buffer = ExAllocatePool(PagedPool, length);
  410. if (buffer != NULL) {
  411. RtlCopyMemory(buffer, APM_INSTANCE_IDS, length);
  412. Irp->IoStatus.Information = (ULONG_PTR)buffer;
  413. status = STATUS_SUCCESS;
  414. } else {
  415. status = STATUS_INSUFFICIENT_RESOURCES;
  416. }
  417. break;
  418. case BusQueryCompatibleIDs:
  419. // The generic ids for installation of this pdo.
  420. break;
  421. }
  422. break;
  423. case IRP_MN_START_DEVICE:
  424. DrDebug(PNP_INFO, ("ntapm: Start Device \n"));
  425. // Here we do what ever initialization and ``turning on'' that is
  426. // required to allow others to access this device.
  427. status = STATUS_SUCCESS;
  428. break;
  429. case IRP_MN_STOP_DEVICE:
  430. case IRP_MN_REMOVE_DEVICE:
  431. case IRP_MN_QUERY_STOP_DEVICE:
  432. case IRP_MN_QUERY_REMOVE_DEVICE:
  433. DrDebug(PNP_INFO, ("ntapm: remove, stop, or Q remove or Q stop\n"));
  434. //
  435. // disallow Stop or Remove, since we don't want to test
  436. // disengagement from APM if we don't have to
  437. //
  438. status = STATUS_UNSUCCESSFUL;
  439. break;
  440. case IRP_MN_CANCEL_STOP_DEVICE:
  441. case IRP_MN_CANCEL_REMOVE_DEVICE:
  442. DrDebug(PNP_INFO, ("ntapm: Cancel Stop Device or Cancel Remove \n"));
  443. status = STATUS_SUCCESS; // more like "noop" than success
  444. break;
  445. case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
  446. break;
  447. case IRP_MN_QUERY_DEVICE_RELATIONS:
  448. if (IrpStack->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation) {
  449. //
  450. // Somebody else can handle this.
  451. //
  452. break;
  453. }
  454. ASSERT(((PULONG_PTR)Irp->IoStatus.Information) == NULL);
  455. relations = (PDEVICE_RELATIONS) ExAllocatePool(PagedPool, sizeof(DEVICE_RELATIONS));
  456. if (relations == NULL) {
  457. status = STATUS_INSUFFICIENT_RESOURCES;
  458. } else {
  459. Irp->IoStatus.Information = (ULONG_PTR) relations;
  460. relations->Count = 1;
  461. relations->Objects[0] = DeviceObject;
  462. ObReferenceObject(DeviceObject);
  463. status = STATUS_SUCCESS;
  464. }
  465. break;
  466. case IRP_MN_READ_CONFIG:
  467. case IRP_MN_WRITE_CONFIG: // we have no config space
  468. case IRP_MN_EJECT:
  469. case IRP_MN_SET_LOCK:
  470. case IRP_MN_QUERY_INTERFACE: // We do not have any non IRP based interfaces.
  471. default:
  472. DrDebug(PNP_INFO, ("ntapm: PNP Not handled 0x%x\n", IrpStack->MinorFunction));
  473. // this is a leaf node
  474. // status = STATUS_NOT_IMPLEMENTED
  475. // For PnP requests to the PDO that we do not understand we should
  476. // return the IRP WITHOUT setting the status or information fields.
  477. // They may have already been set by a filter (eg acpi).
  478. break;
  479. }
  480. Irp->IoStatus.Status = status;
  481. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  482. return status;
  483. }
  484. NTSTATUS
  485. NtApm_CreatePdo (
  486. PFDO_DEVICE_DATA FdoData,
  487. PWCHAR PdoName,
  488. PDEVICE_OBJECT * PDO
  489. )
  490. {
  491. UNICODE_STRING pdoUniName;
  492. NTSTATUS status;
  493. PAGED_CODE ();
  494. //DbgBreakPoint();
  495. //
  496. // Create the PDOs
  497. //
  498. RtlInitUnicodeString (&pdoUniName, PdoName);
  499. DrDebug(PNP_INFO, ("ntapm: CreatePdo: PDO Name: %ws\n", PdoName));
  500. status = IoCreateDevice(
  501. FdoData->Self->DriverObject,
  502. sizeof (PDO_DEVICE_DATA),
  503. &pdoUniName,
  504. FILE_DEVICE_BUS_EXTENDER,
  505. 0,
  506. FALSE,
  507. PDO
  508. );
  509. DrDebug(PNP_L2, ("ntapm: CreatePdo: status = %08lx\n", status));
  510. if (!NT_SUCCESS (status)) {
  511. *PDO = NULL;
  512. }
  513. return status;
  514. }
  515. VOID
  516. NtApm_InitializePdo(
  517. PDEVICE_OBJECT Pdo,
  518. PFDO_DEVICE_DATA FdoData,
  519. PWCHAR Id
  520. )
  521. {
  522. PPDO_DEVICE_DATA pdoData;
  523. PAGED_CODE ();
  524. pdoData = (PPDO_DEVICE_DATA) Pdo->DeviceExtension;
  525. DrDebug(PNP_INFO, ("ntapm: pdo 0x%x, extension 0x%x\n", Pdo, pdoData));
  526. //
  527. // Initialize the rest
  528. //
  529. pdoData->IsFDO = FALSE;
  530. pdoData->Self = Pdo;
  531. pdoData->ParentFdo = FdoData->Self;
  532. pdoData->HardwareIDs = Id;
  533. pdoData->UniqueID = 1;
  534. Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
  535. Pdo->Flags |= DO_POWER_PAGABLE;
  536. }
  537. NTSTATUS
  538. NtApm_Power (
  539. IN PDEVICE_OBJECT DeviceObject,
  540. IN PIRP Irp
  541. )
  542. /*++
  543. We do nothing special for power;
  544. --*/
  545. {
  546. PIO_STACK_LOCATION irpStack;
  547. NTSTATUS status;
  548. PCOMMON_DEVICE_DATA commonData;
  549. PAGED_CODE ();
  550. status = STATUS_SUCCESS;
  551. irpStack = IoGetCurrentIrpStackLocation (Irp);
  552. ASSERT (IRP_MJ_POWER == irpStack->MajorFunction);
  553. commonData = (PCOMMON_DEVICE_DATA) DeviceObject->DeviceExtension;
  554. if (commonData->IsFDO) {
  555. status = NtApm_FDO_Power ((PFDO_DEVICE_DATA) DeviceObject->DeviceExtension,Irp);
  556. } else {
  557. status = NtApm_PDO_Power ((PPDO_DEVICE_DATA) DeviceObject->DeviceExtension,Irp);
  558. }
  559. return status;
  560. }
  561. NTSTATUS
  562. NtApm_FDO_Power (
  563. PFDO_DEVICE_DATA Data,
  564. PIRP Irp
  565. )
  566. {
  567. PIO_STACK_LOCATION stack;
  568. PAGED_CODE ();
  569. PoStartNextPowerIrp(Irp);
  570. IoSkipCurrentIrpStackLocation(Irp);
  571. return PoCallDriver(Data->TopOfStack, Irp);
  572. }
  573. NTSTATUS
  574. NtApm_PDO_Power (
  575. PPDO_DEVICE_DATA PdoData,
  576. PIRP Irp
  577. )
  578. {
  579. NTSTATUS status = STATUS_SUCCESS;
  580. PIO_STACK_LOCATION stack;
  581. stack = IoGetCurrentIrpStackLocation (Irp);
  582. switch (stack->MinorFunction) {
  583. case IRP_MN_SET_POWER:
  584. if ((stack->Parameters.Power.Type == SystemPowerState) &&
  585. (stack->Parameters.Power.State.SystemState == PowerSystemWorking))
  586. {
  587. //
  588. // system has just returned to the working state
  589. // assert the user is present (they must be for the APM case)
  590. // so that the display will light up, idle timers behave, etc.
  591. //
  592. PoSetSystemState(ES_USER_PRESENT);
  593. }
  594. status = STATUS_SUCCESS;
  595. break;
  596. case IRP_MN_QUERY_POWER:
  597. status = STATUS_SUCCESS;
  598. break;
  599. case IRP_MN_WAIT_WAKE:
  600. case IRP_MN_POWER_SEQUENCE:
  601. default:
  602. status = Irp->IoStatus.Status;
  603. break;
  604. }
  605. Irp->IoStatus.Status = status;
  606. PoStartNextPowerIrp(Irp);
  607. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  608. return status;
  609. }