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.

1023 lines
31 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. Module Name:
  4. report.c
  5. Abstract:
  6. This module contains the subroutines used to report resources used by
  7. the drivers and the HAL into the registry resource map.
  8. Author:
  9. Andre Vachon (andreva) 15-Dec-1992
  10. Environment:
  11. Kernel mode, local to I/O system
  12. Revision History:
  13. --*/
  14. #include "pnpmgrp.h"
  15. #pragma hdrstop
  16. #include <hdlsblk.h>
  17. #include <hdlsterm.h>
  18. #define DBG_AR 0
  19. #define MAX_MEMORY_RUN_LENGTH ((ULONG)~(PAGE_SIZE - 1))
  20. extern const WCHAR IopWstrRaw[];
  21. extern const WCHAR IopWstrTranslated[];
  22. extern const WCHAR IopWstrBusTranslated[];
  23. extern const WCHAR IopWstrOtherDrivers[];
  24. extern const WCHAR IopWstrHal[];
  25. extern const WCHAR IopWstrSystem[];
  26. extern const WCHAR IopWstrPhysicalMemory[];
  27. extern const WCHAR IopWstrSpecialMemory[];
  28. extern const WCHAR IopWstrLoaderReservedMemory[];
  29. BOOLEAN
  30. IopChangeInterfaceType(
  31. IN OUT PIO_RESOURCE_REQUIREMENTS_LIST IoResources,
  32. IN OUT PCM_RESOURCE_LIST *AllocatedResource
  33. );
  34. #ifdef ALLOC_PRAGMA
  35. #pragma alloc_text(PAGE, IoReportResourceUsageInternal)
  36. #pragma alloc_text(PAGE, IoReportResourceUsage)
  37. #pragma alloc_text(PAGE, IoReportResourceForDetection)
  38. #pragma alloc_text(PAGE, IopChangeInterfaceType)
  39. #pragma alloc_text(PAGE, IopWriteResourceList)
  40. #pragma alloc_text(INIT, IopInitializeResourceMap)
  41. #pragma alloc_text(INIT, IoReportHalResourceUsage)
  42. #endif
  43. VOID
  44. IopInitializeResourceMap (
  45. PLOADER_PARAMETER_BLOCK LoaderBlock
  46. )
  47. /*++
  48. Initializes the resource map by adding in the physical memory
  49. which is in use by the system.
  50. --*/
  51. {
  52. ULONG i, j, pass, length;
  53. LARGE_INTEGER li;
  54. HANDLE keyHandle;
  55. UNICODE_STRING unicodeString, systemString, listString;
  56. NTSTATUS status;
  57. PCM_RESOURCE_LIST ResourceList;
  58. PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor;
  59. BOOLEAN IncludeType[LoaderMaximum];
  60. PPHYSICAL_MEMORY_DESCRIPTOR MemoryBlock;
  61. LONGLONG rangeLength;
  62. RtlInitUnicodeString( &systemString, IopWstrSystem);
  63. for (pass=0; pass < 3; pass += 1) {
  64. switch (pass) {
  65. case 0:
  66. //
  67. // Add MmPhysicalMemoryBlock to registry
  68. //
  69. RtlInitUnicodeString( &unicodeString, IopWstrPhysicalMemory);
  70. RtlInitUnicodeString( &listString, IopWstrTranslated );
  71. MemoryBlock = MmPhysicalMemoryBlock;
  72. break;
  73. case 1:
  74. //
  75. // Add LoaderSpecialMemory and LoaderHALCachedMemory
  76. // to registry
  77. //
  78. RtlInitUnicodeString( &unicodeString, IopWstrSpecialMemory);
  79. RtlInitUnicodeString( &listString, IopWstrTranslated );
  80. //
  81. // Compute memory limits of LoaderSpecialMemory and
  82. // LoaderHalCachedMemory
  83. //
  84. for (j=0; j < LoaderMaximum; j += 1) {
  85. IncludeType[j] = FALSE;
  86. }
  87. IncludeType[LoaderSpecialMemory] = TRUE;
  88. IncludeType[LoaderHALCachedMemory] = TRUE;
  89. MemoryBlock = MmInitializeMemoryLimits (LoaderBlock,
  90. IncludeType,
  91. NULL);
  92. if (MemoryBlock == NULL) {
  93. continue;
  94. }
  95. break;
  96. case 2:
  97. default:
  98. //
  99. // Create registry key that includes:
  100. // LoaderBad
  101. // LoaderFirmwarePermanent
  102. // LoaderSpecialMemory
  103. // LoaderBBTMemory
  104. // LoaderHALCachedMemory
  105. //
  106. RtlInitUnicodeString( &unicodeString, IopWstrLoaderReservedMemory);
  107. RtlInitUnicodeString( &listString, IopWstrRaw );
  108. //
  109. // Compute memory limits of specified loader memory
  110. // descriptors.
  111. //
  112. for (j=0; j < LoaderMaximum; j += 1) {
  113. IncludeType[j] = FALSE;
  114. }
  115. IncludeType[LoaderBad] = TRUE;
  116. IncludeType[LoaderFirmwarePermanent] = TRUE;
  117. IncludeType[LoaderSpecialMemory] = TRUE;
  118. IncludeType[LoaderBBTMemory] = TRUE;
  119. IncludeType[LoaderHALCachedMemory] = TRUE;
  120. MemoryBlock = MmInitializeMemoryLimits (LoaderBlock,
  121. IncludeType,
  122. NULL);
  123. if (MemoryBlock == NULL) {
  124. return;
  125. }
  126. break;
  127. }
  128. //
  129. // Allocate and build a CM_RESOURCE_LIST to describe all
  130. // of physical memory
  131. //
  132. j = MemoryBlock->NumberOfRuns;
  133. if (j == 0) {
  134. if (pass != 0) {
  135. ExFreePool (MemoryBlock);
  136. }
  137. continue;
  138. }
  139. //
  140. // This is to take care of systems where individual memory run can
  141. // exceed 4G since our current descriptors only have 32-bit length.
  142. // Account for runs with length > MAX_MEMORY_RUN_LENGTH by splitting
  143. // them into lengths <= MAX_MEMORY_RUN_LENGTH.
  144. //
  145. for (i = 0; i < MemoryBlock->NumberOfRuns; i += 1) {
  146. rangeLength = ((LONGLONG)MemoryBlock->Run[i].PageCount) << PAGE_SHIFT;
  147. while ((rangeLength -= MAX_MEMORY_RUN_LENGTH) > 0) {
  148. j += 1;
  149. }
  150. }
  151. length = sizeof(CM_RESOURCE_LIST) + (j-1) * sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR);
  152. ResourceList = (PCM_RESOURCE_LIST) ExAllocatePool (PagedPool, length);
  153. if (!ResourceList) {
  154. if (pass != 0) {
  155. ExFreePool (MemoryBlock);
  156. }
  157. return;
  158. }
  159. RtlZeroMemory ((PVOID) ResourceList, length);
  160. ResourceList->Count = 1;
  161. ResourceList->List[0].PartialResourceList.Count = j;
  162. CmDescriptor = ResourceList->List[0].PartialResourceList.PartialDescriptors;
  163. for (i=0; i < MemoryBlock->NumberOfRuns; i += 1) {
  164. rangeLength = ((LONGLONG)MemoryBlock->Run[i].PageCount) << PAGE_SHIFT;
  165. li.QuadPart = ((LONGLONG)MemoryBlock->Run[i].BasePage) << PAGE_SHIFT;
  166. //
  167. // Split up runs > MAX_MEMORY_RUN_LENGTH into multiple descriptors
  168. // with lengths <= MAX_MEMORY_RUN_LENGTH. All descriptors (except
  169. // the last one) have length = MAX_MEMORY_RUN_LENGTH. Length of the
  170. // last one is the remaining portion.
  171. //
  172. do {
  173. CmDescriptor->Type = CmResourceTypeMemory;
  174. CmDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
  175. CmDescriptor->u.Memory.Start = li;
  176. CmDescriptor->u.Memory.Length = MAX_MEMORY_RUN_LENGTH;
  177. CmDescriptor++;
  178. li.QuadPart += MAX_MEMORY_RUN_LENGTH;
  179. } while ((rangeLength -= MAX_MEMORY_RUN_LENGTH) > 0);
  180. //
  181. // Adjust the length of the last one.
  182. //
  183. (CmDescriptor - 1)->u.Memory.Length = (ULONG)(rangeLength + MAX_MEMORY_RUN_LENGTH);
  184. }
  185. //
  186. // Add the resource list to the resourcemap
  187. //
  188. status = IopCreateRegistryKeyEx( &keyHandle,
  189. (HANDLE) NULL,
  190. &CmRegistryMachineHardwareResourceMapName,
  191. KEY_READ | KEY_WRITE,
  192. REG_OPTION_VOLATILE,
  193. NULL );
  194. if (NT_SUCCESS( status )) {
  195. IopWriteResourceList ( keyHandle,
  196. &systemString,
  197. &unicodeString,
  198. &listString,
  199. ResourceList,
  200. length
  201. );
  202. ZwClose( keyHandle );
  203. }
  204. ExFreePool (ResourceList);
  205. if (pass != 0) {
  206. ExFreePool (MemoryBlock);
  207. }
  208. }
  209. }
  210. NTSTATUS
  211. IoReportHalResourceUsage(
  212. IN PUNICODE_STRING HalName,
  213. IN PCM_RESOURCE_LIST RawResourceList,
  214. IN PCM_RESOURCE_LIST TranslatedResourceList,
  215. IN ULONG ResourceListSize
  216. )
  217. /*++
  218. Routine Description:
  219. This routine is called by the HAL to report its resources.
  220. The HAL is the first component to report its resources, so we don't need
  221. to acquire the resourcemap semaphore and we do not need to check for
  222. conflicts.
  223. Arguments:
  224. HalName - Name of the HAL reporting the resources.
  225. RawResourceList - Pointer to the HAL's raw resource list.
  226. TranslatedResourceList - Pointer to the HAL's translated resource list.
  227. DriverListSize - Value determining the size of the HAL's resource list.
  228. Return Value:
  229. The status returned is the final completion status of the operation.
  230. --*/
  231. {
  232. HANDLE keyHandle;
  233. UNICODE_STRING halString;
  234. UNICODE_STRING listString;
  235. NTSTATUS status;
  236. PCM_RESOURCE_LIST NewList = NULL;
  237. ULONG NewListSize;
  238. PCM_RESOURCE_LIST NewTranslatedList;
  239. ULONG NewTranslatedListSize;
  240. PAGED_CODE();
  241. //
  242. // First open a handle to the RESOURCEMAP key.
  243. //
  244. RtlInitUnicodeString( &halString, IopWstrHal );
  245. status = IopCreateRegistryKeyEx( &keyHandle,
  246. (HANDLE) NULL,
  247. &CmRegistryMachineHardwareResourceMapName,
  248. KEY_READ | KEY_WRITE,
  249. REG_OPTION_VOLATILE,
  250. NULL );
  251. //
  252. // Write out the raw resource list
  253. //
  254. if (NT_SUCCESS( status )) {
  255. RtlInitUnicodeString( &listString, IopWstrRaw);
  256. //
  257. // Add any resources that Headless is reserving.
  258. //
  259. status = HeadlessTerminalAddResources(RawResourceList,
  260. ResourceListSize,
  261. FALSE,
  262. &NewList,
  263. &NewListSize
  264. );
  265. if (NT_SUCCESS(status)) {
  266. status = IopWriteResourceList( keyHandle,
  267. &halString,
  268. HalName,
  269. &listString,
  270. (NewList != NULL) ? NewList : RawResourceList,
  271. (NewList != NULL) ? NewListSize : ResourceListSize
  272. );
  273. }
  274. //
  275. // If we successfully wrote out the raw resource list, write out
  276. // the translated resource list.
  277. //
  278. if (NT_SUCCESS( status )) {
  279. RtlInitUnicodeString( &listString, IopWstrTranslated);
  280. //
  281. // Add any resources that Headless is reserving.
  282. //
  283. status = HeadlessTerminalAddResources(TranslatedResourceList,
  284. ResourceListSize,
  285. TRUE,
  286. &NewTranslatedList,
  287. &NewTranslatedListSize
  288. );
  289. if (NT_SUCCESS(status)) {
  290. status = IopWriteResourceList(keyHandle,
  291. &halString,
  292. HalName,
  293. &listString,
  294. (NewTranslatedList != NULL) ?
  295. NewTranslatedList : TranslatedResourceList,
  296. (NewTranslatedList != NULL) ?
  297. NewTranslatedListSize : ResourceListSize
  298. );
  299. if (NewTranslatedList != NULL) {
  300. ExFreePool(NewTranslatedList);
  301. }
  302. }
  303. }
  304. ZwClose( keyHandle );
  305. }
  306. //
  307. // If every resource looks fine, we will store the copy of the HAL
  308. // resources so we can call Arbiters to reserve the resources after
  309. // they are initialized.
  310. //
  311. if (NT_SUCCESS(status)) {
  312. if (NewList != NULL) {
  313. //
  314. // An easy way is if headless created a new list for us, just don't free it.
  315. //
  316. IopInitHalResources = NewList;
  317. } else {
  318. //
  319. // Otherwise we have to create a copy ourselves.
  320. //
  321. IopInitHalResources = (PCM_RESOURCE_LIST) ExAllocatePool(PagedPool,
  322. ResourceListSize
  323. );
  324. if (IopInitHalResources != NULL) {
  325. RtlCopyMemory(IopInitHalResources, RawResourceList, ResourceListSize);
  326. } else {
  327. status = STATUS_INSUFFICIENT_RESOURCES;
  328. }
  329. }
  330. } else if (NewList != NULL) {
  331. //
  332. // Free any failed list
  333. //
  334. ExFreePool(NewList);
  335. }
  336. return status;
  337. }
  338. NTSTATUS
  339. IoReportResourceForDetection(
  340. IN PDRIVER_OBJECT DriverObject,
  341. IN PCM_RESOURCE_LIST DriverList OPTIONAL,
  342. IN ULONG DriverListSize OPTIONAL,
  343. IN PDEVICE_OBJECT DeviceObject OPTIONAL,
  344. IN PCM_RESOURCE_LIST DeviceList OPTIONAL,
  345. IN ULONG DeviceListSize OPTIONAL,
  346. OUT PBOOLEAN ConflictDetected
  347. )
  348. /*++
  349. Routine Description:
  350. This routine will automatically search through the configuration
  351. registry for resource conflicts between resources requested by a device
  352. and the resources already claimed by previously installed drivers. The
  353. contents of the DriverList and the DeviceList will be matched against
  354. all the other resource list stored in the registry to determine
  355. conflicts.
  356. The function may be called more than once for a given device or driver.
  357. If a new resource list is given, the previous resource list stored in
  358. the registry will be replaced by the new list.
  359. Note, this function is for the drivers acquiring resources for detection.
  360. Arguments:
  361. DriverObject - Pointer to the driver's driver object.
  362. DriverList - Optional pointer to the driver's resource list.
  363. DriverListSize - Optional value determining the size of the driver's
  364. resource list.
  365. DeviceObject - Optional pointer to driver's device object.
  366. DeviceList - Optional pointer to the device's resource list.
  367. DriverListSize - Optional value determining the size of the device's
  368. resource list.
  369. ConflictDetected - Supplies a pointer to a boolean that is set to TRUE
  370. if the resource list conflicts with an already existing resource
  371. list in the configuration registry.
  372. Return Value:
  373. The status returned is the final completion status of the operation.
  374. --*/
  375. {
  376. PAGED_CODE();
  377. //
  378. // Sanity check that the caller did not pass in a PnP PDO.
  379. //
  380. if (DeviceObject) {
  381. if ( DeviceObject->DeviceObjectExtension->DeviceNode &&
  382. !(((PDEVICE_NODE)DeviceObject->DeviceObjectExtension->DeviceNode)->Flags & DNF_LEGACY_RESOURCE_DEVICENODE)) {
  383. PP_SAVE_DRIVEROBJECT_TO_TRIAGE_DUMP(DriverObject);
  384. PP_SAVE_DEVICEOBJECT_TO_TRIAGE_DUMP(DeviceObject);
  385. KeBugCheckEx(PNP_DETECTED_FATAL_ERROR, PNP_ERR_INVALID_PDO, (ULONG_PTR)DeviceObject, (ULONG_PTR)DriverObject, 0);
  386. }
  387. }
  388. return IoReportResourceUsageInternal( ArbiterRequestPnpDetected,
  389. NULL,
  390. DriverObject,
  391. DriverList,
  392. DriverListSize,
  393. DeviceObject,
  394. DeviceList,
  395. DeviceListSize,
  396. FALSE,
  397. ConflictDetected);
  398. }
  399. NTSTATUS
  400. IoReportResourceUsage(
  401. IN PUNICODE_STRING DriverClassName OPTIONAL,
  402. IN PDRIVER_OBJECT DriverObject,
  403. IN PCM_RESOURCE_LIST DriverList OPTIONAL,
  404. IN ULONG DriverListSize OPTIONAL,
  405. IN PDEVICE_OBJECT DeviceObject OPTIONAL,
  406. IN PCM_RESOURCE_LIST DeviceList OPTIONAL,
  407. IN ULONG DeviceListSize OPTIONAL,
  408. IN BOOLEAN OverrideConflict,
  409. OUT PBOOLEAN ConflictDetected
  410. )
  411. /*++
  412. Routine Description:
  413. This routine will automatically search through the configuration
  414. registry for resource conflicts between resources requested by a device
  415. and the resources already claimed by previously installed drivers. The
  416. contents of the DriverList and the DeviceList will be matched against
  417. all the other resource list stored in the registry to determine
  418. conflicts.
  419. If not conflict was detected, or if the OverrideConflict flag is set,
  420. this routine will create appropriate entries in the system resource map
  421. (in the registry) that will contain the specified resource lists.
  422. The function may be called more than once for a given device or driver.
  423. If a new resource list is given, the previous resource list stored in
  424. the registry will be replaced by the new list.
  425. Arguments:
  426. DriverClassName - Optional pointer to a UNICODE_STRING which describes
  427. the class of driver under which the driver information should be
  428. stored. A default type is used if none is given.
  429. DriverObject - Pointer to the driver's driver object.
  430. DriverList - Optional pointer to the driver's resource list.
  431. DriverListSize - Optional value determining the size of the driver's
  432. resource list.
  433. DeviceObject - Optional pointer to driver's device object.
  434. DeviceList - Optional pointer to the device's resource list.
  435. DriverListSize - Optional value determining the size of the driver's
  436. resource list.
  437. OverrideConflict - Determines if the information should be reported
  438. in the configuration registry eventhough a conflict was found with
  439. another driver or device.
  440. ConflictDetected - Supplies a pointer to a boolean that is set to TRUE
  441. if the resource list conflicts with an already existing resource
  442. list in the configuration registry.
  443. Return Value:
  444. The status returned is the final completion status of the operation.
  445. --*/
  446. {
  447. PAGED_CODE();
  448. if (DeviceObject) {
  449. if ( DeviceObject->DeviceObjectExtension->DeviceNode &&
  450. !(((PDEVICE_NODE)DeviceObject->DeviceObjectExtension->DeviceNode)->Flags & DNF_LEGACY_RESOURCE_DEVICENODE)) {
  451. PP_SAVE_DRIVEROBJECT_TO_TRIAGE_DUMP(DriverObject);
  452. PP_SAVE_DEVICEOBJECT_TO_TRIAGE_DUMP(DeviceObject);
  453. KeBugCheckEx(PNP_DETECTED_FATAL_ERROR, PNP_ERR_INVALID_PDO, (ULONG_PTR)DeviceObject, (ULONG_PTR)DriverObject, 0);
  454. }
  455. }
  456. return IoReportResourceUsageInternal( ArbiterRequestLegacyReported,
  457. DriverClassName,
  458. DriverObject,
  459. DriverList,
  460. DriverListSize,
  461. DeviceObject,
  462. DeviceList,
  463. DeviceListSize,
  464. OverrideConflict,
  465. ConflictDetected);
  466. }
  467. NTSTATUS
  468. IoReportResourceUsageInternal(
  469. IN ARBITER_REQUEST_SOURCE AllocationType,
  470. IN PUNICODE_STRING DriverClassName OPTIONAL,
  471. IN PDRIVER_OBJECT DriverObject,
  472. IN PCM_RESOURCE_LIST DriverList OPTIONAL,
  473. IN ULONG DriverListSize OPTIONAL,
  474. IN PDEVICE_OBJECT DeviceObject OPTIONAL,
  475. IN PCM_RESOURCE_LIST DeviceList OPTIONAL,
  476. IN ULONG DeviceListSize OPTIONAL,
  477. IN BOOLEAN OverrideConflict,
  478. OUT PBOOLEAN ConflictDetected
  479. )
  480. /*++
  481. Routine Description:
  482. This internal routine will do all the work for IoReportResourceUsage.
  483. Arguments:
  484. AllocationType - Specifies the request type.
  485. DriverClassName - Optional pointer to a UNICODE_STRING which describes
  486. the class of driver under which the driver information should be
  487. stored. A default type is used if none is given.
  488. DriverObject - Pointer to the driver's driver object.
  489. DriverList - Optional pointer to the driver's resource list.
  490. DriverListSize - Optional value determining the size of the driver's
  491. resource list.
  492. DeviceObject - Optional pointer to driver's device object.
  493. DeviceList - Optional pointer to the device's resource list.
  494. DriverListSize - Optional value determining the size of the driver's
  495. resource list.
  496. OverrideConflict - Determines if the information should be reported
  497. in the configuration registry eventhough a conflict was found with
  498. another driver or device.
  499. ConflictDetected - Supplies a pointer to a boolean that is set to TRUE
  500. if the resource list conflicts with an already existing resource
  501. list in the configuration registry.
  502. Return Value:
  503. The status returned is the final completion status of the operation.
  504. --*/
  505. {
  506. NTSTATUS status = STATUS_UNSUCCESSFUL;
  507. PCM_RESOURCE_LIST resourceList;
  508. PCM_RESOURCE_LIST allocatedResources;
  509. PIO_RESOURCE_REQUIREMENTS_LIST resourceRequirements;
  510. ULONG attempt;
  511. BOOLEAN freeAllocatedResources;
  512. PAGED_CODE();
  513. UNREFERENCED_PARAMETER( DriverClassName );
  514. UNREFERENCED_PARAMETER( DriverListSize );
  515. UNREFERENCED_PARAMETER( DeviceListSize );
  516. UNREFERENCED_PARAMETER( OverrideConflict );
  517. ASSERT(DriverObject && ConflictDetected);
  518. if (DeviceList) {
  519. resourceList = DeviceList;
  520. } else if (DriverList) {
  521. resourceList = DriverList;
  522. } else {
  523. resourceList = NULL;
  524. }
  525. resourceRequirements = NULL;
  526. if (resourceList) {
  527. if (resourceList->Count && resourceList->List[0].PartialResourceList.Count) {
  528. resourceRequirements = IopCmResourcesToIoResources (0, resourceList, LCPRI_NORMAL);
  529. if (resourceRequirements == NULL) {
  530. return status;
  531. }
  532. } else {
  533. resourceList = NULL;
  534. }
  535. }
  536. *ConflictDetected = TRUE;
  537. attempt = 0;
  538. allocatedResources = resourceList;
  539. freeAllocatedResources = FALSE;
  540. do {
  541. //
  542. // Do the legacy resource allocation.
  543. //
  544. status = IopLegacyResourceAllocation ( AllocationType,
  545. DriverObject,
  546. DeviceObject,
  547. resourceRequirements,
  548. &allocatedResources);
  549. if (NT_SUCCESS(status)) {
  550. *ConflictDetected = FALSE;
  551. break;
  552. }
  553. //
  554. // Change the interface type and try again.
  555. //
  556. if (!IopChangeInterfaceType(resourceRequirements, &allocatedResources)) {
  557. break;
  558. }
  559. freeAllocatedResources = TRUE;
  560. } while (++attempt < 2);
  561. if (resourceRequirements) {
  562. ExFreePool(resourceRequirements);
  563. }
  564. if (freeAllocatedResources) {
  565. ExFreePool(allocatedResources);
  566. }
  567. if (NT_SUCCESS(status)) {
  568. status = STATUS_SUCCESS;
  569. } else if (status != STATUS_INSUFFICIENT_RESOURCES) {
  570. status = STATUS_CONFLICTING_ADDRESSES;
  571. }
  572. return status;
  573. }
  574. BOOLEAN
  575. IopChangeInterfaceType(
  576. IN OUT PIO_RESOURCE_REQUIREMENTS_LIST IoResources,
  577. IN OUT PCM_RESOURCE_LIST *AllocatedResources
  578. )
  579. /*++
  580. Routine Description:
  581. This routine takes an Io resourcelist and changes its interfacetype
  582. from internal to default type (isa or eisa or mca).
  583. Arguments:
  584. IoResources - Pointer to requirement list.
  585. AllocatedResources - Pointer to a variable that receives the pointer to the resource list.
  586. Return Value:
  587. BOOLEAN value to indicate if the change was made or not.
  588. --*/
  589. {
  590. PIO_RESOURCE_LIST IoResourceList;
  591. PIO_RESOURCE_DESCRIPTOR IoResourceDescriptor;
  592. PIO_RESOURCE_DESCRIPTOR IoResourceDescriptorEnd;
  593. LONG IoResourceListCount;
  594. BOOLEAN changed;
  595. PAGED_CODE();
  596. ASSERT(AllocatedResources);
  597. changed = FALSE;
  598. if (!IoResources) {
  599. return changed;
  600. }
  601. if (IoResources->InterfaceType == Internal) {
  602. IoResources->InterfaceType = PnpDefaultInterfaceType;
  603. changed = TRUE;
  604. }
  605. IoResourceList = IoResources->List;
  606. IoResourceListCount = IoResources->AlternativeLists;
  607. while (--IoResourceListCount >= 0) {
  608. IoResourceDescriptor = IoResourceList->Descriptors;
  609. IoResourceDescriptorEnd = IoResourceDescriptor + IoResourceList->Count;
  610. for (;IoResourceDescriptor < IoResourceDescriptorEnd; IoResourceDescriptor++) {
  611. if (IoResourceDescriptor->Type == CmResourceTypeReserved &&
  612. IoResourceDescriptor->u.DevicePrivate.Data[0] == Internal) {
  613. IoResourceDescriptor->u.DevicePrivate.Data[0] = PnpDefaultInterfaceType;
  614. changed = TRUE;
  615. }
  616. }
  617. IoResourceList = (PIO_RESOURCE_LIST) IoResourceDescriptorEnd;
  618. }
  619. if (changed) {
  620. PCM_RESOURCE_LIST oldResources = *AllocatedResources;
  621. PCM_RESOURCE_LIST newResources;
  622. PCM_FULL_RESOURCE_DESCRIPTOR cmFullDesc;
  623. PCM_PARTIAL_RESOURCE_DESCRIPTOR cmPartDesc;
  624. ULONG size;
  625. if (oldResources) {
  626. size = IopDetermineResourceListSize(oldResources);
  627. newResources = ExAllocatePool(PagedPool, size);
  628. if (newResources == NULL) {
  629. changed = FALSE;
  630. } else {
  631. ULONG i;
  632. ULONG j;
  633. RtlCopyMemory(newResources, oldResources, size);
  634. //
  635. // Fix up the interface type
  636. //
  637. cmFullDesc = &newResources->List[0];
  638. for (i = 0; i < oldResources->Count; i++) {
  639. if (cmFullDesc->InterfaceType == Internal) {
  640. cmFullDesc->InterfaceType = PnpDefaultInterfaceType;
  641. }
  642. cmPartDesc = &cmFullDesc->PartialResourceList.PartialDescriptors[0];
  643. for (j = 0; j < cmFullDesc->PartialResourceList.Count; j++) {
  644. size = 0;
  645. switch (cmPartDesc->Type) {
  646. case CmResourceTypeDeviceSpecific:
  647. size = cmPartDesc->u.DeviceSpecificData.DataSize;
  648. break;
  649. }
  650. cmPartDesc++;
  651. cmPartDesc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) ((PUCHAR)cmPartDesc + size);
  652. }
  653. cmFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR)cmPartDesc;
  654. }
  655. *AllocatedResources = newResources;
  656. }
  657. }
  658. }
  659. return changed;
  660. }
  661. NTSTATUS
  662. IopWriteResourceList(
  663. HANDLE ResourceMapKey,
  664. PUNICODE_STRING ClassName,
  665. PUNICODE_STRING DriverName,
  666. PUNICODE_STRING DeviceName,
  667. PCM_RESOURCE_LIST ResourceList,
  668. ULONG ResourceListSize
  669. )
  670. /*++
  671. Routine Description:
  672. This routine takes a resourcelist and stores it in the registry resource
  673. map, using the ClassName, DriverName and DeviceName as the path of the
  674. key to store it in.
  675. Arguments:
  676. ResourceMapKey - Handle to the root of the resource map.
  677. ClassName - Pointer to a Unicode String that contains the name of the Class
  678. for this resource list.
  679. DriverName - Pointer to a Unicode String that contains the name of the
  680. Driver for this resource list.
  681. DeviceName - Pointer to a Unicode String that contains the name of the
  682. Device for this resource list.
  683. ResourceList - P to the resource list.
  684. ResourceListSize - Value determining the size of the resource list.
  685. Return Value:
  686. The status returned is the final completion status of the operation.
  687. --*/
  688. {
  689. NTSTATUS status;
  690. HANDLE classKeyHandle;
  691. HANDLE driverKeyHandle;
  692. PAGED_CODE();
  693. status = IopCreateRegistryKeyEx( &classKeyHandle,
  694. ResourceMapKey,
  695. ClassName,
  696. KEY_READ | KEY_WRITE,
  697. REG_OPTION_VOLATILE,
  698. NULL );
  699. if (NT_SUCCESS( status )) {
  700. //
  701. // Take the resulting name to create the key.
  702. //
  703. status = IopCreateRegistryKeyEx( &driverKeyHandle,
  704. classKeyHandle,
  705. DriverName,
  706. KEY_READ | KEY_WRITE,
  707. REG_OPTION_VOLATILE,
  708. NULL );
  709. ZwClose( classKeyHandle );
  710. if (NT_SUCCESS( status )) {
  711. //
  712. // With this key handle, we can now store the required information
  713. // in the value entries of the key.
  714. //
  715. //
  716. // Store the device name as a value name and the device information
  717. // as the rest of the data.
  718. // Only store the information if the CM_RESOURCE_LIST was present.
  719. //
  720. if (ResourceList->Count == 0) {
  721. status = ZwDeleteValueKey( driverKeyHandle,
  722. DeviceName );
  723. } else {
  724. status = ZwSetValueKey( driverKeyHandle,
  725. DeviceName,
  726. 0L,
  727. REG_RESOURCE_LIST,
  728. ResourceList,
  729. ResourceListSize );
  730. }
  731. ZwClose( driverKeyHandle );
  732. }
  733. }
  734. return status;
  735. }