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.

5203 lines
122 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. get.c
  5. Abstract:
  6. This contains some some high-level routines to access data from
  7. the interpreter and do some processing upon the result. The result
  8. requires some manipulation to be useful to the OS. An example would
  9. be reading the _HID and turning that into a DeviceID
  10. Note: There are four basic data types that can be processed by this
  11. module.
  12. The Integer and Data ones assume that the caller is providing the
  13. storage required for the answer
  14. The Buffer and String ones assume that the function should allocate
  15. memory for the answer
  16. Author:
  17. Stephane Plante (splante)
  18. Environment:
  19. NT Kernel Model Driver only
  20. --*/
  21. #include "pch.h"
  22. NTSTATUS
  23. ACPIGet(
  24. IN PVOID Target,
  25. IN ULONG ObjectID,
  26. IN ULONG Flags,
  27. IN PVOID SimpleArgument,
  28. IN ULONG SimpleArgumentSize,
  29. IN PFNACB CallBackRoutine OPTIONAL,
  30. IN PVOID CallBackContext OPTIONAL,
  31. OUT PVOID *Buffer,
  32. OUT ULONG *BufferSize OPTIONAL
  33. )
  34. /*++
  35. Routine Description:
  36. Every Macro calls the above function. It is the only one that is
  37. actually exported outside of this file. The purpose of the function
  38. is to provide a wrapper that others can call.
  39. This version allows the user to specificy an input argument
  40. Arguments:
  41. AcpiObject - The parent object
  42. ObjectID - The name of the control method to run
  43. Flags - Some things that help us in evaluating the result
  44. SimpleArgument - The argument to use
  45. CallBackRoutine - If this is an Async call, then call this when done
  46. CallBackContext - Context to pass when completed
  47. Buffer - Where to write the answer
  48. Buffersize - How large the buffer is
  49. Return Value:
  50. NTSTATUS
  51. --*/
  52. {
  53. BOOLEAN async = FALSE;
  54. KIRQL oldIrql;
  55. NTSTATUS status;
  56. OBJDATA argument;
  57. POBJDATA argumentPtr = NULL;
  58. PACPI_GET_REQUEST request = NULL;
  59. PDEVICE_EXTENSION deviceExtension = NULL;
  60. PFNACB completionRoutine = NULL;
  61. PNSOBJ acpiObject;
  62. ULONG argumentCount = 0;
  63. if ( (Flags & GET_PROP_ASYNCHRONOUS) ) {
  64. async = TRUE;
  65. }
  66. if ( (Flags & GET_PROP_NSOBJ_INTERFACE) ) {
  67. acpiObject = (PNSOBJ) Target;
  68. } else {
  69. deviceExtension = (PDEVICE_EXTENSION) Target;
  70. acpiObject = deviceExtension->AcpiObject;
  71. }
  72. //
  73. // Determine the completion routine that we should use
  74. //
  75. switch( (Flags & GET_REQUEST_MASK) ) {
  76. case GET_REQUEST_BUFFER:
  77. completionRoutine = ACPIGetWorkerForBuffer;
  78. break;
  79. case GET_REQUEST_DATA:
  80. completionRoutine = ACPIGetWorkerForData;
  81. break;
  82. case GET_REQUEST_INTEGER:
  83. completionRoutine = ACPIGetWorkerForInteger;
  84. //
  85. // If this is a GET_CONVERT_TO_DEVICE_PRESENCE request, and the target
  86. // is a dock profile provider, we need to use a different AcpiObject
  87. //
  88. if ( (Flags & GET_CONVERT_TO_DEVICE_PRESENCE) &&
  89. !(Flags & GET_PROP_NSOBJ_INTERFACE) ) {
  90. if (deviceExtension->Flags & DEV_PROP_DOCK) {
  91. ASSERT( deviceExtension->Dock.CorrospondingAcpiDevice );
  92. acpiObject = deviceExtension->Dock.CorrospondingAcpiDevice->AcpiObject;
  93. }
  94. }
  95. break;
  96. case GET_REQUEST_STRING:
  97. completionRoutine = ACPIGetWorkerForString;
  98. break;
  99. case GET_REQUEST_NOTHING:
  100. completionRoutine = ACPIGetWorkerForNothing;
  101. break;
  102. default:
  103. return STATUS_INVALID_PARAMETER_3;
  104. }
  105. //
  106. // Lets try to build the input argument (if possible)
  107. //
  108. if ( (Flags & GET_EVAL_MASK) ) {
  109. ASSERT( SimpleArgumentSize != 0 );
  110. //
  111. // Initialize the input argument
  112. //
  113. RtlZeroMemory( &argument, sizeof(OBJDATA) );
  114. //
  115. // Handle the various different cases
  116. //
  117. if ( (Flags & GET_EVAL_SIMPLE_INTEGER) ) {
  118. argument.dwDataType = OBJTYPE_INTDATA;
  119. argument.uipDataValue = ( (ULONG_PTR) SimpleArgument );
  120. } else if ( (Flags & GET_EVAL_SIMPLE_STRING) ) {
  121. argument.dwDataType = OBJTYPE_STRDATA;
  122. argument.dwDataLen = SimpleArgumentSize;
  123. argument.pbDataBuff = ( (PUCHAR) SimpleArgument );
  124. } else if ( (Flags & GET_EVAL_SIMPLE_BUFFER) ) {
  125. argument.dwDataType = OBJTYPE_BUFFDATA;
  126. argument.dwDataLen = SimpleArgumentSize;
  127. argument.pbDataBuff = ( (PUCHAR) SimpleArgument );
  128. } else {
  129. ACPIInternalError( ACPI_GET );
  130. }
  131. //
  132. // Remember that we have an argument
  133. //
  134. argumentCount = 1;
  135. argumentPtr = &argument;
  136. }
  137. //
  138. // We need to allocate the request to hold the context information
  139. // We have no choice but to allocate this from NonPagedPool --- the
  140. // interpreter will be calling us at DPC level
  141. //
  142. request = ExAllocatePoolWithTag(
  143. NonPagedPool,
  144. sizeof(ACPI_GET_REQUEST),
  145. ACPI_MISC_POOLTAG
  146. );
  147. if (request == NULL) {
  148. return STATUS_INSUFFICIENT_RESOURCES;
  149. }
  150. RtlZeroMemory( request, sizeof(ACPI_GET_REQUEST) );
  151. //
  152. // Propogate the information that the caller provided
  153. //
  154. request->Flags = Flags;
  155. request->ObjectID = ObjectID;
  156. request->DeviceExtension = deviceExtension;
  157. request->AcpiObject = acpiObject;
  158. request->CallBackRoutine = CallBackRoutine;
  159. request->CallBackContext = CallBackContext;
  160. request->Buffer = Buffer;
  161. request->BufferSize = BufferSize;
  162. //
  163. // Make sure that we queue the request onto the list that we use to
  164. // keep track of the requests
  165. //
  166. KeAcquireSpinLock( &AcpiGetLock, &oldIrql );
  167. InsertTailList(
  168. &(AcpiGetListEntry),
  169. &(request->ListEntry)
  170. );
  171. KeReleaseSpinLock( &AcpiGetLock, oldIrql );
  172. //
  173. // Do we have a node with a fake acpi object? This check is required
  174. // to support those devices that we really can run a control method on
  175. //
  176. if (!(Flags & GET_PROP_NSOBJ_INTERFACE) &&
  177. (deviceExtension->Flags & DEV_PROP_NO_OBJECT) &&
  178. (!(deviceExtension->Flags & DEV_PROP_DOCK)) ) {
  179. status = STATUS_OBJECT_NAME_NOT_FOUND;
  180. goto ACPIGetExit;
  181. }
  182. //
  183. // Go out and see if the requested object is present
  184. //
  185. acpiObject = ACPIAmliGetNamedChild(
  186. acpiObject,
  187. ObjectID
  188. );
  189. if (!acpiObject) {
  190. status = STATUS_OBJECT_NAME_NOT_FOUND;
  191. goto ACPIGetExit;
  192. }
  193. //
  194. // What we do now depends on wether or not the user wants us to
  195. // behave async or sync
  196. //
  197. if (async) {
  198. //
  199. // Evaluate the request
  200. //
  201. status = AMLIAsyncEvalObject(
  202. acpiObject,
  203. &(request->ResultData),
  204. argumentCount,
  205. argumentPtr,
  206. completionRoutine,
  207. request
  208. );
  209. if (status == STATUS_PENDING) {
  210. //
  211. // We cannot do anything else here. Wait for the completion routine
  212. // to fire
  213. //
  214. return status;
  215. }
  216. } else {
  217. //
  218. // Evaluate the request
  219. //
  220. status = AMLIEvalNameSpaceObject(
  221. acpiObject,
  222. &(request->ResultData),
  223. argumentCount,
  224. argumentPtr
  225. );
  226. }
  227. if (!NT_SUCCESS(status)) {
  228. //
  229. // We failed for some other reason
  230. //
  231. goto ACPIGetExit;
  232. }
  233. ACPIGetExit:
  234. //
  235. // Remember to not execute the callback routine
  236. //
  237. request->Flags |= GET_PROP_SKIP_CALLBACK;
  238. //
  239. // Call the completion routine to actually do the post-processing
  240. //
  241. (completionRoutine)(
  242. acpiObject,
  243. status,
  244. &(request->ResultData),
  245. request
  246. );
  247. //
  248. // Get the real status value from the completion routine
  249. //
  250. status = request->Status;
  251. //
  252. // Done with the request
  253. //
  254. if (request != NULL) {
  255. //
  256. // Remove the request from the queue
  257. //
  258. KeAcquireSpinLock( &AcpiGetLock, &oldIrql );
  259. RemoveEntryList( &(request->ListEntry) );
  260. KeReleaseSpinLock( &AcpiGetLock, oldIrql );
  261. //
  262. // Free the storage
  263. //
  264. ExFreePool( request );
  265. }
  266. //
  267. // Done
  268. //
  269. return status;
  270. }
  271. NTSTATUS
  272. ACPIGetConvertToAddress(
  273. IN PDEVICE_EXTENSION DeviceExtension,
  274. IN NTSTATUS Status,
  275. IN POBJDATA Result,
  276. IN ULONG Flags,
  277. OUT PVOID *Buffer,
  278. OUT ULONG *BufferSize
  279. )
  280. /*++
  281. Routine Description:
  282. This routine does all the handling required to convert the integer to
  283. an address
  284. Arguments:
  285. DeviceExtension - The device asking for the address
  286. Status - The result of the call to the interpreter
  287. Result - The data passed back from the interpreter
  288. Flags - The flags passed in (ignore overrides, etc)
  289. Buffer - Where to put the answer
  290. BufferSize - Where to put the size of the answer
  291. Return Value:
  292. NTSTATUS
  293. --*/
  294. {
  295. ASSERT( Buffer != NULL );
  296. //
  297. // Did we succeed?
  298. //
  299. if (!(Flags & GET_PROP_NSOBJ_INTERFACE) &&
  300. DeviceExtension->Flags & DEV_PROP_FIXED_ADDRESS) {
  301. *( (PULONG) Buffer) = DeviceExtension->Address;
  302. } else if (!NT_SUCCESS(Status)) {
  303. return Status;
  304. } else if (Result->dwDataType != OBJTYPE_INTDATA) {
  305. //
  306. // If we didn't get an integer, that's very bad.
  307. //
  308. return STATUS_ACPI_INVALID_DATA;
  309. } else {
  310. //
  311. // Set the value for the address
  312. //
  313. *( (PULONG) Buffer) = (ULONG)Result->uipDataValue;
  314. }
  315. //
  316. // Set the size of the buffer (if necessary)
  317. //
  318. if (BufferSize != NULL) {
  319. *BufferSize = sizeof(ULONG);
  320. }
  321. return STATUS_SUCCESS;
  322. }
  323. NTSTATUS
  324. ACPIGetConvertToCompatibleID(
  325. IN PDEVICE_EXTENSION DeviceExtension,
  326. IN NTSTATUS Status,
  327. IN POBJDATA Result,
  328. IN ULONG Flags,
  329. OUT PVOID *Buffer,
  330. OUT ULONG *BufferSize
  331. )
  332. /*++
  333. Routine Description:
  334. This routine generates an string of the form *PNPxxxx\0<Repeat\0>\0.
  335. That is, there is at least one null-terminated elemented, followed
  336. by an arbiterary amount followed by another null. This string is in
  337. ANSI format.
  338. Arguments:
  339. DeviceExtension - The extension to use when building the DeviceID
  340. Status - The status of the operation, so far
  341. Result - The interpreter data
  342. Flags - The flags passed in (ignore overrides, etc)
  343. Buffer - Where to put the answer
  344. BufferSize - Where to put the size of the answer
  345. Return Value:
  346. NTSTATUS
  347. --*/
  348. {
  349. NTSTATUS status = Status;
  350. POBJDATA currentObject;
  351. PPACKAGEOBJ packageObject;
  352. PUCHAR buffer;
  353. PUCHAR *localBufferArray;
  354. PUCHAR ptr;
  355. ULONG i = 0;
  356. ULONG *localBufferSizeArray;
  357. ULONG numElements;
  358. ULONG newBufferSize = 0;
  359. ULONG memSize;
  360. //
  361. // Does this device have a fake CID?
  362. //
  363. if (!(Flags & GET_PROP_NSOBJ_INTERFACE) &&
  364. DeviceExtension->Flags & DEV_PROP_FIXED_CID) {
  365. //
  366. // It does. We can use that string in this one's place
  367. //
  368. memSize = strlen(DeviceExtension->Processor.CompatibleID) + 2;
  369. //
  370. // Allocate the memory
  371. //
  372. buffer = ExAllocatePoolWithTag(
  373. ( (Flags & GET_PROP_ALLOCATE_NON_PAGED) ? NonPagedPool : PagedPool),
  374. memSize * sizeof(UCHAR),
  375. ACPI_STRING_POOLTAG
  376. );
  377. if (buffer == NULL) {
  378. return STATUS_INSUFFICIENT_RESOURCES;
  379. }
  380. RtlZeroMemory( buffer, memSize * sizeof(UCHAR) );
  381. //
  382. // Copy the memory
  383. //
  384. RtlCopyMemory( buffer, DeviceExtension->Processor.CompatibleID, memSize );
  385. //
  386. // Set the result string
  387. //
  388. *Buffer = buffer;
  389. if (BufferSize != NULL) {
  390. *BufferSize = newBufferSize;
  391. }
  392. //
  393. // Done
  394. //
  395. return STATUS_SUCCESS;
  396. }
  397. //
  398. // If we got to this point, and there isn't a successfull status,
  399. // then there is nothing we can do
  400. //
  401. if (!NT_SUCCESS(Status)) {
  402. return Status;
  403. }
  404. //
  405. // Determine the number of data elements that we have.
  406. //
  407. //
  408. switch (Result->dwDataType) {
  409. case OBJTYPE_STRDATA:
  410. case OBJTYPE_INTDATA:
  411. numElements = 1;
  412. break;
  413. case OBJTYPE_PKGDATA:
  414. packageObject = ((PPACKAGEOBJ) Result->pbDataBuff );
  415. numElements = packageObject->dwcElements;
  416. break;
  417. default:
  418. return STATUS_ACPI_INVALID_DATA;
  419. }
  420. //
  421. // Now, lets allocate the storage that we will need to process those
  422. // elements
  423. //
  424. localBufferArray = ExAllocatePoolWithTag(
  425. NonPagedPool,
  426. sizeof(PUCHAR) * numElements,
  427. ACPI_MISC_POOLTAG
  428. );
  429. if (localBufferArray == NULL) {
  430. return STATUS_INSUFFICIENT_RESOURCES;
  431. }
  432. RtlZeroMemory( localBufferArray, sizeof(PUCHAR) * numElements );
  433. //
  434. // Lets allocate storage so that we know how big those elements are
  435. //
  436. localBufferSizeArray = ExAllocatePoolWithTag(
  437. NonPagedPool,
  438. sizeof(ULONG) * numElements,
  439. ACPI_MISC_POOLTAG
  440. );
  441. if (localBufferSizeArray == NULL) {
  442. ExFreePool( localBufferArray );
  443. return STATUS_INSUFFICIENT_RESOURCES;
  444. }
  445. RtlZeroMemory( localBufferSizeArray, sizeof(ULONG) * numElements );
  446. //
  447. // Process the data
  448. //
  449. switch (Result->dwDataType) {
  450. case OBJTYPE_STRDATA:
  451. status = ACPIGetConvertToString(
  452. DeviceExtension,
  453. Status,
  454. Result,
  455. Flags,
  456. &(localBufferArray[0]),
  457. &(localBufferSizeArray[0])
  458. );
  459. newBufferSize = localBufferSizeArray[0];
  460. break;
  461. case OBJTYPE_INTDATA:
  462. status = ACPIGetConvertToPnpID(
  463. DeviceExtension,
  464. Status,
  465. Result,
  466. Flags,
  467. &(localBufferArray[0]),
  468. &(localBufferSizeArray[0])
  469. );
  470. newBufferSize = localBufferSizeArray[0];
  471. break;
  472. case OBJTYPE_PKGDATA:
  473. //
  474. // Iterate over all the elements in the process
  475. //
  476. for (i = 0; i < numElements; i++) {
  477. //
  478. // Look at the element that we want to process
  479. //
  480. currentObject = &( packageObject->adata[i]);
  481. //
  482. // What kind of object to do we have?
  483. //
  484. switch (currentObject->dwDataType) {
  485. case OBJTYPE_STRDATA:
  486. status = ACPIGetConvertToString(
  487. DeviceExtension,
  488. Status,
  489. currentObject,
  490. Flags,
  491. &(localBufferArray[i]),
  492. &(localBufferSizeArray[i])
  493. );
  494. break;
  495. case OBJTYPE_INTDATA:
  496. status = ACPIGetConvertToPnpID(
  497. DeviceExtension,
  498. Status,
  499. currentObject,
  500. Flags,
  501. &(localBufferArray[i]),
  502. &(localBufferSizeArray[i])
  503. );
  504. break;
  505. default:
  506. ACPIInternalError( ACPI_GET );
  507. } // switch
  508. //
  509. // Did we fail?
  510. //
  511. if (!NT_SUCCESS(status)) {
  512. break;
  513. }
  514. //
  515. // Note that it is possible for the buffer to contain just the
  516. // string terminator. Since this would cause us to prematurely
  517. // terminate the resulting string. We must watch out for it
  518. //
  519. if (localBufferSizeArray[i] == 1) {
  520. localBufferSizeArray[i] = 0;
  521. }
  522. //
  523. // Keep running total of the size required
  524. //
  525. newBufferSize += localBufferSizeArray[i];
  526. } // for
  527. break;
  528. } // switch
  529. //
  530. // If we didn't succeed, then we must free all of the memory that
  531. // we tried to build up
  532. //
  533. if (!NT_SUCCESS(status)) {
  534. //
  535. // This is a little cheat that allows to share the cleanup code.
  536. // By making numElements equal to the current index, we place
  537. // a correct bound on the elements that must be freed
  538. //
  539. numElements = i;
  540. goto ACPIGetConvertToCompatibleIDExit;
  541. }
  542. //
  543. // If we have an empty list, or one that is only a null, then we
  544. // won't botther to return anything
  545. //
  546. if (newBufferSize <= 1) {
  547. status = STATUS_ACPI_INVALID_DATA;
  548. newBufferSize = 0;
  549. goto ACPIGetConvertToCompatibleIDExit;
  550. } else {
  551. //
  552. // Remember that we need to have an extra null at the end. Allocate
  553. // space for that null
  554. //
  555. newBufferSize++;
  556. }
  557. //
  558. // Allocate the memory
  559. //
  560. buffer = ExAllocatePoolWithTag(
  561. ( (Flags & GET_PROP_ALLOCATE_NON_PAGED) ? NonPagedPool : PagedPool),
  562. newBufferSize * sizeof(UCHAR),
  563. ACPI_STRING_POOLTAG
  564. );
  565. if (buffer == NULL) {
  566. status = STATUS_INSUFFICIENT_RESOURCES;
  567. goto ACPIGetConvertToCompatibleIDExit;
  568. }
  569. RtlZeroMemory( buffer, newBufferSize * sizeof(UCHAR) );
  570. //
  571. // Iterate over all pieces of the string
  572. //
  573. for (ptr = buffer, i = 0; i < numElements; i++) {
  574. if (localBufferArray[i] != NULL) {
  575. //
  576. // Copy over the interesting memory
  577. //
  578. RtlCopyMemory(
  579. ptr,
  580. localBufferArray[i],
  581. localBufferSizeArray[i] * sizeof(UCHAR)
  582. );
  583. }
  584. //
  585. // Increment the temp pointer to point to the next target location
  586. //
  587. ptr += localBufferSizeArray[i];
  588. }
  589. //
  590. // Set the result string
  591. //
  592. *Buffer = buffer;
  593. if (BufferSize != NULL) {
  594. *BufferSize = newBufferSize;
  595. }
  596. ACPIGetConvertToCompatibleIDExit:
  597. //
  598. // Clean up
  599. //
  600. for (i = 0; i < numElements; i ++) {
  601. if (localBufferArray[i] != NULL ) {
  602. ExFreePool( localBufferArray[i] );
  603. }
  604. }
  605. ExFreePool( localBufferSizeArray );
  606. ExFreePool( localBufferArray );
  607. //
  608. // Return the appropriate status value
  609. //
  610. return status;
  611. }
  612. NTSTATUS
  613. ACPIGetConvertToCompatibleIDWide(
  614. IN PDEVICE_EXTENSION DeviceExtension,
  615. IN NTSTATUS Status,
  616. IN POBJDATA Result,
  617. IN ULONG Flags,
  618. OUT PVOID *Buffer,
  619. OUT ULONG *BufferSize
  620. )
  621. /*++
  622. Routine Description:
  623. This routine generates an string of the form *PNPxxxx\0<Repeat\0>\0.
  624. That is, there is at least one null-terminated elemented, followed
  625. by an arbiterary amount followed by another null. This string is in
  626. UNICODE format.
  627. Arguments:
  628. DeviceExtension - The extension to use when building the DeviceID
  629. Status - The status of the operation, so far
  630. Result - The interpreter data
  631. Flags - The flags passed in (ignore overrides, etc)
  632. Buffer - Where to put the answer
  633. BufferSize - Where to put the size of the answer
  634. Return Value:
  635. NTSTATUS
  636. --*/
  637. {
  638. NTSTATUS status = Status;
  639. POBJDATA currentObject;
  640. PPACKAGEOBJ packageObject;
  641. PWCHAR buffer;
  642. PWCHAR *localBufferArray;
  643. PWCHAR ptr;
  644. ULONG i = 0;
  645. ULONG *localBufferSizeArray;
  646. ULONG numElements = 0;
  647. ULONG newBufferSize = 0;
  648. ULONG memSize;
  649. //
  650. // Does this device have a fake CID?
  651. //
  652. if (!(Flags & GET_PROP_NSOBJ_INTERFACE) &&
  653. DeviceExtension->Flags & DEV_PROP_FIXED_CID) {
  654. //
  655. // It does. We can use that string in this one's place
  656. //
  657. memSize = strlen(DeviceExtension->Processor.CompatibleID) + 2;
  658. //
  659. // Allocate the memory
  660. //
  661. buffer = ExAllocatePoolWithTag(
  662. ( (Flags & GET_PROP_ALLOCATE_NON_PAGED) ? NonPagedPool : PagedPool),
  663. memSize * sizeof(WCHAR),
  664. ACPI_STRING_POOLTAG
  665. );
  666. if (buffer == NULL) {
  667. return STATUS_INSUFFICIENT_RESOURCES;
  668. }
  669. RtlZeroMemory( buffer, memSize * sizeof(WCHAR) );
  670. //
  671. // Generate the string
  672. //
  673. swprintf( buffer, L"%S", DeviceExtension->Processor.CompatibleID );
  674. //
  675. // Set the result string
  676. //
  677. *Buffer = buffer;
  678. if (BufferSize != NULL) {
  679. *BufferSize = newBufferSize;
  680. }
  681. //
  682. // Done
  683. //
  684. return STATUS_SUCCESS;
  685. }
  686. //
  687. // If we got to this point, and there isn't a successfull status,
  688. // then there is nothing we can do
  689. //
  690. if (!NT_SUCCESS(Status)) {
  691. return Status;
  692. }
  693. //
  694. // Determine the number of data elements that we have.
  695. //
  696. //
  697. switch (Result->dwDataType) {
  698. case OBJTYPE_STRDATA:
  699. case OBJTYPE_INTDATA:
  700. numElements = 1;
  701. break;
  702. case OBJTYPE_PKGDATA:
  703. packageObject = ((PPACKAGEOBJ) Result->pbDataBuff );
  704. numElements = packageObject->dwcElements;
  705. break;
  706. default:
  707. return STATUS_ACPI_INVALID_DATA;
  708. }
  709. //
  710. // Now, lets allocate the storage that we will need to process those
  711. // elements
  712. //
  713. localBufferArray = ExAllocatePoolWithTag(
  714. NonPagedPool,
  715. sizeof(PWCHAR) * numElements,
  716. ACPI_MISC_POOLTAG
  717. );
  718. if (localBufferArray == NULL) {
  719. return STATUS_INSUFFICIENT_RESOURCES;
  720. }
  721. RtlZeroMemory( localBufferArray, sizeof(PWCHAR) * numElements );
  722. //
  723. // Lets allocate storage so that we know how big those elements are
  724. //
  725. localBufferSizeArray = ExAllocatePoolWithTag(
  726. NonPagedPool,
  727. sizeof(ULONG) * numElements,
  728. ACPI_MISC_POOLTAG
  729. );
  730. if (localBufferSizeArray == NULL) {
  731. ExFreePool( localBufferArray );
  732. return STATUS_INSUFFICIENT_RESOURCES;
  733. }
  734. RtlZeroMemory( localBufferSizeArray, sizeof(ULONG) * numElements );
  735. //
  736. // Process the data
  737. //
  738. switch (Result->dwDataType) {
  739. case OBJTYPE_STRDATA:
  740. status = ACPIGetConvertToStringWide(
  741. DeviceExtension,
  742. Status,
  743. Result,
  744. Flags,
  745. &(localBufferArray[0]),
  746. &(localBufferSizeArray[0])
  747. );
  748. newBufferSize = localBufferSizeArray[0];
  749. break;
  750. case OBJTYPE_INTDATA:
  751. status = ACPIGetConvertToPnpIDWide(
  752. DeviceExtension,
  753. Status,
  754. Result,
  755. Flags,
  756. &(localBufferArray[0]),
  757. &(localBufferSizeArray[0])
  758. );
  759. newBufferSize = localBufferSizeArray[0];
  760. break;
  761. case OBJTYPE_PKGDATA:
  762. //
  763. // Iterate over all the elements in the process
  764. //
  765. for (i = 0; i < numElements; i++) {
  766. //
  767. // Look at the element that we want to process
  768. //
  769. currentObject = &( packageObject->adata[i]);
  770. //
  771. // What kind of object to do we have?
  772. //
  773. switch (currentObject->dwDataType) {
  774. case OBJTYPE_STRDATA:
  775. status = ACPIGetConvertToStringWide(
  776. DeviceExtension,
  777. Status,
  778. currentObject,
  779. Flags,
  780. &(localBufferArray[i]),
  781. &(localBufferSizeArray[i])
  782. );
  783. break;
  784. case OBJTYPE_INTDATA:
  785. status = ACPIGetConvertToPnpIDWide(
  786. DeviceExtension,
  787. Status,
  788. currentObject,
  789. Flags,
  790. &(localBufferArray[i]),
  791. &(localBufferSizeArray[i])
  792. );
  793. break;
  794. default:
  795. ACPIInternalError( ACPI_GET );
  796. } // switch
  797. //
  798. // Did we fail?
  799. //
  800. if (!NT_SUCCESS(status)) {
  801. break;
  802. }
  803. //
  804. // Note that it is possible for the buffer to contain just the
  805. // string terminator. Since this would cause us to prematurely
  806. // terminate the resulting string. We must watch out for it
  807. //
  808. if (localBufferSizeArray[i] == 1) {
  809. localBufferSizeArray[i] = 0;
  810. }
  811. //
  812. // Keep running total of the size required
  813. //
  814. newBufferSize += localBufferSizeArray[i];
  815. } // for
  816. //
  817. // If we didn't succeed, then we must free all of the memory that
  818. // we tried to build up
  819. //
  820. if (!NT_SUCCESS(status)) {
  821. //
  822. // This is a little cheat that allows to share the cleanup code.
  823. // By making numElements equal to the current index, we place
  824. // a correct bound on the elements that must be freed
  825. //
  826. numElements = i;
  827. }
  828. break;
  829. } // switch
  830. //
  831. // If we didn't succeed, then we must free all of the memory that
  832. // we tried to build up
  833. //
  834. if (!NT_SUCCESS(status)) {
  835. goto ACPIGetConvertToCompatibleIDWideExit;
  836. }
  837. //
  838. // If we have an empty list, or one that is only a null, then we
  839. // won't botther to return anything
  840. //
  841. if (newBufferSize <= 2) {
  842. status = STATUS_ACPI_INVALID_DATA;
  843. newBufferSize = 0;
  844. goto ACPIGetConvertToCompatibleIDWideExit;
  845. } else {
  846. //
  847. // Remember that we need to have an extra null at the end. Allocate
  848. // space for that null
  849. //
  850. newBufferSize += 2;
  851. }
  852. //
  853. // Allocate the memory. Note --- The memory has already been counted in
  854. // size of WCHARs.
  855. //
  856. buffer = ExAllocatePoolWithTag(
  857. ( (Flags & GET_PROP_ALLOCATE_NON_PAGED) ? NonPagedPool : PagedPool),
  858. newBufferSize,
  859. ACPI_STRING_POOLTAG
  860. );
  861. if (buffer == NULL) {
  862. status = STATUS_INSUFFICIENT_RESOURCES;
  863. goto ACPIGetConvertToCompatibleIDWideExit;
  864. }
  865. RtlZeroMemory( buffer, newBufferSize );
  866. //
  867. // Iterate over all pieces of the string
  868. //
  869. for (ptr = buffer, i = 0; i < numElements; i++) {
  870. if (localBufferArray[i] != NULL) {
  871. //
  872. // Copy over the interesting memory
  873. //
  874. RtlCopyMemory(
  875. ptr,
  876. localBufferArray[i],
  877. localBufferSizeArray[i]
  878. );
  879. }
  880. //
  881. // Increment the temp pointer to point to the next target location
  882. //
  883. ptr += localBufferSizeArray[i] / sizeof(WCHAR) ;
  884. }
  885. //
  886. // Set the result string
  887. //
  888. *Buffer = buffer;
  889. if (BufferSize != NULL) {
  890. *BufferSize = newBufferSize;
  891. }
  892. ACPIGetConvertToCompatibleIDWideExit:
  893. //
  894. // Clean up
  895. //
  896. for (i = 0; i < numElements; i ++) {
  897. if (localBufferArray[i] != NULL ) {
  898. ExFreePool( localBufferArray[i] );
  899. }
  900. }
  901. ExFreePool( localBufferSizeArray );
  902. ExFreePool( localBufferArray );
  903. //
  904. // Return the appropriate status value
  905. //
  906. return status;
  907. }
  908. NTSTATUS
  909. ACPIGetConvertToDeviceID(
  910. IN PDEVICE_EXTENSION DeviceExtension,
  911. IN NTSTATUS Status,
  912. IN POBJDATA Result,
  913. IN ULONG Flags,
  914. OUT PVOID *Buffer,
  915. OUT ULONG *BufferSize
  916. )
  917. /*++
  918. Routine Description:
  919. This routine generates an string of the form ACPI\PNPxxxx. This string
  920. is in ANSI format. The code is smart enough to check to see if the
  921. string that should be used is a fake one and already stored in the
  922. device extension
  923. Arguments:
  924. DeviceExtension - The extension to use when building the DeviceID
  925. Status - The status of the operation, so far
  926. Result - The interpreter data
  927. Flags - The flags passed in (ignore overrides, etc)
  928. Buffer - Where to put the answer
  929. BufferSize - Where to put the size of the answer
  930. Return Value:
  931. NTSTATUS
  932. --*/
  933. {
  934. PUCHAR buffer;
  935. PUCHAR tempString;
  936. ULONG memSize;
  937. //
  938. // First, check to see if we are a processor
  939. //
  940. if (!(Flags & GET_PROP_NSOBJ_INTERFACE) &&
  941. DeviceExtension->Flags & DEV_CAP_PROCESSOR) {
  942. //
  943. // If we don't have an _HID method, but we are a processor object,
  944. // then we can actually get the _HID through another mechanism
  945. //
  946. return ACPIGetProcessorID(
  947. DeviceExtension,
  948. Status,
  949. Result,
  950. Flags,
  951. Buffer,
  952. BufferSize
  953. );
  954. }
  955. //
  956. // Does this string have a fake HID?
  957. //
  958. if (!(Flags & GET_PROP_NSOBJ_INTERFACE) &&
  959. DeviceExtension->Flags & DEV_PROP_FIXED_HID) {
  960. //
  961. // It does. We can use that string in this one's place
  962. //
  963. memSize = strlen(DeviceExtension->DeviceID) + 1;
  964. //
  965. // Allocate the memory
  966. //
  967. buffer = ExAllocatePoolWithTag(
  968. ( (Flags & GET_PROP_ALLOCATE_NON_PAGED) ? NonPagedPool : PagedPool),
  969. memSize * sizeof(UCHAR),
  970. ACPI_STRING_POOLTAG
  971. );
  972. if (buffer == NULL) {
  973. return STATUS_INSUFFICIENT_RESOURCES;
  974. }
  975. RtlZeroMemory( buffer, memSize * sizeof(UCHAR) );
  976. //
  977. // Copy the memory
  978. //
  979. RtlCopyMemory( buffer, DeviceExtension->DeviceID, memSize );
  980. //
  981. // Done
  982. //
  983. goto ACPIGetConvertToDeviceIDExit;
  984. }
  985. //
  986. // Are we a PCI Bar Target device? If so, then we have special handling
  987. // rules that we must follow
  988. //
  989. if (!(Flags & GET_PROP_NSOBJ_INTERFACE) &&
  990. DeviceExtension->Flags & DEV_CAP_PCI_BAR_TARGET) {
  991. //
  992. // Right now, lets call the this a "PciBarTarget" device, which
  993. // is 13 characters long (including the NULL). We also need to add
  994. // 5 characters for the ACPI\ part of the name
  995. //
  996. memSize = 18;
  997. //
  998. // Allocate the memory
  999. //
  1000. buffer = ExAllocatePoolWithTag(
  1001. ( (Flags & GET_PROP_ALLOCATE_NON_PAGED) ? NonPagedPool : PagedPool),
  1002. memSize * sizeof(UCHAR),
  1003. ACPI_STRING_POOLTAG
  1004. );
  1005. if (buffer == NULL) {
  1006. return STATUS_INSUFFICIENT_RESOURCES;
  1007. }
  1008. RtlZeroMemory( buffer, memSize * sizeof(UCHAR) );
  1009. //
  1010. // Print the string
  1011. //
  1012. sprintf( buffer, "%s", "ACPI\\PciBarTarget" );
  1013. //
  1014. // Done
  1015. //
  1016. goto ACPIGetConvertToDeviceIDExit;
  1017. }
  1018. //
  1019. // If we got to this point, then that means that there probably wasn't
  1020. // an _HID method *or* the method error'ed out.
  1021. //
  1022. if (!NT_SUCCESS(Status)) {
  1023. return Status;
  1024. }
  1025. //
  1026. // We need to handle things differently based on wether we have an
  1027. // EISAID or a String
  1028. //
  1029. switch (Result->dwDataType) {
  1030. case OBJTYPE_INTDATA:
  1031. //
  1032. // For a device ID, we need 4 (ACPI) + 1 (\\) + 7 (PNPxxxx) + 1 (\0)
  1033. // = 13 characters
  1034. //
  1035. memSize = 13;
  1036. //
  1037. // Allocate the memory
  1038. //
  1039. buffer = ExAllocatePoolWithTag(
  1040. ( (Flags & GET_PROP_ALLOCATE_NON_PAGED) ? NonPagedPool : PagedPool),
  1041. memSize * sizeof(UCHAR),
  1042. ACPI_STRING_POOLTAG
  1043. );
  1044. if (buffer == NULL) {
  1045. return STATUS_INSUFFICIENT_RESOURCES;
  1046. }
  1047. RtlZeroMemory( buffer, memSize * sizeof(UCHAR) );
  1048. //
  1049. // Put the leading characters in place
  1050. //
  1051. sprintf( buffer, "ACPI\\" );
  1052. //
  1053. // Convert the packed string
  1054. //
  1055. ACPIAmliDoubleToName( buffer+5, (ULONG)Result->uipDataValue, FALSE );
  1056. //
  1057. // Done
  1058. //
  1059. break;
  1060. case OBJTYPE_STRDATA:
  1061. //
  1062. // Lets grab a pointer to the string that we will be using
  1063. //
  1064. tempString = Result->pbDataBuff;
  1065. //
  1066. // Does it have a leading '*'? If it does, then we must ignore
  1067. // it
  1068. //
  1069. if (*tempString == '*') {
  1070. tempString++;
  1071. }
  1072. //
  1073. // For a string, make sure that there is no leading '*' and
  1074. // account for the fact that we will preceed the string with
  1075. // the words 'ACPI\\" and NULL
  1076. //
  1077. memSize = 6 + strlen(tempString);
  1078. //
  1079. // Allocate the memory
  1080. //
  1081. buffer = ExAllocatePoolWithTag(
  1082. ( (Flags & GET_PROP_ALLOCATE_NON_PAGED) ? NonPagedPool : PagedPool),
  1083. memSize * sizeof(UCHAR),
  1084. ACPI_STRING_POOLTAG
  1085. );
  1086. if (buffer == NULL) {
  1087. return STATUS_INSUFFICIENT_RESOURCES;
  1088. }
  1089. RtlZeroMemory( buffer, memSize * sizeof(UCHAR) );
  1090. //
  1091. // Put the leading characters in place
  1092. //
  1093. sprintf( buffer, "ACPI\\%s", tempString );
  1094. //
  1095. // Done
  1096. //
  1097. break;
  1098. default:
  1099. return STATUS_ACPI_INVALID_DATA;
  1100. }
  1101. ACPIGetConvertToDeviceIDExit:
  1102. //
  1103. // Let the originator see this copy. Make sure to also see the buffer
  1104. // length, if possible
  1105. //
  1106. *(Buffer) = buffer;
  1107. if (BufferSize != NULL) {
  1108. *(BufferSize) = memSize;
  1109. }
  1110. //
  1111. // Done
  1112. //
  1113. return STATUS_SUCCESS;
  1114. }
  1115. NTSTATUS
  1116. ACPIGetConvertToDeviceIDWide(
  1117. IN PDEVICE_EXTENSION DeviceExtension,
  1118. IN NTSTATUS Status,
  1119. IN POBJDATA Result,
  1120. IN ULONG Flags,
  1121. OUT PVOID *Buffer,
  1122. OUT ULONG *BufferSize
  1123. )
  1124. /*++
  1125. Routine Description:
  1126. This routine generates an string of the form ACPI\PNPxxxx. This string
  1127. is in UNICODE format. The code is smart enough to check to see if the
  1128. string that should be used is a fake one and already stored in the
  1129. device extension
  1130. Arguments:
  1131. DeviceExtension - The extension to use when building the DeviceID
  1132. Status - The status of the operation, so far
  1133. Result - The interpreter data
  1134. Flags - The flags passed in (ignore overrides, etc)
  1135. Buffer - Where to put the answer
  1136. BufferSize - Where to put the size of the answer
  1137. Return Value:
  1138. NTSTATUS
  1139. --*/
  1140. {
  1141. PUCHAR tempString;
  1142. PWSTR buffer;
  1143. ULONG memSize;
  1144. //
  1145. // First, check to see if we are a processor
  1146. //
  1147. if (!(Flags & GET_PROP_NSOBJ_INTERFACE) &&
  1148. DeviceExtension->Flags & DEV_CAP_PROCESSOR) {
  1149. //
  1150. // If we don't have an _HID method, but we are a processor object,
  1151. // then we can actually get the _HID through another mechanism
  1152. //
  1153. return ACPIGetProcessorIDWide(
  1154. DeviceExtension,
  1155. Status,
  1156. Result,
  1157. Flags,
  1158. Buffer,
  1159. BufferSize
  1160. );
  1161. }
  1162. //
  1163. // Does this string have a fake HID?
  1164. //
  1165. if (!(Flags & GET_PROP_NSOBJ_INTERFACE) &&
  1166. DeviceExtension->Flags & DEV_PROP_FIXED_HID) {
  1167. //
  1168. // It does. We can use that string in this one's place
  1169. //
  1170. memSize = strlen(DeviceExtension->DeviceID) + 1;
  1171. //
  1172. // Allocate the memory
  1173. //
  1174. buffer = ExAllocatePoolWithTag(
  1175. ( (Flags & GET_PROP_ALLOCATE_NON_PAGED) ? NonPagedPool : PagedPool),
  1176. memSize * sizeof(WCHAR),
  1177. ACPI_STRING_POOLTAG
  1178. );
  1179. if (buffer == NULL) {
  1180. return STATUS_INSUFFICIENT_RESOURCES;
  1181. }
  1182. RtlZeroMemory( buffer, memSize * sizeof(WCHAR) );
  1183. //
  1184. // Generate the string
  1185. //
  1186. swprintf( buffer, L"%S", DeviceExtension->DeviceID );
  1187. //
  1188. // Done
  1189. //
  1190. goto ACPIGetConvertToDeviceIDWideExit;
  1191. }
  1192. //
  1193. // Are we a PCI Bar Target device? If so, then we have special handling
  1194. // rules that we must follow
  1195. //
  1196. if (!(Flags & GET_PROP_NSOBJ_INTERFACE) &&
  1197. DeviceExtension->Flags & DEV_CAP_PCI_BAR_TARGET) {
  1198. //
  1199. // Right now, lets call the this a "PciBarTarget" device, which
  1200. // is 13 characters long (including the NULL). We also need to add
  1201. // 5 characters for the ACPI\ part of the name
  1202. //
  1203. memSize = 18;
  1204. //
  1205. // Allocate the memory
  1206. //
  1207. buffer = ExAllocatePoolWithTag(
  1208. ( (Flags & GET_PROP_ALLOCATE_NON_PAGED) ? NonPagedPool : PagedPool),
  1209. memSize * sizeof(WCHAR),
  1210. ACPI_STRING_POOLTAG
  1211. );
  1212. if (buffer == NULL) {
  1213. return STATUS_INSUFFICIENT_RESOURCES;
  1214. }
  1215. RtlZeroMemory( buffer, memSize * sizeof(WCHAR) );
  1216. //
  1217. // Print the string
  1218. //
  1219. swprintf( buffer, L"%S", "ACPI\\PciBarTarget" );
  1220. //
  1221. // Done
  1222. //
  1223. goto ACPIGetConvertToDeviceIDWideExit;
  1224. }
  1225. //
  1226. // If we got to this point, then that means that there probably wasn't
  1227. // an _HID method *or* the method error'ed out.
  1228. //
  1229. if (!NT_SUCCESS(Status)) {
  1230. return Status;
  1231. }
  1232. //
  1233. // We need to handle things differently based on wether we have an
  1234. // EISAID or a String
  1235. //
  1236. switch (Result->dwDataType) {
  1237. case OBJTYPE_INTDATA:
  1238. //
  1239. // For a device ID, we need 4 (ACPI) + 1 (\\) + 7 (PNPxxxx) + 1 (\0)
  1240. // = 13 characters
  1241. //
  1242. memSize = 13;
  1243. //
  1244. // Allocate the memory
  1245. //
  1246. buffer = ExAllocatePoolWithTag(
  1247. ( (Flags & GET_PROP_ALLOCATE_NON_PAGED) ? NonPagedPool : PagedPool),
  1248. memSize * sizeof(WCHAR),
  1249. ACPI_STRING_POOLTAG
  1250. );
  1251. if (buffer == NULL) {
  1252. return STATUS_INSUFFICIENT_RESOURCES;
  1253. }
  1254. RtlZeroMemory( buffer, memSize * sizeof(WCHAR) );
  1255. //
  1256. // Put the leading characters in place
  1257. //
  1258. swprintf( buffer, L"ACPI\\" );
  1259. //
  1260. // Convert the packed string
  1261. //
  1262. ACPIAmliDoubleToNameWide( buffer+5, (ULONG)Result->uipDataValue, FALSE );
  1263. //
  1264. // Done
  1265. //
  1266. break;
  1267. case OBJTYPE_STRDATA:
  1268. //
  1269. // Lets grab a pointer to the string that we will be using
  1270. //
  1271. tempString = Result->pbDataBuff;
  1272. //
  1273. // Does it have a leading '*'? If it does, then we must ignore
  1274. // it
  1275. //
  1276. if (*tempString == '*') {
  1277. tempString++;
  1278. }
  1279. //
  1280. // For a string, make sure that there is no leading '*' and
  1281. // account for the fact that we will preceed the string with
  1282. // the words 'ACPI\\" and NULL
  1283. //
  1284. memSize = 6 + strlen(tempString);
  1285. //
  1286. // Allocate the memory
  1287. //
  1288. buffer = ExAllocatePoolWithTag(
  1289. ( (Flags & GET_PROP_ALLOCATE_NON_PAGED) ? NonPagedPool : PagedPool),
  1290. memSize * sizeof(WCHAR),
  1291. ACPI_STRING_POOLTAG
  1292. );
  1293. if (buffer == NULL) {
  1294. return STATUS_INSUFFICIENT_RESOURCES;
  1295. }
  1296. RtlZeroMemory( buffer, memSize * sizeof(WCHAR) );
  1297. //
  1298. // Put the leading characters in place
  1299. //
  1300. swprintf( buffer, L"ACPI\\%S", tempString );
  1301. //
  1302. // Done
  1303. //
  1304. break;
  1305. default:
  1306. return STATUS_ACPI_INVALID_DATA;
  1307. }
  1308. ACPIGetConvertToDeviceIDWideExit:
  1309. //
  1310. // Let the originator see this copy. Make sure to also see the buffer
  1311. // length, if possible
  1312. //
  1313. *(Buffer) = buffer;
  1314. if (BufferSize != NULL) {
  1315. *(BufferSize) = (memSize * sizeof(WCHAR) );
  1316. }
  1317. //
  1318. // Done
  1319. //
  1320. return STATUS_SUCCESS;
  1321. }
  1322. NTSTATUS
  1323. ACPIGetConvertToDevicePresence(
  1324. IN PDEVICE_EXTENSION DeviceExtension,
  1325. IN NTSTATUS Status,
  1326. IN POBJDATA Result,
  1327. IN ULONG Flags,
  1328. OUT PVOID *Buffer,
  1329. OUT ULONG *BufferSize
  1330. )
  1331. /*++
  1332. Routine Description:
  1333. This routine does all the handling required to convert the integer to
  1334. an status value.
  1335. Note that this function is different then the GetStatus one because
  1336. this one
  1337. a) Updates the internal device status
  1338. b) Allows the 'device' to be present even if there is no _STA
  1339. Arguments:
  1340. DeviceExtension - The device asking for the address
  1341. Status - The result of the call to the interpreter
  1342. Result - The data passed back from the interpreter
  1343. Flags - The flags passed in (ignore overrides, etc)
  1344. Buffer - Where to put the answer
  1345. BufferSize - Where to put the size of the answer
  1346. Return Value:
  1347. NTSTATUS
  1348. --*/
  1349. {
  1350. ULONG deviceStatus = STA_STATUS_DEFAULT;
  1351. NTSTATUS status;
  1352. //
  1353. // Profile providers are present if one of the following cases is true:
  1354. // 1) The ACPI object corresponding to the dock is itself present
  1355. // 2) The dock is unattached (ie, requesting attachment)
  1356. //
  1357. if (!(Flags & GET_PROP_NSOBJ_INTERFACE) ) {
  1358. if (DeviceExtension->Flags & DEV_PROP_DOCK) {
  1359. if (DeviceExtension->Flags & DEV_CAP_UNATTACHED_DOCK) {
  1360. goto ACPIGetConvertToDevicePresenceExit;
  1361. }
  1362. //
  1363. // We should have handled the case where we need to run the
  1364. // _STA on the proper target node...
  1365. //
  1366. } else if (DeviceExtension->Flags & DEV_PROP_NO_OBJECT) {
  1367. goto ACPIGetConvertToDevicePresenceExit;
  1368. }
  1369. //
  1370. // At this point, we can see what the control method returned. If the
  1371. // control method returned STATUS_OBJECT_NAME_NOT_FOUND, then we know
  1372. // that the control method doesn't exist. In that case, then we have
  1373. // to use the default status for the device
  1374. //
  1375. if (Status == STATUS_OBJECT_NAME_NOT_FOUND) {
  1376. //
  1377. // We do make exceptions in the case that this is a processor object
  1378. // and we didn't find a control method. In this case, we check the
  1379. // processor affinity mask to see if this processor exists. The reason
  1380. // that we do this is that older multi-proc capable systems with only
  1381. // a single processor will errorneously report both processors.
  1382. //
  1383. if (DeviceExtension->Flags & DEV_CAP_PROCESSOR) {
  1384. //
  1385. // Let the processor specific function to do all the
  1386. // work.
  1387. //
  1388. status = ACPIGetProcessorStatus(
  1389. DeviceExtension,
  1390. Flags,
  1391. &deviceStatus
  1392. );
  1393. if (!NT_SUCCESS(status)) {
  1394. //
  1395. // Something bad occured, so assume that the processor
  1396. // isn't present...
  1397. //
  1398. deviceStatus = 0;
  1399. }
  1400. }
  1401. //
  1402. // Skip a couple of useless steps...
  1403. //
  1404. goto ACPIGetConvertToDevicePresenceExit;
  1405. } else if (!NT_SUCCESS(Status)) {
  1406. deviceStatus = 0;
  1407. goto ACPIGetConvertToDevicePresenceExit;
  1408. }
  1409. //
  1410. // If the data isn't of the correct type, then we *really* should bugcheck
  1411. //
  1412. if (Result->dwDataType != OBJTYPE_INTDATA) {
  1413. PNSOBJ staObject;
  1414. //
  1415. // We need the sta Object for the bugcheck
  1416. //
  1417. staObject= ACPIAmliGetNamedChild(
  1418. DeviceExtension->AcpiObject,
  1419. PACKED_STA
  1420. );
  1421. KeBugCheckEx(
  1422. ACPI_BIOS_ERROR,
  1423. ACPI_EXPECTED_INTEGER,
  1424. (ULONG_PTR) DeviceExtension,
  1425. (ULONG_PTR) staObject,
  1426. Result->dwDataType
  1427. );
  1428. }
  1429. //
  1430. // Get the real result
  1431. //
  1432. deviceStatus = (ULONG)Result->uipDataValue;
  1433. } else {
  1434. if (Status == STATUS_OBJECT_NAME_NOT_FOUND) {
  1435. goto ACPIGetConvertToDevicePresenceExit2;
  1436. }
  1437. if (!NT_SUCCESS(Status)) {
  1438. deviceStatus = 0;
  1439. goto ACPIGetConvertToDevicePresenceExit2;
  1440. }
  1441. if (Result->dwDataType != OBJTYPE_INTDATA) {
  1442. KeBugCheckEx(
  1443. ACPI_BIOS_ERROR,
  1444. ACPI_EXPECTED_INTEGER,
  1445. (ULONG_PTR) DeviceExtension,
  1446. (ULONG_PTR) NULL,
  1447. Result->dwDataType
  1448. );
  1449. }
  1450. //
  1451. // Get the real result
  1452. //
  1453. deviceStatus = (ULONG)Result->uipDataValue;
  1454. goto ACPIGetConvertToDevicePresenceExit2;
  1455. }
  1456. ACPIGetConvertToDevicePresenceExit:
  1457. //
  1458. // If the device is marked as NEVER_PRESENT, then we will always
  1459. // have a status of NOT_PRESENT
  1460. //
  1461. if ((DeviceExtension->Flags & DEV_TYPE_NEVER_PRESENT)&&
  1462. !(Flags & GET_CONVERT_IGNORE_OVERRIDES)) {
  1463. deviceStatus &= ~STA_STATUS_PRESENT;
  1464. }
  1465. //
  1466. // If the device is marked as NEVER_SHOW, then we will have have a
  1467. // a status of !USER_INTERFACE
  1468. //
  1469. if (DeviceExtension->Flags & DEV_CAP_NEVER_SHOW_IN_UI) {
  1470. deviceStatus &= ~STA_STATUS_USER_INTERFACE;
  1471. }
  1472. //
  1473. // Update the device status
  1474. //
  1475. ACPIInternalUpdateDeviceStatus( DeviceExtension, deviceStatus );
  1476. ACPIGetConvertToDevicePresenceExit2:
  1477. //
  1478. // Set the value for the status
  1479. //
  1480. *( (PULONG) Buffer) = deviceStatus;
  1481. if (BufferSize != NULL) {
  1482. *BufferSize = sizeof(ULONG);
  1483. }
  1484. return STATUS_SUCCESS;
  1485. }
  1486. NTSTATUS
  1487. ACPIGetConvertToHardwareID(
  1488. IN PDEVICE_EXTENSION DeviceExtension,
  1489. IN NTSTATUS Status,
  1490. IN POBJDATA Result,
  1491. IN ULONG Flags,
  1492. OUT PVOID *Buffer,
  1493. OUT ULONG *BufferSize
  1494. )
  1495. /*++
  1496. Routine Description:
  1497. This routine generates an string of the form ACPI\PNPxxxx\0*PNPxxxx\0\0.
  1498. This string is in ANSI format. The code is smart enough to check to see
  1499. if the string that should be used is a fake one and already stored in the
  1500. device extension
  1501. Arguments:
  1502. DeviceExtension - The extension to use when building the DeviceID
  1503. Status - The status of the operation, so far
  1504. Result - The interpreter data
  1505. Flags - The flags passed in (ignore overrides, etc)
  1506. Buffer - Where to put the answer
  1507. BufferSize - Where to put the size of the answer
  1508. Return Value:
  1509. NTSTATUS
  1510. --*/
  1511. {
  1512. BOOLEAN freeTempString = FALSE;
  1513. NTSTATUS status = Status;
  1514. PUCHAR buffer;
  1515. PUCHAR tempString;
  1516. ULONG deviceSize;
  1517. ULONG memSize;
  1518. //
  1519. // First, check to see if we are a processor
  1520. //
  1521. if (!(Flags & GET_PROP_NSOBJ_INTERFACE) &&
  1522. DeviceExtension->Flags & DEV_CAP_PROCESSOR) {
  1523. //
  1524. // Use an alternate means to get the processor ID
  1525. //
  1526. status = ACPIGetProcessorID(
  1527. DeviceExtension,
  1528. Status,
  1529. Result,
  1530. Flags,
  1531. &buffer,
  1532. &memSize
  1533. );
  1534. goto ACPIGetConvertToHardwareIDSuccessExit;
  1535. } else if (!(Flags & GET_PROP_NSOBJ_INTERFACE) &&
  1536. DeviceExtension->Flags & DEV_PROP_FIXED_HID) {
  1537. //
  1538. // Does this string have a fake HID?
  1539. //
  1540. //
  1541. // It does. We can use that string in this one's place. We want a
  1542. // string that subtracts the leading 'ACPI\\' and adds a '\0' at
  1543. // the end.
  1544. //
  1545. deviceSize = strlen(DeviceExtension->DeviceID) - 4;
  1546. //
  1547. // Allocate the memory
  1548. //
  1549. tempString = ExAllocatePoolWithTag(
  1550. ( (Flags & GET_PROP_ALLOCATE_NON_PAGED) ? NonPagedPool : PagedPool),
  1551. deviceSize * sizeof(UCHAR),
  1552. ACPI_STRING_POOLTAG
  1553. );
  1554. if (tempString == NULL) {
  1555. status = STATUS_INSUFFICIENT_RESOURCES;
  1556. goto ACPIGetConvertToHardwareIDExit;
  1557. }
  1558. RtlZeroMemory( tempString, deviceSize * sizeof(UCHAR) );
  1559. freeTempString = TRUE;
  1560. //
  1561. // Generate the PNP ID. The offset of +5 will get rid of the
  1562. // leading 'ACPI\\'
  1563. //
  1564. sprintf( tempString, "%s", DeviceExtension->DeviceID + 5 );
  1565. } else if (!(Flags & GET_PROP_NSOBJ_INTERFACE) &&
  1566. DeviceExtension->Flags & DEV_CAP_PCI_BAR_TARGET) {
  1567. //
  1568. // Are we a PCI Bar Target device? If so, then we have special handling
  1569. // rules that we must follow
  1570. //
  1571. //
  1572. // Right now, lets call the this a "PciBarTarget" device, which
  1573. // is 13 characters long (including the NULL)
  1574. //
  1575. deviceSize = 13;
  1576. //
  1577. // Allocate the memory
  1578. //
  1579. tempString = ExAllocatePoolWithTag(
  1580. ( (Flags & GET_PROP_ALLOCATE_NON_PAGED) ? NonPagedPool : PagedPool),
  1581. deviceSize * sizeof(UCHAR),
  1582. ACPI_STRING_POOLTAG
  1583. );
  1584. if (tempString == NULL) {
  1585. return STATUS_INSUFFICIENT_RESOURCES;
  1586. }
  1587. RtlZeroMemory( tempString, deviceSize * sizeof(UCHAR) );
  1588. freeTempString = TRUE;
  1589. //
  1590. // Print the string
  1591. //
  1592. sprintf( tempString, "%s", "PciBarTarget" );
  1593. } else if (!NT_SUCCESS(Status)) {
  1594. //
  1595. // If we got to this point, and there isn't a successfull status,
  1596. // then there is nothing we can do
  1597. //
  1598. return Status;
  1599. } else {
  1600. //
  1601. // We need to handle things differently based on wether we have an
  1602. // EISAID or a String
  1603. //
  1604. switch (Result->dwDataType) {
  1605. case OBJTYPE_INTDATA:
  1606. //
  1607. // For a hardware ID, we need 7 (PNPxxxx) + 1 (\0)
  1608. // = 8 characters
  1609. //
  1610. deviceSize = 8;
  1611. //
  1612. // Allocate the memory
  1613. //
  1614. tempString = ExAllocatePoolWithTag(
  1615. ( (Flags & GET_PROP_ALLOCATE_NON_PAGED) ? NonPagedPool : PagedPool),
  1616. deviceSize * sizeof(UCHAR),
  1617. ACPI_STRING_POOLTAG
  1618. );
  1619. if (tempString == NULL) {
  1620. status = STATUS_INSUFFICIENT_RESOURCES;
  1621. goto ACPIGetConvertToHardwareIDExit;
  1622. }
  1623. RtlZeroMemory( tempString, deviceSize * sizeof(UCHAR) );
  1624. freeTempString = TRUE;
  1625. //
  1626. // Convert the packed string for the PNP ID
  1627. //
  1628. ACPIAmliDoubleToName( tempString, (ULONG)Result->uipDataValue, FALSE );
  1629. //
  1630. // Done
  1631. //
  1632. break;
  1633. case OBJTYPE_STRDATA:
  1634. //
  1635. // Lets grab a pointer to the string that we will be using
  1636. //
  1637. tempString = Result->pbDataBuff;
  1638. //
  1639. // Does it have a leading '*'? If it does, then we must ignore
  1640. // it
  1641. //
  1642. if (*tempString == '*') {
  1643. tempString++;
  1644. }
  1645. //
  1646. // We need to determine how long the string is
  1647. //
  1648. deviceSize = strlen(tempString) + 1;
  1649. //
  1650. // done
  1651. //
  1652. break;
  1653. default:
  1654. return STATUS_ACPI_INVALID_DATA;
  1655. }
  1656. }
  1657. //
  1658. // When we reach this point, we have a string that contains just the
  1659. // PNPxxxx characters and nothing else. We need to generate a string
  1660. // of the form 'ACPI\PNPxxxx\0*PNPxxxx\0\0'. So we take the string length
  1661. // doubled, and add 7
  1662. //
  1663. memSize = 7 + (2 * deviceSize);
  1664. //
  1665. // Allocate the memory
  1666. //
  1667. buffer = ExAllocatePoolWithTag(
  1668. ( (Flags & GET_PROP_ALLOCATE_NON_PAGED) ? NonPagedPool : PagedPool),
  1669. memSize * sizeof(UCHAR),
  1670. ACPI_STRING_POOLTAG
  1671. );
  1672. if (buffer == NULL) {
  1673. status = STATUS_INSUFFICIENT_RESOURCES;
  1674. goto ACPIGetConvertToHardwareIDExit;
  1675. }
  1676. RtlZeroMemory( buffer, memSize * sizeof(UCHAR) );
  1677. //
  1678. // Put the leading characters in place
  1679. //
  1680. sprintf( buffer, "ACPI\\%s", tempString );
  1681. //
  1682. // We need to generate the offset in to the second string. To do this
  1683. // we need to add 5 to the original size
  1684. //
  1685. deviceSize += 5;
  1686. //
  1687. // Put the 2nd string in its place
  1688. //
  1689. sprintf( buffer + deviceSize, "*%s", tempString );
  1690. //
  1691. // Let the originator see this copy. Make sure to also see the buffer
  1692. // length, if possible
  1693. //
  1694. ACPIGetConvertToHardwareIDSuccessExit:
  1695. *(Buffer) = buffer;
  1696. if (BufferSize != NULL) {
  1697. *(BufferSize) = memSize;
  1698. }
  1699. status = STATUS_SUCCESS;
  1700. ACPIGetConvertToHardwareIDExit:
  1701. //
  1702. // Do we need to free the tempString?
  1703. //
  1704. if (freeTempString == TRUE) {
  1705. ExFreePool( tempString );
  1706. }
  1707. //
  1708. // Done
  1709. //
  1710. return status;
  1711. }
  1712. NTSTATUS
  1713. ACPIGetConvertToHardwareIDWide(
  1714. IN PDEVICE_EXTENSION DeviceExtension,
  1715. IN NTSTATUS Status,
  1716. IN POBJDATA Result,
  1717. IN ULONG Flags,
  1718. OUT PVOID *Buffer,
  1719. OUT ULONG *BufferSize
  1720. )
  1721. /*++
  1722. Routine Description:
  1723. This routine generates an string of the form ACPI\PNPxxxx\0*PNPxxxx\0\0.
  1724. This stringis in UNICODE format. The code is smart enough to check to see
  1725. if the string that should be used is a fake one and already stored in the
  1726. device extension
  1727. Arguments:
  1728. DeviceExtension - The extension to use when building the DeviceID
  1729. Status - The status of the operation, so far
  1730. Result - The interpreter data
  1731. Buffer - Where to put the answer
  1732. BufferSize - Where to put the size of the answer
  1733. Return Value:
  1734. NTSTATUS
  1735. --*/
  1736. {
  1737. BOOLEAN freeTempString = FALSE;
  1738. NTSTATUS status = Status;
  1739. PUCHAR tempString;
  1740. PWCHAR buffer;
  1741. ULONG deviceSize;
  1742. ULONG memSize;
  1743. //
  1744. // First, check to see if we are a processor
  1745. //
  1746. if (!(Flags & GET_PROP_NSOBJ_INTERFACE) &&
  1747. DeviceExtension->Flags & DEV_CAP_PROCESSOR) {
  1748. //
  1749. // Use an alternate means to get the processor ID
  1750. //
  1751. status = ACPIGetProcessorIDWide(
  1752. DeviceExtension,
  1753. Status,
  1754. Result,
  1755. Flags,
  1756. &buffer,
  1757. &memSize
  1758. );
  1759. goto ACPIGetConvertToHardwareIDWideSuccessExit;
  1760. } else if (!(Flags & GET_PROP_NSOBJ_INTERFACE) &&
  1761. DeviceExtension->Flags & DEV_PROP_FIXED_HID) {
  1762. //
  1763. // Does this string have a fake HID?
  1764. //
  1765. //
  1766. // It does. We can use that string in this one's place. We want a
  1767. // string that subtracts the leading 'ACPI\\' and adds a '\0' at
  1768. // the end.
  1769. //
  1770. deviceSize = strlen(DeviceExtension->DeviceID) - 4;
  1771. //
  1772. // Allocate the memory
  1773. //
  1774. tempString = ExAllocatePoolWithTag(
  1775. ( (Flags & GET_PROP_ALLOCATE_NON_PAGED) ? NonPagedPool : PagedPool),
  1776. deviceSize * sizeof(UCHAR),
  1777. ACPI_STRING_POOLTAG
  1778. );
  1779. if (tempString == NULL) {
  1780. status = STATUS_INSUFFICIENT_RESOURCES;
  1781. goto ACPIGetConvertToHardwareIDWideExit;
  1782. }
  1783. RtlZeroMemory( tempString, deviceSize * sizeof(UCHAR) );
  1784. freeTempString = TRUE;
  1785. //
  1786. // Generate the PNP ID. The offset of +5 will get rid of the
  1787. // leading 'ACPI\\'
  1788. //
  1789. sprintf( tempString, "%s", DeviceExtension->DeviceID + 5 );
  1790. } else if (!(Flags & GET_PROP_NSOBJ_INTERFACE) &&
  1791. DeviceExtension->Flags & DEV_CAP_PCI_BAR_TARGET) {
  1792. //
  1793. // Are we a PCI Bar Target device? If so, then we have special handling
  1794. // rules that we must follow
  1795. //
  1796. //
  1797. // Right now, lets call the this a "PciBarTarget" device, which
  1798. // is 13 characters long (including the NULL)
  1799. //
  1800. deviceSize = 13;
  1801. //
  1802. // Allocate the memory
  1803. //
  1804. tempString = ExAllocatePoolWithTag(
  1805. ( (Flags & GET_PROP_ALLOCATE_NON_PAGED) ? NonPagedPool : PagedPool),
  1806. deviceSize * sizeof(UCHAR),
  1807. ACPI_STRING_POOLTAG
  1808. );
  1809. if (tempString == NULL) {
  1810. return STATUS_INSUFFICIENT_RESOURCES;
  1811. }
  1812. RtlZeroMemory( tempString, deviceSize * sizeof(UCHAR) );
  1813. freeTempString = TRUE;
  1814. //
  1815. // Print the string
  1816. //
  1817. sprintf( tempString, "%s", "PciBarTarget" );
  1818. } else if (!NT_SUCCESS(Status)) {
  1819. //
  1820. // If we got to this point, and there isn't a successfull status,
  1821. // then there is nothing we can do
  1822. //
  1823. return Status;
  1824. } else {
  1825. //
  1826. // We need to handle things differently based on wether we have an
  1827. // EISAID or a String
  1828. //
  1829. switch (Result->dwDataType) {
  1830. case OBJTYPE_INTDATA:
  1831. //
  1832. // For a hardware ID, we need 7 (PNPxxxx) + 1 (\0)
  1833. // = 8 characters
  1834. //
  1835. deviceSize = 8;
  1836. //
  1837. // Allocate the memory
  1838. //
  1839. tempString = ExAllocatePoolWithTag(
  1840. ( (Flags & GET_PROP_ALLOCATE_NON_PAGED) ? NonPagedPool : PagedPool),
  1841. deviceSize * sizeof(UCHAR),
  1842. ACPI_STRING_POOLTAG
  1843. );
  1844. if (tempString == NULL) {
  1845. status = STATUS_INSUFFICIENT_RESOURCES;
  1846. goto ACPIGetConvertToHardwareIDWideExit;
  1847. }
  1848. RtlZeroMemory( tempString, deviceSize * sizeof(UCHAR) );
  1849. freeTempString = TRUE;
  1850. //
  1851. // Convert the packed string for the PNP ID
  1852. //
  1853. ACPIAmliDoubleToName( tempString, (ULONG)Result->uipDataValue, FALSE );
  1854. //
  1855. // Done
  1856. //
  1857. break;
  1858. case OBJTYPE_STRDATA:
  1859. //
  1860. // Lets grab a pointer to the string that we will be using
  1861. //
  1862. tempString = Result->pbDataBuff;
  1863. //
  1864. // Does it have a leading '*'? If it does, then we must ignore
  1865. // it
  1866. //
  1867. if (*tempString == '*') {
  1868. tempString++;
  1869. }
  1870. //
  1871. // We need to determine how long the string is
  1872. //
  1873. deviceSize = strlen(tempString) + 1;
  1874. //
  1875. // done
  1876. //
  1877. break;
  1878. default:
  1879. return STATUS_ACPI_INVALID_DATA;
  1880. }
  1881. }
  1882. //
  1883. // When we reach this point, we have a string that contains just the
  1884. // PNPxxxx characters and nothing else. We need to generate a string
  1885. // of the form 'ACPI\PNPxxxx\0*PNPxxxx\0\0'. So we take the string length
  1886. // doubled, and add 7
  1887. //
  1888. memSize = 7 + (2 * deviceSize);
  1889. //
  1890. // Allocate the memory
  1891. //
  1892. buffer = ExAllocatePoolWithTag(
  1893. ( (Flags & GET_PROP_ALLOCATE_NON_PAGED) ? NonPagedPool : PagedPool),
  1894. memSize * sizeof(WCHAR),
  1895. ACPI_STRING_POOLTAG
  1896. );
  1897. if (buffer == NULL) {
  1898. status = STATUS_INSUFFICIENT_RESOURCES;
  1899. goto ACPIGetConvertToHardwareIDWideExit;
  1900. }
  1901. RtlZeroMemory( buffer, memSize * sizeof(WCHAR) );
  1902. //
  1903. // Put the leading characters in place
  1904. //
  1905. swprintf( buffer, L"ACPI\\%S", tempString );
  1906. //
  1907. // We need to generate the offset in to the second string. To do this
  1908. // we need to add 5 to the original size
  1909. //
  1910. deviceSize += 5;
  1911. //
  1912. // Put the 2nd string in its place
  1913. //
  1914. swprintf( buffer + deviceSize, L"*%S", tempString );
  1915. //
  1916. // Let the originator see this copy. Make sure to also see the buffer
  1917. // length, if possible
  1918. //
  1919. ACPIGetConvertToHardwareIDWideSuccessExit:
  1920. *(Buffer) = buffer;
  1921. if (BufferSize != NULL) {
  1922. *(BufferSize) = (memSize * sizeof(WCHAR) );
  1923. }
  1924. status = STATUS_SUCCESS;
  1925. ACPIGetConvertToHardwareIDWideExit:
  1926. //
  1927. // Do we need to free the tempString?
  1928. //
  1929. if (freeTempString == TRUE) {
  1930. ExFreePool( tempString );
  1931. }
  1932. //
  1933. // Done
  1934. //
  1935. return status;
  1936. }
  1937. NTSTATUS
  1938. ACPIGetConvertToInstanceID(
  1939. IN PDEVICE_EXTENSION DeviceExtension,
  1940. IN NTSTATUS Status,
  1941. IN POBJDATA Result,
  1942. IN ULONG Flags,
  1943. OUT PVOID *Buffer,
  1944. OUT ULONG *BufferSize
  1945. )
  1946. /*++
  1947. Routine Description:
  1948. This routine generates an string of the form XXXXX (in hex values).
  1949. This string is in ANSI format. The code is smart enough to check to see
  1950. if the string that should be used is a fake one and already stored in the
  1951. device extension
  1952. Arguments:
  1953. DeviceExtension - The extension to use when building the DeviceID
  1954. Status - The status of the operation, so far
  1955. Result - The interpreter data
  1956. Flags - The flags passed in (ignore overrides, etc)
  1957. Buffer - Where to put the answer
  1958. BufferSize - Where to put the size of the answer
  1959. Return Value:
  1960. NTSTATUS
  1961. --*/
  1962. {
  1963. PUCHAR buffer;
  1964. ULONG memSize;
  1965. //
  1966. // Does this string have a fake HID?
  1967. //
  1968. if (!(Flags & GET_PROP_NSOBJ_INTERFACE) &&
  1969. DeviceExtension->Flags & DEV_PROP_FIXED_UID) {
  1970. //
  1971. // It does. We can use that string in this one's place.
  1972. //
  1973. memSize = strlen(DeviceExtension->InstanceID) + 1;
  1974. //
  1975. // Allocate the memory
  1976. //
  1977. buffer = ExAllocatePoolWithTag(
  1978. ( (Flags & GET_PROP_ALLOCATE_NON_PAGED) ? NonPagedPool : PagedPool),
  1979. memSize * sizeof(UCHAR),
  1980. ACPI_STRING_POOLTAG
  1981. );
  1982. if (buffer == NULL) {
  1983. return STATUS_INSUFFICIENT_RESOURCES;
  1984. }
  1985. RtlZeroMemory( buffer, memSize * sizeof(UCHAR) );
  1986. //
  1987. // Generate the PNP ID. The offset of +5 will get rid of the
  1988. // leading 'ACPI\\'
  1989. //
  1990. RtlCopyMemory( buffer, DeviceExtension->InstanceID, memSize );
  1991. //
  1992. // Done
  1993. //
  1994. goto ACPIGetConvertToInstanceIDExit;
  1995. }
  1996. //
  1997. // Are we a PCI Bar Target device? If so, then we have special handling
  1998. // rules that we must follow
  1999. //
  2000. if (!(Flags & GET_PROP_NSOBJ_INTERFACE) &&
  2001. DeviceExtension->Flags & DEV_CAP_PCI_BAR_TARGET) {
  2002. //
  2003. // We are going to use the device's Address (which we should
  2004. // have pre-cached inside the device extension) as the Unique ID.
  2005. // We know that we will need at most nine characters since the
  2006. // Address is limited to a DWORD in size.
  2007. //
  2008. memSize = 9;
  2009. //
  2010. // Allocate the memory
  2011. //
  2012. buffer = ExAllocatePoolWithTag(
  2013. ( (Flags & GET_PROP_ALLOCATE_NON_PAGED) ? NonPagedPool : PagedPool),
  2014. memSize * sizeof(UCHAR),
  2015. ACPI_STRING_POOLTAG
  2016. );
  2017. if (buffer == NULL) {
  2018. return STATUS_INSUFFICIENT_RESOURCES;
  2019. }
  2020. RtlZeroMemory( buffer, memSize * sizeof(UCHAR) );
  2021. //
  2022. // Print the string
  2023. //
  2024. sprintf( buffer, "%lx", DeviceExtension->Address );
  2025. //
  2026. // Done
  2027. //
  2028. goto ACPIGetConvertToInstanceIDExit;
  2029. }
  2030. //
  2031. // If we got to this point, and there isn't a successfull status,
  2032. // then there is nothing we can do
  2033. //
  2034. if (!NT_SUCCESS(Status)) {
  2035. return Status;
  2036. }
  2037. //
  2038. // We need to handle things differently based on wether we have an
  2039. // EISAID or a String
  2040. //
  2041. switch (Result->dwDataType) {
  2042. case OBJTYPE_INTDATA:
  2043. //
  2044. // For an Instance ID, we need at most 9 characters
  2045. //
  2046. memSize = 9;
  2047. //
  2048. // Allocate the memory
  2049. //
  2050. buffer = ExAllocatePoolWithTag(
  2051. ( (Flags & GET_PROP_ALLOCATE_NON_PAGED) ? NonPagedPool : PagedPool),
  2052. memSize * sizeof(UCHAR),
  2053. ACPI_STRING_POOLTAG
  2054. );
  2055. if (buffer == NULL) {
  2056. return STATUS_INSUFFICIENT_RESOURCES;
  2057. }
  2058. RtlZeroMemory( buffer, memSize * sizeof(UCHAR) );
  2059. //
  2060. // Print the string
  2061. //
  2062. sprintf( buffer, "%lx", Result->uipDataValue );
  2063. //
  2064. // Done
  2065. //
  2066. break;
  2067. case OBJTYPE_STRDATA:
  2068. //
  2069. // Just copy the string that was handed to us
  2070. //
  2071. memSize = strlen(Result->pbDataBuff) + 1;
  2072. //
  2073. // Allocate the memory
  2074. //
  2075. buffer = ExAllocatePoolWithTag(
  2076. ( (Flags & GET_PROP_ALLOCATE_NON_PAGED) ? NonPagedPool : PagedPool),
  2077. memSize * sizeof(UCHAR),
  2078. ACPI_STRING_POOLTAG
  2079. );
  2080. if (buffer == NULL) {
  2081. return STATUS_INSUFFICIENT_RESOURCES;
  2082. }
  2083. RtlZeroMemory( buffer, memSize * sizeof(UCHAR) );
  2084. //
  2085. // Put the leading characters in place
  2086. //
  2087. RtlCopyMemory( buffer, Result->pbDataBuff, memSize );
  2088. //
  2089. // Done
  2090. //
  2091. break;
  2092. default:
  2093. return STATUS_ACPI_INVALID_DATA;
  2094. }
  2095. ACPIGetConvertToInstanceIDExit:
  2096. //
  2097. // Let the originator see this copy. Make sure to also see the buffer
  2098. // length, if possible
  2099. //
  2100. *(Buffer) = buffer;
  2101. if (BufferSize != NULL) {
  2102. *(BufferSize) = memSize;
  2103. }
  2104. //
  2105. // Done
  2106. //
  2107. return STATUS_SUCCESS;
  2108. }
  2109. NTSTATUS
  2110. ACPIGetConvertToInstanceIDWide(
  2111. IN PDEVICE_EXTENSION DeviceExtension,
  2112. IN NTSTATUS Status,
  2113. IN POBJDATA Result,
  2114. IN ULONG Flags,
  2115. OUT PVOID *Buffer,
  2116. OUT ULONG *BufferSize
  2117. )
  2118. /*++
  2119. Routine Description:
  2120. This routine generates an string of the form XXXXX (in hex values).
  2121. This string is in ANSI format. The code is smart enough to check to see
  2122. if the string that should be used is a fake one and already stored in the
  2123. device extension
  2124. Arguments:
  2125. DeviceExtension - The extension to use when building the DeviceID
  2126. Status - The status of the operation, so far
  2127. Result - The interpreter data
  2128. Flags - The flags passed in (ignore overrides, etc)
  2129. Buffer - Where to put the answer
  2130. BufferSize - Where to put the size of the answer
  2131. Return Value:
  2132. NTSTATUS
  2133. --*/
  2134. {
  2135. PWCHAR buffer;
  2136. ULONG memSize;
  2137. //
  2138. // Does this string have a fake HID?
  2139. //
  2140. if (!(Flags & GET_PROP_NSOBJ_INTERFACE) &&
  2141. DeviceExtension->Flags & DEV_PROP_FIXED_UID) {
  2142. //
  2143. // It does. We can use that string in this one's place.
  2144. //
  2145. memSize = strlen(DeviceExtension->InstanceID) + 1;
  2146. //
  2147. // Allocate the memory
  2148. //
  2149. buffer = ExAllocatePoolWithTag(
  2150. ( (Flags & GET_PROP_ALLOCATE_NON_PAGED) ? NonPagedPool : PagedPool),
  2151. memSize * sizeof(WCHAR),
  2152. ACPI_STRING_POOLTAG
  2153. );
  2154. if (buffer == NULL) {
  2155. return STATUS_INSUFFICIENT_RESOURCES;
  2156. }
  2157. RtlZeroMemory( buffer, memSize * sizeof(WCHAR) );
  2158. //
  2159. // Generate the PNP ID. The offset of +5 will get rid of the
  2160. // leading 'ACPI\\'
  2161. //
  2162. swprintf( buffer, L"%S", DeviceExtension->InstanceID );
  2163. //
  2164. // Done
  2165. //
  2166. goto ACPIGetConvertToInstanceIDWideExit;
  2167. }
  2168. //
  2169. // Are we a PCI Bar Target device? If so, then we have special handling
  2170. // rules that we must follow
  2171. //
  2172. if (!(Flags & GET_PROP_NSOBJ_INTERFACE) &&
  2173. DeviceExtension->Flags & DEV_CAP_PCI_BAR_TARGET) {
  2174. //
  2175. // We are going to use the device's Address (which we should
  2176. // have pre-cached inside the device extension) as the Unique ID.
  2177. // We know that we will need at most nine characters since the
  2178. // Address is limited to a DWORD in size.
  2179. //
  2180. memSize = 9;
  2181. //
  2182. // Allocate the memory
  2183. //
  2184. buffer = ExAllocatePoolWithTag(
  2185. ( (Flags & GET_PROP_ALLOCATE_NON_PAGED) ? NonPagedPool : PagedPool),
  2186. memSize * sizeof(WCHAR),
  2187. ACPI_STRING_POOLTAG
  2188. );
  2189. if (buffer == NULL) {
  2190. return STATUS_INSUFFICIENT_RESOURCES;
  2191. }
  2192. RtlZeroMemory( buffer, memSize * sizeof(WCHAR) );
  2193. //
  2194. // Print the string
  2195. //
  2196. swprintf( buffer, L"%lx", Result->uipDataValue );
  2197. //
  2198. // Done
  2199. //
  2200. goto ACPIGetConvertToInstanceIDWideExit;
  2201. }
  2202. //
  2203. // If we got to this point, and there isn't a successfull status,
  2204. // then there is nothing we can do
  2205. //
  2206. if (!NT_SUCCESS(Status)) {
  2207. return Status;
  2208. }
  2209. //
  2210. // We need to handle things differently based on wether we have an
  2211. // EISAID or a String
  2212. //
  2213. switch (Result->dwDataType) {
  2214. case OBJTYPE_INTDATA:
  2215. //
  2216. // For an Instance ID, we need at most 9 characters
  2217. //
  2218. memSize = 9;
  2219. //
  2220. // Allocate the memory
  2221. //
  2222. buffer = ExAllocatePoolWithTag(
  2223. ( (Flags & GET_PROP_ALLOCATE_NON_PAGED) ? NonPagedPool : PagedPool),
  2224. memSize * sizeof(WCHAR),
  2225. ACPI_STRING_POOLTAG
  2226. );
  2227. if (buffer == NULL) {
  2228. return STATUS_INSUFFICIENT_RESOURCES;
  2229. }
  2230. RtlZeroMemory( buffer, memSize * sizeof(WCHAR) );
  2231. //
  2232. // Print the string
  2233. //
  2234. swprintf( buffer, L"%lx", Result->uipDataValue );
  2235. //
  2236. // Done
  2237. //
  2238. break;
  2239. case OBJTYPE_STRDATA:
  2240. //
  2241. // Just copy the string that was handed to us
  2242. //
  2243. memSize = strlen(Result->pbDataBuff) + 1;
  2244. //
  2245. // Allocate the memory
  2246. //
  2247. buffer = ExAllocatePoolWithTag(
  2248. ( (Flags & GET_PROP_ALLOCATE_NON_PAGED) ? NonPagedPool : PagedPool),
  2249. memSize * sizeof(WCHAR),
  2250. ACPI_STRING_POOLTAG
  2251. );
  2252. if (buffer == NULL) {
  2253. return STATUS_INSUFFICIENT_RESOURCES;
  2254. }
  2255. RtlZeroMemory( buffer, memSize * sizeof(WCHAR) );
  2256. //
  2257. // Put the leading characters in place
  2258. //
  2259. swprintf( buffer, L"%S", Result->pbDataBuff );
  2260. //
  2261. // Done
  2262. //
  2263. break;
  2264. default:
  2265. return STATUS_ACPI_INVALID_DATA;
  2266. }
  2267. ACPIGetConvertToInstanceIDWideExit:
  2268. //
  2269. // Let the originator see this copy. Make sure to also see the buffer
  2270. // length, if possible
  2271. //
  2272. *(Buffer) = buffer;
  2273. if (BufferSize != NULL) {
  2274. *(BufferSize) = (memSize * sizeof(WCHAR));
  2275. }
  2276. //
  2277. // Done
  2278. //
  2279. return STATUS_SUCCESS;
  2280. }
  2281. NTSTATUS
  2282. ACPIGetConvertToPnpID(
  2283. IN PDEVICE_EXTENSION DeviceExtension,
  2284. IN NTSTATUS Status,
  2285. IN POBJDATA Result,
  2286. IN ULONG Flags,
  2287. OUT PVOID *Buffer,
  2288. OUT ULONG *BufferSize
  2289. )
  2290. /*++
  2291. Routine Description:
  2292. This routine generates an string of the form *PNPxxxx\0.
  2293. This stringis in ANSI format. The code is smart enough to check to see
  2294. if the string that should be used is a fake one and already stored in the
  2295. device extension
  2296. Arguments:
  2297. DeviceExtension - The extension to use when building the DeviceID
  2298. Status - The status of the operation, so far
  2299. Result - The interpreter data
  2300. Flags - The flags passed in (ignore overrides, etc)
  2301. Buffer - Where to put the answer
  2302. BufferSize - Where to put the size of the answer
  2303. Return Value:
  2304. NTSTATUS
  2305. --*/
  2306. {
  2307. PUCHAR buffer;
  2308. PUCHAR tempString;
  2309. ULONG memSize;
  2310. //
  2311. // Does this string have a fake HID?
  2312. //
  2313. if (!(Flags & GET_PROP_NSOBJ_INTERFACE) &&
  2314. DeviceExtension->Flags & DEV_PROP_FIXED_HID) {
  2315. //
  2316. // It does. We can use that string in this one's place. We need
  2317. // to subtract 3 because we need to account for the leading
  2318. // 'ACPI\' (5) and the '*' and '\0' (2) = 3
  2319. //
  2320. memSize = strlen(DeviceExtension->DeviceID) - 3;
  2321. //
  2322. // Allocate the memory
  2323. //
  2324. buffer = ExAllocatePoolWithTag(
  2325. ( (Flags & GET_PROP_ALLOCATE_NON_PAGED) ? NonPagedPool : PagedPool),
  2326. memSize * sizeof(UCHAR),
  2327. ACPI_STRING_POOLTAG
  2328. );
  2329. if (buffer == NULL) {
  2330. return STATUS_INSUFFICIENT_RESOURCES;
  2331. }
  2332. RtlZeroMemory( buffer, memSize * sizeof(UCHAR) );
  2333. //
  2334. // Generate the PNP ID. The offset of +5 will get rid of the
  2335. // leading 'ACPI\\'
  2336. //
  2337. sprintf( buffer, "*%s", DeviceExtension->DeviceID + 5 );
  2338. //
  2339. // Done
  2340. //
  2341. goto ACPIGetConvertToPnpIDExit;
  2342. }
  2343. //
  2344. // Are we a PCI Bar Target device? If so, then we have special handling
  2345. // rules that we must follow
  2346. //
  2347. if (!(Flags & GET_PROP_NSOBJ_INTERFACE) &&
  2348. DeviceExtension->Flags & DEV_CAP_PCI_BAR_TARGET) {
  2349. //
  2350. // Right now, lets call the this a "*PciBarTarget" device, which
  2351. // is 14 characters long (including the NULL)
  2352. //
  2353. memSize = 14;
  2354. //
  2355. // Allocate the memory
  2356. //
  2357. buffer = ExAllocatePoolWithTag(
  2358. ( (Flags & GET_PROP_ALLOCATE_NON_PAGED) ? NonPagedPool : PagedPool),
  2359. memSize * sizeof(UCHAR),
  2360. ACPI_STRING_POOLTAG
  2361. );
  2362. if (buffer == NULL) {
  2363. return STATUS_INSUFFICIENT_RESOURCES;
  2364. }
  2365. RtlZeroMemory( buffer, memSize * sizeof(UCHAR) );
  2366. //
  2367. // Print the string
  2368. //
  2369. sprintf( buffer, "*%s", "PciBarTarget" );
  2370. //
  2371. // Done
  2372. //
  2373. goto ACPIGetConvertToPnpIDExit;
  2374. }
  2375. //
  2376. // If we got to this point, and there isn't a successfull status,
  2377. // then there is nothing we can do
  2378. //
  2379. if (!NT_SUCCESS(Status)) {
  2380. return Status;
  2381. }
  2382. //
  2383. // We need to handle things differently based on wether we have an
  2384. // EISAID or a String
  2385. //
  2386. switch (Result->dwDataType) {
  2387. case OBJTYPE_INTDATA:
  2388. //
  2389. // For a pnp ID, we need 1 (*) + 7 (PNPxxxx) + 1 (\0)
  2390. // = 9 characters
  2391. //
  2392. memSize = 9;
  2393. //
  2394. // Allocate the memory
  2395. //
  2396. buffer = ExAllocatePoolWithTag(
  2397. ( (Flags & GET_PROP_ALLOCATE_NON_PAGED) ? NonPagedPool : PagedPool),
  2398. memSize * sizeof(UCHAR),
  2399. ACPI_STRING_POOLTAG
  2400. );
  2401. if (buffer == NULL) {
  2402. return STATUS_INSUFFICIENT_RESOURCES;
  2403. }
  2404. RtlZeroMemory( buffer, memSize * sizeof(UCHAR) );
  2405. //
  2406. // Convert the packed string
  2407. //
  2408. ACPIAmliDoubleToName( buffer, (ULONG)Result->uipDataValue, TRUE );
  2409. //
  2410. // Done
  2411. //
  2412. break;
  2413. case OBJTYPE_STRDATA:
  2414. //
  2415. // Lets grab a pointer to the string that we will be using
  2416. //
  2417. tempString = Result->pbDataBuff;
  2418. //
  2419. // Does it have a leading '*'? If it does, then we must ignore
  2420. // it
  2421. //
  2422. if (*tempString == '*') {
  2423. tempString++;
  2424. }
  2425. //
  2426. // For a string, make sure that there is no leading '*' and
  2427. // account for the fact that we will preceed the string with
  2428. // a '*' and NULL
  2429. //
  2430. memSize = 2 + strlen(tempString);
  2431. //
  2432. // Allocate the memory
  2433. //
  2434. buffer = ExAllocatePoolWithTag(
  2435. ( (Flags & GET_PROP_ALLOCATE_NON_PAGED) ? NonPagedPool : PagedPool),
  2436. memSize * sizeof(UCHAR),
  2437. ACPI_STRING_POOLTAG
  2438. );
  2439. if (buffer == NULL) {
  2440. return STATUS_INSUFFICIENT_RESOURCES;
  2441. }
  2442. RtlZeroMemory( buffer, memSize * sizeof(UCHAR) );
  2443. //
  2444. // Put the leading characters in place
  2445. //
  2446. sprintf( buffer, "*%s", tempString );
  2447. //
  2448. // Done
  2449. //
  2450. break;
  2451. default:
  2452. return STATUS_ACPI_INVALID_DATA;
  2453. }
  2454. ACPIGetConvertToPnpIDExit:
  2455. //
  2456. // Let the originator see this copy. Make sure to also see the buffer
  2457. // length, if possible
  2458. //
  2459. *(Buffer) = buffer;
  2460. if (BufferSize != NULL) {
  2461. *(BufferSize) = memSize;
  2462. }
  2463. //
  2464. // Done
  2465. //
  2466. return STATUS_SUCCESS;
  2467. }
  2468. NTSTATUS
  2469. ACPIGetConvertToPnpIDWide(
  2470. IN PDEVICE_EXTENSION DeviceExtension,
  2471. IN NTSTATUS Status,
  2472. IN POBJDATA Result,
  2473. IN ULONG Flags,
  2474. OUT PVOID *Buffer,
  2475. OUT ULONG *BufferSize
  2476. )
  2477. /*++
  2478. Routine Description:
  2479. This routine generates an string of the form *PNPxxxx\0.
  2480. This stringis in ANSI format. The code is smart enough to check to see
  2481. if the string that should be used is a fake one and already stored in the
  2482. device extension
  2483. Arguments:
  2484. DeviceExtension - The extension to use when building the DeviceID
  2485. Status - The status of the operation, so far
  2486. Result - The interpreter data
  2487. Flags - The flags passed in (ignore overrides, etc)
  2488. Buffer - Where to put the answer
  2489. BufferSize - Where to put the size of the answer
  2490. Return Value:
  2491. NTSTATUS
  2492. --*/
  2493. {
  2494. PUCHAR tempString;
  2495. PWCHAR buffer;
  2496. ULONG memSize;
  2497. //
  2498. // Does this string have a fake HID?
  2499. //
  2500. if (!(Flags & GET_PROP_NSOBJ_INTERFACE) &&
  2501. DeviceExtension->Flags & DEV_PROP_FIXED_HID) {
  2502. //
  2503. // It does. We can use that string in this one's place. We need
  2504. // to subtract 3 because we need to account for the leading
  2505. // 'ACPI\' (5) and the '*' and '\0' (2) = 3
  2506. //
  2507. memSize = strlen(DeviceExtension->DeviceID) - 3;
  2508. //
  2509. // Allocate the memory
  2510. //
  2511. buffer = ExAllocatePoolWithTag(
  2512. ( (Flags & GET_PROP_ALLOCATE_NON_PAGED) ? NonPagedPool : PagedPool),
  2513. memSize * sizeof(WCHAR),
  2514. ACPI_STRING_POOLTAG
  2515. );
  2516. if (buffer == NULL) {
  2517. return STATUS_INSUFFICIENT_RESOURCES;
  2518. }
  2519. RtlZeroMemory( buffer, memSize * sizeof(WCHAR) );
  2520. //
  2521. // Generate the PNP ID. The offset of +5 will get rid of the
  2522. // leading 'ACPI\\'
  2523. //
  2524. swprintf( buffer, L"*%S", DeviceExtension->DeviceID + 5 );
  2525. //
  2526. // Done
  2527. //
  2528. goto ACPIGetConvertToPnpIDWideExit;
  2529. }
  2530. //
  2531. // Are we a PCI Bar Target device? If so, then we have special handling
  2532. // rules that we must follow
  2533. //
  2534. if (!(Flags & GET_PROP_NSOBJ_INTERFACE) &&
  2535. DeviceExtension->Flags & DEV_CAP_PCI_BAR_TARGET) {
  2536. //
  2537. // Right now, lets call the this a "*PciBarTarget" device, which
  2538. // is 14 characters long (including the NULL)
  2539. //
  2540. memSize = 14;
  2541. //
  2542. // Allocate the memory
  2543. //
  2544. buffer = ExAllocatePoolWithTag(
  2545. ( (Flags & GET_PROP_ALLOCATE_NON_PAGED) ? NonPagedPool : PagedPool),
  2546. memSize * sizeof(WCHAR),
  2547. ACPI_STRING_POOLTAG
  2548. );
  2549. if (buffer == NULL) {
  2550. return STATUS_INSUFFICIENT_RESOURCES;
  2551. }
  2552. RtlZeroMemory( buffer, memSize * sizeof(WCHAR) );
  2553. //
  2554. // Print the string
  2555. //
  2556. swprintf( buffer, L"*%S", "PciBarTarget" );
  2557. //
  2558. // Done
  2559. //
  2560. goto ACPIGetConvertToPnpIDWideExit;
  2561. }
  2562. //
  2563. // If we got to this point, and there isn't a successfull status,
  2564. // then there is nothing we can do
  2565. //
  2566. if (!NT_SUCCESS(Status)) {
  2567. return Status;
  2568. }
  2569. //
  2570. // We need to handle things differently based on wether we have an
  2571. // EISAID or a String
  2572. //
  2573. switch (Result->dwDataType) {
  2574. case OBJTYPE_INTDATA:
  2575. //
  2576. // For a pnp ID, we need 1 (*) + 7 (PNPxxxx) + 1 (\0)
  2577. // = 9 characters
  2578. //
  2579. memSize = 9;
  2580. //
  2581. // Allocate the memory
  2582. //
  2583. buffer = ExAllocatePoolWithTag(
  2584. ( (Flags & GET_PROP_ALLOCATE_NON_PAGED) ? NonPagedPool : PagedPool),
  2585. memSize * sizeof(WCHAR),
  2586. ACPI_STRING_POOLTAG
  2587. );
  2588. if (buffer == NULL) {
  2589. return STATUS_INSUFFICIENT_RESOURCES;
  2590. }
  2591. RtlZeroMemory( buffer, memSize * sizeof(WCHAR) );
  2592. //
  2593. // Convert the packed string
  2594. //
  2595. ACPIAmliDoubleToNameWide( buffer, (ULONG)Result->uipDataValue, TRUE );
  2596. //
  2597. // Done
  2598. //
  2599. break;
  2600. case OBJTYPE_STRDATA:
  2601. //
  2602. // Lets grab a pointer to the string that we will be using
  2603. //
  2604. tempString = Result->pbDataBuff;
  2605. //
  2606. // Does it have a leading '*'? If it does, then we must ignore
  2607. // it
  2608. //
  2609. if (*tempString == '*') {
  2610. tempString++;
  2611. }
  2612. //
  2613. // For a string, make sure that there is no leading '*' and
  2614. // account for the fact that we will preceed the string with
  2615. // a '*' and NULL
  2616. //
  2617. memSize = 2 + strlen(tempString);
  2618. //
  2619. // Allocate the memory
  2620. //
  2621. buffer = ExAllocatePoolWithTag(
  2622. ( (Flags & GET_PROP_ALLOCATE_NON_PAGED) ? NonPagedPool : PagedPool),
  2623. memSize * sizeof(WCHAR),
  2624. ACPI_STRING_POOLTAG
  2625. );
  2626. if (buffer == NULL) {
  2627. return STATUS_INSUFFICIENT_RESOURCES;
  2628. }
  2629. RtlZeroMemory( buffer, memSize * sizeof(WCHAR) );
  2630. //
  2631. // Put the leading characters in place
  2632. //
  2633. swprintf( buffer, L"*%S", tempString );
  2634. //
  2635. // Done
  2636. //
  2637. break;
  2638. default:
  2639. return STATUS_ACPI_INVALID_DATA;
  2640. }
  2641. ACPIGetConvertToPnpIDWideExit:
  2642. //
  2643. // Let the originator see this copy. Make sure to also see the buffer
  2644. // length, if possible
  2645. //
  2646. *(Buffer) = buffer;
  2647. if (BufferSize != NULL) {
  2648. *(BufferSize) = (memSize * sizeof(WCHAR) );
  2649. }
  2650. //
  2651. // Done
  2652. //
  2653. return STATUS_SUCCESS;
  2654. }
  2655. NTSTATUS
  2656. ACPIGetConvertToSerialIDWide(
  2657. IN PDEVICE_EXTENSION DeviceExtension,
  2658. IN NTSTATUS Status,
  2659. IN POBJDATA Result,
  2660. IN ULONG Flags,
  2661. OUT PVOID *Buffer,
  2662. OUT ULONG *BufferSize OPTIONAL
  2663. )
  2664. /*++
  2665. Routine Description:
  2666. This routine generates an string or number of the form ????
  2667. This string is in UNICODE format.
  2668. Arguments:
  2669. DeviceExtension - The extension to use when building the DeviceID
  2670. Status - The status of the operation, so far
  2671. Result - The interpreter data
  2672. Flags - The flags passed in (ignore overrides, etc)
  2673. Buffer - Where to put the answer
  2674. BufferSize - Where to put the size of the answer
  2675. Return Value:
  2676. NTSTATUS
  2677. --*/
  2678. {
  2679. PWCHAR buffer ;
  2680. //
  2681. // If we got to this point, and there isn't a successfull status,
  2682. // then there is nothing we can do
  2683. //
  2684. if (!NT_SUCCESS(Status)) {
  2685. return Status;
  2686. }
  2687. switch (Result->dwDataType) {
  2688. case OBJTYPE_INTDATA:
  2689. buffer = ExAllocatePoolWithTag(
  2690. ( (Flags & GET_PROP_ALLOCATE_NON_PAGED) ? NonPagedPool : PagedPool),
  2691. 9 * sizeof(WCHAR), // 9 WCHARS, or L"nnnnnnnn\0"
  2692. ACPI_STRING_POOLTAG
  2693. );
  2694. if (buffer == NULL) {
  2695. return STATUS_INSUFFICIENT_RESOURCES;
  2696. }
  2697. //
  2698. // Convert to string
  2699. //
  2700. swprintf( buffer, L"%X", (ULONG)Result->uipDataValue );
  2701. *(Buffer) = buffer;
  2702. if (BufferSize != NULL) {
  2703. *(BufferSize) = (9 * sizeof(WCHAR) );
  2704. }
  2705. //
  2706. // Done
  2707. //
  2708. return STATUS_SUCCESS;
  2709. case OBJTYPE_STRDATA:
  2710. return ACPIGetConvertToStringWide(
  2711. DeviceExtension,
  2712. Status,
  2713. Result,
  2714. Flags,
  2715. Buffer,
  2716. BufferSize
  2717. ) ;
  2718. default:
  2719. return STATUS_ACPI_INVALID_DATA;
  2720. }
  2721. }
  2722. NTSTATUS
  2723. ACPIGetConvertToString(
  2724. IN PDEVICE_EXTENSION DeviceExtension,
  2725. IN NTSTATUS Status,
  2726. IN POBJDATA Result,
  2727. IN ULONG Flags,
  2728. OUT PVOID *Buffer,
  2729. OUT ULONG *BufferSize
  2730. )
  2731. /*++
  2732. Routine Description:
  2733. This routine generates an string of the form ????
  2734. This stringis in ANSI format.
  2735. Arguments:
  2736. DeviceExtension - The extension to use when building the DeviceID
  2737. Status - The status of the operation, so far
  2738. Result - The interpreter data
  2739. Flags - The flags passed in (ignore overrides, etc)
  2740. Buffer - Where to put the answer
  2741. BufferSize - Where to put the size of the answer
  2742. Return Value:
  2743. NTSTATUS
  2744. --*/
  2745. {
  2746. PUCHAR buffer;
  2747. ULONG memSize;
  2748. //
  2749. // If we got to this point, and there isn't a successfull status,
  2750. // then there is nothing we can do
  2751. //
  2752. if (!NT_SUCCESS(Status)) {
  2753. return Status;
  2754. }
  2755. //
  2756. // Do we not have a string?
  2757. //
  2758. if (Result->dwDataType != OBJTYPE_STRDATA) {
  2759. return STATUS_ACPI_INVALID_DATA;
  2760. }
  2761. //
  2762. // For a string, make sure that there is no leading '*' and
  2763. // account for the fact that we will preceed the string with
  2764. // a '*' and NULL
  2765. //
  2766. memSize = strlen(Result->pbDataBuff) + 1;
  2767. //
  2768. // Allocate the memory
  2769. //
  2770. buffer = ExAllocatePoolWithTag(
  2771. ( (Flags & GET_PROP_ALLOCATE_NON_PAGED) ? NonPagedPool : PagedPool),
  2772. memSize * sizeof(UCHAR),
  2773. ACPI_STRING_POOLTAG
  2774. );
  2775. if (buffer == NULL) {
  2776. return STATUS_INSUFFICIENT_RESOURCES;
  2777. }
  2778. RtlZeroMemory( buffer, memSize * sizeof(UCHAR) );
  2779. //
  2780. // Copy the string
  2781. //
  2782. RtlCopyMemory( buffer, Result->pbDataBuff, memSize );
  2783. //
  2784. // Let the originator see this copy. Make sure to also see the buffer
  2785. // length, if possible
  2786. //
  2787. *(Buffer) = buffer;
  2788. if (BufferSize != NULL) {
  2789. *(BufferSize) = memSize;
  2790. }
  2791. //
  2792. // Done
  2793. //
  2794. return STATUS_SUCCESS;
  2795. }
  2796. NTSTATUS
  2797. ACPIGetConvertToStringWide(
  2798. IN PDEVICE_EXTENSION DeviceExtension,
  2799. IN NTSTATUS Status,
  2800. IN POBJDATA Result,
  2801. IN ULONG Flags,
  2802. OUT PVOID *Buffer,
  2803. OUT ULONG *BufferSize OPTIONAL
  2804. )
  2805. /*++
  2806. Routine Description:
  2807. This routine generates an string of the form ????
  2808. This stringis in UNICODE format.
  2809. Arguments:
  2810. DeviceExtension - The extension to use when building the DeviceID
  2811. Status - The status of the operation, so far
  2812. Result - The interpreter data
  2813. Flags - The flags passed in (ignore overrides, etc)
  2814. Buffer - Where to put the answer
  2815. BufferSize - Where to put the size of the answer
  2816. Return Value:
  2817. NTSTATUS
  2818. --*/
  2819. {
  2820. PWCHAR buffer;
  2821. ULONG memSize;
  2822. //
  2823. // If we got to this point, and there isn't a successfull status,
  2824. // then there is nothing we can do
  2825. //
  2826. if (!NT_SUCCESS(Status)) {
  2827. return Status;
  2828. }
  2829. //
  2830. // Do we not have a string?
  2831. //
  2832. if (Result->dwDataType != OBJTYPE_STRDATA) {
  2833. return STATUS_ACPI_INVALID_DATA;
  2834. }
  2835. //
  2836. // For a string, make sure that there is no leading '*' and
  2837. // account for the fact that we will preceed the string with
  2838. // a '*' and NULL
  2839. //
  2840. memSize = strlen(Result->pbDataBuff) + 1;
  2841. //
  2842. // Allocate the memory
  2843. //
  2844. buffer = ExAllocatePoolWithTag(
  2845. ( (Flags & GET_PROP_ALLOCATE_NON_PAGED) ? NonPagedPool : PagedPool),
  2846. memSize * sizeof(WCHAR),
  2847. ACPI_STRING_POOLTAG
  2848. );
  2849. if (buffer == NULL) {
  2850. return STATUS_INSUFFICIENT_RESOURCES;
  2851. }
  2852. RtlZeroMemory( buffer, memSize * sizeof(WCHAR) );
  2853. //
  2854. // Generate the string
  2855. //
  2856. swprintf( buffer, L"%S", Result->pbDataBuff );
  2857. //
  2858. // Let the originator see this copy. Make sure to also see the buffer
  2859. // length, if possible
  2860. //
  2861. *(Buffer) = buffer;
  2862. if (BufferSize != NULL) {
  2863. *(BufferSize) = (memSize * sizeof(WCHAR) );
  2864. }
  2865. //
  2866. // Done
  2867. //
  2868. return STATUS_SUCCESS;
  2869. }
  2870. NTSTATUS
  2871. ACPIGetProcessorID(
  2872. IN PDEVICE_EXTENSION DeviceExtension,
  2873. IN NTSTATUS Status,
  2874. IN POBJDATA Result,
  2875. IN ULONG Flags,
  2876. OUT PVOID *Buffer,
  2877. OUT ULONG *BufferSize
  2878. )
  2879. /*++
  2880. Routine Description:
  2881. This routine generates an string in either the hardware or device form
  2882. (see the Flags to decide which one to create). This string
  2883. is in ANSI format. This function interogates the processor directly
  2884. to determine which string to return
  2885. Arguments:
  2886. DeviceExtension - The extension to use when building the ID
  2887. Status - The status of the operation, so far
  2888. Result - The interpreter data
  2889. Flags - The flags passed in (ignore overrides, etc)
  2890. Buffer - Where to put the answer
  2891. BufferSize - Where to put the size of the answer
  2892. Return Value:
  2893. NTSTATUS
  2894. --*/
  2895. {
  2896. PUCHAR buffer;
  2897. PUCHAR tempPtr;
  2898. PUCHAR defaultString;
  2899. ULONG i;
  2900. ULONG max;
  2901. ULONG memSize;
  2902. ULONG offset;
  2903. //
  2904. // We store the name of the processor string in a global...
  2905. //
  2906. defaultString = AcpiProcessorString.Buffer;
  2907. //
  2908. // Calculate how much space we need for the base string
  2909. // (which is ACPI\\%s)
  2910. //
  2911. offset = AcpiProcessorString.Length;
  2912. memSize = AcpiProcessorString.Length + 5;
  2913. //
  2914. // If we are building a Hardware ID, then we are going to
  2915. // need to replicate the string a few times to generate some
  2916. // substrings --- we could use an algorithm that gets us the correct
  2917. // size, but its easier to just overshoot
  2918. //
  2919. if (Flags & GET_CONVERT_TO_HARDWAREID) {
  2920. //
  2921. // Walk the string from the end and try to determine how many subparts
  2922. // there are to it
  2923. //
  2924. i = offset;
  2925. max = 0;
  2926. while (i > 0) {
  2927. //
  2928. // Is the character a number or not?
  2929. //
  2930. if (ISDIGIT(defaultString[i-1])) {
  2931. //
  2932. // Increment the number of parts that we need and try to
  2933. // find the previous space
  2934. //
  2935. max++;
  2936. i--;
  2937. while (i > 0) {
  2938. if (defaultString[i-1] != ' ') {
  2939. i--;
  2940. }
  2941. break;
  2942. }
  2943. //
  2944. // Since we made a hit, continue the while loop, which will
  2945. // mean that we also don't decr i again
  2946. //
  2947. continue;
  2948. }
  2949. //
  2950. // Look at the previous character
  2951. //
  2952. i--;
  2953. }
  2954. memSize *= (max * 2);
  2955. }
  2956. //
  2957. // Allocate the memory
  2958. //
  2959. buffer = ExAllocatePoolWithTag(
  2960. ( (Flags & GET_PROP_ALLOCATE_NON_PAGED) ? NonPagedPool : PagedPool),
  2961. memSize * sizeof(UCHAR),
  2962. ACPI_STRING_POOLTAG
  2963. );
  2964. if (buffer == NULL) {
  2965. *(Buffer) = NULL;
  2966. if (BufferSize != NULL) {
  2967. *(BufferSize) = 0;
  2968. }
  2969. return STATUS_INSUFFICIENT_RESOURCES;
  2970. }
  2971. RtlZeroMemory( buffer, memSize * sizeof(UCHAR) );
  2972. //
  2973. // Lets just deal with the simple case of the device id string
  2974. //
  2975. if (Flags & GET_CONVERT_TO_DEVICEID) {
  2976. sprintf( buffer, "ACPI\\%s", defaultString );
  2977. goto ACPIGetProcessorIDExit;
  2978. }
  2979. //
  2980. // At this point, we have to iterate over the entire buffer and fill
  2981. // it in with parts of the Processor String. We will also take this
  2982. // time to calculate the exact amount of memory required by this string
  2983. //
  2984. memSize = 2;
  2985. tempPtr = buffer;
  2986. for (i = 0; i < max; i++) {
  2987. //
  2988. // First step is to find the nearest "number" from the end of the
  2989. // default string
  2990. //
  2991. while (offset > 0) {
  2992. if (ISDIGIT(defaultString[offset-1])) {
  2993. break;
  2994. }
  2995. offset--;
  2996. }
  2997. //
  2998. // Generate the ACPI\\%s string
  2999. //
  3000. sprintf(tempPtr,"ACPI\\%*s",offset,defaultString);
  3001. tempPtr += (offset + 5);
  3002. *tempPtr = '\0';
  3003. tempPtr++;
  3004. memSize += (offset + 6);
  3005. //
  3006. // Generate the *%s string
  3007. //
  3008. sprintf(tempPtr,"*%*s",offset,defaultString);
  3009. tempPtr += (offset + 1);
  3010. *tempPtr = '\0';
  3011. tempPtr++;
  3012. memSize += (offset + 2);
  3013. //
  3014. // Now try to find the previous space in the substring so that we
  3015. // don't accidently match on a two digit number
  3016. //
  3017. while (offset > 0) {
  3018. if (defaultString[offset-1] == ' ') {
  3019. break;
  3020. }
  3021. offset--;
  3022. }
  3023. }
  3024. //
  3025. // Put in the final null Character
  3026. //
  3027. *tempPtr = L'\0';
  3028. //
  3029. // Let the originator see this copy. Make sure to also see the buffer
  3030. // length, if possible
  3031. //
  3032. ACPIGetProcessorIDExit:
  3033. *(Buffer) = buffer;
  3034. if (BufferSize != NULL) {
  3035. *(BufferSize) = memSize;
  3036. }
  3037. //
  3038. // Done
  3039. //
  3040. return STATUS_SUCCESS;
  3041. }
  3042. NTSTATUS
  3043. ACPIGetProcessorIDWide(
  3044. IN PDEVICE_EXTENSION DeviceExtension,
  3045. IN NTSTATUS Status,
  3046. IN POBJDATA Result,
  3047. IN ULONG Flags,
  3048. OUT PVOID *Buffer,
  3049. OUT ULONG *BufferSize
  3050. )
  3051. /*++
  3052. Routine Description:
  3053. This routine generates an string in either the hardware or device form
  3054. (see the Flags to decide which one to create). This string
  3055. is in UNICODE format. This function interogates the processor directly
  3056. to determine which string to return
  3057. Arguments:
  3058. DeviceExtension - The extension to use when building the ID
  3059. Status - The status of the operation, so far
  3060. Result - The interpreter data
  3061. Flags - The flags passed in (ignore overrides, etc)
  3062. Buffer - Where to put the answer
  3063. BufferSize - Where to put the size of the answer
  3064. Return Value:
  3065. NTSTATUS
  3066. --*/
  3067. {
  3068. PUCHAR defaultString;
  3069. PWCHAR buffer;
  3070. PWCHAR tempPtr;
  3071. ULONG i;
  3072. ULONG max;
  3073. ULONG memSize;
  3074. ULONG offset;
  3075. //
  3076. // We store the name of the processor string in a global...
  3077. //
  3078. defaultString = AcpiProcessorString.Buffer;
  3079. //
  3080. // Calculate how much space we need for the base string
  3081. // (which is ACPI\\%s)
  3082. //
  3083. offset = AcpiProcessorString.Length;
  3084. memSize = AcpiProcessorString.Length + 5;
  3085. //
  3086. // If we are building a Hardware ID, then we are going to
  3087. // need to replicate the string a few times to generate some
  3088. // substrings --- we could use an algorithm that gets us the correct
  3089. // size, but its easier to just overshoot
  3090. //
  3091. if (Flags & GET_CONVERT_TO_HARDWAREID) {
  3092. //
  3093. // Walk the string from the end and try to determine how many subparts
  3094. // there are to it
  3095. //
  3096. i = offset;
  3097. max = 0;
  3098. while (i > 0) {
  3099. //
  3100. // Is the character a number or not?
  3101. //
  3102. if (ISDIGIT(defaultString[i-1])) {
  3103. //
  3104. // Increment the number of parts that we need and try to
  3105. // find the previous space
  3106. //
  3107. max++;
  3108. i--;
  3109. while (i > 0) {
  3110. if (defaultString[i-1] != ' ') {
  3111. i--;
  3112. }
  3113. break;
  3114. }
  3115. //
  3116. // Since we made a hit, continue the while loop, which will
  3117. // mean that we also don't decr i again
  3118. //
  3119. continue;
  3120. }
  3121. //
  3122. // Look at the previous character
  3123. //
  3124. i--;
  3125. }
  3126. memSize *= (max * 2);
  3127. }
  3128. //
  3129. // Allocate the memory
  3130. //
  3131. buffer = ExAllocatePoolWithTag(
  3132. ( (Flags & GET_PROP_ALLOCATE_NON_PAGED) ? NonPagedPool : PagedPool),
  3133. memSize * sizeof(WCHAR),
  3134. ACPI_STRING_POOLTAG
  3135. );
  3136. if (buffer == NULL) {
  3137. *(Buffer) = NULL;
  3138. if (BufferSize != NULL) {
  3139. *(BufferSize) = 0;
  3140. }
  3141. return STATUS_INSUFFICIENT_RESOURCES;
  3142. }
  3143. RtlZeroMemory( buffer, memSize * sizeof(WCHAR) );
  3144. //
  3145. // Lets just deal with the simple case of the device id string
  3146. //
  3147. if (Flags & GET_CONVERT_TO_DEVICEID) {
  3148. swprintf( buffer, L"ACPI\\%S", defaultString );
  3149. goto ACPIGetProcessorIDWideExit;
  3150. }
  3151. //
  3152. // At this point, we have to iterate over the entire buffer and fill
  3153. // it in with parts of the Processor String. We will also take this
  3154. // time to calculate the exact amount of memory required by this string
  3155. //
  3156. memSize = 2;
  3157. tempPtr = buffer;
  3158. for (i = 0; i < max; i++) {
  3159. //
  3160. // First step is to find the nearest "number" from the end of the
  3161. // default string
  3162. //
  3163. while (offset > 0) {
  3164. if (ISDIGIT(defaultString[offset-1])) {
  3165. break;
  3166. }
  3167. offset--;
  3168. }
  3169. //
  3170. // Generate the ACPI\\%s string
  3171. //
  3172. swprintf(tempPtr,L"ACPI\\%*S",offset,defaultString);
  3173. tempPtr += (offset + 5);
  3174. *tempPtr = L'\0';
  3175. tempPtr++;
  3176. memSize += (offset + 6);
  3177. //
  3178. // Generate the *%s string
  3179. //
  3180. swprintf(tempPtr,L"*%*S",offset,defaultString);
  3181. tempPtr += (offset + 1);
  3182. *tempPtr = L'\0';
  3183. tempPtr++;
  3184. memSize += (offset + 2);
  3185. //
  3186. // Now try to find the previous space in the substring so that we
  3187. // don't accidently match on a two digit number
  3188. //
  3189. while (offset > 0) {
  3190. if (defaultString[offset-1] == ' ') {
  3191. break;
  3192. }
  3193. offset--;
  3194. }
  3195. }
  3196. //
  3197. // Put in the final null Character
  3198. //
  3199. *tempPtr = L'\0';
  3200. //
  3201. // Let the originator see this copy. Make sure to also see the buffer
  3202. // length, if possible
  3203. //
  3204. ACPIGetProcessorIDWideExit:
  3205. *(Buffer) = buffer;
  3206. if (BufferSize != NULL) {
  3207. *(BufferSize) = (memSize * sizeof(WCHAR));
  3208. }
  3209. //
  3210. // Done
  3211. //
  3212. return STATUS_SUCCESS;
  3213. }
  3214. NTSTATUS
  3215. ACPIGetProcessorStatus(
  3216. IN PDEVICE_EXTENSION DeviceExtension,
  3217. IN ULONG Flags,
  3218. OUT PULONG DeviceStatus
  3219. )
  3220. /*++
  3221. Routine Description:
  3222. This routine looks at the MAPIC table, finds the proper LOCAL APIC
  3223. table and determines wether or not the processor is present. This
  3224. routine is only called if there is no _STA method for the processor.
  3225. Arguments:
  3226. DeviceExtension - The device asking for the address
  3227. Flags - The flags passed in (ignore overrides, etc)
  3228. Buffer - Where to put the answer
  3229. Return Value:
  3230. NTSTATUS
  3231. --*/
  3232. {
  3233. NTSTATUS status = STATUS_SUCCESS;
  3234. PAPICTABLE apicEntry;
  3235. PMAPIC apicTable;
  3236. PPROCLOCALAPIC localApic;
  3237. PPROCLOCALSAPIC localSapic;
  3238. PROCESSOROBJ *procObj;
  3239. PUCHAR traversePtr;
  3240. ULONG deviceStatus = STA_STATUS_DEFAULT;
  3241. ULONG_PTR tableEnd;
  3242. USHORT entryFlags;
  3243. BOOLEAN foundMatch = FALSE;
  3244. static UCHAR processorCount;
  3245. static UCHAR processorId;
  3246. //
  3247. // Look at the device extension's acpi object and make sure that
  3248. // this is a processor...
  3249. //
  3250. ASSERT( DeviceExtension->AcpiObject != NULL );
  3251. ASSERT( NSGETOBJTYPE(DeviceExtension->AcpiObject) == OBJTYPE_PROCESSOR );
  3252. if (!DeviceExtension->AcpiObject ||
  3253. NSGETOBJTYPE(DeviceExtension->AcpiObject) != OBJTYPE_PROCESSOR ||
  3254. DeviceExtension->AcpiObject->ObjData.pbDataBuff == NULL) {
  3255. //
  3256. // The effect of this code is that the ACPI Namespace's Processor
  3257. // Object is 100% formed like we would expect it to be, then this
  3258. // function will fail, and the calling function all assume that the
  3259. // device is *NOT* present.
  3260. //
  3261. status = STATUS_INVALID_DEVICE_REQUEST;
  3262. goto ACPIGetProcessorStatusExit;
  3263. }
  3264. //
  3265. // Store the pointer to the processor information
  3266. //
  3267. procObj = (PROCESSOROBJ *)DeviceExtension->AcpiObject->ObjData.pbDataBuff;
  3268. //
  3269. // Walk the MAPIC table
  3270. //
  3271. apicTable = AcpiInformation->MultipleApicTable;
  3272. if (!apicTable) {
  3273. //
  3274. // If there is no MAPIC, then we assume there is only one processor
  3275. // present.
  3276. //
  3277. //
  3278. // First time through, we save the ProcessorId of the processor,
  3279. // this is the only processor that we consider present from this
  3280. // point forward. NOTE: this could be problematic with table unloading
  3281. // if there are multiple processors defined in the Acpi Namespace, and
  3282. // the one we picked is in a table we later unload.
  3283. //
  3284. if (processorCount == 0) {
  3285. processorId = procObj->bApicID;
  3286. processorCount++;
  3287. }
  3288. if (processorId != procObj->bApicID) {
  3289. deviceStatus = 0;
  3290. }
  3291. goto ACPIGetProcessorStatusExit;
  3292. }
  3293. //
  3294. // Walk all the elements in the MAPIC table
  3295. //
  3296. traversePtr = (PUCHAR) apicTable->APICTables;
  3297. tableEnd = (ULONG_PTR) apicTable + apicTable->Header.Length;
  3298. while ( (ULONG_PTR) traversePtr < tableEnd) {
  3299. //
  3300. // Look at the current entry in the table and determine if its
  3301. // a local processor APIC
  3302. //
  3303. apicEntry = (PAPICTABLE) traversePtr;
  3304. if (apicEntry->Type == PROCESSOR_LOCAL_APIC &&
  3305. apicEntry->Length == PROCESSOR_LOCAL_APIC_LENGTH) {
  3306. //
  3307. // At this point, we have found a processor local APIC, so
  3308. // see if we can match the processor ID with the one in the
  3309. // device extension
  3310. //
  3311. localApic = (PPROCLOCALAPIC) traversePtr;
  3312. if (localApic->ACPIProcessorID != procObj->bApicID) {
  3313. traversePtr += localApic->Length;
  3314. continue;
  3315. }
  3316. //
  3317. // Found matching Local APIC entry
  3318. //
  3319. foundMatch = TRUE;
  3320. //
  3321. // Is the processor enabled or not?
  3322. //
  3323. if (!(localApic->Flags & PLAF_ENABLED)) {
  3324. //
  3325. // No, then don't pretend that the device is here...
  3326. //
  3327. deviceStatus = 0;
  3328. }
  3329. //
  3330. // If we found the correct APIC table, then there is nothing more
  3331. // todo, so stop walking the MAPIC table...
  3332. //
  3333. break;
  3334. }
  3335. if (apicEntry->Type == LOCAL_SAPIC &&
  3336. apicEntry->Length == PROCESSOR_LOCAL_SAPIC_LENGTH) {
  3337. //
  3338. // At this point, we have found a processor local SAPIC, so
  3339. // see if we can match the processor ID with the one in the
  3340. // device extension
  3341. //
  3342. localSapic = (PPROCLOCALSAPIC) traversePtr;
  3343. if (localSapic->ACPIProcessorID != procObj->bApicID) {
  3344. traversePtr += localSapic->Length;
  3345. continue;
  3346. }
  3347. //
  3348. // Found matching Local SAPIC entry
  3349. //
  3350. foundMatch = TRUE;
  3351. //
  3352. // Is the processor enabled or not?
  3353. //
  3354. if (!(localSapic->Flags & PLAF_ENABLED)) {
  3355. //
  3356. // No, then don't pretend that the device is here...
  3357. //
  3358. deviceStatus = 0;
  3359. }
  3360. //
  3361. // If we found the correct APIC table, then there is nothing more
  3362. // todo, so stop walking the MAPIC table...
  3363. //
  3364. break;
  3365. }
  3366. //
  3367. // Sanity check to make sure that we abort tables with bogus length
  3368. // entries
  3369. //
  3370. if (apicEntry->Length == 0) {
  3371. break;
  3372. }
  3373. traversePtr += apicEntry->Length;
  3374. continue;
  3375. }
  3376. //
  3377. // if we didn't find a match, then processor must not be present
  3378. //
  3379. if (!foundMatch) {
  3380. deviceStatus = 0;
  3381. }
  3382. ACPIGetProcessorStatusExit:
  3383. //
  3384. // Set the value for the status
  3385. //
  3386. *DeviceStatus = deviceStatus;
  3387. //
  3388. // We are done ... return whatever status we calculated...
  3389. //
  3390. return status;
  3391. }
  3392. VOID
  3393. EXPORT
  3394. ACPIGetWorkerForBuffer(
  3395. IN PNSOBJ AcpiObject,
  3396. IN NTSTATUS Status,
  3397. IN POBJDATA Result,
  3398. IN PVOID Context
  3399. )
  3400. /*++
  3401. Routine Description:
  3402. This routine is called to process the request to turn the result object
  3403. into a buffer that can be handled by the requestor
  3404. Arguments:
  3405. AcpiObject - The AcpiObject that was executed
  3406. Status - The status result of the operation
  3407. Result - The data returned by the operation
  3408. Context - PACPI_GET_REQUEST
  3409. Return Value:
  3410. NTSTATUS
  3411. --*/
  3412. {
  3413. BOOLEAN freeData = TRUE;
  3414. KIRQL oldIrql;
  3415. NTSTATUS status = Status;
  3416. PACPI_GET_REQUEST request = (PACPI_GET_REQUEST) Context;
  3417. PUCHAR buffer;
  3418. //
  3419. // If we didn't succeed, then do nothing here
  3420. //
  3421. if (!NT_SUCCESS(status)) {
  3422. freeData = FALSE;
  3423. goto ACPIGetWorkerForBufferExit;
  3424. }
  3425. //
  3426. // Check to see that we got the correct data type
  3427. //
  3428. if ( Result->dwDataType != OBJTYPE_BUFFDATA ) {
  3429. //
  3430. // On this kind of error, we have to determine wether or not
  3431. // to bugcheck
  3432. //
  3433. if ( (request->Flags & GET_PROP_NO_ERRORS) ) {
  3434. ACPIInternalError( ACPI_GET );
  3435. }
  3436. status = STATUS_ACPI_INVALID_DATA;
  3437. goto ACPIGetWorkerForBufferExit;
  3438. }
  3439. if ( !(Result->dwDataLen) ) {
  3440. status = STATUS_ACPI_INVALID_DATA;
  3441. goto ACPIGetWorkerForBufferExit;
  3442. }
  3443. //
  3444. // Allocate a buffer
  3445. //
  3446. buffer = ExAllocatePoolWithTag(
  3447. ( (request->Flags & GET_PROP_ALLOCATE_NON_PAGED) ? NonPagedPool : PagedPool),
  3448. Result->dwDataLen,
  3449. ACPI_BUFFER_POOLTAG
  3450. );
  3451. if (buffer == NULL) {
  3452. status = STATUS_INSUFFICIENT_RESOURCES;
  3453. goto ACPIGetWorkerForBufferExit;
  3454. }
  3455. //
  3456. // Copy the data over to it
  3457. //
  3458. RtlCopyMemory( buffer, Result->pbDataBuff, Result->dwDataLen );
  3459. //
  3460. // Let the originator see this copy. Make sure to also see the buffer
  3461. // length, if possible
  3462. //
  3463. if (request->Buffer != NULL) {
  3464. *(request->Buffer) = buffer;
  3465. if (request->BufferSize != NULL) {
  3466. *(request->BufferSize) = Result->dwDataLen;
  3467. }
  3468. }
  3469. ACPIGetWorkerForBufferExit:
  3470. //
  3471. // Make sure that the request is updated with the current state of
  3472. // the request
  3473. //
  3474. request->Status = status;
  3475. //
  3476. // We need to free the AML object
  3477. //
  3478. if (freeData) {
  3479. AMLIFreeDataBuffs( Result, 1 );
  3480. }
  3481. //
  3482. // We are done, but we must check to see if we are the async or the
  3483. // sync case. If we are the sync case, then we have much less cleanup
  3484. // to perform
  3485. //
  3486. if ( !(request->Flags & GET_PROP_SKIP_CALLBACK) ) {
  3487. //
  3488. // Is there a callback routine to call?
  3489. //
  3490. if (request->CallBackRoutine != NULL) {
  3491. (request->CallBackRoutine)(
  3492. AcpiObject,
  3493. status,
  3494. NULL,
  3495. request->CallBackContext
  3496. );
  3497. }
  3498. //
  3499. // Remove the request from the queue
  3500. //
  3501. KeAcquireSpinLock( &AcpiGetLock, &oldIrql );
  3502. RemoveEntryList( &(request->ListEntry) );
  3503. KeReleaseSpinLock( &AcpiGetLock, oldIrql );
  3504. //
  3505. // We can now free the request itself
  3506. //
  3507. ExFreePool( request );
  3508. }
  3509. }
  3510. VOID
  3511. EXPORT
  3512. ACPIGetWorkerForData(
  3513. IN PNSOBJ AcpiObject,
  3514. IN NTSTATUS Status,
  3515. IN POBJDATA Result,
  3516. IN PVOID Context
  3517. )
  3518. /*++
  3519. Routine Description:
  3520. This routine is called when the originator wants to handle the data
  3521. directly. This is actually a pretty bad thing for the originator
  3522. to do, but we must support some of the older code.
  3523. This routine plays some tricks because it 'knows' what the behaviour
  3524. of the GetSync and GetAsync routines are. Don't try this at home
  3525. Arguments:
  3526. AcpiObject - The AcpiObject that was executed
  3527. Status - The status result of the operation
  3528. Result - The data returned by the operation
  3529. Context - PACPI_GET_REQUEST
  3530. Return Value:
  3531. NTSTATUS
  3532. --*/
  3533. {
  3534. BOOLEAN freeData = TRUE;
  3535. KIRQL oldIrql;
  3536. NTSTATUS status = Status;
  3537. PACPI_GET_REQUEST request = (PACPI_GET_REQUEST) Context;
  3538. //
  3539. // If we didn't succeed, then remember not to free the data
  3540. //
  3541. if (!NT_SUCCESS(status)) {
  3542. freeData = FALSE;
  3543. }
  3544. //
  3545. // For this one routine, the caller *must* provide storage on his end
  3546. //
  3547. ASSERT( request->Buffer != NULL );
  3548. if (request->Buffer == NULL) {
  3549. status = STATUS_INSUFFICIENT_RESOURCES;
  3550. }
  3551. //
  3552. // If we didn't succeed, then do nothing here
  3553. //
  3554. if (!NT_SUCCESS(status)) {
  3555. goto ACPIGetWorkerForDataExit;
  3556. }
  3557. //
  3558. // Copy over the object --- the caller will call 'AmliFreeDataBuffs'
  3559. // on this object
  3560. //
  3561. RtlCopyMemory( request->Buffer, Result, sizeof(OBJDATA) );
  3562. //
  3563. // Play some tricks on the result pointer. This will ensure that we
  3564. // won't accidently free the result before the requestor has a chance
  3565. // to see it
  3566. //
  3567. RtlZeroMemory( Result, sizeof(OBJDATA) );
  3568. //
  3569. // Remember not to free the data
  3570. //
  3571. freeData = FALSE;
  3572. ACPIGetWorkerForDataExit:
  3573. //
  3574. // Make sure that the request is updated with the current state of
  3575. // the request
  3576. //
  3577. request->Status = status;
  3578. //
  3579. // We need to free the AML object
  3580. //
  3581. if (freeData) {
  3582. AMLIFreeDataBuffs( Result, 1 );
  3583. }
  3584. //
  3585. // We are done, but we must check to see if we are the async or the
  3586. // sync case. If we are the sync case, then we have much less cleanup
  3587. // to perform
  3588. //
  3589. if ( !(request->Flags & GET_PROP_SKIP_CALLBACK) ) {
  3590. //
  3591. // Is there a callback routine to call?
  3592. //
  3593. if (request->CallBackRoutine != NULL) {
  3594. (request->CallBackRoutine)(
  3595. AcpiObject,
  3596. status,
  3597. NULL,
  3598. request->CallBackContext
  3599. );
  3600. }
  3601. //
  3602. // Remove the request from the queue
  3603. //
  3604. KeAcquireSpinLock( &AcpiGetLock, &oldIrql );
  3605. RemoveEntryList( &(request->ListEntry) );
  3606. KeReleaseSpinLock( &AcpiGetLock, oldIrql );
  3607. //
  3608. // We can now free the request itself
  3609. //
  3610. ExFreePool( request );
  3611. }
  3612. }
  3613. VOID
  3614. EXPORT
  3615. ACPIGetWorkerForInteger(
  3616. IN PNSOBJ AcpiObject,
  3617. IN NTSTATUS Status,
  3618. IN POBJDATA Result,
  3619. IN PVOID Context
  3620. )
  3621. /*++
  3622. Routine Description:
  3623. This routine is called when the originator wants to handle the integers.
  3624. Arguments:
  3625. AcpiObject - The AcpiObject that was executed
  3626. Status - The status result of the operation
  3627. Result - The data returned by the operation
  3628. Context - PACPI_GET_REQUEST
  3629. Return Value:
  3630. NTSTATUS
  3631. --*/
  3632. {
  3633. BOOLEAN freeData = FALSE;
  3634. KIRQL oldIrql;
  3635. NTSTATUS status = Status;
  3636. PACPI_GET_REQUEST request = (PACPI_GET_REQUEST) Context;
  3637. PULONG buffer = NULL;
  3638. //
  3639. // If the call did succeed, then remember that we *must* free the data
  3640. //
  3641. if (NT_SUCCESS(status)) {
  3642. freeData = TRUE;
  3643. }
  3644. //
  3645. // For this one routine, the caller *must* provide storage on his end
  3646. //
  3647. ASSERT( request->Buffer != NULL );
  3648. if (request->Buffer == NULL) {
  3649. status = STATUS_INSUFFICIENT_RESOURCES;
  3650. goto ACPIGetWorkerForIntegerExit;
  3651. }
  3652. //
  3653. // Are we doing some kind of type conversion? Note that these routines may
  3654. // choose to override an incoming failure...
  3655. //
  3656. if (request->Flags & GET_CONVERT_TO_ADDRESS) {
  3657. status = ACPIGetConvertToAddress(
  3658. request->DeviceExtension,
  3659. Status,
  3660. Result,
  3661. request->Flags,
  3662. request->Buffer,
  3663. request->BufferSize
  3664. );
  3665. } else if (request->Flags & GET_CONVERT_TO_DEVICE_PRESENCE) {
  3666. status = ACPIGetConvertToDevicePresence(
  3667. request->DeviceExtension,
  3668. Status,
  3669. Result,
  3670. request->Flags,
  3671. request->Buffer,
  3672. request->BufferSize
  3673. );
  3674. } else if (NT_SUCCESS(status)) {
  3675. if ((request->Flags & GET_CONVERT_VALIDATE_INTEGER) &&
  3676. (Result->dwDataType != OBJTYPE_INTDATA)) {
  3677. status = STATUS_ACPI_INVALID_DATA;
  3678. } else {
  3679. //
  3680. // Set the value to what we should return
  3681. //
  3682. *( (PULONG) (request->Buffer) ) = (ULONG)Result->uipDataValue;
  3683. if (request->BufferSize != NULL) {
  3684. *(request->BufferSize) = sizeof(ULONG);
  3685. }
  3686. status = STATUS_SUCCESS;
  3687. }
  3688. }
  3689. ACPIGetWorkerForIntegerExit:
  3690. //
  3691. // Make sure that the request is updated with the current state of
  3692. // the request
  3693. //
  3694. request->Status = status;
  3695. //
  3696. // We need to free the AML object
  3697. //
  3698. if (freeData) {
  3699. AMLIFreeDataBuffs( Result, 1 );
  3700. }
  3701. //
  3702. // We are done, but we must check to see if we are the async or the
  3703. // sync case. If we are the sync case, then we have much less cleanup
  3704. // to perform
  3705. //
  3706. if ( !(request->Flags & GET_PROP_SKIP_CALLBACK) ) {
  3707. //
  3708. // Is there a callback routine to call?
  3709. //
  3710. if (request->CallBackRoutine != NULL) {
  3711. (request->CallBackRoutine)(
  3712. AcpiObject,
  3713. status,
  3714. NULL,
  3715. request->CallBackContext
  3716. );
  3717. }
  3718. //
  3719. // Remove the request from the queue
  3720. //
  3721. KeAcquireSpinLock( &AcpiGetLock, &oldIrql );
  3722. RemoveEntryList( &(request->ListEntry) );
  3723. KeReleaseSpinLock( &AcpiGetLock, oldIrql );
  3724. //
  3725. // We can now free the request itself
  3726. //
  3727. ExFreePool( request );
  3728. }
  3729. }
  3730. VOID
  3731. EXPORT
  3732. ACPIGetWorkerForNothing(
  3733. IN PNSOBJ AcpiObject,
  3734. IN NTSTATUS Status,
  3735. IN POBJDATA Result,
  3736. IN PVOID Context
  3737. )
  3738. /*++
  3739. Routine Description:
  3740. This routine is called when the originator wants to handle the case
  3741. where no data is returned
  3742. Arguments:
  3743. AcpiObject - The AcpiObject that was executed
  3744. Status - The status result of the operation
  3745. Result - The data returned by the operation
  3746. Context - PACPI_GET_REQUEST
  3747. Return Value:
  3748. NTSTATUS
  3749. --*/
  3750. {
  3751. BOOLEAN freeData = FALSE;
  3752. KIRQL oldIrql;
  3753. PACPI_GET_REQUEST request = (PACPI_GET_REQUEST) Context;
  3754. //
  3755. // If the call did succeed, then remember that we *must* free the data
  3756. //
  3757. if (NT_SUCCESS(Status)) {
  3758. freeData = TRUE;
  3759. }
  3760. //
  3761. // Make sure that the request is updated with the current state of
  3762. // the request
  3763. //
  3764. request->Status = Status;
  3765. //
  3766. // We need to free the AML object
  3767. //
  3768. if (freeData) {
  3769. AMLIFreeDataBuffs( Result, 1 );
  3770. }
  3771. //
  3772. // We are done, but we must check to see if we are the async or the
  3773. // sync case. If we are the sync case, then we have much less cleanup
  3774. // to perform
  3775. //
  3776. if ( !(request->Flags & GET_PROP_SKIP_CALLBACK) ) {
  3777. //
  3778. // Is there a callback routine to call?
  3779. //
  3780. if (request->CallBackRoutine != NULL) {
  3781. (request->CallBackRoutine)(
  3782. AcpiObject,
  3783. Status,
  3784. NULL,
  3785. request->CallBackContext
  3786. );
  3787. }
  3788. //
  3789. // Remove the request from the queue
  3790. //
  3791. KeAcquireSpinLock( &AcpiGetLock, &oldIrql );
  3792. RemoveEntryList( &(request->ListEntry) );
  3793. KeReleaseSpinLock( &AcpiGetLock, oldIrql );
  3794. //
  3795. // We can now free the request itself
  3796. //
  3797. ExFreePool( request );
  3798. }
  3799. }
  3800. VOID
  3801. EXPORT
  3802. ACPIGetWorkerForString(
  3803. IN PNSOBJ AcpiObject,
  3804. IN NTSTATUS Status,
  3805. IN POBJDATA Result,
  3806. IN PVOID Context
  3807. )
  3808. /*++
  3809. Routine Description:
  3810. This routine is called when the originator wants to handle the strings.
  3811. Arguments:
  3812. AcpiObject - The AcpiObject that was executed
  3813. Status - The status result of the operation
  3814. Result - The data returned by the operation
  3815. Context - PACPI_GET_REQUEST
  3816. Return Value:
  3817. NTSTATUS
  3818. --*/
  3819. {
  3820. BOOLEAN freeData = FALSE;
  3821. KIRQL oldIrql;
  3822. NTSTATUS status = Status;
  3823. PACPI_GET_REQUEST request = (PACPI_GET_REQUEST) Context;
  3824. //
  3825. // If the call did succeed, then remember that we *must* free the data
  3826. //
  3827. if (NT_SUCCESS(status)) {
  3828. freeData = TRUE;
  3829. }
  3830. //
  3831. // For this one routine, the caller *must* provide storage on his end
  3832. //
  3833. ASSERT( request->Buffer != NULL );
  3834. if (request->Buffer == NULL) {
  3835. status = STATUS_INSUFFICIENT_RESOURCES;
  3836. goto ACPIGetWorkerForStringExit;
  3837. }
  3838. //
  3839. // Make sure that we don't allocate empty storage
  3840. //
  3841. if (Result->dwDataType == OBJTYPE_STRDATA &&
  3842. (Result->pbDataBuff == NULL || Result->dwDataLen == 0)) {
  3843. status = STATUS_ACPI_INVALID_DATA;
  3844. goto ACPIGetWorkerForStringExit;
  3845. }
  3846. //
  3847. // Do do we want unicode or ansi output?
  3848. //
  3849. if (request->Flags & GET_CONVERT_TO_WIDESTRING) {
  3850. //
  3851. // Are we doing some other kind of conversion? Eg: DeviceID,
  3852. // InstanceIDs, etc, etc?
  3853. //
  3854. if (request->Flags & GET_CONVERT_TO_DEVICEID) {
  3855. status = ACPIGetConvertToDeviceIDWide(
  3856. request->DeviceExtension,
  3857. Status,
  3858. Result,
  3859. request->Flags,
  3860. request->Buffer,
  3861. request->BufferSize
  3862. );
  3863. } else if (request->Flags & GET_CONVERT_TO_HARDWAREID) {
  3864. status = ACPIGetConvertToHardwareIDWide(
  3865. request->DeviceExtension,
  3866. Status,
  3867. Result,
  3868. request->Flags,
  3869. request->Buffer,
  3870. request->BufferSize
  3871. );
  3872. } else if (request->Flags & GET_CONVERT_TO_INSTANCEID) {
  3873. status = ACPIGetConvertToInstanceIDWide(
  3874. request->DeviceExtension,
  3875. Status,
  3876. Result,
  3877. request->Flags,
  3878. request->Buffer,
  3879. request->BufferSize
  3880. );
  3881. } else if (request->Flags & GET_CONVERT_TO_PNPID) {
  3882. status = ACPIGetConvertToPnpIDWide(
  3883. request->DeviceExtension,
  3884. Status,
  3885. Result,
  3886. request->Flags,
  3887. request->Buffer,
  3888. request->BufferSize
  3889. );
  3890. } else if (request->Flags & GET_CONVERT_TO_COMPATIBLEID) {
  3891. status = ACPIGetConvertToCompatibleIDWide(
  3892. request->DeviceExtension,
  3893. Status,
  3894. Result,
  3895. request->Flags,
  3896. request->Buffer,
  3897. request->BufferSize
  3898. );
  3899. } else if (request->Flags & GET_CONVERT_TO_SERIAL_ID) {
  3900. status = ACPIGetConvertToSerialIDWide(
  3901. request->DeviceExtension,
  3902. Status,
  3903. Result,
  3904. request->Flags,
  3905. request->Buffer,
  3906. request->BufferSize
  3907. );
  3908. } else {
  3909. status = ACPIGetConvertToStringWide(
  3910. request->DeviceExtension,
  3911. Status,
  3912. Result,
  3913. request->Flags,
  3914. request->Buffer,
  3915. request->BufferSize
  3916. );
  3917. }
  3918. } else {
  3919. //
  3920. // Are we doing some other kind of conversion? Eg: DeviceID,
  3921. // InstanceIDs, etc, etc?
  3922. //
  3923. if (request->Flags & GET_CONVERT_TO_DEVICEID) {
  3924. status = ACPIGetConvertToDeviceID(
  3925. request->DeviceExtension,
  3926. Status,
  3927. Result,
  3928. request->Flags,
  3929. request->Buffer,
  3930. request->BufferSize
  3931. );
  3932. } else if (request->Flags & GET_CONVERT_TO_HARDWAREID) {
  3933. status = ACPIGetConvertToHardwareID(
  3934. request->DeviceExtension,
  3935. Status,
  3936. Result,
  3937. request->Flags,
  3938. request->Buffer,
  3939. request->BufferSize
  3940. );
  3941. } else if (request->Flags & GET_CONVERT_TO_INSTANCEID) {
  3942. status = ACPIGetConvertToInstanceID(
  3943. request->DeviceExtension,
  3944. Status,
  3945. Result,
  3946. request->Flags,
  3947. request->Buffer,
  3948. request->BufferSize
  3949. );
  3950. } else if (request->Flags & GET_CONVERT_TO_PNPID) {
  3951. status = ACPIGetConvertToPnpID(
  3952. request->DeviceExtension,
  3953. Status,
  3954. Result,
  3955. request->Flags,
  3956. request->Buffer,
  3957. request->BufferSize
  3958. );
  3959. } else if (request->Flags & GET_CONVERT_TO_COMPATIBLEID) {
  3960. status = ACPIGetConvertToCompatibleID(
  3961. request->DeviceExtension,
  3962. Status,
  3963. Result,
  3964. request->Flags,
  3965. request->Buffer,
  3966. request->BufferSize
  3967. );
  3968. } else {
  3969. status = ACPIGetConvertToString(
  3970. request->DeviceExtension,
  3971. Status,
  3972. Result,
  3973. request->Flags,
  3974. request->Buffer,
  3975. request->BufferSize
  3976. );
  3977. }
  3978. }
  3979. ACPIGetWorkerForStringExit:
  3980. //
  3981. // Make sure that the request is updated with the current state of
  3982. // the request
  3983. //
  3984. request->Status = status;
  3985. //
  3986. // We need to free the AML object
  3987. //
  3988. if (freeData) {
  3989. AMLIFreeDataBuffs( Result, 1 );
  3990. }
  3991. //
  3992. // We are done, but we must check to see if we are the async or the
  3993. // sync case. If we are the sync case, then we have much less cleanup
  3994. // to perform
  3995. //
  3996. if ( !(request->Flags & GET_PROP_SKIP_CALLBACK) ) {
  3997. //
  3998. // Is there a callback routine to call?
  3999. //
  4000. if (request->CallBackRoutine != NULL) {
  4001. (request->CallBackRoutine)(
  4002. AcpiObject,
  4003. status,
  4004. NULL,
  4005. request->CallBackContext
  4006. );
  4007. }
  4008. //
  4009. // Remove the request from the queue
  4010. //
  4011. KeAcquireSpinLock( &AcpiGetLock, &oldIrql );
  4012. RemoveEntryList( &(request->ListEntry) );
  4013. KeReleaseSpinLock( &AcpiGetLock, oldIrql );
  4014. //
  4015. // We can now free the request itself
  4016. //
  4017. ExFreePool( request );
  4018. }
  4019. }