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.

3205 lines
91 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. wmimap.c
  5. Abstract:
  6. ACPI to WMI mapping layer
  7. Author:
  8. Alan Warwick
  9. Environment:
  10. Kernel mode
  11. Revision History:
  12. --*/
  13. #define INITGUID
  14. #include <wdm.h>
  15. #ifdef MEMPHIS
  16. //
  17. // Lifted from ntrtl.h
  18. NTSYSAPI
  19. ULONG
  20. NTAPI
  21. RtlxUnicodeStringToAnsiSize(
  22. PUNICODE_STRING UnicodeString
  23. );
  24. //
  25. // NTSYSAPI
  26. // ULONG
  27. // NTAPI
  28. // RtlUnicodeStringToAnsiSize(
  29. // PUNICODE_STRING UnicodeString
  30. // );
  31. //
  32. #define RtlUnicodeStringToAnsiSize(STRING) ( \
  33. NLS_MB_CODE_PAGE_TAG ? \
  34. RtlxUnicodeStringToAnsiSize(STRING) : \
  35. ((STRING)->Length + sizeof(UNICODE_NULL)) / sizeof(WCHAR) \
  36. )
  37. #endif
  38. #include <devioctl.h>
  39. #include <acpiioct.h>
  40. #include <wmistr.h>
  41. #include <wmilib.h>
  42. #include <wdmguid.h>
  43. #include "wmimap.h"
  44. NTSTATUS
  45. DriverEntry(
  46. IN PDRIVER_OBJECT DriverObject,
  47. IN PUNICODE_STRING RegistryPath
  48. );
  49. NTSTATUS
  50. WmiAcpiPowerDispatch(
  51. IN PDEVICE_OBJECT DeviceObject,
  52. IN PIRP Irp
  53. );
  54. NTSTATUS
  55. WmiAcpiSystemControlDispatch(
  56. IN PDEVICE_OBJECT DeviceObject,
  57. IN PIRP Irp
  58. );
  59. NTSTATUS
  60. WmiAcpiPnP(
  61. IN PDEVICE_OBJECT DeviceObject,
  62. IN PIRP Irp
  63. );
  64. NTSTATUS
  65. WmiAcpiForwardIrp(
  66. IN PDEVICE_OBJECT DeviceObject,
  67. IN PIRP Irp
  68. );
  69. VOID
  70. WmiAcpiUnload(
  71. IN PDRIVER_OBJECT DriverObject
  72. );
  73. NTSTATUS
  74. WmiAcpiAddDevice(
  75. IN PDRIVER_OBJECT DriverObject,
  76. IN PDEVICE_OBJECT PhysicalDeviceObject
  77. );
  78. NTSTATUS
  79. WmiAcpiSynchronousRequest (
  80. IN PDEVICE_OBJECT DeviceObject,
  81. IN PIRP Irp,
  82. IN PVOID Context
  83. );
  84. NTSTATUS
  85. WmiAcpiGetAcpiInterfaces(
  86. IN PDEVICE_EXTENSION DeviceExtension,
  87. IN PDEVICE_OBJECT Pdo
  88. );
  89. NTSTATUS
  90. WmiAcpiCheckIncomingString(
  91. PUNICODE_STRING UnicodeString,
  92. ULONG BufferSize,
  93. PUCHAR Buffer,
  94. PWCHAR EmptyString
  95. );
  96. VOID
  97. WmiAcpiNotificationWorkItem(
  98. IN PVOID Context
  99. );
  100. VOID
  101. WmiAcpiNotificationRoutine (
  102. IN PVOID Context,
  103. IN ULONG NotifyValue
  104. );
  105. CHAR WmiAcpiXtoA(
  106. UCHAR HexDigit
  107. );
  108. NTSTATUS
  109. WmiAcpiAsyncEvalCompletionRoutine(
  110. IN PDEVICE_OBJECT DeviceObject,
  111. IN PIRP Irp,
  112. IN PVOID Context
  113. );
  114. NTSTATUS
  115. WmiAcpiSendAsyncDownStreamIrp(
  116. IN PDEVICE_OBJECT DeviceObject,
  117. IN PDEVICE_OBJECT Pdo,
  118. IN ULONG Ioctl,
  119. IN ULONG InputBufferSize,
  120. IN ULONG OutputBufferSize,
  121. IN PVOID Buffer,
  122. IN PWORKER_THREAD_ROUTINE CompletionRoutine,
  123. IN PVOID CompletionContext,
  124. IN PBOOLEAN IrpPassed
  125. );
  126. NTSTATUS
  127. WmiAcpiSendDownStreamIrp(
  128. IN PDEVICE_OBJECT Pdo,
  129. IN ULONG Ioctl,
  130. IN PVOID InputBuffer,
  131. IN ULONG InputSize,
  132. IN PVOID OutputBuffer,
  133. IN ULONG *OutputBufferSize
  134. );
  135. ULONG WmiAcpiArgumentSize(
  136. IN PACPI_METHOD_ARGUMENT Argument
  137. );
  138. NTSTATUS WmiAcpiCopyArgument(
  139. OUT PUCHAR Buffer,
  140. IN ULONG BufferSize,
  141. IN PACPI_METHOD_ARGUMENT Argument
  142. );
  143. NTSTATUS WmiAcpiProcessResult(
  144. IN NTSTATUS Status,
  145. IN PACPI_EVAL_OUTPUT_BUFFER OutputBuffer,
  146. IN ULONG OutputBufferSize,
  147. OUT PUCHAR ResultBuffer,
  148. OUT ULONG *ResultSize,
  149. OUT USHORT *ResultType
  150. );
  151. NTSTATUS WmiAcpiSendMethodEvalIrp(
  152. IN PDEVICE_OBJECT DeviceObject,
  153. IN PUCHAR InputBuffer,
  154. IN ULONG InputBufferSize,
  155. OUT PUCHAR ResultBuffer,
  156. IN OUT ULONG *ResultSize,
  157. OUT USHORT *ResultType
  158. );
  159. NTSTATUS WmiAcpiEvalMethod(
  160. IN PDEVICE_OBJECT DeviceObject,
  161. IN ULONG MethodAsUlong,
  162. OUT PUCHAR ResultBuffer,
  163. IN OUT ULONG *ResultSize,
  164. OUT USHORT *ResultType
  165. );
  166. NTSTATUS WmiAcpiEvalMethodInt(
  167. IN PDEVICE_OBJECT DeviceObject,
  168. IN ULONG MethodAsUlong,
  169. IN ULONG IntegerArgument,
  170. OUT PUCHAR ResultBuffer,
  171. IN OUT ULONG *ResultSize,
  172. OUT USHORT *ResultType
  173. );
  174. NTSTATUS WmiAcpiEvalMethodIntBuffer(
  175. IN PDEVICE_OBJECT DeviceObject,
  176. IN ULONG MethodAsUlong,
  177. IN ULONG IntegerArgument,
  178. IN ULONG BufferArgumentSize,
  179. IN PUCHAR BufferArgument,
  180. OUT PUCHAR ResultBuffer,
  181. IN OUT ULONG *ResultSize,
  182. OUT USHORT *ResultType
  183. );
  184. NTSTATUS WmiAcpiEvalMethodIntIntBuffer(
  185. IN PDEVICE_OBJECT DeviceObject,
  186. IN ULONG MethodAsUlong,
  187. IN ULONG IntegerArgument,
  188. IN ULONG IntegerArgument2,
  189. IN ULONG BufferArgumentSize,
  190. IN PUCHAR BufferArgument,
  191. OUT PUCHAR ResultBuffer,
  192. IN OUT ULONG *ResultSize,
  193. OUT USHORT *ResultType
  194. );
  195. NTSTATUS WmiAcpiEvalMethodIntString(
  196. IN PDEVICE_OBJECT DeviceObject,
  197. IN ULONG MethodAsUlong,
  198. IN ULONG IntegerArgument,
  199. IN PUNICODE_STRING StringArgument,
  200. OUT PUCHAR ResultBuffer,
  201. IN OUT ULONG *ResultSize,
  202. OUT USHORT *ResultType
  203. );
  204. NTSTATUS WmiAcpiEvalMethodIntIntString(
  205. IN PDEVICE_OBJECT DeviceObject,
  206. IN ULONG MethodAsUlong,
  207. IN ULONG IntegerArgument,
  208. IN ULONG IntegerArgument2,
  209. IN PUNICODE_STRING StringArgument,
  210. OUT PUCHAR ResultBuffer,
  211. IN OUT ULONG *ResultSize,
  212. OUT USHORT *ResultType
  213. );
  214. NTSTATUS WmiAcpiEvalMethodIntAsync(
  215. IN PDEVICE_OBJECT DeviceObject,
  216. IN PDEVICE_OBJECT Pdo,
  217. IN ULONG MethodAsUlong,
  218. IN ULONG IntegerArgument,
  219. OUT PUCHAR ResultBuffer,
  220. IN ULONG ResultBufferSize,
  221. IN PWORKER_THREAD_ROUTINE CompletionRoutine,
  222. IN PVOID CompletionContext,
  223. IN PBOOLEAN IrpPassed
  224. );
  225. NTSTATUS
  226. WmiAcpiQueryWmiRegInfo(
  227. IN PDEVICE_OBJECT DeviceObject,
  228. OUT ULONG *RegFlags,
  229. OUT PUNICODE_STRING InstanceName,
  230. OUT PUNICODE_STRING *RegistryPath,
  231. OUT PUNICODE_STRING MofResourceName,
  232. OUT PDEVICE_OBJECT *Pdo
  233. );
  234. NTSTATUS
  235. WmiAcpiQueryWmiDataBlock(
  236. IN PDEVICE_OBJECT DeviceObject,
  237. IN PIRP Irp,
  238. IN ULONG GuidIndex,
  239. IN ULONG InstanceIndex,
  240. IN ULONG InstanceCount,
  241. IN OUT PULONG InstanceLengthArray,
  242. IN ULONG BufferAvail,
  243. OUT PUCHAR Buffer
  244. );
  245. NTSTATUS
  246. WmiAcpiSetWmiDataBlock(
  247. IN PDEVICE_OBJECT DeviceObject,
  248. IN PIRP Irp,
  249. IN ULONG GuidIndex,
  250. IN ULONG InstanceIndex,
  251. IN ULONG BufferSize,
  252. IN PUCHAR Buffer
  253. );
  254. NTSTATUS
  255. WmiAcpiSetWmiDataItem(
  256. IN PDEVICE_OBJECT DeviceObject,
  257. IN PIRP Irp,
  258. IN ULONG GuidIndex,
  259. IN ULONG InstanceIndex,
  260. IN ULONG DataItemId,
  261. IN ULONG BufferSize,
  262. IN PUCHAR Buffer
  263. );
  264. NTSTATUS
  265. WmiAcpiExecuteWmiMethod(
  266. IN PDEVICE_OBJECT DeviceObject,
  267. IN PIRP Irp,
  268. IN ULONG GuidIndex,
  269. IN ULONG InstanceIndex,
  270. IN ULONG MethodId,
  271. IN ULONG InBufferSize,
  272. IN ULONG OutBufferSize,
  273. IN PUCHAR Buffer
  274. );
  275. NTSTATUS
  276. WmiAcpiFunctionControl(
  277. IN PDEVICE_OBJECT DeviceObject,
  278. IN PIRP Irp,
  279. IN ULONG GuidIndex,
  280. IN WMIENABLEDISABLECONTROL Function,
  281. IN BOOLEAN Enable
  282. );
  283. #ifdef ALLOC_PRAGMA
  284. #pragma alloc_text(INIT,DriverEntry)
  285. #pragma alloc_text(PAGE,WmiAcpiSystemControlDispatch)
  286. #pragma alloc_text(PAGE,WmiAcpiPnP)
  287. #pragma alloc_text(PAGE,WmiAcpiUnload)
  288. #pragma alloc_text(PAGE,WmiAcpiAddDevice)
  289. #pragma alloc_text(PAGE,WmiAcpiSynchronousRequest)
  290. #pragma alloc_text(PAGE,WmiAcpiGetAcpiInterfaces)
  291. #pragma alloc_text(PAGE,WmiAcpiNotificationWorkItem)
  292. #pragma alloc_text(PAGE,WmiAcpiCheckIncomingString)
  293. #pragma alloc_text(PAGE,WmiAcpiXtoA)
  294. #pragma alloc_text(PAGE,WmiAcpiArgumentSize)
  295. #pragma alloc_text(PAGE,WmiAcpiCopyArgument)
  296. #pragma alloc_text(PAGE,WmiAcpiProcessResult)
  297. #pragma alloc_text(PAGE,WmiAcpiSendDownStreamIrp)
  298. #pragma alloc_text(PAGE,WmiAcpiSendMethodEvalIrp)
  299. #pragma alloc_text(PAGE,WmiAcpiEvalMethod)
  300. #pragma alloc_text(PAGE,WmiAcpiEvalMethodInt)
  301. #pragma alloc_text(PAGE,WmiAcpiEvalMethodIntBuffer)
  302. #pragma alloc_text(PAGE,WmiAcpiEvalMethodIntIntBuffer)
  303. #pragma alloc_text(PAGE,WmiAcpiEvalMethodIntString)
  304. #pragma alloc_text(PAGE,WmiAcpiEvalMethodIntIntString)
  305. #pragma alloc_text(PAGE,WmiAcpiQueryWmiRegInfo)
  306. #pragma alloc_text(PAGE,WmiAcpiQueryWmiDataBlock)
  307. #pragma alloc_text(PAGE,WmiAcpiSetWmiDataBlock)
  308. #pragma alloc_text(PAGE,WmiAcpiSetWmiDataItem)
  309. #pragma alloc_text(PAGE,WmiAcpiExecuteWmiMethod)
  310. #pragma alloc_text(PAGE,WmiAcpiFunctionControl)
  311. #endif
  312. #if DBG
  313. ULONG WmiAcpiDebug = 0;
  314. #endif
  315. UNICODE_STRING WmiAcpiRegistryPath;
  316. NTSTATUS
  317. DriverEntry(
  318. IN PDRIVER_OBJECT DriverObject,
  319. IN PUNICODE_STRING RegistryPath
  320. )
  321. /*++
  322. Routine Description:
  323. Installable driver initialization entry point.
  324. This is where the driver is called when the driver is being loaded
  325. by the I/O system. This entry point is called directly by the I/O system.
  326. Arguments:
  327. DriverObject - pointer to the driver object
  328. RegistryPath - pointer to a unicode string representing the path
  329. to driver-specific key in the registry
  330. Return Value:
  331. STATUS_SUCCESS if successful,
  332. STATUS_UNSUCCESSFUL otherwise
  333. --*/
  334. {
  335. NTSTATUS ntStatus = STATUS_SUCCESS;
  336. WmiAcpiPrint(WmiAcpiBasicTrace,
  337. ("WmiAcpiDriverEntry: %x Enter\n",
  338. DriverObject
  339. ));
  340. //
  341. // Save registry path for registering with WMI
  342. WmiAcpiRegistryPath.Length = 0;
  343. WmiAcpiRegistryPath.MaximumLength = RegistryPath->Length;
  344. WmiAcpiRegistryPath.Buffer = ExAllocatePoolWithTag(PagedPool,
  345. RegistryPath->Length+sizeof(WCHAR),
  346. WmiAcpiPoolTag);
  347. if (WmiAcpiRegistryPath.Buffer != NULL)
  348. {
  349. RtlCopyUnicodeString(&WmiAcpiRegistryPath, RegistryPath);
  350. }
  351. //
  352. // Set up the device driver entry points.
  353. //
  354. DriverObject->DriverUnload = WmiAcpiUnload;
  355. DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = WmiAcpiForwardIrp;
  356. DriverObject->MajorFunction[IRP_MJ_CREATE] = WmiAcpiForwardIrp;
  357. DriverObject->MajorFunction[IRP_MJ_CLOSE] = WmiAcpiForwardIrp;
  358. DriverObject->MajorFunction[IRP_MJ_POWER] = WmiAcpiPowerDispatch;
  359. DriverObject->MajorFunction[IRP_MJ_PNP] = WmiAcpiPnP;
  360. DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = WmiAcpiSystemControlDispatch;
  361. DriverObject->DriverExtension->AddDevice = WmiAcpiAddDevice;
  362. WmiAcpiPrint(WmiAcpiBasicTrace,
  363. ("WmiAcpiDriverEntry: %x Return %x\n", DriverObject, ntStatus));
  364. return(ntStatus);
  365. }
  366. NTSTATUS
  367. WmiAcpiPowerDispatch(
  368. IN PDEVICE_OBJECT DeviceObject,
  369. IN PIRP Irp
  370. )
  371. /*++
  372. Routine Description:
  373. This routine is the dispatch routine for power requests.
  374. Arguments:
  375. DeviceObject - Pointer to class device object.
  376. Irp - Pointer to the request packet.
  377. Return Value:
  378. Status is returned.
  379. --*/
  380. {
  381. NTSTATUS status;
  382. PDEVICE_EXTENSION deviceExtension;
  383. PIO_STACK_LOCATION irpSp;
  384. irpSp = IoGetCurrentIrpStackLocation(Irp);
  385. WmiAcpiPrint(WmiAcpiBasicTrace,
  386. ("WmiAcpiPowerDispatch: %x Irp %x, Minor Function %x, Parameters %x %x %x %x\n",
  387. DeviceObject,
  388. Irp,
  389. irpSp->MinorFunction,
  390. irpSp->Parameters.WMI.ProviderId,
  391. irpSp->Parameters.WMI.DataPath,
  392. irpSp->Parameters.WMI.BufferSize,
  393. irpSp->Parameters.WMI.Buffer));
  394. deviceExtension = DeviceObject->DeviceExtension;
  395. PoStartNextPowerIrp( Irp );
  396. if (deviceExtension->LowerDeviceObject != NULL) {
  397. //
  398. // Forward the request along
  399. //
  400. IoSkipCurrentIrpStackLocation( Irp );
  401. status = PoCallDriver( deviceExtension->LowerDeviceObject, Irp );
  402. } else {
  403. //
  404. // Complete the request with the current status
  405. //
  406. status = Irp->IoStatus.Status;
  407. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  408. }
  409. return(status);
  410. }
  411. NTSTATUS
  412. WmiAcpiSystemControlDispatch(
  413. IN PDEVICE_OBJECT DeviceObject,
  414. IN PIRP Irp
  415. )
  416. {
  417. PWMILIB_CONTEXT wmilibContext;
  418. PDEVICE_EXTENSION deviceExtension;
  419. PIO_STACK_LOCATION irpSp;
  420. NTSTATUS status;
  421. SYSCTL_IRP_DISPOSITION disposition;
  422. PAGED_CODE();
  423. deviceExtension = DeviceObject->DeviceExtension;
  424. wmilibContext = &deviceExtension->WmilibContext;
  425. irpSp = IoGetCurrentIrpStackLocation(Irp);
  426. WmiAcpiPrint(WmiAcpiBasicTrace,
  427. ("WmiAcpiSystemControl: %x Irp %x, Minor Function %x, Provider Id %x, DataPath %x, BufferSize %x, Buffer %x\n",
  428. DeviceObject,
  429. Irp,
  430. irpSp->MinorFunction,
  431. irpSp->Parameters.WMI.ProviderId,
  432. irpSp->Parameters.WMI.DataPath,
  433. irpSp->Parameters.WMI.BufferSize,
  434. irpSp->Parameters.WMI.Buffer));
  435. status = WmiSystemControl(wmilibContext,
  436. DeviceObject,
  437. Irp,
  438. &disposition);
  439. WmiAcpiPrint(WmiAcpiBasicTrace,
  440. ("WmiAcpiSystemControl: %x Irp %x returns %x, disposition %d\n",
  441. DeviceObject,
  442. Irp,
  443. status,
  444. disposition));
  445. switch(disposition)
  446. {
  447. case IrpProcessed:
  448. {
  449. //
  450. // This irp has been processed and may be completed or pending.
  451. break;
  452. }
  453. case IrpNotCompleted:
  454. {
  455. //
  456. // This irp has not been completed, but has been fully processed.
  457. // we will complete it now
  458. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  459. break;
  460. }
  461. case IrpForward:
  462. case IrpNotWmi:
  463. {
  464. //
  465. // This irp is either not a WMI irp or is a WMI irp targetted
  466. // at a device lower in the stack.
  467. status = WmiAcpiForwardIrp(DeviceObject, Irp);
  468. break;
  469. }
  470. default:
  471. {
  472. //
  473. // We really should never get here, but if we do just forward....
  474. ASSERT(FALSE);
  475. status = WmiAcpiForwardIrp(DeviceObject,
  476. Irp);
  477. break;
  478. }
  479. }
  480. return(status);
  481. }
  482. NTSTATUS
  483. WmiAcpiPnP(
  484. IN PDEVICE_OBJECT DeviceObject,
  485. IN PIRP Irp
  486. )
  487. /*++
  488. Routine Description:
  489. Process the IRPs sent to this device.
  490. Arguments:
  491. DeviceObject - pointer to a device object
  492. Irp - pointer to an I/O Request Packet
  493. Return Value:
  494. NTSTATUS
  495. --*/
  496. {
  497. PIO_STACK_LOCATION irpSp;
  498. NTSTATUS status;
  499. PDEVICE_EXTENSION deviceExtension;
  500. PWMILIB_CONTEXT wmilibContext;
  501. PAGED_CODE();
  502. deviceExtension = DeviceObject->DeviceExtension;
  503. wmilibContext = &deviceExtension->WmilibContext;
  504. irpSp = IoGetCurrentIrpStackLocation (Irp);
  505. WmiAcpiPrint(WmiAcpiBasicTrace,
  506. ("WmiAcpiPnp: %x Irp %x, Minor Function %x, Parameters %x %x %x %x\n",
  507. DeviceObject,
  508. Irp,
  509. irpSp->MinorFunction,
  510. irpSp->Parameters.WMI.ProviderId,
  511. irpSp->Parameters.WMI.DataPath,
  512. irpSp->Parameters.WMI.BufferSize,
  513. irpSp->Parameters.WMI.Buffer));
  514. switch (irpSp->MinorFunction)
  515. {
  516. case IRP_MN_START_DEVICE:
  517. {
  518. status = IoWMIRegistrationControl(DeviceObject,
  519. WMIREG_ACTION_REGISTER);
  520. if (! NT_SUCCESS(status))
  521. {
  522. //
  523. // If registration with WMI fails then there is no point
  524. // in starting the device.
  525. WmiAcpiPrint(WmiAcpiError,
  526. ("WmiAcpiPnP: %x IoWMIRegister failed %x\n",
  527. DeviceObject,
  528. status));
  529. Irp->IoStatus.Status = status;
  530. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  531. return(status);
  532. } else {
  533. deviceExtension->Flags |= DEVFLAG_WMIREGED;
  534. }
  535. break;
  536. }
  537. case IRP_MN_REMOVE_DEVICE:
  538. {
  539. deviceExtension->Flags |= DEVFLAG_REMOVED;
  540. if (deviceExtension->AcpiNotificationEnabled)
  541. {
  542. deviceExtension->WmiAcpiDirectInterface.UnregisterForDeviceNotifications(
  543. deviceExtension->WmiAcpiDirectInterface.Context,
  544. WmiAcpiNotificationRoutine);
  545. deviceExtension->AcpiNotificationEnabled = FALSE;
  546. }
  547. if (deviceExtension->Flags & DEVFLAG_WMIREGED)
  548. {
  549. if (deviceExtension->WmiAcpiMapInfo != NULL)
  550. {
  551. ExFreePool(deviceExtension->WmiAcpiMapInfo);
  552. deviceExtension->WmiAcpiMapInfo = NULL;
  553. }
  554. if (wmilibContext->GuidList != NULL)
  555. {
  556. ExFreePool(wmilibContext->GuidList);
  557. wmilibContext->GuidList = NULL;
  558. }
  559. IoWMIRegistrationControl(DeviceObject,
  560. WMIREG_ACTION_DEREGISTER);
  561. deviceExtension->Flags &= ~DEVFLAG_WMIREGED;
  562. }
  563. IoDetachDevice(deviceExtension->LowerDeviceObject);
  564. IoDeleteDevice(DeviceObject);
  565. break;
  566. }
  567. }
  568. IoSkipCurrentIrpStackLocation(Irp);
  569. status = IoCallDriver(deviceExtension->LowerDeviceObject, Irp);
  570. return(status);
  571. }
  572. NTSTATUS
  573. WmiAcpiForwardIrp(
  574. IN PDEVICE_OBJECT DeviceObject,
  575. IN PIRP Irp
  576. )
  577. {
  578. NTSTATUS status;
  579. PDEVICE_EXTENSION deviceExtension;
  580. PIO_STACK_LOCATION irpSp;
  581. deviceExtension = DeviceObject->DeviceExtension;
  582. irpSp = IoGetCurrentIrpStackLocation (Irp);
  583. WmiAcpiPrint(WmiAcpiBasicTrace,
  584. ("WmiAcpiForwardIrp: %x Irp %x, Major %x Minor %x, Parameters %x %x %x %x\n",
  585. DeviceObject,
  586. Irp,
  587. irpSp->MajorFunction,
  588. irpSp->MinorFunction,
  589. irpSp->Parameters.WMI.ProviderId,
  590. irpSp->Parameters.WMI.DataPath,
  591. irpSp->Parameters.WMI.BufferSize,
  592. irpSp->Parameters.WMI.Buffer));
  593. IoSkipCurrentIrpStackLocation(Irp);
  594. status = IoCallDriver(deviceExtension->LowerDeviceObject, Irp);
  595. return(status);
  596. }
  597. VOID
  598. WmiAcpiUnload(
  599. IN PDRIVER_OBJECT DriverObject
  600. )
  601. /*++
  602. Routine Description:
  603. Free all the allocated resources, etc.
  604. Arguments:
  605. DriverObject - pointer to a driver object
  606. Return Value:
  607. None
  608. --*/
  609. {
  610. PAGED_CODE();
  611. WmiAcpiPrint(WmiAcpiBasicTrace,
  612. ("WmiAcpiUnload: Driver %x is unloading\n",
  613. DriverObject));
  614. ExFreePool(WmiAcpiRegistryPath.Buffer);
  615. }
  616. NTSTATUS
  617. WmiAcpiAddDevice(
  618. IN PDRIVER_OBJECT DriverObject,
  619. IN PDEVICE_OBJECT PhysicalDeviceObject
  620. )
  621. /*++
  622. Routine Description:
  623. This routine is called to create a new instance of the device
  624. Arguments:
  625. DriverObject - pointer to the driver object for this instance of Sample
  626. PhysicalDeviceObject - pointer to a device object created by the bus
  627. Return Value:
  628. STATUS_SUCCESS if successful,
  629. STATUS_UNSUCCESSFUL otherwise
  630. --*/
  631. {
  632. NTSTATUS status;
  633. PDEVICE_OBJECT deviceObject = NULL;
  634. PWMILIB_CONTEXT wmilibContext;
  635. PDEVICE_EXTENSION deviceExtension;
  636. PAGED_CODE();
  637. WmiAcpiPrint(WmiAcpiBasicTrace,
  638. ("WmiAcpiAddDevice: Driver %x, PDO %x\n",
  639. DriverObject, PhysicalDeviceObject));
  640. status = IoCreateDevice (DriverObject,
  641. sizeof(DEVICE_EXTENSION),
  642. NULL,
  643. FILE_DEVICE_UNKNOWN,
  644. 0,
  645. FALSE,
  646. &deviceObject);
  647. if (NT_SUCCESS(status))
  648. {
  649. deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  650. deviceExtension = deviceObject->DeviceExtension;
  651. deviceExtension->LowerPDO = PhysicalDeviceObject;
  652. deviceExtension->LowerDeviceObject =
  653. IoAttachDeviceToDeviceStack(deviceObject, PhysicalDeviceObject);
  654. WmiAcpiPrint(WmiAcpiError,
  655. ("WmiAcpiAddDevice: Created device %x to stack %x PDO %x\n",
  656. deviceObject,
  657. deviceExtension->LowerDeviceObject,
  658. deviceExtension->LowerPDO));
  659. if (deviceExtension->LowerDeviceObject->Flags & DO_POWER_PAGABLE)
  660. {
  661. deviceObject->Flags |= DO_POWER_PAGABLE;
  662. }
  663. wmilibContext = &deviceExtension->WmilibContext;
  664. wmilibContext->GuidCount = 0;
  665. wmilibContext->GuidList = NULL;
  666. wmilibContext->QueryWmiRegInfo = WmiAcpiQueryWmiRegInfo;
  667. wmilibContext->QueryWmiDataBlock = WmiAcpiQueryWmiDataBlock;
  668. wmilibContext->SetWmiDataBlock = WmiAcpiSetWmiDataBlock;
  669. wmilibContext->SetWmiDataItem = WmiAcpiSetWmiDataItem;
  670. wmilibContext->ExecuteWmiMethod = WmiAcpiExecuteWmiMethod;
  671. wmilibContext->WmiFunctionControl = WmiAcpiFunctionControl;
  672. } else {
  673. WmiAcpiPrint(WmiAcpiError,
  674. ("WmiAcpiAddDevice: Create device failed %x\n",
  675. status));
  676. }
  677. return(status);
  678. }
  679. NTSTATUS
  680. WmiAcpiSynchronousRequest (
  681. IN PDEVICE_OBJECT DeviceObject,
  682. IN PIRP Irp,
  683. IN PVOID Context
  684. )
  685. /*++
  686. Routine Description:
  687. Completion function for synchronous IRPs sent to this driver.
  688. No event.
  689. --*/
  690. {
  691. PAGED_CODE();
  692. return STATUS_MORE_PROCESSING_REQUIRED;
  693. }
  694. NTSTATUS
  695. WmiAcpiGetAcpiInterfaces(
  696. IN PDEVICE_EXTENSION DeviceExtension,
  697. IN PDEVICE_OBJECT Pdo
  698. )
  699. /*++
  700. Routine Description:
  701. Call ACPI driver to get the direct-call interfaces. It does
  702. this the first time it is called, no more.
  703. Arguments:
  704. None.
  705. Return Value:
  706. Status
  707. --*/
  708. {
  709. NTSTATUS Status = STATUS_SUCCESS;
  710. PIRP Irp;
  711. PIO_STACK_LOCATION IrpSp;
  712. PDEVICE_OBJECT LowerPdo;
  713. PAGED_CODE();
  714. //
  715. // Only need to do this once
  716. //
  717. if (DeviceExtension->WmiAcpiDirectInterface.RegisterForDeviceNotifications == NULL) {
  718. LowerPdo = IoGetAttachedDeviceReference (Pdo);
  719. //
  720. // Allocate an IRP for below
  721. //
  722. Irp = IoAllocateIrp (LowerPdo->StackSize, FALSE); // Get stack size from PDO
  723. if (!Irp) {
  724. WmiAcpiPrint(WmiAcpiError,
  725. ("WmiAcpiGetAcpiInterfaces: %x Failed to allocate Irp\n",
  726. Pdo));
  727. ObDereferenceObject(LowerPdo);
  728. return(STATUS_INSUFFICIENT_RESOURCES);
  729. }
  730. IrpSp = IoGetNextIrpStackLocation(Irp);
  731. //
  732. // Use QUERY_INTERFACE to get the address of the direct-call ACPI interfaces.
  733. //
  734. IrpSp->MajorFunction = IRP_MJ_PNP;
  735. IrpSp->MinorFunction = IRP_MN_QUERY_INTERFACE;
  736. IrpSp->Parameters.QueryInterface.InterfaceType = (LPGUID) &GUID_ACPI_INTERFACE_STANDARD;
  737. IrpSp->Parameters.QueryInterface.Version = 1;
  738. IrpSp->Parameters.QueryInterface.Size = sizeof (DeviceExtension->WmiAcpiDirectInterface);
  739. IrpSp->Parameters.QueryInterface.Interface = (PINTERFACE) &DeviceExtension->WmiAcpiDirectInterface;
  740. IrpSp->Parameters.QueryInterface.InterfaceSpecificData = NULL;
  741. IoSetCompletionRoutine (Irp, WmiAcpiSynchronousRequest, NULL, TRUE, TRUE, TRUE);
  742. Status = IoCallDriver (LowerPdo, Irp);
  743. IoFreeIrp (Irp);
  744. if (!NT_SUCCESS(Status)) {
  745. WmiAcpiPrint(WmiAcpiError,
  746. ("WmiAcpiGetAcpiInterfaces: Could not get ACPI driver interfaces, status = %x\n", Status));
  747. }
  748. ObDereferenceObject(LowerPdo);
  749. }
  750. return(Status);
  751. }
  752. NTSTATUS
  753. WmiAcpiQueryWmiRegInfo(
  754. IN PDEVICE_OBJECT DeviceObject,
  755. OUT ULONG *RegFlags,
  756. OUT PUNICODE_STRING InstanceName,
  757. OUT PUNICODE_STRING *RegistryPath,
  758. OUT PUNICODE_STRING MofResourceName,
  759. OUT PDEVICE_OBJECT *Pdo
  760. )
  761. /*++
  762. Routine Description:
  763. This routine is a callback into the driver to retrieve the list of
  764. guids or data blocks that the driver wants to register with WMI. This
  765. routine may not pend or block. Driver should NOT call
  766. ClassWmiCompleteRequest.
  767. Arguments:
  768. DeviceObject is the device whose data block is being queried
  769. *RegFlags returns with a set of flags that describe the guids being
  770. registered for this device. If the device wants enable and disable
  771. collection callbacks before receiving queries for the registered
  772. guids then it should return the WMIREG_FLAG_EXPENSIVE flag. Also the
  773. returned flags may specify WMIREG_FLAG_INSTANCE_PDO in which case
  774. the instance name is determined from the PDO associated with the
  775. device object. Note that the PDO must have an associated devnode. If
  776. WMIREG_FLAG_INSTANCE_PDO is not set then Name must return a unique
  777. name for the device.
  778. InstanceName returns with the instance name for the guids if
  779. WMIREG_FLAG_INSTANCE_PDO is not set in the returned *RegFlags. The
  780. caller will call ExFreePool with the buffer returned.
  781. *RegistryPath returns with the registry path of the driver
  782. *MofResourceName returns with the name of the MOF resource attached to
  783. the binary file. If the driver does not have a mof resource attached
  784. then this can be returned as NULL.
  785. *Pdo returns with the device object for the PDO associated with this
  786. device if the WMIREG_FLAG_INSTANCE_PDO flag is retured in
  787. *RegFlags.
  788. Return Value:
  789. status
  790. --*/
  791. {
  792. PWMILIB_CONTEXT wmilibContext;
  793. PDEVICE_EXTENSION deviceExtension;
  794. USHORT resultType;
  795. ULONG bufferSize;
  796. PUCHAR buffer;
  797. ULONG guidCount;
  798. NTSTATUS status;
  799. ULONG sizeNeeded;
  800. PWMIGUIDREGINFO guidList;
  801. PWMIACPIMAPINFO guidMapInfo;
  802. PWMIACPIGUIDMAP guidMap;
  803. ULONG i;
  804. PAGED_CODE();
  805. deviceExtension = DeviceObject->DeviceExtension;
  806. wmilibContext = &deviceExtension->WmilibContext;
  807. //
  808. // Setup to use PDO instance names and our own registry path
  809. *RegFlags = WMIREG_FLAG_INSTANCE_PDO;
  810. if (WmiAcpiRegistryPath.Buffer != NULL)
  811. {
  812. *RegistryPath = &WmiAcpiRegistryPath;
  813. } else {
  814. *RegistryPath = NULL;
  815. }
  816. *Pdo = deviceExtension->LowerPDO;
  817. RtlInitUnicodeString(MofResourceName, L"MofResource");
  818. //
  819. // Build guid registration list from information obtained by calling
  820. // _WDG acpi method
  821. if (wmilibContext->GuidList == NULL)
  822. {
  823. bufferSize = 512;
  824. status = STATUS_BUFFER_TOO_SMALL;
  825. buffer = NULL;
  826. while (status == STATUS_BUFFER_TOO_SMALL)
  827. {
  828. if (buffer != NULL)
  829. {
  830. ExFreePool(buffer);
  831. }
  832. buffer = ExAllocatePoolWithTag(PagedPool,
  833. bufferSize,
  834. WmiAcpiPoolTag);
  835. if (buffer != NULL)
  836. {
  837. status = WmiAcpiEvalMethod(deviceExtension->LowerPDO,
  838. _WDGMethodAsULONG,
  839. buffer,
  840. &bufferSize,
  841. &resultType);
  842. } else {
  843. status = STATUS_INSUFFICIENT_RESOURCES;
  844. }
  845. }
  846. if (NT_SUCCESS(status))
  847. {
  848. guidCount = bufferSize / sizeof(WMIACPIGUIDMAP);
  849. sizeNeeded = guidCount * sizeof(WMIGUIDREGINFO);
  850. wmilibContext->GuidCount = guidCount;
  851. wmilibContext->GuidList = ExAllocatePoolWithTag(PagedPool,
  852. sizeNeeded,
  853. WmiAcpiPoolTag);
  854. if (wmilibContext->GuidList != NULL)
  855. {
  856. sizeNeeded = guidCount * sizeof(WMIACPIMAPINFO);
  857. deviceExtension->GuidMapCount = guidCount;
  858. deviceExtension->WmiAcpiMapInfo = ExAllocatePoolWithTag(
  859. NonPagedPool,
  860. sizeNeeded,
  861. WmiAcpiPoolTag);
  862. if (deviceExtension->WmiAcpiMapInfo != NULL)
  863. {
  864. guidMap = (PWMIACPIGUIDMAP)buffer;
  865. guidList = wmilibContext->GuidList;
  866. guidMapInfo = deviceExtension->WmiAcpiMapInfo;
  867. for (i = 0; i < guidCount; i++, guidMap++, guidList++, guidMapInfo++)
  868. {
  869. //
  870. // Cannot be both an event and a method or be both a
  871. // method and data block.
  872. ASSERT( ! ((guidMap->Flags & WMIACPI_REGFLAG_EVENT) &&
  873. (guidMap->Flags & WMIACPI_REGFLAG_METHOD)));
  874. guidMapInfo->ObjectId[0] = guidMap->ObjectId[0];
  875. guidMapInfo->ObjectId[1] = guidMap->ObjectId[1];
  876. guidMapInfo->Flags = guidMap->Flags;
  877. guidMapInfo->Guid = guidMap->Guid;
  878. guidList->Flags = 0;
  879. guidList->Guid = &guidMapInfo->Guid;
  880. guidList->InstanceCount = guidMap->InstanceCount;
  881. if (guidMap->Flags & WMIACPI_REGFLAG_EXPENSIVE)
  882. {
  883. guidList->Flags |= WMIREG_FLAG_EXPENSIVE;
  884. }
  885. if (guidMap->Flags & WMIACPI_REGFLAG_EVENT)
  886. {
  887. guidList->Flags |= WMIREG_FLAG_EVENT_ONLY_GUID;
  888. }
  889. }
  890. } else {
  891. ExFreePool(wmilibContext->GuidList);
  892. wmilibContext->GuidList = NULL;
  893. status = STATUS_INSUFFICIENT_RESOURCES;
  894. }
  895. } else {
  896. status = STATUS_INSUFFICIENT_RESOURCES;
  897. }
  898. }
  899. if (buffer != NULL)
  900. {
  901. ExFreePool(buffer);
  902. }
  903. } else {
  904. status = STATUS_SUCCESS;
  905. }
  906. return(status);
  907. }
  908. NTSTATUS
  909. WmiAcpiQueryWmiDataBlock(
  910. IN PDEVICE_OBJECT DeviceObject,
  911. IN PIRP Irp,
  912. IN ULONG GuidIndex,
  913. IN ULONG InstanceIndex,
  914. IN ULONG InstanceCount,
  915. IN OUT PULONG InstanceLengthArray,
  916. IN ULONG BufferAvail,
  917. OUT PUCHAR Buffer
  918. )
  919. /*++
  920. Routine Description:
  921. This routine is a callback into the driver to query for the contents of
  922. all instances of a data block. When the driver has finished filling the
  923. data block it must call IoWMICompleteRequest to complete the irp. The
  924. driver can return STATUS_PENDING if the irp cannot be completed
  925. immediately.
  926. Arguments:
  927. DeviceObject is the device whose data block is being queried
  928. Irp is the Irp that makes this request
  929. GuidIndex is the index into the list of guids provided when the
  930. device registered
  931. InstanceCount is the number of instnaces expected to be returned for
  932. the data block.
  933. InstanceLengthArray is a pointer to an array of ULONG that returns the
  934. lengths of each instance of the data block. If this is NULL then
  935. there was not enough space in the output buffer to fufill the request
  936. so the irp should be completed with the buffer needed.
  937. BufferAvail on entry has the maximum size available to write the data
  938. blocks.
  939. Buffer on return is filled with the returned data blocks. Note that each
  940. instance of the data block must be aligned on a 8 byte boundry.
  941. Return Value:
  942. status
  943. --*/
  944. {
  945. NTSTATUS status;
  946. PDEVICE_EXTENSION deviceExtension;
  947. ULONG sizeNeeded;
  948. ULONG padNeeded;
  949. ULONG i;
  950. ULONG methodAsUlong;
  951. PWMIACPIMAPINFO guidMapInfo;
  952. USHORT resultType;
  953. PUCHAR outBuffer;
  954. ULONG outBufferSize;
  955. ULONG currentInstanceIndex;
  956. BOOLEAN bufferTooSmall;
  957. PWMILIB_CONTEXT wmilibContext;
  958. PAGED_CODE();
  959. #if DBG
  960. if (BufferAvail > 0)
  961. {
  962. RtlZeroMemory(Buffer, BufferAvail);
  963. }
  964. #endif
  965. deviceExtension = DeviceObject->DeviceExtension;
  966. wmilibContext = &deviceExtension->WmilibContext;
  967. ASSERT(GuidIndex < wmilibContext->GuidCount);
  968. guidMapInfo = &((PWMIACPIMAPINFO)deviceExtension->WmiAcpiMapInfo)[GuidIndex];
  969. //
  970. // Query only valid for those datablocks registered as not events
  971. // or methods.
  972. bufferTooSmall = FALSE;
  973. if ((guidMapInfo->Flags &
  974. (WMIACPI_REGFLAG_METHOD | WMIACPI_REGFLAG_EVENT)) == 0)
  975. {
  976. methodAsUlong = WmiAcpiMethodToMethodAsUlong('W', 'Q',
  977. guidMapInfo->ObjectId[0],
  978. guidMapInfo->ObjectId[1]);
  979. status = STATUS_SUCCESS;
  980. sizeNeeded = 0;
  981. padNeeded = 0;
  982. for (i = 0; (i < InstanceCount) && NT_SUCCESS(status) ; i++)
  983. {
  984. currentInstanceIndex = i + InstanceIndex;
  985. sizeNeeded += padNeeded;
  986. if ((! bufferTooSmall) && (sizeNeeded < BufferAvail))
  987. {
  988. outBufferSize = BufferAvail - sizeNeeded;
  989. outBuffer = Buffer + sizeNeeded;
  990. } else {
  991. bufferTooSmall = TRUE;
  992. outBufferSize = 0;
  993. outBuffer = NULL;
  994. }
  995. status = WmiAcpiEvalMethodInt(deviceExtension->LowerPDO,
  996. methodAsUlong,
  997. currentInstanceIndex,
  998. outBuffer,
  999. &outBufferSize,
  1000. &resultType);
  1001. sizeNeeded += outBufferSize;
  1002. padNeeded = ((sizeNeeded + 7) & ~7) - sizeNeeded;
  1003. if (NT_SUCCESS(status))
  1004. {
  1005. InstanceLengthArray[i] = outBufferSize;
  1006. }
  1007. if (status == STATUS_BUFFER_TOO_SMALL)
  1008. {
  1009. bufferTooSmall = TRUE;
  1010. status = STATUS_SUCCESS;
  1011. }
  1012. }
  1013. } else if (guidMapInfo->Flags & WMIACPI_REGFLAG_METHOD) {
  1014. //
  1015. // WBEM requires methods respond queries
  1016. sizeNeeded = 0;
  1017. if (InstanceLengthArray != NULL)
  1018. {
  1019. for (i = 0; i < InstanceCount; i++)
  1020. {
  1021. InstanceLengthArray[i] = 0;
  1022. }
  1023. status = STATUS_SUCCESS;
  1024. } else {
  1025. status = STATUS_BUFFER_TOO_SMALL;
  1026. }
  1027. } else {
  1028. sizeNeeded = 0;
  1029. status = STATUS_WMI_GUID_NOT_FOUND;
  1030. }
  1031. if (NT_SUCCESS(status) && bufferTooSmall)
  1032. {
  1033. status = STATUS_BUFFER_TOO_SMALL;
  1034. }
  1035. status = WmiCompleteRequest(
  1036. DeviceObject,
  1037. Irp,
  1038. status,
  1039. sizeNeeded,
  1040. IO_NO_INCREMENT);
  1041. return(status);
  1042. }
  1043. NTSTATUS
  1044. WmiAcpiCheckIncomingString(
  1045. PUNICODE_STRING UnicodeString,
  1046. ULONG BufferSize,
  1047. PUCHAR Buffer,
  1048. PWCHAR EmptyString
  1049. )
  1050. {
  1051. ULONG status;
  1052. USHORT stringLength;
  1053. PAGED_CODE();
  1054. if (BufferSize > sizeof(USHORT))
  1055. {
  1056. //
  1057. // The length declared in the string must fit within the
  1058. // passed in buffer
  1059. stringLength = *((PUSHORT)Buffer);
  1060. if ((stringLength + sizeof(USHORT)) <= BufferSize)
  1061. {
  1062. UnicodeString->Length = stringLength;
  1063. UnicodeString->MaximumLength = stringLength;
  1064. UnicodeString->Buffer = (PWCHAR)(Buffer + sizeof(USHORT));
  1065. status = STATUS_SUCCESS;
  1066. } else {
  1067. status = STATUS_INVALID_PARAMETER;
  1068. }
  1069. } else if (BufferSize == 0) {
  1070. //
  1071. // An empty incoming buffer is translated into an empty string
  1072. UnicodeString->Length = 0;
  1073. UnicodeString->MaximumLength = 0;
  1074. *EmptyString = UNICODE_NULL;
  1075. UnicodeString->Buffer = EmptyString;
  1076. status = STATUS_SUCCESS;
  1077. } else {
  1078. status = STATUS_INVALID_PARAMETER;
  1079. }
  1080. return(status);
  1081. }
  1082. NTSTATUS
  1083. WmiAcpiSetWmiDataBlock(
  1084. IN PDEVICE_OBJECT DeviceObject,
  1085. IN PIRP Irp,
  1086. IN ULONG GuidIndex,
  1087. IN ULONG InstanceIndex,
  1088. IN ULONG BufferSize,
  1089. IN PUCHAR Buffer
  1090. )
  1091. /*++
  1092. Routine Description:
  1093. This routine is a callback into the driver to query for the contents of
  1094. a data block. When the driver has finished filling the data block it
  1095. must call ClassWmiCompleteRequest to complete the irp. The driver can
  1096. return STATUS_PENDING if the irp cannot be completed immediately.
  1097. Arguments:
  1098. DeviceObject is the device whose data block is being queried
  1099. Irp is the Irp that makes this request
  1100. GuidIndex is the index into the list of guids provided when the
  1101. device registered
  1102. BufferSize has the size of the data block passed
  1103. Buffer has the new values for the data block
  1104. Return Value:
  1105. status
  1106. --*/
  1107. {
  1108. NTSTATUS status;
  1109. PDEVICE_EXTENSION deviceExtension;
  1110. ULONG methodAsUlong;
  1111. PWMIACPIMAPINFO guidMapInfo;
  1112. USHORT resultType;
  1113. ULONG outBufferSize;
  1114. PWMILIB_CONTEXT wmilibContext;
  1115. UNICODE_STRING unicodeString;
  1116. WCHAR emptyString;
  1117. PAGED_CODE();
  1118. deviceExtension = DeviceObject->DeviceExtension;
  1119. wmilibContext = &deviceExtension->WmilibContext;
  1120. ASSERT(GuidIndex < wmilibContext->GuidCount);
  1121. guidMapInfo = &((PWMIACPIMAPINFO)deviceExtension->WmiAcpiMapInfo)[GuidIndex];
  1122. //
  1123. // Query only valid for those datablocks registered as not events
  1124. // or methods.
  1125. if ((guidMapInfo->Flags &
  1126. (WMIACPI_REGFLAG_METHOD | WMIACPI_REGFLAG_EVENT)) == 0)
  1127. {
  1128. methodAsUlong = WmiAcpiMethodToMethodAsUlong('W', 'S',
  1129. guidMapInfo->ObjectId[0],
  1130. guidMapInfo->ObjectId[1]);
  1131. outBufferSize = 0;
  1132. if (guidMapInfo->Flags & WMIACPI_REGFLAG_STRING)
  1133. {
  1134. status = WmiAcpiCheckIncomingString(&unicodeString,
  1135. BufferSize,
  1136. Buffer,
  1137. &emptyString);
  1138. if (NT_SUCCESS(status))
  1139. {
  1140. status = WmiAcpiEvalMethodIntString(deviceExtension->LowerPDO,
  1141. methodAsUlong,
  1142. InstanceIndex,
  1143. &unicodeString,
  1144. NULL,
  1145. &outBufferSize,
  1146. &resultType);
  1147. }
  1148. } else {
  1149. status = WmiAcpiEvalMethodIntBuffer(deviceExtension->LowerPDO,
  1150. methodAsUlong,
  1151. InstanceIndex,
  1152. BufferSize,
  1153. Buffer,
  1154. NULL,
  1155. &outBufferSize,
  1156. &resultType);
  1157. }
  1158. if (status == STATUS_BUFFER_TOO_SMALL)
  1159. {
  1160. //
  1161. // Since this operation is not supposed to return any results
  1162. // then we need to ignore the fact that the return buffer
  1163. // was too small.
  1164. status = STATUS_SUCCESS;
  1165. }
  1166. } else {
  1167. status = STATUS_WMI_GUID_NOT_FOUND;
  1168. }
  1169. status = WmiCompleteRequest(
  1170. DeviceObject,
  1171. Irp,
  1172. status,
  1173. 0,
  1174. IO_NO_INCREMENT);
  1175. return(status);
  1176. }
  1177. NTSTATUS
  1178. WmiAcpiSetWmiDataItem(
  1179. IN PDEVICE_OBJECT DeviceObject,
  1180. IN PIRP Irp,
  1181. IN ULONG GuidIndex,
  1182. IN ULONG InstanceIndex,
  1183. IN ULONG DataItemId,
  1184. IN ULONG BufferSize,
  1185. IN PUCHAR Buffer
  1186. )
  1187. /*++
  1188. Routine Description:
  1189. This routine is a callback into the driver to query for the contents of
  1190. a data block. When the driver has finished filling the data block it
  1191. must call ClassWmiCompleteRequest to complete the irp. The driver can
  1192. return STATUS_PENDING if the irp cannot be completed immediately.
  1193. Arguments:
  1194. DeviceObject is the device whose data block is being queried
  1195. Irp is the Irp that makes this request
  1196. GuidIndex is the index into the list of guids provided when the
  1197. device registered
  1198. DataItemId has the id of the data item being set
  1199. BufferSize has the size of the data item passed
  1200. Buffer has the new values for the data item
  1201. Return Value:
  1202. status
  1203. --*/
  1204. {
  1205. NTSTATUS status;
  1206. PAGED_CODE();
  1207. status = STATUS_INVALID_DEVICE_REQUEST;
  1208. status = WmiCompleteRequest(
  1209. DeviceObject,
  1210. Irp,
  1211. status,
  1212. 0,
  1213. IO_NO_INCREMENT);
  1214. return(status);
  1215. }
  1216. NTSTATUS
  1217. WmiAcpiExecuteWmiMethod(
  1218. IN PDEVICE_OBJECT DeviceObject,
  1219. IN PIRP Irp,
  1220. IN ULONG GuidIndex,
  1221. IN ULONG InstanceIndex,
  1222. IN ULONG MethodId,
  1223. IN ULONG InBufferSize,
  1224. IN ULONG OutBufferSize,
  1225. IN PUCHAR Buffer
  1226. )
  1227. /*++
  1228. Routine Description:
  1229. This routine is a callback into the driver to execute a method. When the
  1230. driver has finished filling the data block it must call
  1231. ClassWmiCompleteRequest to complete the irp. The driver can
  1232. return STATUS_PENDING if the irp cannot be completed immediately.
  1233. Arguments:
  1234. DeviceObject is the device whose data block is being queried
  1235. Irp is the Irp that makes this request
  1236. GuidIndex is the index into the list of guids provided when the
  1237. device registered
  1238. MethodId has the id of the method being called
  1239. InBufferSize has the size of the data block passed in as the input to
  1240. the method.
  1241. OutBufferSize on entry has the maximum size available to write the
  1242. returned data block.
  1243. Buffer is filled with the returned data block
  1244. Return Value:
  1245. status
  1246. --*/
  1247. {
  1248. NTSTATUS status;
  1249. PDEVICE_EXTENSION deviceExtension;
  1250. ULONG methodAsUlong;
  1251. PWMIACPIMAPINFO guidMapInfo;
  1252. USHORT resultType;
  1253. PWMILIB_CONTEXT wmilibContext;
  1254. BOOLEAN voidResultExpected;
  1255. UNICODE_STRING unicodeString;
  1256. WCHAR emptyString;
  1257. PAGED_CODE();
  1258. deviceExtension = DeviceObject->DeviceExtension;
  1259. wmilibContext = &deviceExtension->WmilibContext;
  1260. ASSERT(GuidIndex < wmilibContext->GuidCount);
  1261. guidMapInfo = &((PWMIACPIMAPINFO)deviceExtension->WmiAcpiMapInfo)[GuidIndex];
  1262. //
  1263. // Query only valid for those datablocks registered as not events
  1264. // or methods.
  1265. if (guidMapInfo->Flags & WMIACPI_REGFLAG_METHOD)
  1266. {
  1267. methodAsUlong = WmiAcpiMethodToMethodAsUlong('W', 'M',
  1268. guidMapInfo->ObjectId[0],
  1269. guidMapInfo->ObjectId[1]);
  1270. voidResultExpected = (OutBufferSize == 0);
  1271. if (guidMapInfo->Flags & WMIACPI_REGFLAG_STRING)
  1272. {
  1273. status = WmiAcpiCheckIncomingString(&unicodeString,
  1274. InBufferSize,
  1275. Buffer,
  1276. &emptyString);
  1277. if (NT_SUCCESS(status))
  1278. {
  1279. status = WmiAcpiEvalMethodIntIntString(deviceExtension->LowerPDO,
  1280. methodAsUlong,
  1281. InstanceIndex,
  1282. MethodId,
  1283. &unicodeString,
  1284. Buffer,
  1285. &OutBufferSize,
  1286. &resultType);
  1287. }
  1288. } else {
  1289. status = WmiAcpiEvalMethodIntIntBuffer(deviceExtension->LowerPDO,
  1290. methodAsUlong,
  1291. InstanceIndex,
  1292. MethodId,
  1293. InBufferSize,
  1294. Buffer,
  1295. Buffer,
  1296. &OutBufferSize,
  1297. &resultType);
  1298. }
  1299. if (voidResultExpected && (status == STATUS_BUFFER_TOO_SMALL))
  1300. {
  1301. //
  1302. // Since this operation is not supposed to return any results
  1303. // then we need to ignore the fact that the return buffer
  1304. // was too small.
  1305. status = STATUS_SUCCESS;
  1306. OutBufferSize = 0;
  1307. }
  1308. } else {
  1309. status = STATUS_WMI_GUID_NOT_FOUND;
  1310. }
  1311. status = WmiCompleteRequest(
  1312. DeviceObject,
  1313. Irp,
  1314. status,
  1315. OutBufferSize,
  1316. IO_NO_INCREMENT);
  1317. return(status);
  1318. }
  1319. VOID
  1320. WmiAcpiNotificationWorkItem(
  1321. IN PVOID Context
  1322. )
  1323. /*++
  1324. Routine Description:
  1325. Arguments:
  1326. Return Value:
  1327. None
  1328. --*/
  1329. {
  1330. NTSTATUS status;
  1331. PACPI_EVAL_OUTPUT_BUFFER buffer;
  1332. ULONG bufferSize;
  1333. PDEVICE_EXTENSION deviceExtension;
  1334. ULONG processedBufferSize;
  1335. PUCHAR processedBuffer;
  1336. USHORT resultType;
  1337. PIRP_CONTEXT_BLOCK irpContextBlock;
  1338. LPGUID guid;
  1339. PDEVICE_OBJECT deviceObject;
  1340. PAGED_CODE();
  1341. irpContextBlock = (PIRP_CONTEXT_BLOCK)Context;
  1342. deviceObject = irpContextBlock->DeviceObject;
  1343. deviceExtension = deviceObject->DeviceExtension;
  1344. status = irpContextBlock->Status;
  1345. buffer = (PACPI_EVAL_OUTPUT_BUFFER)irpContextBlock->OutBuffer;
  1346. bufferSize = irpContextBlock->OutBufferSize;
  1347. guid = irpContextBlock->CallerContext;
  1348. WmiAcpiPrint(WmiAcpiEvalTrace,
  1349. ("WmiAcpi: %x _WED --> %x, size = %d\n",
  1350. deviceObject,
  1351. status,
  1352. bufferSize));
  1353. if (NT_SUCCESS(status) && (bufferSize > 0))
  1354. {
  1355. processedBufferSize = _WEDBufferSize * sizeof(WCHAR);
  1356. processedBuffer = ExAllocatePoolWithTag(PagedPool,
  1357. processedBufferSize,
  1358. WmiAcpiPoolTag);
  1359. if (processedBuffer != NULL)
  1360. {
  1361. status = WmiAcpiProcessResult(status,
  1362. buffer,
  1363. bufferSize,
  1364. processedBuffer,
  1365. &processedBufferSize,
  1366. &resultType);
  1367. } else {
  1368. status = STATUS_INSUFFICIENT_RESOURCES;
  1369. }
  1370. if (! NT_SUCCESS(status))
  1371. {
  1372. processedBufferSize = 0;
  1373. }
  1374. } else {
  1375. processedBufferSize = 0;
  1376. processedBuffer = NULL;
  1377. }
  1378. status = WmiFireEvent(
  1379. deviceObject,
  1380. guid,
  1381. 0,
  1382. processedBufferSize,
  1383. processedBuffer);
  1384. #if DBG
  1385. if (! NT_SUCCESS(status))
  1386. {
  1387. WmiAcpiPrint(WmiAcpiError,
  1388. ("WmiAcpi: %x WmiWriteEvent failed %x\n",
  1389. deviceObject,
  1390. status));
  1391. }
  1392. #endif
  1393. ExFreePool(buffer);
  1394. ExFreePool(irpContextBlock);
  1395. }
  1396. VOID
  1397. WmiAcpiNotificationRoutine (
  1398. IN PVOID Context,
  1399. IN ULONG NotifyValue
  1400. )
  1401. /*++
  1402. Routine Description:
  1403. ACPI calls back this routine whenever the ACPI code fires a notification
  1404. Arguments:
  1405. Context is the device object of the device whose ACPI code fired the event
  1406. NotifyValue is the notify value fired by the ACPI code
  1407. Return Value:
  1408. None
  1409. --*/
  1410. {
  1411. PDEVICE_OBJECT deviceObject;
  1412. PDEVICE_EXTENSION deviceExtension;
  1413. PWMIACPIMAPINFO guidMapInfo;
  1414. PUCHAR outBuffer;
  1415. ULONG outBufferSize;
  1416. ULONG i;
  1417. NTSTATUS status;
  1418. BOOLEAN irpPassed;
  1419. #if 0
  1420. KIRQL oldIrql;
  1421. oldIrql = KeRaiseIrqlToDpcLevel();
  1422. #endif
  1423. deviceObject = (PDEVICE_OBJECT)Context;
  1424. deviceExtension = deviceObject->DeviceExtension;
  1425. guidMapInfo = (PWMIACPIMAPINFO)deviceExtension->WmiAcpiMapInfo;
  1426. for (i = 0; i < deviceExtension->GuidMapCount; i++, guidMapInfo++)
  1427. {
  1428. if ((guidMapInfo->Flags & WMIACPI_REGFLAG_EVENT) &&
  1429. (guidMapInfo->NotifyId.NotificationValue == NotifyValue))
  1430. {
  1431. outBufferSize = _WEDBufferSize;
  1432. outBuffer = ExAllocatePoolWithTag(NonPagedPool,
  1433. outBufferSize,
  1434. WmiAcpiPoolTag);
  1435. irpPassed = FALSE;
  1436. if (outBuffer != NULL)
  1437. {
  1438. status = WmiAcpiEvalMethodIntAsync(deviceObject,
  1439. deviceExtension->LowerPDO,
  1440. _WEDMethodAsULONG,
  1441. NotifyValue,
  1442. outBuffer,
  1443. outBufferSize,
  1444. WmiAcpiNotificationWorkItem,
  1445. (PVOID)&guidMapInfo->Guid,
  1446. &irpPassed);
  1447. } else {
  1448. WmiAcpiPrint(WmiAcpiError,
  1449. ("WmiAcpi: Event %d data lost due to insufficient resources\n",
  1450. NotifyValue));
  1451. }
  1452. if (! irpPassed)
  1453. {
  1454. //
  1455. // If ACPI could not be called with an irp then fire an
  1456. // empty event and cleanup.
  1457. status = WmiFireEvent(
  1458. deviceObject,
  1459. &guidMapInfo[i].Guid,
  1460. 0,
  1461. 0,
  1462. NULL);
  1463. if (outBuffer != NULL)
  1464. {
  1465. ExFreePool(outBuffer);
  1466. }
  1467. #if DBG
  1468. if (! NT_SUCCESS(status))
  1469. {
  1470. WmiAcpiPrint(WmiAcpiError,
  1471. ("WmiAcpi: %x notification %x IoWMIFireEvent -> %x\n",
  1472. deviceObject, NotifyValue, status));
  1473. }
  1474. #endif
  1475. }
  1476. }
  1477. }
  1478. #if 0
  1479. KeLowerIrql(oldIrql);
  1480. #endif
  1481. }
  1482. CHAR WmiAcpiXtoA(
  1483. UCHAR HexDigit
  1484. )
  1485. {
  1486. CHAR c;
  1487. PAGED_CODE();
  1488. if ((HexDigit >= 0x0a) && (HexDigit <= 0x0f))
  1489. {
  1490. c = HexDigit + 'A' - 0x0a;
  1491. } else {
  1492. c = HexDigit + '0';
  1493. }
  1494. return(c);
  1495. }
  1496. NTSTATUS
  1497. WmiAcpiFunctionControl(
  1498. IN PDEVICE_OBJECT DeviceObject,
  1499. IN PIRP Irp,
  1500. IN ULONG GuidIndex,
  1501. IN WMIENABLEDISABLECONTROL Function,
  1502. IN BOOLEAN Enable
  1503. )
  1504. /*++
  1505. Routine Description:
  1506. This routine is a callback into the driver to enabled or disable event
  1507. generation or data block collection. A device should only expect a
  1508. single enable when the first event or data consumer enables events or
  1509. data collection and a single disable when the last event or data
  1510. consumer disables events or data collection. Data blocks will only
  1511. receive collection enable/disable if they were registered as requiring
  1512. it.
  1513. Arguments:
  1514. DeviceObject is the device whose data block is being queried
  1515. GuidIndex is the index into the list of guids provided when the
  1516. device registered
  1517. Function specifies which functionality is being enabled or disabled
  1518. Enable is TRUE then the function is being enabled else disabled
  1519. Return Value:
  1520. status
  1521. --*/
  1522. {
  1523. NTSTATUS status = STATUS_SUCCESS;
  1524. PDEVICE_EXTENSION deviceExtension;
  1525. ULONG methodAsUlong;
  1526. PWMIACPIMAPINFO guidMapInfo;
  1527. USHORT resultType;
  1528. ULONG outBufferSize;
  1529. PWMILIB_CONTEXT wmilibContext;
  1530. CHAR c1, c2;
  1531. PAGED_CODE();
  1532. deviceExtension = DeviceObject->DeviceExtension;
  1533. wmilibContext = &deviceExtension->WmilibContext;
  1534. ASSERT(GuidIndex < wmilibContext->GuidCount);
  1535. guidMapInfo = &((PWMIACPIMAPINFO)deviceExtension->WmiAcpiMapInfo)[GuidIndex];
  1536. if (Function == WmiDataBlockControl)
  1537. {
  1538. methodAsUlong = WmiAcpiMethodToMethodAsUlong('W', 'C',
  1539. guidMapInfo->ObjectId[0],
  1540. guidMapInfo->ObjectId[1]);
  1541. } else {
  1542. if (guidMapInfo->Flags & WMIACPI_REGFLAG_EVENT)
  1543. {
  1544. if (Enable)
  1545. {
  1546. status = WmiAcpiGetAcpiInterfaces(deviceExtension,
  1547. deviceExtension->LowerPDO);
  1548. if (NT_SUCCESS(status))
  1549. {
  1550. if (! deviceExtension->AcpiNotificationEnabled)
  1551. {
  1552. status = deviceExtension->WmiAcpiDirectInterface.RegisterForDeviceNotifications(
  1553. deviceExtension->WmiAcpiDirectInterface.Context,
  1554. WmiAcpiNotificationRoutine,
  1555. DeviceObject);
  1556. deviceExtension->AcpiNotificationEnabled = NT_SUCCESS(status);
  1557. }
  1558. }
  1559. }
  1560. c1 = WmiAcpiXtoA((UCHAR)(guidMapInfo->NotifyId.NotificationValue >> 4));
  1561. c2 = WmiAcpiXtoA((UCHAR)(guidMapInfo->NotifyId.NotificationValue & 0x0f));
  1562. methodAsUlong = WmiAcpiMethodToMethodAsUlong('W', 'E',
  1563. c1,
  1564. c2);
  1565. } else {
  1566. methodAsUlong = 0;
  1567. }
  1568. }
  1569. //
  1570. // Query only valid for those datablocks registered as not events
  1571. // or methods.
  1572. if (NT_SUCCESS(status))
  1573. {
  1574. if (methodAsUlong != 0)
  1575. {
  1576. outBufferSize = 0;
  1577. status = WmiAcpiEvalMethodInt(deviceExtension->LowerPDO,
  1578. methodAsUlong,
  1579. Enable ? 1 : 0,
  1580. NULL,
  1581. &outBufferSize,
  1582. &resultType);
  1583. if (status == STATUS_BUFFER_TOO_SMALL)
  1584. {
  1585. //
  1586. // Since this operation is not supposed to return any results
  1587. // then we need to ignore the fact that the return buffer
  1588. // was too small.
  1589. status = STATUS_SUCCESS;
  1590. }
  1591. } else {
  1592. status = STATUS_SUCCESS;
  1593. }
  1594. } else {
  1595. WmiAcpiPrint(WmiAcpiError,
  1596. ("WmiAcpi: RegisterForDeviceNotification(%x) -> %x\n",
  1597. DeviceObject, status));
  1598. }
  1599. status = WmiCompleteRequest(
  1600. DeviceObject,
  1601. Irp,
  1602. status,
  1603. 0,
  1604. IO_NO_INCREMENT);
  1605. return(status);
  1606. }
  1607. NTSTATUS
  1608. WmiAcpiAsyncEvalCompletionRoutine(
  1609. IN PDEVICE_OBJECT DeviceObject,
  1610. IN PIRP Irp,
  1611. IN PVOID Context
  1612. )
  1613. {
  1614. PIRP_CONTEXT_BLOCK irpContextBlock;
  1615. irpContextBlock = (PIRP_CONTEXT_BLOCK)Context;
  1616. irpContextBlock->Status = Irp->IoStatus.Status;
  1617. irpContextBlock->OutBufferSize = (ULONG)Irp->IoStatus.Information;
  1618. irpContextBlock->OutBuffer = Irp->AssociatedIrp.SystemBuffer;
  1619. ExInitializeWorkItem( &irpContextBlock->WorkQueueItem,
  1620. irpContextBlock->CallerWorkItemRoutine,
  1621. irpContextBlock );
  1622. ExQueueWorkItem( &irpContextBlock->WorkQueueItem, DelayedWorkQueue );
  1623. IoFreeIrp(Irp);
  1624. return(STATUS_MORE_PROCESSING_REQUIRED);
  1625. }
  1626. NTSTATUS
  1627. WmiAcpiSendAsyncDownStreamIrp(
  1628. IN PDEVICE_OBJECT DeviceObject,
  1629. IN PDEVICE_OBJECT Pdo,
  1630. IN ULONG Ioctl,
  1631. IN ULONG InputBufferSize,
  1632. IN ULONG OutputBufferSize,
  1633. IN PVOID Buffer,
  1634. IN PWORKER_THREAD_ROUTINE CompletionRoutine,
  1635. IN PVOID CompletionContext,
  1636. IN PBOOLEAN IrpPassed
  1637. )
  1638. /*++
  1639. Routine Description:
  1640. Sends asynchronously an IRP_MJ_DEVICE_CONTROL to a device object
  1641. Arguments:
  1642. Pdo - The request is sent to this device object
  1643. Ioctl - the request
  1644. InputBuffer - The incoming request
  1645. InputSize - The size of the incoming request
  1646. OutputBuffer - The answer
  1647. OutputSize - The size of the answer buffer
  1648. Return Value:
  1649. NT Status of the operation
  1650. --*/
  1651. {
  1652. PIRP_CONTEXT_BLOCK irpContextBlock;
  1653. NTSTATUS status;
  1654. PIRP irp;
  1655. PIO_STACK_LOCATION irpSp;
  1656. irpContextBlock = ExAllocatePoolWithTag(NonPagedPool,
  1657. sizeof(IRP_CONTEXT_BLOCK),
  1658. WmiAcpiPoolTag);
  1659. if (irpContextBlock == NULL)
  1660. {
  1661. WmiAcpiPrint(WmiAcpiError,
  1662. ("WmiAcpiSendAsyncDownStreamIrp: %x Failed to allocate Irp Context Block\n",
  1663. DeviceObject));
  1664. *IrpPassed = FALSE;
  1665. return(STATUS_INSUFFICIENT_RESOURCES);
  1666. }
  1667. irp = IoAllocateIrp(Pdo->StackSize, TRUE);
  1668. if (!irp)
  1669. {
  1670. WmiAcpiPrint(WmiAcpiError,
  1671. ("WmiAcpiSendAsyncDownStreamIrp: %x Failed to allocate Irp\n",
  1672. DeviceObject));
  1673. *IrpPassed = FALSE;
  1674. ExFreePool(irpContextBlock);
  1675. return(STATUS_INSUFFICIENT_RESOURCES);
  1676. }
  1677. irpSp = IoGetNextIrpStackLocation( irp );
  1678. irpSp->MajorFunction = IRP_MJ_DEVICE_CONTROL;
  1679. irpSp->Parameters.DeviceIoControl.IoControlCode = Ioctl;
  1680. irpSp->Parameters.DeviceIoControl.OutputBufferLength = OutputBufferSize;
  1681. irpSp->Parameters.DeviceIoControl.InputBufferLength = InputBufferSize;
  1682. irp->AssociatedIrp.SystemBuffer = Buffer;
  1683. irp->Flags = IRP_BUFFERED_IO;
  1684. irpContextBlock->CallerContext = CompletionContext;
  1685. irpContextBlock->CallerWorkItemRoutine = CompletionRoutine;
  1686. irpContextBlock->DeviceObject = DeviceObject;
  1687. IoSetCompletionRoutine(irp,
  1688. WmiAcpiAsyncEvalCompletionRoutine,
  1689. irpContextBlock,
  1690. TRUE,
  1691. TRUE,
  1692. TRUE);
  1693. //
  1694. // Pass request to Pdo
  1695. //
  1696. status = IoCallDriver(Pdo, irp);
  1697. WmiAcpiPrint(WmiAcpiEvalTrace,
  1698. ("WmiAcpiSendAsyncDownStreamIrp: %x Irp %x completed %x! \n",
  1699. DeviceObject, irp, status )
  1700. );
  1701. *IrpPassed = TRUE;
  1702. return(status);
  1703. }
  1704. NTSTATUS
  1705. WmiAcpiSendDownStreamIrp(
  1706. IN PDEVICE_OBJECT Pdo,
  1707. IN ULONG Ioctl,
  1708. IN PVOID InputBuffer,
  1709. IN ULONG InputSize,
  1710. IN PVOID OutputBuffer,
  1711. IN ULONG *OutputBufferSize
  1712. )
  1713. /*++
  1714. Routine Description:
  1715. Sends synchronously an IRP_MJ_DEVICE_CONTROL to a device object
  1716. Arguments:
  1717. Pdo - The request is sent to this device object
  1718. Ioctl - the request
  1719. InputBuffer - The incoming request
  1720. InputSize - The size of the incoming request
  1721. OutputBuffer - The answer
  1722. OutputSize - The size of the answer buffer
  1723. Return Value:
  1724. NT Status of the operation
  1725. --*/
  1726. {
  1727. IO_STATUS_BLOCK ioBlock;
  1728. KEVENT event;
  1729. NTSTATUS status;
  1730. PIRP irp;
  1731. ULONG OutputSize = *OutputBufferSize;
  1732. PAGED_CODE();
  1733. //
  1734. // Initialize an event to wait on
  1735. //
  1736. KeInitializeEvent( &event, SynchronizationEvent, FALSE );
  1737. //
  1738. // Build the request
  1739. //
  1740. irp = IoBuildDeviceIoControlRequest(
  1741. Ioctl,
  1742. Pdo,
  1743. InputBuffer,
  1744. InputSize,
  1745. OutputBuffer,
  1746. OutputSize,
  1747. FALSE,
  1748. &event,
  1749. &ioBlock
  1750. );
  1751. if (!irp)
  1752. {
  1753. WmiAcpiPrint(WmiAcpiError,
  1754. ("WmiAcpiSendDownStreamIrp: %x Failed to allocate Irp\n",
  1755. Pdo
  1756. ));
  1757. return(STATUS_INSUFFICIENT_RESOURCES);
  1758. }
  1759. //
  1760. // Pass request to Pdo, always wait for completion routine
  1761. //
  1762. status = IoCallDriver(Pdo, irp);
  1763. if (status == STATUS_PENDING) {
  1764. //
  1765. // Wait for the irp to be completed, then grab the real status code
  1766. //
  1767. KeWaitForSingleObject(
  1768. &event,
  1769. Executive,
  1770. KernelMode,
  1771. FALSE,
  1772. NULL
  1773. );
  1774. }
  1775. //
  1776. // Always get the return status from the irp. We don't trust the return
  1777. // value since acpienum.c smashes it to STATUS_SUCCESS on memphis for some
  1778. // reason.
  1779. status = ioBlock.Status;
  1780. //
  1781. // Sanity check the data
  1782. //
  1783. *OutputBufferSize = (ULONG)ioBlock.Information;
  1784. WmiAcpiPrint(WmiAcpiEvalTrace,
  1785. ("WmiAcpiSendDownStreamIrp: %x Irp %x completed %x! \n",
  1786. Pdo, irp, status )
  1787. );
  1788. return(status);
  1789. }
  1790. ULONG WmiAcpiArgumentSize(
  1791. IN PACPI_METHOD_ARGUMENT Argument
  1792. )
  1793. /*++
  1794. Routine Description:
  1795. Determine the size needed to write the argument data into the WMI callers
  1796. output buffer. For integers and buffers this is done by getting the size
  1797. specified in the header. For strings this is done by determining the
  1798. size of the string in UNICODE and adding the size of the preceedeing
  1799. USHORT that holds the stirng length
  1800. Arguments:
  1801. Argument is the ACPI method argument whose for whose data the WMI size
  1802. is to be determined
  1803. Return Value:
  1804. WMI size for the argument data
  1805. --*/
  1806. {
  1807. ULONG size;
  1808. ANSI_STRING AnsiString;
  1809. PAGED_CODE();
  1810. if (Argument->Type == ACPI_METHOD_ARGUMENT_STRING)
  1811. {
  1812. AnsiString.Length = Argument->DataLength;
  1813. AnsiString.MaximumLength = Argument->DataLength;
  1814. AnsiString.Buffer = Argument->Data;
  1815. size = RtlAnsiStringToUnicodeSize(&AnsiString) + sizeof(USHORT);
  1816. } else {
  1817. size = Argument->DataLength;
  1818. }
  1819. return(size);
  1820. }
  1821. NTSTATUS WmiAcpiCopyArgument(
  1822. OUT PUCHAR Buffer,
  1823. IN ULONG BufferSize,
  1824. IN PACPI_METHOD_ARGUMENT Argument
  1825. )
  1826. /*++
  1827. Routine Description:
  1828. Copy the argument data from the ACPI method argument into the WMI output
  1829. buffer. For integer and buffers this is a straight copy, but for strings
  1830. the string is converted to UNICODE with a USHORT containing the length
  1831. (in bytes) of the string prependedded.
  1832. Arguments:
  1833. Buffer has output buffer to which to write the data
  1834. Argument is the ACPI method argument whose for whose data the WMI size
  1835. is to be determined
  1836. Return Value:
  1837. NT status code
  1838. --*/
  1839. {
  1840. NTSTATUS status;
  1841. ANSI_STRING AnsiString;
  1842. UNICODE_STRING UnicodeString;
  1843. PAGED_CODE();
  1844. if (Argument->Type == ACPI_METHOD_ARGUMENT_STRING)
  1845. {
  1846. AnsiString.Length = Argument->DataLength;
  1847. AnsiString.MaximumLength = Argument->DataLength;
  1848. AnsiString.Buffer = Argument->Data;
  1849. UnicodeString.MaximumLength = (USHORT)BufferSize;
  1850. UnicodeString.Length = 0;
  1851. UnicodeString.Buffer = (PWCHAR)(Buffer + sizeof(USHORT));
  1852. status = RtlAnsiStringToUnicodeString(&UnicodeString,
  1853. &AnsiString,
  1854. FALSE);
  1855. if (NT_SUCCESS(status))
  1856. {
  1857. *((PUSHORT)Buffer) = UnicodeString.Length + sizeof(WCHAR);
  1858. }
  1859. } else {
  1860. RtlCopyMemory(Buffer, Argument->Data, Argument->DataLength);
  1861. status = STATUS_SUCCESS;
  1862. }
  1863. return(status);
  1864. }
  1865. NTSTATUS WmiAcpiProcessResult(
  1866. IN NTSTATUS Status,
  1867. IN PACPI_EVAL_OUTPUT_BUFFER OutputBuffer,
  1868. IN ULONG OutputBufferSize,
  1869. OUT PUCHAR ResultBuffer,
  1870. OUT ULONG *ResultSize,
  1871. OUT USHORT *ResultType
  1872. )
  1873. /*++
  1874. Routine Description:
  1875. Validates the results from a method evaluation and returns a pointer to
  1876. the result data and the result size
  1877. Arguments:
  1878. Status has the return status from the method evaluation irp
  1879. OutputBufferSize is the number of bytes available in OutputBuffer that
  1880. ACPI can use to write the result data structure
  1881. OutputBuffer is the buffer acpi uses to return the result data structure
  1882. ResultBuffer is the buffer to return the result data.
  1883. *ResultSize on entry has the maximum number of bytes that can be
  1884. written into ResultBuffer. On return it has the actual number of
  1885. bytes written to result buffer if ResultBuffer is large enough. If
  1886. ResultBuffer is not large enough STATUS_BUFFER_TOO_SMALL is returned
  1887. and *ResultSize returns the actual number of bytes needed.
  1888. *ResultType returns with the data type for the method result
  1889. Return Value:
  1890. NT Status of the operation
  1891. --*/
  1892. {
  1893. PACPI_METHOD_ARGUMENT argument, nextArgument;
  1894. ULONG count;
  1895. ULONG i;
  1896. ULONG sizeNeeded;
  1897. ULONG maxSize;
  1898. ULONG argumentSize;
  1899. PUCHAR resultPtr;
  1900. PCHAR stringPtr;
  1901. PAGED_CODE();
  1902. if (NT_SUCCESS(Status))
  1903. {
  1904. ASSERT((OutputBufferSize == 0) ||
  1905. (OutputBufferSize >= sizeof(ACPI_EVAL_OUTPUT_BUFFER)));
  1906. if (OutputBufferSize != 0)
  1907. {
  1908. if (OutputBuffer->Signature != ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE)
  1909. {
  1910. Status = STATUS_UNSUCCESSFUL;
  1911. } else if (OutputBuffer->Count == 0) {
  1912. //
  1913. // Apparently no data is returned from the method
  1914. *ResultSize = 0;
  1915. } else {
  1916. count = OutputBuffer->Count;
  1917. argument = &OutputBuffer->Argument[0];
  1918. if (count == 1)
  1919. {
  1920. *ResultType = argument->Type;
  1921. } else {
  1922. //
  1923. // Return buffer as the data type of a package
  1924. *ResultType = ACPI_METHOD_ARGUMENT_BUFFER;
  1925. }
  1926. maxSize = *ResultSize;
  1927. sizeNeeded = 0;
  1928. for (i = 0; (i < count) ; i++)
  1929. {
  1930. nextArgument = ACPI_METHOD_NEXT_ARGUMENT(argument);
  1931. if ((argument->Type == ACPI_METHOD_ARGUMENT_STRING) &&
  1932. (argument->DataLength != 0))
  1933. {
  1934. //
  1935. // ACPI will return strings that are padded at the
  1936. // end with extra NULs. We want to strip out the
  1937. // padding.
  1938. stringPtr = argument->Data + argument->DataLength - 1;
  1939. while ((stringPtr >= argument->Data) &&
  1940. (*stringPtr == 0))
  1941. {
  1942. argument->DataLength--;
  1943. stringPtr--;
  1944. }
  1945. }
  1946. argumentSize = WmiAcpiArgumentSize(argument);
  1947. if (argument->Type == ACPI_METHOD_ARGUMENT_INTEGER)
  1948. {
  1949. //
  1950. // If the argument is an integer then we need to
  1951. // ensure that it is aligned properly on a 4 byte
  1952. // boundry.
  1953. sizeNeeded = (sizeNeeded + 3) & ~3;
  1954. } else if (argument->Type == ACPI_METHOD_ARGUMENT_STRING) {
  1955. //
  1956. // If the argument is an string then we need to
  1957. // ensure that it is aligned properly on a 2 byte
  1958. // boundry.
  1959. sizeNeeded = (sizeNeeded + 1) & ~1;
  1960. }
  1961. resultPtr = ResultBuffer + sizeNeeded;
  1962. sizeNeeded += argumentSize;
  1963. if (sizeNeeded <= maxSize)
  1964. {
  1965. //
  1966. // If there is enough room in the output buffer then
  1967. // copy the data to it.
  1968. WmiAcpiCopyArgument(resultPtr,
  1969. argumentSize,
  1970. argument);
  1971. } else {
  1972. Status = STATUS_BUFFER_TOO_SMALL;
  1973. }
  1974. argument = nextArgument;
  1975. }
  1976. *ResultSize = sizeNeeded;
  1977. }
  1978. } else {
  1979. //
  1980. // Result is a void
  1981. *ResultType = ACPI_METHOD_ARGUMENT_BUFFER;
  1982. *ResultSize = 0;
  1983. }
  1984. } else if (Status == STATUS_BUFFER_OVERFLOW) {
  1985. ASSERT((OutputBufferSize == 0) ||
  1986. (OutputBufferSize >= sizeof(ACPI_EVAL_OUTPUT_BUFFER)));
  1987. if (OutputBufferSize >= sizeof(ACPI_EVAL_OUTPUT_BUFFER))
  1988. {
  1989. //
  1990. // If the result is a package, that is has multiple arguments
  1991. // then we need to multiply the size needed by sizeof(WCHAR)
  1992. // in case the returned arguments are strings. We also
  1993. // include the size needed for the result data plus
  1994. // extra space for the argument descriptors since the result
  1995. // is a package.
  1996. *ResultSize = (OutputBuffer->Length * sizeof(WCHAR)) +
  1997. (OutputBuffer->Count * sizeof(ACPI_METHOD_ARGUMENT));
  1998. Status = STATUS_BUFFER_TOO_SMALL;
  1999. } else {
  2000. Status = STATUS_UNSUCCESSFUL;
  2001. }
  2002. } else {
  2003. //
  2004. // We much all other ACPI status codes into this one since the ACPI
  2005. // codes are not mapped to any user mode error codes.
  2006. Status = STATUS_UNSUCCESSFUL;
  2007. }
  2008. return(Status);
  2009. }
  2010. NTSTATUS WmiAcpiSendMethodEvalIrp(
  2011. IN PDEVICE_OBJECT DeviceObject,
  2012. IN PUCHAR InputBuffer,
  2013. IN ULONG InputBufferSize,
  2014. OUT PUCHAR ResultBuffer,
  2015. IN OUT ULONG *ResultSize,
  2016. OUT USHORT *ResultType
  2017. )
  2018. /*++
  2019. Routine Description:
  2020. Evaluates a simple ACPI method that take an integer and a buffer argument
  2021. and returns a buffer.
  2022. Arguments:
  2023. DeviceObject is device object that will evaluate the method
  2024. InputBuffer is a buffer containing an ACPI_EVAL_INPUT_BUFFER_* structure
  2025. InputBufferSize is the size of InputBuffer in bytes
  2026. ResultBuffer is the WMI buffer to return the result data
  2027. *ResultSize on entry has the maximum number of bytes that can be
  2028. written into ResultBuffer. On return it has the actual number of
  2029. bytes written to result buffer if ResultBuffer is large enough. If
  2030. ResultBuffer is not large enough STATUS_BUFFER_TOO_SMALL is returned
  2031. and *ResultSize returns the actual number of bytes needed.
  2032. *ResultType returns with the data type for the method result
  2033. Return Value:
  2034. NT Status of the operation
  2035. --*/
  2036. {
  2037. NTSTATUS status;
  2038. PACPI_EVAL_OUTPUT_BUFFER outputBuffer;
  2039. ULONG outputBufferSize;
  2040. PAGED_CODE();
  2041. outputBufferSize = *ResultSize + ACPI_EVAL_OUTPUT_FUDGE;
  2042. outputBuffer = ExAllocatePoolWithTag(PagedPool,
  2043. outputBufferSize,
  2044. WmiAcpiPoolTag);
  2045. if (outputBuffer != NULL)
  2046. {
  2047. WmiAcpiPrint(WmiAcpiEvalTrace,
  2048. ("WmiAcpiSendMethodEvalIrp: %x Eval Method %c%c%c%c \n",
  2049. DeviceObject,
  2050. ((PACPI_EVAL_INPUT_BUFFER)InputBuffer)->MethodName[0],
  2051. ((PACPI_EVAL_INPUT_BUFFER)InputBuffer)->MethodName[1],
  2052. ((PACPI_EVAL_INPUT_BUFFER)InputBuffer)->MethodName[2],
  2053. ((PACPI_EVAL_INPUT_BUFFER)InputBuffer)->MethodName[3]
  2054. )
  2055. );
  2056. status = WmiAcpiSendDownStreamIrp(
  2057. DeviceObject,
  2058. IOCTL_ACPI_EVAL_METHOD,
  2059. InputBuffer,
  2060. InputBufferSize,
  2061. outputBuffer,
  2062. &outputBufferSize);
  2063. WmiAcpiPrint(WmiAcpiEvalTrace,
  2064. ("WmiAcpiSendMethodEvalIrp: %x Evaluated Method %c%c%c%c -> %x \n",
  2065. DeviceObject,
  2066. ((PACPI_EVAL_INPUT_BUFFER)InputBuffer)->MethodName[0],
  2067. ((PACPI_EVAL_INPUT_BUFFER)InputBuffer)->MethodName[1],
  2068. ((PACPI_EVAL_INPUT_BUFFER)InputBuffer)->MethodName[2],
  2069. ((PACPI_EVAL_INPUT_BUFFER)InputBuffer)->MethodName[3],
  2070. status
  2071. )
  2072. );
  2073. status = WmiAcpiProcessResult(status,
  2074. outputBuffer,
  2075. outputBufferSize,
  2076. ResultBuffer,
  2077. ResultSize,
  2078. ResultType);
  2079. if (outputBuffer != NULL)
  2080. {
  2081. ExFreePool(outputBuffer);
  2082. }
  2083. } else {
  2084. status = STATUS_INSUFFICIENT_RESOURCES;
  2085. }
  2086. return(status);
  2087. }
  2088. NTSTATUS WmiAcpiEvalMethod(
  2089. IN PDEVICE_OBJECT DeviceObject,
  2090. IN ULONG MethodAsUlong,
  2091. OUT PUCHAR ResultBuffer,
  2092. IN OUT ULONG *ResultSize,
  2093. OUT USHORT *ResultType
  2094. )
  2095. /*++
  2096. Routine Description:
  2097. Evaluates a simple ACPI method that take no input arguments and returns
  2098. a buffer.
  2099. Arguments:
  2100. DeviceObject is device object that will evaluate the method
  2101. MethodAsUlong is the name of the method packed in a ULONG
  2102. ResultBuffer is the buffer to return the result data
  2103. *ResultSize on entry has the maximum number of bytes that can be
  2104. written into ResultBuffer. On return it has the actual number of
  2105. bytes written to result buffer if ResultBuffer is large enough. If
  2106. ResultBuffer is not large enough STATUS_BUFFER_TOO_SMALL is returned
  2107. and *ResultSize returns the actual number of bytes needed.
  2108. *ResultType returns with the data type for the method result
  2109. Return Value:
  2110. NT Status of the operation
  2111. --*/
  2112. {
  2113. NTSTATUS status;
  2114. ACPI_EVAL_INPUT_BUFFER inputBuffer;
  2115. PAGED_CODE();
  2116. inputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE;
  2117. inputBuffer.MethodNameAsUlong = MethodAsUlong;
  2118. status = WmiAcpiSendMethodEvalIrp(DeviceObject,
  2119. (PUCHAR)&inputBuffer,
  2120. sizeof(ACPI_EVAL_INPUT_BUFFER),
  2121. ResultBuffer,
  2122. ResultSize,
  2123. ResultType);
  2124. return(status);
  2125. }
  2126. NTSTATUS WmiAcpiEvalMethodInt(
  2127. IN PDEVICE_OBJECT DeviceObject,
  2128. IN ULONG MethodAsUlong,
  2129. IN ULONG IntegerArgument,
  2130. OUT PUCHAR ResultBuffer,
  2131. IN OUT ULONG *ResultSize,
  2132. OUT USHORT *ResultType
  2133. )
  2134. /*++
  2135. Routine Description:
  2136. Evaluates a simple ACPI method that take a single integer argument and
  2137. returns a buffer.
  2138. Arguments:
  2139. DeviceObject is device object that will evaluate the method
  2140. MethodAsUlong is the name of the method packed in a ULONG
  2141. IntegerArgument is the integer argument to pass to the method
  2142. ResultBuffer is the buffer to return the result data
  2143. *ResultSize on entry has the maximum number of bytes that can be
  2144. written into ResultBuffer. On return it has the actual number of
  2145. bytes written to result buffer if ResultBuffer is large enough. If
  2146. ResultBuffer is not large enough STATUS_BUFFER_TOO_SMALL is returned
  2147. and *ResultSize returns the actual number of bytes needed.
  2148. *ResultType returns with the data type for the method result
  2149. Return Value:
  2150. NT Status of the operation
  2151. --*/
  2152. {
  2153. NTSTATUS status;
  2154. ACPI_EVAL_INPUT_BUFFER_SIMPLE_INTEGER inputBuffer;
  2155. PAGED_CODE();
  2156. inputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIMPLE_INTEGER_SIGNATURE;
  2157. inputBuffer.MethodNameAsUlong = MethodAsUlong;
  2158. inputBuffer.IntegerArgument = IntegerArgument;
  2159. status = WmiAcpiSendMethodEvalIrp(DeviceObject,
  2160. (PUCHAR)&inputBuffer,
  2161. sizeof(ACPI_EVAL_INPUT_BUFFER_SIMPLE_INTEGER),
  2162. ResultBuffer,
  2163. ResultSize,
  2164. ResultType);
  2165. return(status);
  2166. }
  2167. NTSTATUS WmiAcpiEvalMethodIntBuffer(
  2168. IN PDEVICE_OBJECT DeviceObject,
  2169. IN ULONG MethodAsUlong,
  2170. IN ULONG IntegerArgument,
  2171. IN ULONG BufferArgumentSize,
  2172. IN PUCHAR BufferArgument,
  2173. OUT PUCHAR ResultBuffer,
  2174. IN OUT ULONG *ResultSize,
  2175. OUT USHORT *ResultType
  2176. )
  2177. /*++
  2178. Routine Description:
  2179. Evaluates a simple ACPI method that take an integer and a buffer argument
  2180. and returns a buffer.
  2181. Arguments:
  2182. DeviceObject is device object that will evaluate the method
  2183. MethodAsUlong is the name of the method packed in a ULONG
  2184. IntegerArgument is the integer argument to pass to the method
  2185. BufferArgumentSize is the number of bytes contained in the buffer argument
  2186. BufferArgument is a pointer to the buffer argument
  2187. ResultBuffer is the buffer to return the result data
  2188. *ResultSize on entry has the maximum number of bytes that can be
  2189. written into ResultBuffer. On return it has the actual number of
  2190. bytes written to result buffer if ResultBuffer is large enough. If
  2191. ResultBuffer is not large enough STATUS_BUFFER_TOO_SMALL is returned
  2192. and *ResultSize returns the actual number of bytes needed.
  2193. *ResultType returns with the data type for the method result
  2194. Return Value:
  2195. NT Status of the operation
  2196. --*/
  2197. {
  2198. NTSTATUS status;
  2199. PACPI_EVAL_INPUT_BUFFER_COMPLEX inputBuffer;
  2200. ULONG inputBufferSize;
  2201. PACPI_METHOD_ARGUMENT argument;
  2202. PAGED_CODE();
  2203. inputBufferSize = sizeof(ACPI_EVAL_INPUT_BUFFER_COMPLEX) +
  2204. sizeof(ACPI_METHOD_ARGUMENT) +
  2205. BufferArgumentSize;
  2206. inputBuffer = ExAllocatePoolWithTag(PagedPool,
  2207. inputBufferSize,
  2208. WmiAcpiPoolTag);
  2209. if (inputBuffer != NULL)
  2210. {
  2211. inputBuffer->Signature = ACPI_EVAL_INPUT_BUFFER_COMPLEX_SIGNATURE;
  2212. inputBuffer->MethodNameAsUlong = MethodAsUlong;
  2213. inputBuffer->ArgumentCount = 2;
  2214. inputBuffer->Size = inputBufferSize;
  2215. argument = &inputBuffer->Argument[0];
  2216. argument->Type = ACPI_METHOD_ARGUMENT_INTEGER;
  2217. argument->DataLength = sizeof(ULONG);
  2218. argument->Argument = IntegerArgument;
  2219. argument = ACPI_METHOD_NEXT_ARGUMENT(argument);
  2220. argument->Type = ACPI_METHOD_ARGUMENT_BUFFER;
  2221. argument->DataLength = (USHORT)BufferArgumentSize;
  2222. RtlCopyMemory(argument->Data,
  2223. BufferArgument,
  2224. argument->DataLength);
  2225. status = WmiAcpiSendMethodEvalIrp(DeviceObject,
  2226. (PUCHAR)inputBuffer,
  2227. inputBufferSize,
  2228. ResultBuffer,
  2229. ResultSize,
  2230. ResultType);
  2231. ExFreePool(inputBuffer);
  2232. } else {
  2233. status = STATUS_INSUFFICIENT_RESOURCES;
  2234. }
  2235. return(status);
  2236. }
  2237. NTSTATUS WmiAcpiEvalMethodIntIntBuffer(
  2238. IN PDEVICE_OBJECT DeviceObject,
  2239. IN ULONG MethodAsUlong,
  2240. IN ULONG IntegerArgument,
  2241. IN ULONG IntegerArgument2,
  2242. IN ULONG BufferArgumentSize,
  2243. IN PUCHAR BufferArgument,
  2244. OUT PUCHAR ResultBuffer,
  2245. IN OUT ULONG *ResultSize,
  2246. OUT USHORT *ResultType
  2247. )
  2248. /*++
  2249. Routine Description:
  2250. Evaluates a simple ACPI method that take an integer and a buffer argument
  2251. and returns a buffer.
  2252. Arguments:
  2253. DeviceObject is device object that will evaluate the method
  2254. MethodAsUlong is the name of the method packed in a ULONG
  2255. IntegerArgument is the integer argument to pass to the method
  2256. IntegerArgument2 is the second integer argument to pass to the method
  2257. BufferArgumentSize is the number of bytes contained in the buffer argument
  2258. BufferArgument is a pointer to the buffer argument
  2259. ResultBuffer is the buffer to return the result data
  2260. *ResultSize on entry has the maximum number of bytes that can be
  2261. written into ResultBuffer. On return it has the actual number of
  2262. bytes written to result buffer if ResultBuffer is large enough. If
  2263. ResultBuffer is not large enough STATUS_BUFFER_TOO_SMALL is returned
  2264. and *ResultSize returns the actual number of bytes needed.
  2265. *ResultType returns with the data type for the method result
  2266. Return Value:
  2267. NT Status of the operation
  2268. --*/
  2269. {
  2270. NTSTATUS status;
  2271. PACPI_EVAL_INPUT_BUFFER_COMPLEX inputBuffer;
  2272. ULONG inputBufferSize;
  2273. PACPI_METHOD_ARGUMENT argument;
  2274. PAGED_CODE();
  2275. inputBufferSize = sizeof(ACPI_EVAL_INPUT_BUFFER_COMPLEX) +
  2276. 2 * sizeof(ACPI_METHOD_ARGUMENT) +
  2277. BufferArgumentSize;
  2278. inputBuffer = ExAllocatePoolWithTag(PagedPool,
  2279. inputBufferSize,
  2280. WmiAcpiPoolTag);
  2281. if (inputBuffer != NULL)
  2282. {
  2283. inputBuffer->Signature = ACPI_EVAL_INPUT_BUFFER_COMPLEX_SIGNATURE;
  2284. inputBuffer->MethodNameAsUlong = MethodAsUlong;
  2285. inputBuffer->ArgumentCount = 3;
  2286. inputBuffer->Size = inputBufferSize;
  2287. argument = &inputBuffer->Argument[0];
  2288. argument->Type = ACPI_METHOD_ARGUMENT_INTEGER;
  2289. argument->DataLength = sizeof(ULONG);
  2290. argument->Argument = IntegerArgument;
  2291. argument = ACPI_METHOD_NEXT_ARGUMENT(argument);
  2292. argument->Type = ACPI_METHOD_ARGUMENT_INTEGER;
  2293. argument->DataLength = sizeof(ULONG);
  2294. argument->Argument = IntegerArgument2;
  2295. argument = ACPI_METHOD_NEXT_ARGUMENT(argument);
  2296. argument->Type = ACPI_METHOD_ARGUMENT_BUFFER;
  2297. argument->DataLength = (USHORT)BufferArgumentSize;
  2298. RtlCopyMemory(argument->Data,
  2299. BufferArgument,
  2300. argument->DataLength);
  2301. status = WmiAcpiSendMethodEvalIrp(DeviceObject,
  2302. (PUCHAR)inputBuffer,
  2303. inputBufferSize,
  2304. ResultBuffer,
  2305. ResultSize,
  2306. ResultType);
  2307. ExFreePool(inputBuffer);
  2308. } else {
  2309. status = STATUS_INSUFFICIENT_RESOURCES;
  2310. }
  2311. return(status);
  2312. }
  2313. NTSTATUS WmiAcpiEvalMethodIntString(
  2314. IN PDEVICE_OBJECT DeviceObject,
  2315. IN ULONG MethodAsUlong,
  2316. IN ULONG IntegerArgument,
  2317. IN PUNICODE_STRING StringArgument,
  2318. OUT PUCHAR ResultBuffer,
  2319. IN OUT ULONG *ResultSize,
  2320. OUT USHORT *ResultType
  2321. )
  2322. /*++
  2323. Routine Description:
  2324. Evaluates a simple ACPI method that take an integer and a string argument
  2325. and returns a buffer.
  2326. Arguments:
  2327. DeviceObject is device object that will evaluate the method
  2328. MethodAsUlong is the name of the method packed in a ULONG
  2329. IntegerArgument is the integer argument to pass to the method
  2330. StringArgument is a pointer to the string argument. This will be
  2331. converted from unicode to ansi
  2332. ResultBuffer is the buffer to return the result data
  2333. *ResultSize on entry has the maximum number of bytes that can be
  2334. written into ResultBuffer. On return it has the actual number of
  2335. bytes written to result buffer if ResultBuffer is large enough. If
  2336. ResultBuffer is not large enough STATUS_BUFFER_TOO_SMALL is returned
  2337. and *ResultSize returns the actual number of bytes needed.
  2338. *ResultType returns with the data type for the method result
  2339. Return Value:
  2340. NT Status of the operation
  2341. --*/
  2342. {
  2343. NTSTATUS status;
  2344. PACPI_EVAL_INPUT_BUFFER_COMPLEX inputBuffer;
  2345. ULONG inputBufferSize;
  2346. PACPI_METHOD_ARGUMENT argument;
  2347. USHORT stringLength;
  2348. ANSI_STRING ansiString;
  2349. PAGED_CODE();
  2350. stringLength = (USHORT)(RtlUnicodeStringToAnsiSize(StringArgument) + 1);
  2351. inputBufferSize = sizeof(ACPI_EVAL_INPUT_BUFFER_COMPLEX) +
  2352. sizeof(ACPI_METHOD_ARGUMENT) +
  2353. stringLength;
  2354. inputBuffer = ExAllocatePoolWithTag(PagedPool,
  2355. inputBufferSize,
  2356. WmiAcpiPoolTag);
  2357. if (inputBuffer != NULL)
  2358. {
  2359. inputBuffer->Signature = ACPI_EVAL_INPUT_BUFFER_COMPLEX_SIGNATURE;
  2360. inputBuffer->MethodNameAsUlong = MethodAsUlong;
  2361. inputBuffer->ArgumentCount = 2;
  2362. inputBuffer->Size = inputBufferSize;
  2363. argument = &inputBuffer->Argument[0];
  2364. argument->Type = ACPI_METHOD_ARGUMENT_INTEGER;
  2365. argument->DataLength = sizeof(ULONG);
  2366. argument->Argument = IntegerArgument;
  2367. argument = ACPI_METHOD_NEXT_ARGUMENT(argument);
  2368. argument->Type = ACPI_METHOD_ARGUMENT_STRING;
  2369. ansiString.MaximumLength = stringLength;
  2370. ansiString.Length = 0;
  2371. ansiString.Buffer = (PCHAR)&argument->Data;
  2372. status = RtlUnicodeStringToAnsiString(&ansiString,
  2373. StringArgument,
  2374. FALSE);
  2375. if (NT_SUCCESS(status))
  2376. {
  2377. argument->DataLength = ansiString.Length;
  2378. status = WmiAcpiSendMethodEvalIrp(DeviceObject,
  2379. (PUCHAR)inputBuffer,
  2380. inputBufferSize,
  2381. ResultBuffer,
  2382. ResultSize,
  2383. ResultType);
  2384. } else {
  2385. WmiAcpiPrint(WmiAcpiError,
  2386. ("WmiAcpi: %x unicode to ansi conversion failed %x\n",
  2387. DeviceObject,
  2388. status));
  2389. }
  2390. ExFreePool(inputBuffer);
  2391. } else {
  2392. status = STATUS_INSUFFICIENT_RESOURCES;
  2393. }
  2394. return(status);
  2395. }
  2396. NTSTATUS WmiAcpiEvalMethodIntIntString(
  2397. IN PDEVICE_OBJECT DeviceObject,
  2398. IN ULONG MethodAsUlong,
  2399. IN ULONG IntegerArgument,
  2400. IN ULONG IntegerArgument2,
  2401. IN PUNICODE_STRING StringArgument,
  2402. OUT PUCHAR ResultBuffer,
  2403. IN OUT ULONG *ResultSize,
  2404. OUT USHORT *ResultType
  2405. )
  2406. /*++
  2407. Routine Description:
  2408. Evaluates a simple ACPI method that take an integer and a string argument
  2409. and returns a buffer.
  2410. Arguments:
  2411. DeviceObject is device object that will evaluate the method
  2412. MethodAsUlong is the name of the method packed in a ULONG
  2413. IntegerArgument is the integer argument to pass to the method
  2414. IntegerArgument2 is the second integer argument to pass to the method
  2415. StringArgument is a pointer to the string argument. This will be
  2416. converted from unicode to ansi
  2417. ResultBuffer is the buffer to return the result data
  2418. *ResultSize on entry has the maximum number of bytes that can be
  2419. written into ResultBuffer. On return it has the actual number of
  2420. bytes written to result buffer if ResultBuffer is large enough. If
  2421. ResultBuffer is not large enough STATUS_BUFFER_TOO_SMALL is returned
  2422. and *ResultSize returns the actual number of bytes needed.
  2423. *ResultType returns with the data type for the method result
  2424. Return Value:
  2425. NT Status of the operation
  2426. --*/
  2427. {
  2428. NTSTATUS status;
  2429. PACPI_EVAL_INPUT_BUFFER_COMPLEX inputBuffer;
  2430. ULONG inputBufferSize;
  2431. PACPI_METHOD_ARGUMENT argument;
  2432. USHORT stringLength;
  2433. ANSI_STRING ansiString;
  2434. PAGED_CODE();
  2435. stringLength = (USHORT)(RtlUnicodeStringToAnsiSize(StringArgument) + 1);
  2436. inputBufferSize = sizeof(ACPI_EVAL_INPUT_BUFFER_COMPLEX) +
  2437. 2 * sizeof(ACPI_METHOD_ARGUMENT) +
  2438. stringLength;
  2439. inputBuffer = ExAllocatePoolWithTag(PagedPool,
  2440. inputBufferSize,
  2441. WmiAcpiPoolTag);
  2442. if (inputBuffer != NULL)
  2443. {
  2444. inputBuffer->Signature = ACPI_EVAL_INPUT_BUFFER_COMPLEX_SIGNATURE;
  2445. inputBuffer->MethodNameAsUlong = MethodAsUlong;
  2446. inputBuffer->ArgumentCount = 3;
  2447. inputBuffer->Size = inputBufferSize;
  2448. argument = &inputBuffer->Argument[0];
  2449. argument->Type = ACPI_METHOD_ARGUMENT_INTEGER;
  2450. argument->DataLength = sizeof(ULONG);
  2451. argument->Argument = IntegerArgument;
  2452. argument = ACPI_METHOD_NEXT_ARGUMENT(argument);
  2453. argument->Type = ACPI_METHOD_ARGUMENT_INTEGER;
  2454. argument->DataLength = sizeof(ULONG);
  2455. argument->Argument = IntegerArgument2;
  2456. argument = ACPI_METHOD_NEXT_ARGUMENT(argument);
  2457. argument->Type = ACPI_METHOD_ARGUMENT_STRING;
  2458. ansiString.MaximumLength = stringLength;
  2459. ansiString.Length = 0;
  2460. ansiString.Buffer = (PCHAR)&argument->Data;
  2461. status = RtlUnicodeStringToAnsiString(&ansiString,
  2462. StringArgument,
  2463. FALSE);
  2464. if (NT_SUCCESS(status))
  2465. {
  2466. argument->DataLength = ansiString.Length;
  2467. status = WmiAcpiSendMethodEvalIrp(DeviceObject,
  2468. (PUCHAR)inputBuffer,
  2469. inputBufferSize,
  2470. ResultBuffer,
  2471. ResultSize,
  2472. ResultType);
  2473. } else {
  2474. WmiAcpiPrint(WmiAcpiError,
  2475. ("WmiAcpi: %x unicode to ansi conversion failed %x\n",
  2476. DeviceObject,
  2477. status));
  2478. }
  2479. ExFreePool(inputBuffer);
  2480. } else {
  2481. status = STATUS_INSUFFICIENT_RESOURCES;
  2482. }
  2483. return(status);
  2484. }
  2485. NTSTATUS WmiAcpiEvalMethodIntAsync(
  2486. IN PDEVICE_OBJECT DeviceObject,
  2487. IN PDEVICE_OBJECT Pdo,
  2488. IN ULONG MethodAsUlong,
  2489. IN ULONG IntegerArgument,
  2490. OUT PUCHAR ResultBuffer,
  2491. IN ULONG ResultBufferSize,
  2492. IN PWORKER_THREAD_ROUTINE CompletionRoutine,
  2493. IN PVOID CompletionContext,
  2494. IN PBOOLEAN IrpPassed
  2495. )
  2496. /*++
  2497. Routine Description:
  2498. Evaluates a simple ACPI method that take a single integer argument and
  2499. returns a buffer.
  2500. Arguments:
  2501. DeviceObject is device object that will evaluate the method
  2502. MethodAsUlong is the name of the method packed in a ULONG
  2503. IntegerArgument is the integer argument to pass to the method
  2504. ResultBuffer is the buffer to return the result data
  2505. *ResultSize on entry has the maximum number of bytes that can be
  2506. written into ResultBuffer. On return it has the actual number of
  2507. bytes written to result buffer if ResultBuffer is large enough. If
  2508. ResultBuffer is not large enough STATUS_BUFFER_TOO_SMALL is returned
  2509. and *ResultSize returns the actual number of bytes needed.
  2510. *ResultType returns with the data type for the method result
  2511. Return Value:
  2512. NT Status of the operation
  2513. --*/
  2514. {
  2515. NTSTATUS status;
  2516. PACPI_EVAL_INPUT_BUFFER_SIMPLE_INTEGER inputBuffer;
  2517. ASSERT(ResultBuffer != NULL);
  2518. ASSERT(ResultBufferSize >= sizeof(ACPI_EVAL_INPUT_BUFFER_SIMPLE_INTEGER));
  2519. inputBuffer = (PACPI_EVAL_INPUT_BUFFER_SIMPLE_INTEGER)ResultBuffer;
  2520. inputBuffer->Signature = ACPI_EVAL_INPUT_BUFFER_SIMPLE_INTEGER_SIGNATURE;
  2521. inputBuffer->MethodNameAsUlong = MethodAsUlong;
  2522. inputBuffer->IntegerArgument = IntegerArgument;
  2523. status = WmiAcpiSendAsyncDownStreamIrp(
  2524. DeviceObject,
  2525. Pdo,
  2526. IOCTL_ACPI_ASYNC_EVAL_METHOD,
  2527. sizeof(ACPI_EVAL_INPUT_BUFFER_SIMPLE_INTEGER),
  2528. ResultBufferSize,
  2529. ResultBuffer,
  2530. CompletionRoutine,
  2531. CompletionContext,
  2532. IrpPassed);
  2533. return(status);
  2534. }