Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1039 lines
24 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. regcd.c
  5. Abstract:
  6. This contains all of the registry munging code of the NT-specific
  7. side of the ACPI driver
  8. Author:
  9. Stephane Plante (splante)
  10. Environment:
  11. Kernel mode only.
  12. Revision History:
  13. 31-Mar-96 Initial Revision
  14. --*/
  15. #include "pch.h"
  16. NTSTATUS
  17. OSOpenUnicodeHandle(
  18. PUNICODE_STRING UnicodeKey,
  19. HANDLE ParentHandle,
  20. PHANDLE ChildHandle
  21. );
  22. #ifdef ALLOC_PRAGMA
  23. #pragma alloc_text(PAGE,OSCloseHandle)
  24. #pragma alloc_text(PAGE,OSCreateHandle)
  25. #pragma alloc_text(PAGE,OSGetRegistryValue)
  26. #pragma alloc_text(PAGE,OSOpenHandle)
  27. #pragma alloc_text(PAGE,OSOpenUnicodeHandle)
  28. #pragma alloc_text(PAGE,OSOpenLargestSubkey)
  29. #pragma alloc_text(PAGE,OSReadAcpiConfigurationData)
  30. #pragma alloc_text(PAGE,OSReadRegValue)
  31. #pragma alloc_text(PAGE,OSWriteRegValue)
  32. #endif
  33. WCHAR rgzAcpiBiosIdentifier[] = L"ACPI BIOS";
  34. WCHAR rgzAcpiConfigurationDataIdentifier[] = L"Configuration Data";
  35. WCHAR rgzAcpiMultiFunctionAdapterIdentifier[] = L"\\Registry\\Machine\\Hardware\\Description\\System\\MultiFunctionAdapter";
  36. WCHAR rgzAcpiRegistryIdentifier[] = L"Identifier";
  37. NTSTATUS
  38. OSCloseHandle(
  39. HANDLE Key
  40. )
  41. {
  42. //
  43. // Call the function that will close the handle now...
  44. //
  45. PAGED_CODE();
  46. return ZwClose( Key );
  47. }
  48. NTSTATUS
  49. OSCreateHandle(
  50. PSZ KeyName,
  51. HANDLE ParentHandle,
  52. PHANDLE ChildHandle
  53. )
  54. /*++
  55. Routine Description:
  56. Creates a registry key for writting
  57. Arguments:
  58. KeyName - Name of the key to create
  59. ParentHandle - Handle of parent key
  60. ChildHandle - Pointer to where the handle is returned
  61. Return Value:
  62. Status of create/open
  63. --*/
  64. {
  65. ANSI_STRING ansiKey;
  66. NTSTATUS status;
  67. OBJECT_ATTRIBUTES objectAttributes;
  68. UNICODE_STRING unicodeKey;
  69. PAGED_CODE();
  70. ACPIDebugEnter("OSCreateHandle");
  71. //
  72. // We need to convert the given narrow character string into unicode
  73. //
  74. RtlInitAnsiString( &ansiKey, KeyName );
  75. status = RtlAnsiStringToUnicodeString( &unicodeKey, &ansiKey, TRUE );
  76. if (!NT_SUCCESS(status)) {
  77. ACPIPrint( (
  78. ACPI_PRINT_CRITICAL,
  79. "OSCreateHandle: RtlAnsiStringToUnicodeString = %#08lx\n",
  80. status
  81. ) );
  82. return status;
  83. }
  84. //
  85. // Initialize the OBJECT Attributes to a known value
  86. //
  87. RtlZeroMemory( &objectAttributes, sizeof(OBJECT_ATTRIBUTES) );
  88. InitializeObjectAttributes(
  89. &objectAttributes,
  90. &unicodeKey,
  91. OBJ_CASE_INSENSITIVE,
  92. ParentHandle,
  93. NULL
  94. );
  95. //
  96. // Create the key here
  97. //
  98. *ChildHandle = 0;
  99. status = ZwCreateKey(
  100. ChildHandle,
  101. KEY_WRITE,
  102. &objectAttributes,
  103. 0,
  104. NULL,
  105. REG_OPTION_NON_VOLATILE,
  106. NULL
  107. );
  108. //
  109. // We no longer care about the Key after this point...
  110. //
  111. RtlFreeUnicodeString( &unicodeKey );
  112. if (!NT_SUCCESS(status)) {
  113. ACPIPrint( (
  114. ACPI_PRINT_REGISTRY,
  115. "OSCreateHandle: ZwCreateKey = %#08lx\n",
  116. status
  117. ) );
  118. }
  119. return status;
  120. ACPIDebugExit("OSCreateHandle");
  121. }
  122. NTSTATUS
  123. OSGetRegistryValue(
  124. IN HANDLE ParentHandle,
  125. IN PWSTR ValueName,
  126. OUT PKEY_VALUE_PARTIAL_INFORMATION_ALIGN64 *Information
  127. )
  128. {
  129. NTSTATUS status;
  130. PKEY_VALUE_PARTIAL_INFORMATION_ALIGN64 infoBuffer;
  131. ULONG keyValueLength;
  132. UNICODE_STRING unicodeString;
  133. PAGED_CODE();
  134. ACPIDebugEnter("OSGetRegistryValue");
  135. RtlInitUnicodeString( &unicodeString, ValueName );
  136. //
  137. // Figure out how big the data value is so that we can allocate the
  138. // proper sized buffer
  139. //
  140. status = ZwQueryValueKey(
  141. ParentHandle,
  142. &unicodeString,
  143. KeyValuePartialInformationAlign64,
  144. (PVOID) NULL,
  145. 0,
  146. &keyValueLength
  147. );
  148. if (status != STATUS_BUFFER_OVERFLOW && status != STATUS_BUFFER_TOO_SMALL) {
  149. return status;
  150. }
  151. //
  152. // Allocate a buffer large enough to contain the entire key data value
  153. //
  154. infoBuffer = ExAllocatePoolWithTag(
  155. NonPagedPool,
  156. keyValueLength,
  157. ACPI_STRING_POOLTAG
  158. );
  159. if (infoBuffer == NULL) {
  160. return STATUS_INSUFFICIENT_RESOURCES;
  161. }
  162. //
  163. // Now query the data again and this time it will work
  164. //
  165. status = ZwQueryValueKey(
  166. ParentHandle,
  167. &unicodeString,
  168. KeyValuePartialInformationAlign64,
  169. (PVOID) infoBuffer,
  170. keyValueLength,
  171. &keyValueLength
  172. );
  173. if (!NT_SUCCESS(status)) {
  174. ExFreePool( infoBuffer );
  175. return status;
  176. }
  177. //
  178. // Everything worked - so simply return the address of the allocated
  179. // structure buffer to the caller, who is now responsible for freeing it
  180. //
  181. *Information = infoBuffer;
  182. return STATUS_SUCCESS;
  183. ACPIDebugExit("OSGetRegistryValue");
  184. }
  185. NTSTATUS
  186. OSOpenHandle(
  187. PSZ KeyName,
  188. HANDLE ParentHandle,
  189. PHANDLE ChildHandle
  190. )
  191. {
  192. ANSI_STRING ansiKey;
  193. NTSTATUS status;
  194. UNICODE_STRING unicodeKey;
  195. PAGED_CODE();
  196. ACPIDebugEnter("OSOpenHandle");
  197. //
  198. // We need to convert the given narrow character string into unicode
  199. //
  200. RtlInitAnsiString( &ansiKey, KeyName );
  201. status = RtlAnsiStringToUnicodeString( &unicodeKey, &ansiKey, TRUE );
  202. if (!NT_SUCCESS(status)) {
  203. ACPIPrint( (
  204. ACPI_PRINT_CRITICAL,
  205. "OSOpenHandle: RtlAnsiStringToUnicodeString = %#08lx\n",
  206. status
  207. ) );
  208. return status;
  209. }
  210. status = OSOpenUnicodeHandle( &unicodeKey, ParentHandle, ChildHandle );
  211. //
  212. // We no longer care about the Key after this point...
  213. //
  214. RtlFreeUnicodeString( &unicodeKey );
  215. return status;
  216. ACPIDebugExit("OSOpenHandle");
  217. }
  218. NTSTATUS
  219. OSOpenUnicodeHandle(
  220. PUNICODE_STRING UnicodeKey,
  221. HANDLE ParentHandle,
  222. PHANDLE ChildHandle
  223. )
  224. {
  225. NTSTATUS status;
  226. OBJECT_ATTRIBUTES objectAttributes;
  227. PAGED_CODE();
  228. //
  229. // Initialize the OBJECT Attributes to a known value
  230. //
  231. RtlZeroMemory( &objectAttributes, sizeof(OBJECT_ATTRIBUTES) );
  232. InitializeObjectAttributes(
  233. &objectAttributes,
  234. UnicodeKey,
  235. OBJ_CASE_INSENSITIVE,
  236. ParentHandle,
  237. NULL
  238. );
  239. //
  240. // Open the key here
  241. //
  242. status = ZwOpenKey(
  243. ChildHandle,
  244. KEY_READ,
  245. &objectAttributes
  246. );
  247. if (!NT_SUCCESS(status)) {
  248. ACPIPrint( (
  249. ACPI_PRINT_REGISTRY,
  250. "OSOpenUnicodeHandle: ZwOpenKey = %#08lx\n",
  251. status
  252. ) );
  253. }
  254. return status;
  255. }
  256. NTSTATUS
  257. OSOpenLargestSubkey(
  258. HANDLE ParentHandle,
  259. PHANDLE ChildHandle,
  260. ULONG RomVersion
  261. )
  262. /*++
  263. Routine Description:
  264. Open the largest (numerically) subkey under the given parent key.
  265. Arguments:
  266. ParentHandle - Handle to the parent key
  267. ChildHandle - Pointer to where the handle is returned
  268. RomVersion - Minimum version number that is acceptable
  269. Return Value:
  270. Status of open
  271. --*/
  272. {
  273. NTSTATUS status;
  274. UNICODE_STRING unicodeName;
  275. PKEY_BASIC_INFORMATION keyInformation;
  276. ULONG resultLength;
  277. ULONG i;
  278. HANDLE workingDir = NULL;
  279. HANDLE largestDir = NULL;
  280. ULONG largestRev = 0;
  281. ULONG thisRev = 0;
  282. PAGED_CODE();
  283. ACPIDebugEnter( "OSOpenLargestSubkey" );
  284. keyInformation = ExAllocatePoolWithTag(
  285. PagedPool,
  286. 512,
  287. ACPI_MISC_POOLTAG
  288. );
  289. if (keyInformation == NULL) {
  290. return STATUS_INSUFFICIENT_RESOURCES;
  291. }
  292. //
  293. // Traverse all subkeys
  294. //
  295. for (i = 0; ; i++) {
  296. //
  297. // Get a subkey
  298. //
  299. status = ZwEnumerateKey(
  300. ParentHandle,
  301. i,
  302. KeyBasicInformation,
  303. keyInformation,
  304. 512,
  305. &resultLength
  306. );
  307. if (!NT_SUCCESS(status)) { // Fail when no more subkeys
  308. break;
  309. }
  310. //
  311. // Create a UNICODE_STRING using the counted string passed back to
  312. // us in the information structure, and convert to an integer.
  313. //
  314. unicodeName.Length = (USHORT) keyInformation->NameLength;
  315. unicodeName.MaximumLength = (USHORT) keyInformation->NameLength;
  316. unicodeName.Buffer = keyInformation->Name;
  317. RtlUnicodeStringToInteger(&unicodeName, 16, &thisRev);
  318. //
  319. // Save this one if it is the largest
  320. //
  321. if ( (workingDir == NULL) || thisRev > largestRev) {
  322. //
  323. // We'll just open the target rather than save
  324. // away the name to open later
  325. //
  326. status = OSOpenUnicodeHandle(
  327. &unicodeName,
  328. ParentHandle,
  329. &workingDir
  330. );
  331. if ( NT_SUCCESS(status) ) {
  332. if (largestDir) {
  333. OSCloseHandle (largestDir); // Close previous
  334. }
  335. largestDir = workingDir; // Save handle
  336. largestRev = thisRev; // Save version number
  337. }
  338. }
  339. }
  340. //
  341. // Done with KeyInformation
  342. //
  343. ExFreePool( keyInformation );
  344. //
  345. // No subkey found/opened, this is a problem
  346. //
  347. if (largestDir == NULL) {
  348. return ( NT_SUCCESS(status) ? STATUS_UNSUCCESSFUL : status );
  349. }
  350. //
  351. // Use the subkey only if it the revision is equal or greater than the
  352. // ROM version
  353. //
  354. if (largestRev < RomVersion) {
  355. OSCloseHandle (largestDir);
  356. return STATUS_REVISION_MISMATCH;
  357. }
  358. *ChildHandle = largestDir; // Return handle to subkey
  359. return STATUS_SUCCESS;
  360. ACPIDebugExit( "OSOpenLargestSubkey" );
  361. }
  362. NTSTATUS
  363. OSReadAcpiConfigurationData(
  364. PKEY_VALUE_PARTIAL_INFORMATION_ALIGN64 *KeyInfo
  365. )
  366. /*++
  367. Routine Description:
  368. This very specialized routine looks in the Registry and tries to find
  369. the information that was written there by ntdetect. It returns a pointer
  370. to the keyvalue that will then be processed by the caller to find the
  371. pointer to the RSDT and the E820 memory table
  372. Arguments:
  373. KeyInfo - Where to store the pointer to the information from the registry
  374. Return Value:
  375. NTSTATUS
  376. --*/
  377. {
  378. BOOLEAN sameId;
  379. HANDLE functionHandle;
  380. HANDLE multiHandle;
  381. NTSTATUS status;
  382. ULONG i;
  383. ULONG length;
  384. UNICODE_STRING biosId;
  385. UNICODE_STRING functionId;
  386. UNICODE_STRING registryId;
  387. WCHAR wbuffer[4];
  388. ASSERT( KeyInfo != NULL );
  389. if (KeyInfo == NULL) {
  390. return STATUS_INVALID_PARAMETER;
  391. }
  392. *KeyInfo = NULL;
  393. //
  394. // Open the handle for the MultiFunctionAdapter
  395. //
  396. RtlInitUnicodeString( &functionId, rgzAcpiMultiFunctionAdapterIdentifier );
  397. status = OSOpenUnicodeHandle(
  398. &functionId,
  399. NULL,
  400. &multiHandle
  401. );
  402. if (!NT_SUCCESS(status)) {
  403. ACPIPrint( (
  404. ACPI_PRINT_CRITICAL,
  405. "OSReadAcpiConfigurationData: Cannot open MFA Handle = %08lx\n",
  406. status
  407. ) );
  408. ACPIBreakPoint();
  409. return status;
  410. }
  411. //
  412. // Initialize the unicode strings we will need shortly
  413. //
  414. RtlInitUnicodeString( &biosId, rgzAcpiBiosIdentifier );
  415. functionId.Buffer = wbuffer;
  416. functionId.MaximumLength = sizeof(wbuffer);
  417. //
  418. // Loop until we run out of children in the MFA node
  419. //
  420. for (i = 0; i < 999; i++) {
  421. //
  422. // Open the subkey
  423. //
  424. RtlIntegerToUnicodeString(i, 10, &functionId );
  425. status = OSOpenUnicodeHandle(
  426. &functionId,
  427. multiHandle,
  428. &functionHandle
  429. );
  430. if (!NT_SUCCESS(status)) {
  431. ACPIPrint( (
  432. ACPI_PRINT_CRITICAL,
  433. "OSReadAcpiConfigurationData: Cannot open MFA %ws = %08lx\n",
  434. functionId.Buffer,
  435. status
  436. ) );
  437. ACPIBreakPoint();
  438. OSCloseHandle( multiHandle );
  439. return status;
  440. }
  441. //
  442. // Check the identifier to see if this is an ACPI BIOS entry
  443. //
  444. status = OSGetRegistryValue(
  445. functionHandle,
  446. rgzAcpiRegistryIdentifier,
  447. KeyInfo
  448. );
  449. if (!NT_SUCCESS(status)) {
  450. OSCloseHandle( functionHandle );
  451. continue;
  452. }
  453. //
  454. // Convert the key information into a unicode string
  455. //
  456. registryId.Buffer = (PWSTR) ( (PUCHAR) (*KeyInfo)->Data);
  457. registryId.MaximumLength = (USHORT) ( (*KeyInfo)->DataLength );
  458. length = ( (*KeyInfo)->DataLength ) / sizeof(WCHAR);
  459. //
  460. // Determine the real length of the ID string
  461. //
  462. while (length) {
  463. if (registryId.Buffer[length-1] == UNICODE_NULL) {
  464. length--;
  465. continue;
  466. }
  467. break;
  468. }
  469. registryId.Length = (USHORT) ( length * sizeof(WCHAR) );
  470. //
  471. // Compare the bios string and the registry string
  472. //
  473. sameId = RtlEqualUnicodeString( &biosId, &registryId, TRUE );
  474. //
  475. // We are done with this information at this point
  476. //
  477. ExFreePool( *KeyInfo );
  478. //
  479. // Did the two strings match
  480. //
  481. if (sameId == FALSE) {
  482. OSCloseHandle( functionHandle );
  483. continue;
  484. }
  485. //
  486. // Read the configuration data from the entry
  487. //
  488. status = OSGetRegistryValue(
  489. functionHandle,
  490. rgzAcpiConfigurationDataIdentifier,
  491. KeyInfo
  492. );
  493. //
  494. // We are done with the function handle, no matter what
  495. //
  496. OSCloseHandle( functionHandle );
  497. //
  498. // Did we read what we wanted to?
  499. //
  500. if (!NT_SUCCESS(status)) {
  501. continue;
  502. }
  503. //
  504. // At this point, we don't need the bus handle
  505. //
  506. OSCloseHandle( multiHandle );
  507. return STATUS_SUCCESS;
  508. }
  509. //
  510. // If we got here, then there is nothing to return
  511. //
  512. ACPIPrint( (
  513. ACPI_PRINT_CRITICAL,
  514. "OSReadAcpiConfigurationData - Could not find entry\n"
  515. ) );
  516. ACPIBreakPoint();
  517. return STATUS_OBJECT_NAME_NOT_FOUND;
  518. }
  519. NTSTATUS
  520. OSReadRegValue(
  521. PSZ ValueName,
  522. HANDLE ParentHandle,
  523. PUCHAR Buffer,
  524. PULONG BufferSize
  525. )
  526. /*++
  527. Routine Description:
  528. This function is responsible for returning the data in the specified value
  529. over to the calling function.
  530. Arguments:
  531. ValueName - What we are looking for
  532. ParentHandle - Our Parent Handle
  533. Buffer - Where to store the data
  534. BufferSize - Length of the buffer and where to store the # read
  535. Return Value:
  536. NTSTATUS
  537. --*/
  538. {
  539. ANSI_STRING ansiValue;
  540. HANDLE localHandle = NULL;
  541. NTSTATUS status;
  542. PKEY_VALUE_PARTIAL_INFORMATION_ALIGN64 data = NULL;
  543. ULONG currentLength = 0;
  544. ULONG desiredLength = 0;
  545. UNICODE_STRING unicodeValue;
  546. PAGED_CODE();
  547. ACPIDebugEnter( "OSReadRegValue" );
  548. //
  549. // First, try to open a handle to the key
  550. //
  551. if (ParentHandle == NULL) {
  552. status= OSOpenHandle(
  553. ACPI_PARAMETERS_REGISTRY_KEY,
  554. 0,
  555. &localHandle
  556. );
  557. if (!NT_SUCCESS(status) || localHandle == NULL) {
  558. ACPIPrint( (
  559. ACPI_PRINT_WARNING,
  560. "OSReadRegValue: OSOpenHandle = %#08lx\n",
  561. status
  562. ) );
  563. return (ULONG) status;
  564. }
  565. } else {
  566. localHandle = ParentHandle;
  567. }
  568. //
  569. // Now that we have an open handle, we can convert the value to a
  570. // unicode string and query it
  571. //
  572. RtlInitAnsiString( &ansiValue, ValueName );
  573. status = RtlAnsiStringToUnicodeString( &unicodeValue, &ansiValue, TRUE );
  574. if (!NT_SUCCESS(status)) {
  575. ACPIPrint( (
  576. ACPI_PRINT_CRITICAL,
  577. "OSReadRegValue: RtlAnsiStringToUnicodeString = %#08lx\n",
  578. status
  579. ) );
  580. if (ParentHandle == NULL) {
  581. OSCloseHandle( localHandle );
  582. }
  583. return status;
  584. }
  585. //
  586. // Next, we need to figure out how much memore we need to hold the
  587. // entire key
  588. //
  589. status = ZwQueryValueKey(
  590. localHandle,
  591. &unicodeValue,
  592. KeyValuePartialInformationAlign64,
  593. data,
  594. currentLength,
  595. &desiredLength
  596. );
  597. //
  598. // We expect this to fail with STATUS_BUFFER_OVERFLOW, so lets make
  599. // sure that this is what happened
  600. //
  601. if (status != STATUS_BUFFER_OVERFLOW && status != STATUS_BUFFER_TOO_SMALL) {
  602. ACPIPrint( (
  603. ACPI_PRINT_WARNING,
  604. "OSReadRegValue: ZwQueryValueKey = %#08lx\n",
  605. status
  606. ) );
  607. //
  608. // Free resources
  609. //
  610. RtlFreeUnicodeString( &unicodeValue );
  611. if (ParentHandle == NULL) {
  612. OSCloseHandle( localHandle );
  613. }
  614. return (NT_SUCCESS(status) ? STATUS_UNSUCCESSFUL : status);
  615. }
  616. while (status == STATUS_BUFFER_OVERFLOW ||
  617. status == STATUS_BUFFER_TOO_SMALL) {
  618. //
  619. // Set the new currentLength
  620. //
  621. currentLength = desiredLength;
  622. //
  623. // Allocate a correctly sized buffer
  624. //
  625. data = ExAllocatePoolWithTag(
  626. PagedPool,
  627. currentLength,
  628. ACPI_MISC_POOLTAG
  629. );
  630. if (data == NULL) {
  631. ACPIPrint( (
  632. ACPI_PRINT_CRITICAL,
  633. "OSReadRegValue: ExAllocatePool(NonPagedPool,%#08lx) failed\n",
  634. desiredLength
  635. ) );
  636. RtlFreeUnicodeString( &unicodeValue );
  637. if (ParentHandle == NULL) {
  638. OSCloseHandle( localHandle );
  639. }
  640. return STATUS_INSUFFICIENT_RESOURCES;
  641. }
  642. //
  643. // Actually try to read the entire key now
  644. //
  645. status = ZwQueryValueKey(
  646. localHandle,
  647. &unicodeValue,
  648. KeyValuePartialInformationAlign64,
  649. data,
  650. currentLength,
  651. &desiredLength
  652. );
  653. //
  654. // If we don't have enough resources, lets just loop again
  655. //
  656. if (status == STATUS_BUFFER_OVERFLOW ||
  657. status == STATUS_BUFFER_TOO_SMALL) {
  658. //
  659. // Make sure to free the old buffer -- otherwise, we could
  660. // have a major memory leak
  661. //
  662. ExFreePool( data );
  663. continue;
  664. }
  665. if (!NT_SUCCESS(status)) {
  666. ACPIPrint( (
  667. ACPI_PRINT_FAILURE,
  668. "OSReadRegValue: ZwQueryValueKey = %#08lx\n",
  669. status
  670. ) );
  671. RtlFreeUnicodeString( &unicodeValue );
  672. if (ParentHandle == NULL) {
  673. OSCloseHandle( localHandle );
  674. }
  675. ExFreePool( data );
  676. return status;
  677. }
  678. //
  679. // Done
  680. //
  681. break;
  682. } // while (status == ...
  683. //
  684. // Free Resources
  685. //
  686. RtlFreeUnicodeString( &unicodeValue );
  687. if (ParentHandle == NULL) {
  688. OSCloseHandle( localHandle );
  689. }
  690. //
  691. // The value read from the registry is a UNICODE Value, however
  692. // we are asked for an ANSI string. So we just work the conversion
  693. // backwards
  694. //
  695. if ( data->Type == REG_SZ ||
  696. data->Type == REG_MULTI_SZ) {
  697. RtlInitUnicodeString( &unicodeValue, (PWSTR) data->Data );
  698. status = RtlUnicodeStringToAnsiString( &ansiValue, &unicodeValue, TRUE);
  699. ExFreePool( data );
  700. if (!NT_SUCCESS(status)) {
  701. ACPIPrint( (
  702. ACPI_PRINT_CRITICAL,
  703. "OSReadRegValue: RtlAnsiStringToUnicodeString = %#08lx\n",
  704. status
  705. ) );
  706. return (ULONG) status;
  707. }
  708. //
  709. // Is our buffer big enough?
  710. //
  711. if ( *BufferSize < ansiValue.MaximumLength) {
  712. ACPIPrint( (
  713. ACPI_PRINT_WARNING,
  714. "OSReadRegValue: %#08lx < %#08lx\n",
  715. *BufferSize,
  716. ansiValue.MaximumLength
  717. ) );
  718. RtlFreeAnsiString( &ansiValue );
  719. return (ULONG) STATUS_BUFFER_OVERFLOW;
  720. } else {
  721. //
  722. // Set the returned size
  723. //
  724. *BufferSize = ansiValue.MaximumLength;
  725. }
  726. //
  727. // Copy the required information
  728. //
  729. RtlCopyMemory( Buffer, ansiValue.Buffer, *BufferSize);
  730. RtlFreeAnsiString( &ansiValue );
  731. } else if ( *BufferSize >= data->DataLength) {
  732. //
  733. // Copy the memory
  734. //
  735. RtlCopyMemory( Buffer, data->Data, data->DataLength );
  736. *BufferSize = data->DataLength;
  737. ExFreePool( data );
  738. } else {
  739. ExFreePool( data );
  740. return STATUS_BUFFER_OVERFLOW;
  741. }
  742. //
  743. // Done
  744. //
  745. return STATUS_SUCCESS;
  746. ACPIDebugExit( "OSReadRegValue" );
  747. }
  748. NTSTATUS
  749. OSWriteRegValue(
  750. PSZ ValueName,
  751. HANDLE Handle,
  752. PVOID Data,
  753. ULONG DataSize
  754. )
  755. /*++
  756. Routine Description:
  757. Creates a value item in a registry key, and writes data to it
  758. Arguments:
  759. ValueName - Name of the value item to create
  760. Handle - Handle of the parent key
  761. Data - Raw data to be written to the value
  762. DataSize - Size of the data to write
  763. Return Value:
  764. Status of create/write
  765. --*/
  766. {
  767. ANSI_STRING ansiKey;
  768. NTSTATUS status;
  769. OBJECT_ATTRIBUTES objectAttributes;
  770. UNICODE_STRING unicodeKey;
  771. PAGED_CODE();
  772. ACPIDebugEnter("OSWriteRegValue");
  773. //
  774. // We need to convert the given narrow character string into unicode
  775. //
  776. RtlInitAnsiString( &ansiKey, ValueName );
  777. status = RtlAnsiStringToUnicodeString( &unicodeKey, &ansiKey, TRUE );
  778. if (!NT_SUCCESS(status)) {
  779. ACPIPrint( (
  780. ACPI_PRINT_CRITICAL,
  781. "OSWriteRegValue: RtlAnsiStringToUnicodeString = %#08lx\n",
  782. status
  783. ) );
  784. return status;
  785. }
  786. //
  787. // Create the value
  788. //
  789. status = ZwSetValueKey(
  790. Handle,
  791. &unicodeKey,
  792. 0,
  793. REG_BINARY,
  794. Data,
  795. DataSize
  796. );
  797. if (!NT_SUCCESS(status)) {
  798. ACPIPrint( (
  799. ACPI_PRINT_REGISTRY,
  800. "OSRegWriteValue: ZwSetValueKey = %#08lx\n",
  801. status
  802. ) );
  803. }
  804. //
  805. // We no longer care about the Key after this point...
  806. //
  807. RtlFreeUnicodeString( &unicodeKey );
  808. return status;
  809. ACPIDebugExit("OSRegWriteValue");
  810. }