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.

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