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.

1812 lines
43 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. init.c
  5. Abstract:
  6. This modules contains the init code
  7. Author:
  8. Stephane Plante (splante)
  9. Environment:
  10. NT Kernel Model Driver only
  11. --*/
  12. #include "pch.h"
  13. #ifdef ALLOC_PRAGMA
  14. #pragma alloc_text(PAGE,ACPIInitMultiString)
  15. #pragma alloc_text(PAGE,ACPIInitStopDevice)
  16. #pragma alloc_text(PAGE,ACPIInitUnicodeString)
  17. #endif
  18. VOID
  19. ACPIInitDeleteChildDeviceList(
  20. IN PDEVICE_EXTENSION DeviceExtension
  21. )
  22. /*++
  23. Routine Description:
  24. This routine looks at all of the children of the current devnode and
  25. deletes their device objects, basically resetting them to the unenumerated
  26. state
  27. Arguments:
  28. DeviceExtension - The extension whose children should go away
  29. Return Value:
  30. None
  31. --*/
  32. {
  33. EXTENSIONLIST_ENUMDATA eled;
  34. PDEVICE_EXTENSION childExtension;
  35. //
  36. // Setup the list so that we can walk it
  37. //
  38. ACPIExtListSetupEnum(
  39. &eled,
  40. &(DeviceExtension->ChildDeviceList),
  41. &AcpiDeviceTreeLock,
  42. SiblingDeviceList,
  43. WALKSCHEME_REFERENCE_ENTRIES
  44. );
  45. for (childExtension = ACPIExtListStartEnum( &eled );
  46. ACPIExtListTestElement( &eled, (BOOLEAN) TRUE );
  47. childExtension = ACPIExtListEnumNext( &eled) ) {
  48. //
  49. // Reset the device
  50. //
  51. ACPIInitResetDeviceExtension( childExtension );
  52. }
  53. }
  54. VOID
  55. ACPIInitDeleteDeviceExtension(
  56. IN PDEVICE_EXTENSION DeviceExtension
  57. )
  58. /*++
  59. Routine Description:
  60. This routine does the cleanup associated with removing a device object
  61. Arguments:
  62. DeviceExtension
  63. ReturnValue:
  64. None
  65. --*/
  66. {
  67. PDEVICE_EXTENSION currentExtension, parentExtension ;
  68. //
  69. // We must be under the tree lock.
  70. //
  71. ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL) ; // Close enough...
  72. //
  73. // Nobody should care about this node.
  74. //
  75. ASSERT(!DeviceExtension->ReferenceCount) ;
  76. for(currentExtension = DeviceExtension ;
  77. currentExtension;
  78. currentExtension = parentExtension) {
  79. //
  80. // And there should be no children.
  81. //
  82. ASSERT( IsListEmpty( &currentExtension->ChildDeviceList ) );
  83. //
  84. // Unlink the dead extension (does nothing if alreeady unlinked)
  85. //
  86. RemoveEntryList(&currentExtension->SiblingDeviceList);
  87. //
  88. // We also don't want to be part of anyone's ejection list either
  89. // This also removes the extension from the unresolved list as well
  90. //
  91. RemoveEntryList(&currentExtension->EjectDeviceList);
  92. //
  93. // If this device had any ejection relations, most all of those
  94. // unto the unresolved list
  95. //
  96. if (!IsListEmpty( &(currentExtension->EjectDeviceHead) ) ) {
  97. ACPIInternalMoveList(
  98. &(currentExtension->EjectDeviceHead),
  99. &AcpiUnresolvedEjectList
  100. );
  101. }
  102. //
  103. // At this point, we need to check if the ACPI namespace
  104. // object associated with it is also going away
  105. //
  106. if (currentExtension->Flags & DEV_PROP_UNLOADING) {
  107. //
  108. // Let the world know
  109. //
  110. ACPIDevPrint( (
  111. ACPI_PRINT_CRITICAL,
  112. currentExtension,
  113. "- tell Interperter to unload %x\n",
  114. currentExtension->AcpiObject
  115. ) );
  116. AMLIDestroyFreedObjs( currentExtension->AcpiObject );
  117. }
  118. //
  119. // Free the common resources
  120. //
  121. if ( (currentExtension->Flags & DEV_PROP_HID) &&
  122. currentExtension->DeviceID != NULL) {
  123. ExFreePool( currentExtension->DeviceID );
  124. }
  125. if ( (currentExtension->Flags & DEV_PROP_UID) &&
  126. currentExtension->InstanceID != NULL) {
  127. ExFreePool( currentExtension->InstanceID );
  128. }
  129. if (currentExtension->ResourceList != NULL) {
  130. ExFreePool( currentExtension->ResourceList );
  131. }
  132. if (currentExtension->PnpResourceList != NULL) {
  133. ExFreePool( currentExtension->PnpResourceList );
  134. }
  135. if (currentExtension->Flags & DEV_PROP_FIXED_CID &&
  136. currentExtension->Processor.CompatibleID != NULL) {
  137. ExFreePool( currentExtension->Processor.CompatibleID );
  138. }
  139. //
  140. // Free any device-specific allocations we might have made
  141. //
  142. if (currentExtension->Flags & DEV_CAP_THERMAL_ZONE &&
  143. currentExtension->Thermal.Info != NULL) {
  144. ExFreePool( currentExtension->Thermal.Info );
  145. }
  146. //
  147. // Remember the parent's device extension
  148. //
  149. parentExtension = currentExtension->ParentExtension;
  150. //
  151. // Free the extension back to the proper place
  152. //
  153. ExFreeToNPagedLookasideList(
  154. &DeviceExtensionLookAsideList,
  155. currentExtension
  156. );
  157. //
  158. // Sanity check
  159. //
  160. if (parentExtension == NULL) {
  161. break;
  162. }
  163. if (InterlockedDecrement(&parentExtension->ReferenceCount)) {
  164. //
  165. // Parent still has a reference count, bail out.
  166. //
  167. break;
  168. }
  169. }
  170. return;
  171. }
  172. NTSTATUS
  173. ACPIInitDosDeviceName(
  174. IN PDEVICE_EXTENSION DeviceExtension
  175. )
  176. /*++
  177. Routine Description:
  178. If this device has a _DDN method, it is evaluated and the result is
  179. stored within the Device Registry Key
  180. N.B. This routine must be called at Passive level
  181. Arguments:
  182. DeviceExtension - The extension that we wish to find a _DDN for
  183. Return Value:
  184. NTSTATUS
  185. --*/
  186. {
  187. ANSI_STRING ansiString;
  188. HANDLE devHandle;
  189. NTSTATUS status;
  190. OBJDATA objData;
  191. PNSOBJ ddnObject;
  192. PWSTR fixString = L"FirmwareIdentified";
  193. PWSTR pathString = L"DosDeviceName";
  194. ULONG fixValue = 1;
  195. UNICODE_STRING unicodeString;
  196. UNICODE_STRING ddnString;
  197. //
  198. // Initialize the unicode string
  199. //
  200. RtlInitUnicodeString( &unicodeString, fixString);
  201. //
  202. // Open the handle that we need
  203. //
  204. status = IoOpenDeviceRegistryKey(
  205. DeviceExtension->PhysicalDeviceObject,
  206. PLUGPLAY_REGKEY_DEVICE,
  207. STANDARD_RIGHTS_WRITE,
  208. &devHandle
  209. );
  210. if (!NT_SUCCESS(status)) {
  211. //
  212. // Let the world know. But return success anyways
  213. //
  214. ACPIDevPrint( (
  215. ACPI_PRINT_FAILURE,
  216. DeviceExtension,
  217. "ACPIInitDosDeviceName - open failed %08lx\n",
  218. status
  219. ) );
  220. return STATUS_SUCCESS;
  221. }
  222. //
  223. // Try to set the value
  224. //
  225. status = ZwSetValueKey(
  226. devHandle,
  227. &unicodeString,
  228. 0,
  229. REG_DWORD,
  230. &fixValue,
  231. sizeof(fixValue)
  232. );
  233. //
  234. // Initialize the unicode string
  235. //
  236. RtlInitUnicodeString( &unicodeString, pathString);
  237. //
  238. // Lets look for the _DDN
  239. //
  240. ddnObject = ACPIAmliGetNamedChild(
  241. DeviceExtension->AcpiObject,
  242. PACKED_DDN
  243. );
  244. if (ddnObject == NULL) {
  245. ZwClose( devHandle );
  246. return STATUS_SUCCESS;
  247. }
  248. //
  249. // Evaluate the method
  250. //
  251. status = AMLIEvalNameSpaceObject(
  252. ddnObject,
  253. &objData,
  254. 0,
  255. NULL
  256. );
  257. if (!NT_SUCCESS(status)) {
  258. //
  259. // Let the world know. But return success anyways
  260. //
  261. ACPIDevPrint( (
  262. ACPI_PRINT_FAILURE,
  263. DeviceExtension,
  264. "ACPIInitDosDeviceName - eval returns %08lx\n",
  265. status
  266. ) );
  267. ZwClose( devHandle );
  268. return STATUS_SUCCESS;
  269. }
  270. if (objData.dwDataType != OBJTYPE_STRDATA) {
  271. //
  272. // Let the world know. But return success anyways
  273. //
  274. ACPIDevPrint( (
  275. ACPI_PRINT_FAILURE,
  276. DeviceExtension,
  277. "ACPIInitDosDeviceName - eval returns wrong type %d\n",
  278. objData.dwDataType
  279. ) );
  280. AMLIFreeDataBuffs( &objData, 1 );
  281. ZwClose( devHandle );
  282. return STATUS_SUCCESS;
  283. }
  284. //
  285. // Convert the string to an ansi string
  286. //
  287. RtlInitAnsiString( &ansiString, objData.pbDataBuff );
  288. status = RtlAnsiStringToUnicodeString(
  289. &ddnString,
  290. &ansiString,
  291. TRUE
  292. );
  293. if (!NT_SUCCESS(status)) {
  294. ACPIDevPrint( (
  295. ACPI_PRINT_FAILURE,
  296. DeviceExtension,
  297. "ACPIInitDosDeviceName - cannot convert to unicode string %x\n",
  298. status
  299. ) );
  300. AMLIFreeDataBuffs( &objData, 1 );
  301. ZwClose( devHandle );
  302. return status;
  303. }
  304. //
  305. // Try to set the value
  306. //
  307. status = ZwSetValueKey(
  308. devHandle,
  309. &unicodeString,
  310. 0,
  311. REG_SZ,
  312. ddnString.Buffer,
  313. ddnString.Length
  314. );
  315. //
  316. // No longer need the object data and the handle
  317. //
  318. AMLIFreeDataBuffs( &objData, 1 );
  319. ZwClose( devHandle );
  320. //
  321. // What happened
  322. //
  323. if (!NT_SUCCESS(status)) {
  324. //
  325. // Let the world know. But return success anyways
  326. //
  327. ACPIDevPrint( (
  328. ACPI_PRINT_FAILURE,
  329. DeviceExtension,
  330. "ACPIInitDosDeviceName - set failed %08lx\n",
  331. status
  332. ) );
  333. }
  334. return STATUS_SUCCESS;
  335. }
  336. NTSTATUS
  337. ACPIInitMultiString(
  338. PUNICODE_STRING MultiString,
  339. ...
  340. )
  341. /*++
  342. Routine Description:
  343. This routine will take a null terminated list of ascii strings and combine
  344. them together to generate a unicode multi-string block
  345. Arguments:
  346. MultiString - a unicode structure in which a multi-string will be built
  347. ... - a null terminated list of narrow strings which will be combined
  348. together. This list must contain at least a trailing NULL
  349. Return Value:
  350. NTSTATUS
  351. --*/
  352. {
  353. ANSI_STRING ansiString;
  354. NTSTATUS status;
  355. PCSTR rawString;
  356. PWSTR unicodeLocation;
  357. ULONG multiLength = 0;
  358. UNICODE_STRING unicodeString;
  359. va_list ap;
  360. PAGED_CODE();
  361. va_start(ap,MultiString);
  362. //
  363. // Make sure that we won't memory leak
  364. //
  365. ASSERT(MultiString->Buffer == NULL);
  366. rawString = va_arg(ap, PCSTR);
  367. while (rawString != NULL) {
  368. RtlInitAnsiString(&ansiString, rawString);
  369. multiLength += RtlAnsiStringToUnicodeSize(&(ansiString));
  370. rawString = va_arg(ap, PCSTR);
  371. } // while
  372. va_end( ap );
  373. if (multiLength == 0) {
  374. //
  375. // Done
  376. //
  377. RtlInitUnicodeString( MultiString, NULL );
  378. return STATUS_SUCCESS;
  379. }
  380. //
  381. // We need an extra null
  382. //
  383. multiLength += sizeof(WCHAR);
  384. MultiString->MaximumLength = (USHORT) multiLength;
  385. MultiString->Buffer = ExAllocatePoolWithTag(
  386. PagedPool,
  387. multiLength,
  388. ACPI_STRING_POOLTAG
  389. );
  390. if (MultiString->Buffer == NULL) {
  391. return STATUS_INSUFFICIENT_RESOURCES;
  392. }
  393. RtlZeroMemory(MultiString->Buffer, multiLength);
  394. unicodeString.Buffer = MultiString->Buffer;
  395. unicodeString.MaximumLength = (USHORT) multiLength;
  396. va_start( ap, MultiString);
  397. rawString = va_arg(ap, PCSTR);
  398. while (rawString != NULL) {
  399. RtlInitAnsiString(&ansiString,rawString);
  400. status = RtlAnsiStringToUnicodeString(
  401. &unicodeString,
  402. &ansiString,
  403. FALSE
  404. );
  405. //
  406. // We don't allocate memory, so if something goes wrong here,
  407. // its the function thats at fault
  408. //
  409. ASSERT( NT_SUCCESS(status) );
  410. //
  411. // Move the buffers along
  412. //
  413. unicodeString.Buffer += ( (unicodeString.Length/sizeof(WCHAR)) + 1);
  414. unicodeString.MaximumLength -= (unicodeString.Length + sizeof(WCHAR));
  415. unicodeString.Length = 0;
  416. //
  417. // Next
  418. //
  419. rawString = va_arg(ap, PCSTR);
  420. } // while
  421. va_end(ap);
  422. ASSERT(unicodeString.MaximumLength == sizeof(WCHAR));
  423. //
  424. // Stick the final null there
  425. //
  426. unicodeString.Buffer[0] = L'\0';
  427. MultiString->Length = MultiString->MaximumLength;
  428. return STATUS_SUCCESS;
  429. }
  430. VOID
  431. ACPIInitPowerRequestCompletion(
  432. IN PDEVICE_EXTENSION DeviceExtension,
  433. IN PVOID Context,
  434. IN NTSTATUS Status
  435. )
  436. /*++
  437. Routine Description:
  438. This function is called when the PowerRequest from a StartDevice
  439. or a StopDevice has completed
  440. Arguments:
  441. DeviceExtension - The DeviceExtension of the completed device
  442. Context - KEVENT
  443. Status - The result of the operation
  444. Return Value:
  445. VOID
  446. --*/
  447. {
  448. PKEVENT event = (PKEVENT) Context;
  449. //
  450. // Set the event
  451. //
  452. KeSetEvent( event, IO_NO_INCREMENT, FALSE );
  453. }
  454. VOID
  455. ACPIInitReadRegistryKeys(
  456. )
  457. /*++
  458. Routine Description:
  459. This routine is called by DriverEntry to read all the information
  460. from the registry that is global to the life of the driver
  461. Arguments:
  462. None
  463. Return Value:
  464. None
  465. --*/
  466. {
  467. HANDLE processorKey = NULL;
  468. NTSTATUS status;
  469. PUCHAR identifierString = NULL;
  470. PUCHAR processorString = NULL;
  471. PUCHAR steppingString = NULL;
  472. PUCHAR idString = NULL;
  473. ULONG argSize;
  474. ULONG baseSize;
  475. ULONG identifierStringSize;
  476. ULONG processorStringSize;
  477. //
  478. // Read the Override Attribute from the registry
  479. //
  480. argSize = sizeof(AcpiOverrideAttributes);
  481. status = OSReadRegValue(
  482. "Attributes",
  483. (HANDLE) NULL,
  484. &AcpiOverrideAttributes,
  485. &argSize
  486. );
  487. if (!NT_SUCCESS(status)) {
  488. AcpiOverrideAttributes = 0;
  489. }
  490. //
  491. // Make sure that we initialize the Processor String...
  492. //
  493. RtlZeroMemory( &AcpiProcessorString, sizeof(ANSI_STRING) );
  494. //
  495. // Open the Processor Handle
  496. //
  497. status = OSOpenHandle(
  498. ACPI_PROCESSOR_INFORMATION_KEY,
  499. NULL,
  500. &processorKey
  501. );
  502. if ( !NT_SUCCESS(status) ) {
  503. ACPIPrint ((
  504. ACPI_PRINT_FAILURE,
  505. "ACPIInitReadRegistryKeys: failed to open Processor Key (rc=%x)\n",
  506. status));
  507. return;
  508. }
  509. //
  510. // Default guess as to how many bytes we need for the processor string
  511. //
  512. baseSize = 40;
  513. //
  514. // Try to read the processor ID string
  515. //
  516. do {
  517. //
  518. // If we had allocated memory, then free it
  519. //
  520. if (processorString != NULL) {
  521. ExFreePool( processorString );
  522. }
  523. //
  524. // Allocate the amount of memory we think we need
  525. //
  526. processorString = ExAllocatePoolWithTag(
  527. PagedPool,
  528. baseSize * sizeof(UCHAR),
  529. ACPI_STRING_POOLTAG
  530. );
  531. if (!processorString) {
  532. status = STATUS_INSUFFICIENT_RESOURCES;
  533. goto ACPIInitReadRegistryKeysExit;
  534. }
  535. RtlZeroMemory( processorString, baseSize * sizeof(UCHAR) );
  536. //
  537. // Update the amount we think we would need for next time
  538. //
  539. argSize = baseSize * sizeof(UCHAR);
  540. baseSize += 10;
  541. //
  542. // Try to read the key
  543. //
  544. status = OSReadRegValue(
  545. "Identifier",
  546. processorKey,
  547. processorString,
  548. &argSize
  549. );
  550. } while ( status == STATUS_BUFFER_OVERFLOW );
  551. //
  552. // Did we get the identifier?
  553. //
  554. if (!NT_SUCCESS( status )) {
  555. ACPIPrint( (
  556. ACPI_PRINT_FAILURE,
  557. "ACPIInitReadRegistryKeys: failed to read Identifier Value (rc=%x)\n",
  558. status
  559. ) );
  560. goto ACPIInitReadRegistryKeysExit;
  561. }
  562. //
  563. // Remove Stepping information from the identifier string.
  564. //
  565. steppingString = strstr(processorString, ACPI_PROCESSOR_STEPPING_IDENTIFIER);
  566. if (steppingString) {
  567. steppingString[-1] = 0;
  568. }
  569. //
  570. // Remember how many bytes are in the processorString
  571. //
  572. processorStringSize = strlen(processorString) + 1;
  573. //
  574. // Reset our guess for how many bytes we will need for the identifier
  575. //
  576. baseSize = 10;
  577. //
  578. // Try to read the vendor processor ID string
  579. //
  580. do {
  581. //
  582. // If we had allocated memory, then free it
  583. //
  584. if (identifierString != NULL) {
  585. ExFreePool( identifierString );
  586. }
  587. //
  588. // Allocate the amount of memory we think we need
  589. //
  590. identifierString = ExAllocatePoolWithTag(
  591. PagedPool,
  592. baseSize * sizeof(UCHAR),
  593. ACPI_STRING_POOLTAG
  594. );
  595. if (!identifierString) {
  596. status = STATUS_INSUFFICIENT_RESOURCES;
  597. goto ACPIInitReadRegistryKeysExit;
  598. }
  599. RtlZeroMemory( identifierString, baseSize * sizeof(UCHAR) );
  600. //
  601. // Update the amount we think we would need for next time
  602. //
  603. argSize = baseSize * sizeof(UCHAR);
  604. baseSize += 10;
  605. //
  606. // Try to read the key
  607. //
  608. status = OSReadRegValue(
  609. "VendorIdentifier",
  610. processorKey,
  611. identifierString,
  612. &argSize
  613. );
  614. } while ( status == STATUS_BUFFER_OVERFLOW );
  615. //
  616. // Did we get the identifier?
  617. //
  618. if (!NT_SUCCESS( status )) {
  619. ACPIPrint( (
  620. ACPI_PRINT_FAILURE,
  621. "ACPIInitReadRegistryKeys: failed to read Vendor Value (rc=%x)\n",
  622. status
  623. ) );
  624. goto ACPIInitReadRegistryKeysExit;
  625. }
  626. //
  627. // Remember how many bytes are in the processorString
  628. //
  629. identifierStringSize = argSize;
  630. //
  631. // At this point, we can calculate how many bytes we will need for the
  632. // total string. Since the total string is the concatenatation of
  633. // identifierString + " - " + processorString, we just add 2 to the
  634. // sum of the both string sizes (since both sizes include the NULL
  635. // terminator at the end...
  636. //
  637. baseSize = 2 + identifierStringSize + processorStringSize;
  638. //
  639. // Allocate this memory. In the future, we will (probably) need to
  640. // touch this string at DPC level, so it must be fron Non-Paged-Pool
  641. //
  642. idString = ExAllocatePoolWithTag(
  643. NonPagedPool,
  644. baseSize * sizeof(UCHAR),
  645. ACPI_STRING_POOLTAG
  646. );
  647. if (!idString) {
  648. status = STATUS_INSUFFICIENT_RESOURCES;
  649. goto ACPIInitReadRegistryKeysExit;
  650. }
  651. //
  652. // Generate the string
  653. //
  654. sprintf( idString, "%s - %s", identifierString, processorString );
  655. //
  656. // Remember the string for the future
  657. //
  658. AcpiProcessorString.Buffer = idString,
  659. AcpiProcessorString.Length = AcpiProcessorString.MaximumLength = (USHORT) baseSize;
  660. //
  661. // Clean up time
  662. //
  663. ACPIInitReadRegistryKeysExit:
  664. if (processorKey) {
  665. OSCloseHandle(processorKey);
  666. }
  667. if (identifierString) {
  668. ExFreePool(identifierString);
  669. }
  670. if (processorString) {
  671. ExFreePool(processorString);
  672. }
  673. }
  674. VOID
  675. ACPIInitRemoveDeviceExtension(
  676. IN PDEVICE_EXTENSION DeviceExtension
  677. )
  678. /*++
  679. Routine Description:
  680. This routine removes the device extension the ACPI namespace tree add
  681. adds it to the list of surprised removed extensions (which is kept for
  682. debugging purposes only)
  683. This routine is called with the ACPI device tree lock owned
  684. Arguments:
  685. DeviceExtension - the device to remove from the tree
  686. Return Value:
  687. None
  688. --*/
  689. {
  690. PDEVICE_EXTENSION currentExtension, parentExtension;
  691. //
  692. // We must be under the tree lock.
  693. //
  694. ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL) ; // Close enough...
  695. //
  696. // Unlink the dead extension (does nothing if alreeady unlinked)
  697. //
  698. RemoveEntryList(&DeviceExtension->SiblingDeviceList);
  699. //
  700. // We also don't want to be part of anyone's ejection list either.
  701. // This removes the device extension from the unresolved list as well...
  702. //
  703. RemoveEntryList(&DeviceExtension->EjectDeviceList);
  704. //
  705. // If this device has ejection relations, then move all of them
  706. // to the unresolved list
  707. //
  708. if (!IsListEmpty( &(DeviceExtension->EjectDeviceHead) ) ) {
  709. ACPIInternalMoveList(
  710. &(DeviceExtension->EjectDeviceHead),
  711. &AcpiUnresolvedEjectList
  712. );
  713. }
  714. //
  715. // We no longer have any parents
  716. //
  717. parentExtension = DeviceExtension->ParentExtension ;
  718. DeviceExtension->ParentExtension = NULL;
  719. //
  720. // Remember that we removed this extension...
  721. //
  722. AcpiSurpriseRemovedDeviceExtensions[AcpiSurpriseRemovedIndex] =
  723. DeviceExtension;
  724. AcpiSurpriseRemovedIndex = (AcpiSurpriseRemovedIndex + 1) %
  725. ACPI_MAX_REMOVED_EXTENSIONS;
  726. //
  727. // Now, we have to look at the parent and decrement its ref count
  728. // as is appropriate --- crawling up the tree and decrementing ref
  729. // counts as we go
  730. //
  731. for(currentExtension = parentExtension;
  732. currentExtension;
  733. currentExtension = parentExtension) {
  734. //
  735. // Decrement the reference on the current extension...
  736. // We have to do this because we previously unlinked one of its
  737. // children
  738. //
  739. if (InterlockedDecrement(&currentExtension->ReferenceCount)) {
  740. //
  741. // Parent still has a reference count, bail out.
  742. //
  743. break;
  744. }
  745. //
  746. // Get the parent
  747. //
  748. parentExtension = currentExtension->ParentExtension ;
  749. //
  750. // Remember that we removed this extension...
  751. //
  752. AcpiSurpriseRemovedDeviceExtensions[AcpiSurpriseRemovedIndex] =
  753. currentExtension;
  754. AcpiSurpriseRemovedIndex = (AcpiSurpriseRemovedIndex + 1) %
  755. ACPI_MAX_REMOVED_EXTENSIONS;
  756. //
  757. // We don't actually expect the device's ref count to drop to
  758. // zero, but if it does, then we must delete the extension
  759. //
  760. ACPIInitDeleteDeviceExtension( currentExtension );
  761. }
  762. }
  763. VOID
  764. ACPIInitResetDeviceExtension(
  765. IN PDEVICE_EXTENSION DeviceExtension
  766. )
  767. /*++
  768. Routine Description:
  769. Clear up a device extension
  770. Arguments:
  771. DeviceExtension - The extension we wish to reset
  772. Return Value:
  773. None
  774. --*/
  775. {
  776. KIRQL oldIrql;
  777. LONG oldReferenceCount;
  778. PCM_RESOURCE_LIST cmResourceList;
  779. PDEVICE_OBJECT deviceObject = NULL;
  780. PDEVICE_OBJECT targetObject = NULL;
  781. //
  782. // We require the spinlock for parts of this
  783. //
  784. KeAcquireSpinLock( &AcpiDeviceTreeLock, &oldIrql );
  785. //
  786. // Clean up those parts that are associated with us being a filter
  787. //
  788. if (DeviceExtension->Flags & DEV_TYPE_FILTER) {
  789. if (DeviceExtension->Flags & DEV_TYPE_PDO) {
  790. //
  791. // If we are a PDO, then we need to release the reference we took on
  792. // TargetDeviceObject in Buildsrc.c
  793. //
  794. if (DeviceExtension->TargetDeviceObject) {
  795. ObDereferenceObject(DeviceExtension->TargetDeviceObject) ;
  796. }
  797. } else {
  798. //
  799. // If we are a Filter, then we need to remember to detach ourselves
  800. // from the device
  801. //
  802. targetObject = DeviceExtension->TargetDeviceObject;
  803. }
  804. }
  805. //
  806. // Step one is to zero out the things that we no longer care about
  807. //
  808. if (DeviceExtension->PnpResourceList != NULL) {
  809. ExFreePool( DeviceExtension->PnpResourceList );
  810. DeviceExtension->PnpResourceList = NULL;
  811. }
  812. cmResourceList = DeviceExtension->ResourceList;
  813. if (DeviceExtension->ResourceList != NULL) {
  814. DeviceExtension->ResourceList = NULL;
  815. }
  816. deviceObject = DeviceExtension->DeviceObject;
  817. if (deviceObject != NULL) {
  818. deviceObject->DeviceExtension = NULL;
  819. DeviceExtension->DeviceObject = NULL;
  820. //
  821. // The reference count should have value > 0
  822. //
  823. oldReferenceCount = InterlockedDecrement(
  824. &(DeviceExtension->ReferenceCount)
  825. );
  826. ASSERT(oldReferenceCount >= 0) ;
  827. if ( oldReferenceCount == 0) {
  828. //
  829. // Delete the extension
  830. //
  831. ACPIInitDeleteDeviceExtension( DeviceExtension );
  832. goto ACPIInitResetDeviceExtensionExit;
  833. }
  834. }
  835. //
  836. // If we got to this point, we aren't deleting the device extension
  837. //
  838. DeviceExtension->TargetDeviceObject = NULL;
  839. DeviceExtension->PhysicalDeviceObject = NULL;
  840. //
  841. // Mark the node as being fresh and untouched. Only do this if the device
  842. // isn't marked as NEVER_PRESENT. If its never present, we will just trust
  843. // the device to contain the correct information.
  844. //
  845. if (!(DeviceExtension->Flags & DEV_TYPE_NEVER_PRESENT)) {
  846. ACPIInternalUpdateFlags( &(DeviceExtension->Flags), DEV_MASK_TYPE, TRUE );
  847. ACPIInternalUpdateFlags( &(DeviceExtension->Flags), DEV_TYPE_NOT_FOUND, FALSE );
  848. ACPIInternalUpdateFlags( &(DeviceExtension->Flags), DEV_TYPE_REMOVED, FALSE );
  849. }
  850. ACPIInitResetDeviceExtensionExit:
  851. //
  852. // Done with the spinlock
  853. //
  854. KeReleaseSpinLock( &AcpiDeviceTreeLock, oldIrql );
  855. //
  856. // Now we can do the things we need to do at passive level
  857. //
  858. if (cmResourceList != NULL) {
  859. ExFreePool( cmResourceList );
  860. }
  861. if (targetObject != NULL) {
  862. IoDetachDevice( targetObject );
  863. }
  864. if (deviceObject != NULL) {
  865. IoDeleteDevice( deviceObject );
  866. }
  867. }
  868. NTSTATUS
  869. ACPIInitStartACPI(
  870. IN PDEVICE_OBJECT DeviceObject
  871. )
  872. /*++
  873. Routine Description:
  874. This function is called as soon as we think that the
  875. START_DEVICE Irp for the ACPI driver FDO is going to
  876. complete successfully
  877. Arguments:
  878. DeviceObject - DeviceObject that is being started
  879. Return Value:
  880. NTSTATUS
  881. --*/
  882. {
  883. KEVENT event;
  884. KIRQL oldIrql;
  885. NTSTATUS status;
  886. OBJDATA objData;
  887. PDEVICE_EXTENSION deviceExtension = ACPIInternalGetDeviceExtension(DeviceObject);
  888. PNSOBJ acpiObject = NULL;
  889. PNSOBJ sleepObject = NULL;
  890. PNSOBJ childObject = NULL;
  891. POWER_STATE state;
  892. //
  893. // This will prevent the system from processing power irps
  894. //
  895. KeAcquireSpinLock( &AcpiDeviceTreeLock, &oldIrql );
  896. AcpiSystemInitialized = FALSE;
  897. KeReleaseSpinLock( &AcpiDeviceTreeLock, oldIrql );
  898. //
  899. // Initialize the event
  900. //
  901. KeInitializeEvent( &event, SynchronizationEvent, FALSE );
  902. //
  903. // Setup the synchronization request
  904. //
  905. status = ACPIBuildSynchronizationRequest(
  906. deviceExtension,
  907. ACPIBuildNotifyEvent,
  908. &event,
  909. &AcpiBuildDeviceList,
  910. FALSE
  911. );
  912. //
  913. // What happened?
  914. //
  915. if (!NT_SUCCESS(status)) {
  916. return status;
  917. }
  918. //
  919. // Start the initilization
  920. //
  921. // NOTE: This routine causes many things to happens. Namely, it starts
  922. // the process of loading ACPI tables. This (eventually) causes the
  923. // Driver to start building device extensions. For this function to
  924. // work properly, after we call this function, we need to wait until
  925. // we have finished building device extensions. That means that we
  926. // must wait for the event to be signaled
  927. //
  928. if (ACPIInitialize( (PVOID) DeviceObject ) == FALSE) {
  929. return STATUS_DEVICE_DOES_NOT_EXIST;
  930. }
  931. //
  932. // At this point, we have to wait. The check for STATUS_PENDING is
  933. // just good programming practice sicne BuildSynchronizationRequest can
  934. // only return Failure or STATUS_PENDING
  935. //
  936. if (status == STATUS_PENDING) {
  937. //
  938. // We had better wait for the above to complete
  939. //
  940. KeWaitForSingleObject(
  941. &event,
  942. Executive,
  943. KernelMode,
  944. FALSE,
  945. NULL
  946. );
  947. }
  948. //
  949. // Hand all the machine state stuff to the HAL
  950. //
  951. NotifyHalWithMachineStates();
  952. //
  953. // Register the Power Callback
  954. //
  955. ACPIInternalRegisterPowerCallBack(
  956. deviceExtension,
  957. (PCALLBACK_FUNCTION) ACPIRootPowerCallBack
  958. );
  959. //
  960. // Cause the Power DPC to be fired for the first time
  961. //
  962. KeAcquireSpinLock( &AcpiPowerQueueLock, &oldIrql );
  963. if (!AcpiPowerDpcRunning) {
  964. KeInsertQueueDpc( &AcpiPowerDpc, NULL, NULL );
  965. }
  966. KeReleaseSpinLock( &AcpiPowerQueueLock, oldIrql );
  967. //
  968. // This will allow the system to get power irps again
  969. //
  970. KeAcquireSpinLock( &AcpiDeviceTreeLock, &oldIrql );
  971. AcpiSystemInitialized = TRUE;
  972. KeReleaseSpinLock( &AcpiDeviceTreeLock, oldIrql );
  973. //
  974. // Start the IRQ arbiter so that we can handle children's resources.
  975. //
  976. AcpiInitIrqArbiter(DeviceObject);
  977. //
  978. // Done
  979. //
  980. return STATUS_SUCCESS;
  981. }
  982. NTSTATUS
  983. ACPIInitStartDevice(
  984. IN PDEVICE_OBJECT DeviceObject,
  985. IN PCM_RESOURCE_LIST SuppliedList,
  986. IN PACPI_POWER_CALLBACK CallBack,
  987. IN PVOID CallBackContext,
  988. IN PIRP Irp
  989. )
  990. /*++
  991. Routine Description:
  992. This routine is tasked with starting the device by programming in the
  993. supplied resources
  994. Arguments:
  995. DeviceObject - The object that we care about
  996. SuppliedList - The resources associated with the device
  997. CallBack - The function to call when done
  998. Irp - The argument to pass to the callback
  999. Return Value:
  1000. NTSTATUS
  1001. --*/
  1002. {
  1003. KIRQL oldIrql;
  1004. NTSTATUS status = STATUS_SUCCESS;
  1005. OBJDATA crsData;
  1006. PCM_RESOURCE_LIST resList;
  1007. PDEVICE_EXTENSION deviceExtension = ACPIInternalGetDeviceExtension(DeviceObject);
  1008. PNSOBJ acpiObject = deviceExtension->AcpiObject;
  1009. PNSOBJ crsObject;
  1010. PNSOBJ srsObject;
  1011. POBJDATA srsData;
  1012. ULONG resSize;
  1013. ULONG srsSize;
  1014. ULONG deviceStatus;
  1015. ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
  1016. //
  1017. // Do we have resources? Or a valid list?
  1018. //
  1019. if (SuppliedList == NULL || SuppliedList->Count != 1) {
  1020. //
  1021. // Ignore this resource list
  1022. //
  1023. goto ACPIInitStartDeviceSendD0;
  1024. }
  1025. //
  1026. // Can we program this device? That is there a _CRS and an _SRS child?
  1027. //
  1028. crsObject = ACPIAmliGetNamedChild( acpiObject, PACKED_CRS );
  1029. srsObject = ACPIAmliGetNamedChild( acpiObject, PACKED_SRS );
  1030. if (crsObject == NULL || srsObject == NULL) {
  1031. ACPIDevPrint( (
  1032. ACPI_PRINT_WARNING,
  1033. deviceExtension,
  1034. "ACPIInitStartDevice - No SRS or CRS\n"
  1035. ) );
  1036. goto ACPIInitStartDeviceSendD0;
  1037. }
  1038. //
  1039. // Run the _CRS method
  1040. //
  1041. status = AMLIEvalNameSpaceObject(
  1042. crsObject,
  1043. &crsData,
  1044. 0,
  1045. NULL
  1046. );
  1047. if (!NT_SUCCESS(status)) {
  1048. //
  1049. // Failed
  1050. //
  1051. ACPIDevPrint( (
  1052. ACPI_PRINT_CRITICAL,
  1053. deviceExtension,
  1054. "ACPIInitStartDevice - _CRS failed %08lx\n",
  1055. status
  1056. ) );
  1057. goto ACPIInitStartDeviceError;
  1058. }
  1059. if (crsData.dwDataType != OBJTYPE_BUFFDATA ||
  1060. crsData.dwDataLen == 0 ||
  1061. crsData.pbDataBuff == NULL) {
  1062. //
  1063. // Failed
  1064. //
  1065. ACPIDevPrint( (
  1066. ACPI_PRINT_CRITICAL,
  1067. deviceExtension,
  1068. "ACPIInitStartDevice - _CRS return invalid data\n",
  1069. crsData.dwDataType
  1070. ) );
  1071. AMLIFreeDataBuffs( &crsData, 1 );
  1072. status = STATUS_UNSUCCESSFUL;
  1073. goto ACPIInitStartDeviceError;
  1074. }
  1075. //
  1076. // Dump the list
  1077. //
  1078. #if DBG
  1079. if (NT_SUCCESS(status)) {
  1080. ACPIDebugCmResourceList( SuppliedList, deviceExtension );
  1081. }
  1082. #endif
  1083. //
  1084. // Allocate memory and copy the list...
  1085. //
  1086. resSize = sizeof(CM_RESOURCE_LIST) +
  1087. (SuppliedList->List[0].PartialResourceList.Count - 1) *
  1088. sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
  1089. resList = ExAllocatePoolWithTag(
  1090. PagedPool,
  1091. resSize,
  1092. ACPI_STRING_POOLTAG
  1093. );
  1094. if (resList == NULL) {
  1095. //
  1096. // Not enough resources
  1097. //
  1098. ACPIDevPrint( (
  1099. ACPI_PRINT_CRITICAL,
  1100. deviceExtension,
  1101. "ACPIInitStartDevice - Could not allocate %08lx bytes\n",
  1102. resSize
  1103. ) );
  1104. AMLIFreeDataBuffs( &crsData, 1 );
  1105. status = STATUS_INSUFFICIENT_RESOURCES;
  1106. goto ACPIInitStartDeviceError;
  1107. }
  1108. RtlCopyMemory( resList, SuppliedList, resSize );
  1109. //
  1110. // Now, make a copy of the crs object, but store it in non paged pool
  1111. // because it will be used at DPC level
  1112. //
  1113. srsSize = sizeof(OBJDATA) + crsData.dwDataLen;
  1114. srsData = ExAllocatePoolWithTag(
  1115. NonPagedPool,
  1116. srsSize,
  1117. ACPI_OBJECT_POOLTAG
  1118. );
  1119. if (srsData == NULL) {
  1120. //
  1121. // Not enough resources
  1122. //
  1123. ACPIDevPrint( (
  1124. ACPI_PRINT_CRITICAL,
  1125. deviceExtension,
  1126. "ACPIInitStartDevice - Could not allocate %08lx bytes\n",
  1127. srsSize
  1128. ) );
  1129. AMLIFreeDataBuffs( &crsData, 1 );
  1130. ExFreePool( resList );
  1131. status = STATUS_INSUFFICIENT_RESOURCES;
  1132. goto ACPIInitStartDeviceError;
  1133. }
  1134. RtlCopyMemory( srsData, &crsData, sizeof(OBJDATA) );
  1135. srsData->pbDataBuff = ( (PUCHAR) srsData ) + sizeof(OBJDATA);
  1136. RtlCopyMemory( srsData->pbDataBuff, crsData.pbDataBuff, crsData.dwDataLen );
  1137. //
  1138. // At this point, we no longer care about the _CRS data
  1139. //
  1140. AMLIFreeDataBuffs( &crsData, 1 );
  1141. //
  1142. // Make the new _srs
  1143. //
  1144. status = PnpCmResourcesToBiosResources( resList, srsData->pbDataBuff );
  1145. if (!NT_SUCCESS(status)) {
  1146. ACPIDevPrint( (
  1147. ACPI_PRINT_CRITICAL,
  1148. deviceExtension,
  1149. "ACPIInitStartDevice - PnpCmResourceToBiosResources = %08lx\n",
  1150. status
  1151. ) );
  1152. ExFreePool( resList );
  1153. ExFreePool( srsData );
  1154. goto ACPIInitStartDeviceError;
  1155. }
  1156. //
  1157. // The call to make the _SRS is destructive --- recopy the original list
  1158. //
  1159. RtlCopyMemory( resList, SuppliedList, resSize );
  1160. //
  1161. // We need to hold this lock to set this resource
  1162. //
  1163. KeAcquireSpinLock( &AcpiDeviceTreeLock, &oldIrql );
  1164. if (deviceExtension->PnpResourceList != NULL) {
  1165. ExFreePool( deviceExtension->PnpResourceList );
  1166. }
  1167. deviceExtension->PnpResourceList = srsData;
  1168. KeReleaseSpinLock( &AcpiDeviceTreeLock, oldIrql );
  1169. //
  1170. // We keep this around for debug information
  1171. //
  1172. if (deviceExtension->ResourceList != NULL) {
  1173. //
  1174. // If we already have a resource list, make sure that we free it
  1175. //
  1176. ExFreePool( deviceExtension->ResourceList );
  1177. }
  1178. deviceExtension->ResourceList = resList;
  1179. ACPIInitStartDeviceSendD0:
  1180. //
  1181. // Mark the irp as pending... We need to this because InternalDevice will
  1182. // return STATUS_PENDING if it behaves in the correct manner
  1183. //
  1184. IoMarkIrpPending( Irp );
  1185. //
  1186. // I don't want to block in this driver if I can help it. Since there
  1187. // is already a mechanism for me to execute a D0 and execute a completion
  1188. // routine, I will choose to exercise that option
  1189. //
  1190. status = ACPIDeviceInternalDeviceRequest(
  1191. deviceExtension,
  1192. PowerDeviceD0,
  1193. CallBack,
  1194. CallBackContext,
  1195. DEVICE_REQUEST_LOCK_DEVICE
  1196. );
  1197. if (status == STATUS_MORE_PROCESSING_REQUIRED) {
  1198. //
  1199. // We do this to make sure that we don't also call the completion
  1200. // routine
  1201. //
  1202. status = STATUS_PENDING;
  1203. }
  1204. //
  1205. // Done
  1206. //
  1207. return status;
  1208. //
  1209. // This label is the the point where we should jump to if any device
  1210. // cannot program its resources, but we are going to return success
  1211. //
  1212. ACPIInitStartDeviceError:
  1213. ASSERT(!NT_SUCCESS(status));
  1214. //
  1215. // We have a failure here. As the completion routine was *not* called, we
  1216. // must do that ourselves.
  1217. //
  1218. CallBack(
  1219. deviceExtension,
  1220. CallBackContext,
  1221. status
  1222. );
  1223. //
  1224. // Done
  1225. //
  1226. return status;
  1227. }
  1228. NTSTATUS
  1229. ACPIInitStopACPI(
  1230. IN PDEVICE_OBJECT DeviceObject
  1231. )
  1232. /*++
  1233. Routine Description:
  1234. This routine stops the ACPI FDO
  1235. Arguments:
  1236. DeviceObject - The pointer to the ACPI FDO
  1237. Return Value:
  1238. NTSTATUS
  1239. --*/
  1240. {
  1241. //
  1242. // We will *never* stop ACPI
  1243. //
  1244. return STATUS_SUCCESS;
  1245. }
  1246. NTSTATUS
  1247. ACPIInitStopDevice(
  1248. IN PDEVICE_EXTENSION DeviceExtension,
  1249. IN BOOLEAN UnlockDevice
  1250. )
  1251. /*++
  1252. Routine Description:
  1253. This routine stops a device
  1254. Arguments:
  1255. DeviceExtension - The extension of the device to stop. An extension
  1256. is passed in as the device object may have already
  1257. been deleted by the PDO below our device object.
  1258. UnlockDevice - True if the device should be unlocked after being
  1259. stopped.
  1260. Return Value:
  1261. NTSTATUS
  1262. --*/
  1263. {
  1264. NTSTATUS status = STATUS_SUCCESS;
  1265. PNSOBJ acpiObject = DeviceExtension->AcpiObject;
  1266. PNSOBJ workObject;
  1267. POWER_STATE state;
  1268. ULONG deviceStatus;
  1269. PAGED_CODE();
  1270. //
  1271. // First step is try to turn off the device. We should only do this
  1272. // if the device is in an *known* state
  1273. //
  1274. if (DeviceExtension->PowerInfo.PowerState != PowerDeviceUnspecified) {
  1275. KEVENT event;
  1276. KeInitializeEvent( &event, SynchronizationEvent, FALSE );
  1277. status = ACPIDeviceInternalDeviceRequest(
  1278. DeviceExtension,
  1279. PowerDeviceD3,
  1280. ACPIInitPowerRequestCompletion,
  1281. &event,
  1282. UnlockDevice ? DEVICE_REQUEST_UNLOCK_DEVICE : 0
  1283. );
  1284. if (status == STATUS_PENDING) {
  1285. KeWaitForSingleObject(
  1286. &event,
  1287. Executive,
  1288. KernelMode,
  1289. FALSE,
  1290. NULL
  1291. );
  1292. status = STATUS_SUCCESS;
  1293. }
  1294. }
  1295. //
  1296. // Nothing to stop...
  1297. //
  1298. if (acpiObject == NULL) {
  1299. goto ACPIInitStopDeviceExit;
  1300. }
  1301. //
  1302. // Second step is try to disable the device...
  1303. //
  1304. if ( (workObject = ACPIAmliGetNamedChild( acpiObject, PACKED_DIS ) ) != NULL ) {
  1305. //
  1306. // There is a method to do this
  1307. //
  1308. status = AMLIEvalNameSpaceObject( workObject, NULL, 0, NULL );
  1309. if (!NT_SUCCESS(status) ) {
  1310. goto ACPIInitStopDeviceExit;
  1311. }
  1312. //
  1313. // See if the device is disabled
  1314. //
  1315. status = ACPIGetDevicePresenceSync(
  1316. DeviceExtension,
  1317. &deviceStatus,
  1318. NULL
  1319. );
  1320. if (!NT_SUCCESS(status)) {
  1321. ACPIDevPrint( (
  1322. ACPI_PRINT_CRITICAL,
  1323. DeviceExtension,
  1324. "ACPIInitStopDevice - GetDevicePresenceSync = 0x%08lx\n",
  1325. status
  1326. ) );
  1327. goto ACPIInitStopDeviceExit;
  1328. }
  1329. if (deviceStatus & STA_STATUS_ENABLED) {
  1330. ACPIDevPrint( (
  1331. ACPI_PRINT_CRITICAL,
  1332. DeviceExtension,
  1333. "ACPIInitStopDevice - STA_STATUS_ENABLED - 0x%08lx\n",
  1334. deviceStatus
  1335. ) );
  1336. goto ACPIInitStopDeviceExit;
  1337. }
  1338. }
  1339. ACPIInitStopDeviceExit:
  1340. if (DeviceExtension->ResourceList != NULL) {
  1341. ExFreePool( DeviceExtension->ResourceList );
  1342. DeviceExtension->ResourceList = NULL;
  1343. }
  1344. return STATUS_SUCCESS;
  1345. }
  1346. NTSTATUS
  1347. ACPIInitUnicodeString(
  1348. IN PUNICODE_STRING UnicodeString,
  1349. IN PCHAR Buffer
  1350. )
  1351. /*++
  1352. Routine Description:
  1353. This routine takes an ASCII string and converts it to a Unicode string. The
  1354. Caller is responsible for call RtlFreeUnicodeString() on the returned string
  1355. Arguments:
  1356. UnicodeString - Where to store the new unicode string
  1357. Buffer - What we will convert to unicode
  1358. Return Value:
  1359. NTSTATUS
  1360. --*/
  1361. {
  1362. ANSI_STRING ansiString;
  1363. NTSTATUS status;
  1364. ULONG maxLength;
  1365. PAGED_CODE();
  1366. //
  1367. // Make sure that we won't memory leak
  1368. //
  1369. ASSERT(UnicodeString->Buffer == NULL);
  1370. //
  1371. // We need to do this first before we run the convertion code. Buidling a
  1372. // counted Ansi String is important
  1373. //
  1374. RtlInitAnsiString(&ansiString, Buffer);
  1375. //
  1376. // How long is the ansi string
  1377. //
  1378. maxLength = RtlAnsiStringToUnicodeSize(&(ansiString));
  1379. if (maxLength > MAXUSHORT) {
  1380. return STATUS_INVALID_PARAMETER_2;
  1381. }
  1382. UnicodeString->MaximumLength = (USHORT) maxLength;
  1383. //
  1384. // Allocate a buffer for the string
  1385. //
  1386. UnicodeString->Buffer = ExAllocatePoolWithTag(
  1387. PagedPool,
  1388. maxLength,
  1389. ACPI_STRING_POOLTAG
  1390. );
  1391. if (UnicodeString->Buffer == NULL) {
  1392. return STATUS_INSUFFICIENT_RESOURCES;
  1393. }
  1394. //
  1395. // Convert the counted ANSI string to a counted Unicode string
  1396. //
  1397. status = RtlAnsiStringToUnicodeString(
  1398. UnicodeString,
  1399. &ansiString,
  1400. FALSE
  1401. );
  1402. //
  1403. // Done
  1404. //
  1405. return status;
  1406. }