Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1148 lines
26 KiB

  1. #include <windows.h>
  2. #include <windowsx.h>
  3. #include <stdio.h>
  4. #include <tchar.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <regstr.h>
  8. #include <cfgmgr32.h>
  9. #include "pnpstuff.h"
  10. //
  11. // Globals
  12. //
  13. DEV_INFO *g_pdiDevList; // Head of device list
  14. /*++
  15. Routine Description: (21) GetDevNodeInfoAndCreateNewDevInfoNode
  16. Creates new list node, then gets registry and resource information for
  17. a specific device and copies it into that node. Finally, adds new node
  18. to beginning of linked list
  19. Arguments:
  20. dnDevNode: the device to find information about
  21. szDevNodeID: the registry path name of the device
  22. szEnumBuffer: name of enumerator this device is under
  23. Return Value:
  24. BOOL: TRUE if function succeeds, FALSE if not
  25. --*/
  26. BOOL GetDevNodeInfoAndCreateNewDevInfoNode(IN DEVNODE dnDevNode,
  27. IN PTCHAR szDevNodeID,
  28. IN PTCHAR szEnumBuffer)
  29. {
  30. LOG_CONF lcLogConf = 0, lcLogConfNew;
  31. CONFIGRET cmret, cmret2;
  32. BOOL boolForced;
  33. PDEV_INFO pdiDevInfo=(PDEV_INFO)malloc(sizeof(DEV_INFO));
  34. int i;
  35. BOOL boolForcedFound = FALSE, boolAllocFound = FALSE;
  36. USHORT ushLogConfType[4] = {BOOT_LOG_CONF,
  37. ALLOC_LOG_CONF,
  38. BASIC_LOG_CONF,
  39. FORCED_LOG_CONF};
  40. if (pdiDevInfo == NULL)
  41. {
  42. goto RetFALSE;
  43. }
  44. //
  45. // If this is not a PnP device, skip it
  46. //
  47. if (!lstrcmpi(szEnumBuffer, TEXT("Root")))
  48. {
  49. free(pdiDevInfo);
  50. goto RetTRUE;
  51. }
  52. //
  53. // Initialize fields inside the node
  54. //
  55. if (!InitializeInfoNode(pdiDevInfo, szDevNodeID, dnDevNode))
  56. {
  57. //
  58. // This is a device we don't want to list. Skip it
  59. //
  60. free(pdiDevInfo);
  61. goto RetTRUE;
  62. }
  63. for (i = 0; i < NUM_LOG_CONF_TYPES; i++)
  64. {
  65. //
  66. // Get logical configuration information
  67. //
  68. cmret = CM_Get_First_Log_Conf(&lcLogConfNew,
  69. dnDevNode,
  70. ushLogConfType[i]);
  71. while (CR_SUCCESS == cmret)
  72. {
  73. lcLogConf = lcLogConfNew;
  74. if (ALLOC_LOG_CONF == ushLogConfType[i])
  75. {
  76. boolAllocFound = TRUE;
  77. }
  78. if (!(GetResDesList(pdiDevInfo, lcLogConf, ushLogConfType[i])))
  79. {
  80. goto RetFALSE;
  81. }
  82. cmret = CM_Get_Next_Log_Conf(&lcLogConfNew,
  83. lcLogConf,
  84. 0);
  85. cmret2 = CM_Free_Log_Conf_Handle(lcLogConf);
  86. }
  87. }
  88. //
  89. // If device has no Alloc configurations, skip
  90. // to the next device
  91. //
  92. if (!boolAllocFound)
  93. {
  94. //free(pdiDevInfo);
  95. //goto RetTRUE;
  96. }
  97. //
  98. // Insert new pdiDevInfo into Linked List of DevNodes
  99. //
  100. if (g_pdiDevList == NULL)
  101. {
  102. //
  103. // DevList is empty
  104. //
  105. g_pdiDevList = pdiDevInfo;
  106. }
  107. else
  108. {
  109. //
  110. // Add new pdiDevInfo to beginning of linked list
  111. //
  112. pdiDevInfo->Next = g_pdiDevList;
  113. g_pdiDevList->Prev = pdiDevInfo;
  114. g_pdiDevList = pdiDevInfo;
  115. }
  116. RetTRUE:
  117. return TRUE;
  118. RetFALSE:
  119. return FALSE;
  120. } /* GetDevNodeInfoAndCreateNewDevInfoNode */
  121. /*++
  122. Routine Description: (20) ParseEnumerator
  123. Gets devices listed under enumerator name in registry
  124. Arguments:
  125. szEnumBuffer: the enumerator name
  126. Return Value:
  127. BOOL: TRUE if function succeeds, FALSE if not
  128. --*/
  129. BOOL ParseEnumerator(IN PTCHAR szEnumBuffer)
  130. {
  131. PTCHAR szDevIDBuffer = NULL;
  132. PTCHAR szDevNodeID = NULL;
  133. ULONG ulDevIDBufferLen = 0, ulCount = 0, ulStart = 0;
  134. CONFIGRET cmret = CR_SUCCESS;
  135. DEVNODE dnDevNode;
  136. //
  137. // Get buffer length
  138. //
  139. cmret = CM_Get_Device_ID_List_Size(&ulDevIDBufferLen,
  140. szEnumBuffer,
  141. CM_GETIDLIST_FILTER_ENUMERATOR);
  142. if (CR_SUCCESS != cmret)
  143. {
  144. //ErrorLog(20, TEXT("CM_Get_Device_ID_List_Size"), cmret, NULL);
  145. goto RetFALSE;
  146. }
  147. if ((szDevIDBuffer = malloc(sizeof(TCHAR) * ulDevIDBufferLen)) == NULL ||
  148. (szDevNodeID = malloc(sizeof(TCHAR) * ulDevIDBufferLen)) == NULL)
  149. {
  150. goto RetFALSE;
  151. }
  152. //
  153. // Get the Device ID List
  154. //
  155. cmret = CM_Get_Device_ID_List(szEnumBuffer,
  156. szDevIDBuffer,
  157. ulDevIDBufferLen,
  158. CM_GETIDLIST_FILTER_ENUMERATOR);
  159. if (CR_SUCCESS != cmret)
  160. {
  161. //ErrorLog(20, TEXT("CM_Get_Device_ID_List"), cmret, NULL);
  162. goto RetFALSE;
  163. }
  164. //
  165. // Note that ulDevIDBufferLen is a loose upper bound. The API may have
  166. // returned a size greater than the actual size of the list of strings.
  167. //
  168. for (ulCount = 0; ulCount < ulDevIDBufferLen; ulCount++)
  169. {
  170. ulStart = ulCount;
  171. if (szDevIDBuffer[ulCount] != '\0')
  172. {
  173. cmret = CM_Locate_DevNode(&dnDevNode,
  174. szDevIDBuffer + ulCount,
  175. CM_LOCATE_DEVNODE_NORMAL);
  176. //
  177. // Go to the next substring
  178. //
  179. while (szDevIDBuffer[ulCount] != TEXT('\0'))
  180. {
  181. ulCount++;
  182. }
  183. // Stop when we reach the double-NULL terminator
  184. if (szDevIDBuffer[ulCount+1] == TEXT('\0'))
  185. {
  186. ulCount=ulDevIDBufferLen;
  187. continue;
  188. }
  189. if (cmret == CR_SUCCESS)
  190. {
  191. wsprintf(szDevNodeID, TEXT("%s"), szDevIDBuffer + ulStart);
  192. //
  193. // Found the DevNode, so add its information to the device list
  194. //
  195. if (!(GetDevNodeInfoAndCreateNewDevInfoNode(dnDevNode,
  196. szDevNodeID,
  197. szEnumBuffer)))
  198. {
  199. goto RetFALSE;
  200. }
  201. }
  202. }
  203. }
  204. return TRUE;
  205. RetFALSE:
  206. return FALSE;
  207. } /* Parse Enumerator */
  208. void CollectDevData()
  209. {
  210. CONFIGRET cmret = CR_SUCCESS;
  211. ULONG ulIndexNum = 0;
  212. ULONG ulEnumBufferLen = 0;
  213. PTCHAR szEnumBuffer;
  214. szEnumBuffer = malloc(sizeof(TCHAR) * MAX_DEVNODE_ID_LEN);
  215. for (ulIndexNum = 0; cmret == CR_SUCCESS; ulIndexNum++)
  216. {
  217. ulEnumBufferLen = MAX_DEVNODE_ID_LEN;
  218. cmret = CM_Enumerate_Enumerators(ulIndexNum,
  219. szEnumBuffer,
  220. &ulEnumBufferLen,
  221. 0);
  222. if (cmret == CR_SUCCESS)
  223. {
  224. ParseEnumerator(szEnumBuffer);
  225. }
  226. }
  227. } /* CollectDevData */
  228. /*++
  229. Routine Description: (22) CopyRegistryLine
  230. Copies one specific string of registry data to new list node
  231. Arguments:
  232. dnDevNode: the device to get information about
  233. ulpropertyType: which registry string to get
  234. pdiDevInfo: the new list node
  235. Return Value:
  236. BOOL: TRUE if function succeeds, FALSE if not
  237. --*/
  238. BOOL CopyRegistryLine(IN DEVNODE dnDevNode,
  239. IN ULONG ulPropertyType,
  240. IN PDEV_INFO pdiDevInfo)
  241. {
  242. ULONG ulRegDataLen = 0, ulRegDataType = 0;
  243. CONFIGRET cmret = CR_SUCCESS;
  244. PTCHAR szRegData = NULL;
  245. //
  246. // Get the length of the buffer don't bother checking return value
  247. // If RegProperty doesn't exist, we'll just move on
  248. //
  249. CM_Get_DevNode_Registry_Property(dnDevNode,
  250. ulPropertyType,
  251. NULL,
  252. NULL,
  253. &ulRegDataLen,
  254. 0);
  255. if (!ulRegDataLen ||
  256. (szRegData = malloc(sizeof(TCHAR) * ulRegDataLen)) == NULL)
  257. {
  258. goto RetFALSE;
  259. }
  260. //
  261. // Now get the registry information
  262. //
  263. cmret = CM_Get_DevNode_Registry_Property(dnDevNode,
  264. ulPropertyType,
  265. &ulRegDataType,
  266. szRegData,
  267. &ulRegDataLen,
  268. 0);
  269. if (CR_SUCCESS == cmret)
  270. {
  271. if (!(CopyRegDataToDevInfoNode(pdiDevInfo,
  272. ulPropertyType,
  273. szRegData)))
  274. {
  275. goto RetFALSE;
  276. }
  277. }
  278. return TRUE;
  279. RetFALSE:
  280. return FALSE;
  281. } /* CopyRegistryLine */
  282. /*++
  283. Routine Description: (23) CopyRegDataToDevInfoNode
  284. Copies a registry string to a list node
  285. Arguments:
  286. pdiDevInfo: the new list node
  287. ulPropertyType: which registry string to copy
  288. szRegData: the data to be copied
  289. Return Value:
  290. BOOL: TRUE if function succeeds, FALSE if not
  291. --*/
  292. BOOL CopyRegDataToDevInfoNode(IN OUT PDEV_INFO pdiDevInfo,
  293. IN ULONG ulPropertyType,
  294. IN PTCHAR szRegData)
  295. {
  296. if (pdiDevInfo == NULL)
  297. {
  298. goto RetFALSE;
  299. }
  300. switch (ulPropertyType)
  301. {
  302. case CM_DRP_DEVICEDESC:
  303. wsprintf(pdiDevInfo->szDescription, TEXT("%s"), szRegData);
  304. break;
  305. case CM_DRP_HARDWAREID:
  306. wsprintf(pdiDevInfo->szHardwareID, TEXT("%s"), szRegData);
  307. break;
  308. case CM_DRP_SERVICE:
  309. wsprintf(pdiDevInfo->szService, TEXT("%s"), szRegData);
  310. break;
  311. case CM_DRP_CLASS:
  312. wsprintf(pdiDevInfo->szClass, TEXT("%s"), szRegData);
  313. break;
  314. case CM_DRP_MFG:
  315. wsprintf(pdiDevInfo->szManufacturer, TEXT("%s"), szRegData);
  316. break;
  317. case CM_DRP_CONFIGFLAGS:
  318. wsprintf(pdiDevInfo->szConfigFlags, TEXT("%s"), szRegData);
  319. break;
  320. // Log(23, SEV2, TEXT("Invalid property type"));
  321. }
  322. return TRUE;
  323. RetFALSE:
  324. return FALSE;
  325. } /* CopyRegDataToDevInfoNode */
  326. /*++
  327. Routine Description: (58) InitializeInfoNode
  328. Initialized fields inside the new node
  329. Arguments:
  330. pdiDevInfo: the node
  331. szDevNodeID: used to find the dnDevNode in the future
  332. dnDevNode: the device we're storing information about
  333. Return Value:
  334. BOOL: TRUE if we should keep this node, FALSE if we should throw it away
  335. --*/
  336. BOOL InitializeInfoNode(IN PDEV_INFO pdiDevInfo,
  337. IN PTCHAR szDevNodeID,
  338. IN DEVNODE dnDevNode)
  339. {
  340. if (pdiDevInfo)
  341. {
  342. pdiDevInfo->Next = NULL;
  343. pdiDevInfo->Prev = NULL;
  344. pdiDevInfo->szDevNodeID[0] = '\0';
  345. pdiDevInfo->szDescription[0] = '\0';
  346. pdiDevInfo->szHardwareID[0] = '\0';
  347. pdiDevInfo->szService[0] = '\0';
  348. pdiDevInfo->szClass[0] = '\0';
  349. pdiDevInfo->szManufacturer[0] = '\0';
  350. pdiDevInfo->szConfigFlags[0] = '\0';
  351. pdiDevInfo->szFriendlyName[0] = '\0';
  352. pdiDevInfo->boolSavedOrigConfiguration = FALSE;
  353. pdiDevInfo->boolDisabled = FALSE;
  354. pdiDevInfo->prddForcedResDesData = NULL;
  355. pdiDevInfo->prddAllocResDesData = NULL;
  356. pdiDevInfo->prddBasicResDesData = NULL;
  357. pdiDevInfo->prddBootResDesData = NULL;
  358. //
  359. // Store devNodeID in pdiDevInfo to get handles to devnode in future
  360. //
  361. wsprintf(pdiDevInfo->szDevNodeID, TEXT("%s"), szDevNodeID);
  362. //
  363. // Extract information from the registry about this DevNode
  364. //
  365. CopyRegistryLine(dnDevNode, CM_DRP_DEVICEDESC, pdiDevInfo);
  366. CopyRegistryLine(dnDevNode, CM_DRP_HARDWAREID, pdiDevInfo);
  367. CopyRegistryLine(dnDevNode, CM_DRP_SERVICE, pdiDevInfo);
  368. CopyRegistryLine(dnDevNode, CM_DRP_CLASS, pdiDevInfo);
  369. CopyRegistryLine(dnDevNode, CM_DRP_MFG, pdiDevInfo);
  370. CopyRegistryLine(dnDevNode, CM_DRP_CONFIGFLAGS, pdiDevInfo);
  371. RecordFriendlyName(pdiDevInfo);
  372. }
  373. //
  374. // Check the friendly name to see if we want to throw this node away
  375. //
  376. if (strcmp(pdiDevInfo->szFriendlyName, "STORAGE/Volume") == 0 ||
  377. strcmp(pdiDevInfo->szFriendlyName, "Unknown Device") == 0)
  378. {
  379. return FALSE;
  380. }
  381. return TRUE;
  382. } /* InitializeInfoNode */
  383. /*++
  384. Routine Description: (57) RecordFriendlyName
  385. Finds the best user friendly name for this device
  386. Arguments:
  387. pdiDevInfo: node containing all possible names
  388. Return Value:
  389. void
  390. --*/
  391. void RecordFriendlyName(IN PDEV_INFO pdiDevInfo)
  392. {
  393. if (pdiDevInfo)
  394. {
  395. if (pdiDevInfo->szDescription &&
  396. pdiDevInfo->szDescription[0] != '\0')
  397. {
  398. wsprintf(pdiDevInfo->szFriendlyName, TEXT("%s"),
  399. pdiDevInfo->szDescription);
  400. }
  401. else if (pdiDevInfo->szHardwareID &&
  402. pdiDevInfo->szHardwareID[0] != '\0')
  403. {
  404. wsprintf(pdiDevInfo->szFriendlyName, TEXT("%s"),
  405. pdiDevInfo->szHardwareID);
  406. }
  407. else if (pdiDevInfo->szManufacturer &&
  408. pdiDevInfo->szManufacturer[0] != '\0')
  409. {
  410. wsprintf(pdiDevInfo->szFriendlyName, TEXT("%s"),
  411. pdiDevInfo->szHardwareID);
  412. }
  413. else if (pdiDevInfo->szService &&
  414. pdiDevInfo->szService[0] != '\0')
  415. {
  416. wsprintf(pdiDevInfo->szFriendlyName, TEXT("%s"),
  417. pdiDevInfo->szService);
  418. }
  419. else if (pdiDevInfo->szClass &&
  420. pdiDevInfo->szClass[0] != '\0')
  421. {
  422. wsprintf(pdiDevInfo->szFriendlyName, TEXT("%s"),
  423. pdiDevInfo->szClass);
  424. }
  425. else
  426. {
  427. wsprintf(pdiDevInfo->szFriendlyName, TEXT("Unknown Device"));
  428. }
  429. }
  430. } /* RecordFriendlyName */
  431. /*++
  432. Routine Description: (24) GetResDesList
  433. Creates new resource data node and copies resource information to that node
  434. Arguments:
  435. pdiDevInfo: the list node which will contain the new resource node
  436. lcLogConf: the logical configuration information
  437. ulLogConfType: FORCED, ALLOC, BOOT, or BASIC logical configuration
  438. Return Value:
  439. BOOL: TRUE if function succeeds, FALSE if not
  440. --*/
  441. BOOL GetResDesList(IN OUT PDEV_INFO pdiDevInfo,
  442. IN LOG_CONF lcLogConf,
  443. IN ULONG ulLogConfType)
  444. {
  445. CONFIGRET cmret, cmret2;
  446. RES_DES rdResDes = 0, rdResDesNew;
  447. RESOURCEID ridResourceID = 0;
  448. PRES_DES_DATA prddResDesData;
  449. prddResDesData = (PRES_DES_DATA)malloc(sizeof(RES_DES_DATA));
  450. if (prddResDesData == NULL)
  451. {
  452. // Log(24, SEV2, TEXT("ResDesData malloc failed."));
  453. goto RetFALSE;
  454. }
  455. prddResDesData->Next = NULL;
  456. prddResDesData->Prev = NULL;
  457. prddResDesData->pmresMEMResource = NULL;
  458. prddResDesData->piresIOResource = NULL;
  459. prddResDesData->pdresDMAResource = NULL;
  460. prddResDesData->pqresIRQResource = NULL;
  461. cmret = CM_Get_Next_Res_Des(&rdResDesNew,
  462. lcLogConf,
  463. ResType_All,
  464. &ridResourceID,
  465. 0);
  466. //
  467. // Go through each resource type and copy data to new node
  468. //
  469. while (CR_SUCCESS == cmret)
  470. {
  471. rdResDes = rdResDesNew;
  472. if (ridResourceID >= ResType_Mem && ridResourceID <= ResType_IRQ)
  473. {
  474. if (!(ProcessResDesInfo(prddResDesData,
  475. rdResDes,
  476. ridResourceID)))
  477. {
  478. goto RetFALSE;
  479. }
  480. }
  481. cmret = CM_Get_Next_Res_Des(&rdResDesNew,
  482. rdResDes,
  483. ResType_All,
  484. &ridResourceID,
  485. 0);
  486. cmret2 = CM_Free_Res_Des_Handle(rdResDes);
  487. if (cmret2 != CR_SUCCESS)
  488. {
  489. //ErrorLog(24, TEXT("CM_Free_Res_Des_Handle"), cmret2, NULL);
  490. }
  491. }
  492. //
  493. // **** change this by making resDesData = pdiDevInfo->----ResDesDAta
  494. // and merging into one code
  495. //
  496. //
  497. // Add the new node to the linked list
  498. //
  499. switch (ulLogConfType)
  500. {
  501. case FORCED_LOG_CONF:
  502. if (!pdiDevInfo->prddForcedResDesData)
  503. {
  504. //
  505. // This is the first entry into the linked list
  506. //
  507. pdiDevInfo->prddForcedResDesData = prddResDesData;
  508. }
  509. else
  510. {
  511. //
  512. // Add new node to beginning of linked list
  513. //
  514. prddResDesData->Next = pdiDevInfo->prddForcedResDesData;
  515. pdiDevInfo->prddForcedResDesData->Prev = prddResDesData;
  516. pdiDevInfo->prddForcedResDesData = prddResDesData;
  517. }
  518. break;
  519. case ALLOC_LOG_CONF:
  520. if (!pdiDevInfo->prddAllocResDesData)
  521. {
  522. //
  523. // This is the first entry into the linked list
  524. //
  525. pdiDevInfo->prddAllocResDesData = prddResDesData;
  526. }
  527. else
  528. {
  529. //
  530. // Add new node to beginning of linked list
  531. //
  532. prddResDesData->Next = pdiDevInfo->prddAllocResDesData;
  533. pdiDevInfo->prddAllocResDesData->Prev = prddResDesData;
  534. pdiDevInfo->prddAllocResDesData = prddResDesData;
  535. }
  536. break;
  537. case BASIC_LOG_CONF:
  538. if (!pdiDevInfo->prddBasicResDesData)
  539. {
  540. //
  541. // This is the first entry into the linked list
  542. //
  543. pdiDevInfo->prddBasicResDesData = prddResDesData;
  544. }
  545. else
  546. {
  547. //
  548. // Add new node to beginning of linked list
  549. //
  550. prddResDesData->Next = pdiDevInfo->prddBasicResDesData;
  551. pdiDevInfo->prddBasicResDesData->Prev = prddResDesData;
  552. pdiDevInfo->prddBasicResDesData = prddResDesData;
  553. }
  554. break;
  555. case BOOT_LOG_CONF:
  556. if (!pdiDevInfo->prddBootResDesData)
  557. {
  558. //
  559. // This is the first entry into the linked list
  560. //
  561. pdiDevInfo->prddBootResDesData = prddResDesData;
  562. }
  563. else
  564. {
  565. //
  566. // Add new node to beginning of linked list
  567. //
  568. prddResDesData->Next = pdiDevInfo->prddBootResDesData;
  569. pdiDevInfo->prddBootResDesData->Prev = prddResDesData;
  570. pdiDevInfo->prddBootResDesData = prddResDesData;
  571. }
  572. break;
  573. default:
  574. // Log(24, SEV2, TEXT("Illegal LogConfType\n - %ul"), ulLogConfType);
  575. goto RetFALSE;
  576. }
  577. return TRUE;
  578. RetFALSE:
  579. return FALSE;
  580. } /* GetResDestList */
  581. /*++
  582. Routine Description: (25) ProcessResDesInfo
  583. Gets information for one resource descriptor
  584. Arguments:
  585. prddResDesData: the new resource data node receiving the info
  586. rdResDes: the resource descriptor containing the info
  587. ridResourceID: tells the resource type (DMA, IO, MEM, IRQ, or CS)
  588. Return Value:
  589. BOOL: TRUE if function succeeds, FALSE if not
  590. --*/
  591. BOOL ProcessResDesInfo(IN OUT PRES_DES_DATA prddResDesData,
  592. IN RES_DES rdResDes,
  593. IN RESOURCEID ridResourceID)
  594. {
  595. PVOID pvResDesDataBuffer = NULL;
  596. ULONG ulResDesDataBufferLen;
  597. CONFIGRET cmret;
  598. cmret = CM_Get_Res_Des_Data_Size(&ulResDesDataBufferLen,
  599. rdResDes,
  600. 0);
  601. if (CR_SUCCESS != cmret)
  602. {
  603. //ErrorLog(25, TEXT("CM_Get_Res_Des_Data_Size"), cmret, NULL);
  604. goto RetFALSE;
  605. }
  606. if ((pvResDesDataBuffer = malloc(sizeof(PVOID) * ulResDesDataBufferLen))
  607. == NULL)
  608. {
  609. // Log(25, SEV2, TEXT("resDesDataBuffer malloc size of %d failed."),
  610. // ulResDesDataBufferLen);
  611. goto RetFALSE;
  612. }
  613. //
  614. // Get the data
  615. //
  616. cmret = CM_Get_Res_Des_Data(rdResDes,
  617. pvResDesDataBuffer,
  618. ulResDesDataBufferLen,
  619. 0);
  620. if (CR_SUCCESS != cmret)
  621. {
  622. //ErrorLog(25, TEXT("CM_Get_Res_Des_Data"), cmret, NULL);
  623. goto RetFALSE;
  624. }
  625. //
  626. // Copy data into ResDesData node
  627. //
  628. switch (ridResourceID)
  629. {
  630. case ResType_Mem:
  631. prddResDesData->pmresMEMResource = (PMEM_RESOURCE)pvResDesDataBuffer;
  632. break;
  633. case ResType_IO:
  634. prddResDesData->piresIOResource = (PIO_RESOURCE)pvResDesDataBuffer;
  635. break;
  636. case ResType_DMA:
  637. prddResDesData->pdresDMAResource = (PDMA_RESOURCE)pvResDesDataBuffer;
  638. break;
  639. case ResType_IRQ:
  640. prddResDesData->pqresIRQResource = (PIRQ_RESOURCE)pvResDesDataBuffer;
  641. break;
  642. default:
  643. // Log(25, SEV2, TEXT("Illegal ResourceID - %ul"), ridResourceID);
  644. goto RetFALSE;
  645. }
  646. return TRUE;
  647. RetFALSE:
  648. return FALSE;
  649. } /* ProcessResDesInfo */
  650. /*++
  651. Routine Description: (26) UpdateDeviceList
  652. Frees resource information for all devices and then collects the
  653. information again
  654. Arguments:
  655. none (g_pdiDevList is global head of device list)
  656. Return Value:
  657. BOOL: TRUE if function succeeds, FALSE if not
  658. --*/
  659. BOOL UpdateDeviceList()
  660. {
  661. PDEV_INFO pdiTmpDevInfo;
  662. pdiTmpDevInfo = g_pdiDevList;
  663. //
  664. // Go through linked list and delete each node's ResDes lists
  665. //
  666. while (pdiTmpDevInfo)
  667. {
  668. if (pdiTmpDevInfo->prddForcedResDesData)
  669. {
  670. DeleteResDesDataNode(pdiTmpDevInfo->prddForcedResDesData);
  671. pdiTmpDevInfo->prddForcedResDesData = NULL;
  672. }
  673. if (pdiTmpDevInfo->prddAllocResDesData)
  674. {
  675. DeleteResDesDataNode(pdiTmpDevInfo->prddAllocResDesData);
  676. pdiTmpDevInfo->prddAllocResDesData = NULL;
  677. }
  678. if (pdiTmpDevInfo->prddBasicResDesData)
  679. {
  680. DeleteResDesDataNode(pdiTmpDevInfo->prddBasicResDesData);
  681. pdiTmpDevInfo->prddBasicResDesData = NULL;
  682. }
  683. if (pdiTmpDevInfo->prddBootResDesData)
  684. {
  685. DeleteResDesDataNode(pdiTmpDevInfo->prddBootResDesData);
  686. pdiTmpDevInfo->prddBootResDesData = NULL;
  687. }
  688. pdiTmpDevInfo = pdiTmpDevInfo->Next;
  689. }
  690. pdiTmpDevInfo = g_pdiDevList;
  691. //
  692. // Recreate the ResDesLists for each node
  693. //
  694. while (pdiTmpDevInfo)
  695. {
  696. if (!(RecreateResDesList(pdiTmpDevInfo, FORCED_LOG_CONF)))
  697. goto RetFALSE;
  698. if (!(RecreateResDesList(pdiTmpDevInfo, ALLOC_LOG_CONF)))
  699. goto RetFALSE;
  700. if (!(RecreateResDesList(pdiTmpDevInfo, BASIC_LOG_CONF)))
  701. goto RetFALSE;
  702. if (!(RecreateResDesList(pdiTmpDevInfo, BOOT_LOG_CONF)))
  703. goto RetFALSE;
  704. pdiTmpDevInfo = pdiTmpDevInfo->Next;
  705. }
  706. return TRUE;
  707. RetFALSE:
  708. return FALSE;
  709. } /* UpdateDeviceList */
  710. /*++
  711. Routine Description: (27) DeleteResDesDataNode
  712. Deletes a string of RES_DES_DATA structures
  713. Arguments:
  714. prddTmpResDes: the head of the linked list
  715. Return Value:
  716. void
  717. --*/
  718. void DeleteResDesDataNode(IN PRES_DES_DATA prddTmpResDes)
  719. {
  720. PRES_DES_DATA prddNextResDes;
  721. while (prddTmpResDes)
  722. {
  723. prddNextResDes = prddTmpResDes->Next;
  724. free (prddTmpResDes);
  725. prddTmpResDes = prddNextResDes;
  726. }
  727. } /* DeleteResDesDataNode */
  728. /*++
  729. Routine Description: (56) CopyDataToLogConf
  730. Calls CM_Add_Res_Des to add a resDes to a lcLogConf
  731. Arguments:
  732. lcLogConf: the lcLogConf receiving the resDes
  733. ridResType: ResType_Mem, IO, DMA or IRQ
  734. pvResData: the new data
  735. ulResourceLen: size of the data
  736. Return Value:
  737. BOOL: TRUE if the CM call succeeds, FALSE if not
  738. --*/
  739. BOOL CopyDataToLogConf(IN LOG_CONF lcLogConf,
  740. IN RESOURCEID ridResType,
  741. IN PVOID pvResData,
  742. IN ULONG ulResourceLen)
  743. {
  744. CONFIGRET cmret;
  745. RES_DES rdResDes;
  746. //
  747. // Copy the data to the logConf
  748. //
  749. cmret = CM_Add_Res_Des(&rdResDes,
  750. lcLogConf,
  751. ridResType,
  752. pvResData,
  753. ulResourceLen,
  754. 0);
  755. if (CR_SUCCESS != cmret)
  756. {
  757. goto RetFALSE;
  758. }
  759. return TRUE;
  760. RetFALSE:
  761. return FALSE;
  762. } /* CopyDataToLogConf */
  763. /*++
  764. Routine Description: (28) RecreateResDesList
  765. Uses CM calls to find ResDes information and creates linked list
  766. of this information inside of given DEV_INFO
  767. Arguments:
  768. pdiTmpDevInfo: the node receiving the information
  769. ulLogConfType: the LogConf type (FORCED_LOG_CONF,
  770. ALLOC_LOG_CONF,
  771. BASIC_LOG_CONF,
  772. BOOT_LOG_CONF)
  773. Return Value:
  774. BOOL: TRUE if function succeeds, FALSE if not
  775. --*/
  776. BOOL RecreateResDesList(IN OUT PDEV_INFO pdiTmpDevInfo,
  777. IN ULONG ulLogConfType)
  778. {
  779. CONFIGRET cmret, cmret2;
  780. DEVNODE dnDevNode;
  781. LOG_CONF lcLogConf, lcLogConfNew;
  782. //
  783. // Get handle to the devnode
  784. //
  785. cmret = CM_Locate_DevNode(&dnDevNode,
  786. pdiTmpDevInfo->szDevNodeID,
  787. CM_LOCATE_DEVNODE_NORMAL);
  788. if (CR_SUCCESS != cmret)
  789. {
  790. //ErrorLog(28, TEXT("CM_Locate_DevNode"), cmret, NULL);
  791. goto RetFALSE;
  792. }
  793. //
  794. // Get logical configuration information
  795. //
  796. cmret = CM_Get_First_Log_Conf(&lcLogConfNew,
  797. dnDevNode,
  798. ulLogConfType);
  799. while (CR_SUCCESS == cmret)
  800. {
  801. lcLogConf = lcLogConfNew;
  802. if (!(GetResDesList(pdiTmpDevInfo, lcLogConf, ulLogConfType)))
  803. {
  804. goto RetFALSE;
  805. }
  806. cmret = CM_Get_Next_Log_Conf(&lcLogConfNew,
  807. lcLogConf,
  808. 0);
  809. cmret2 = CM_Free_Log_Conf_Handle(lcLogConf);
  810. if (CR_SUCCESS != cmret2)
  811. {
  812. //ErrorLog(28, TEXT("CM_Free_Log_Conf"), cmret2, NULL);
  813. }
  814. }
  815. return TRUE;
  816. RetFALSE:
  817. return FALSE;
  818. } /* RecreateResDesList */
  819. void Cleanup()
  820. {
  821. PDEV_INFO pdiDevInfo = g_pdiDevList;
  822. PDEV_INFO pdiNextInfoNode;
  823. while (pdiDevInfo)
  824. {
  825. pdiNextInfoNode = pdiDevInfo->Next;
  826. DeleteResDesDataNode(pdiDevInfo->prddForcedResDesData);
  827. DeleteResDesDataNode(pdiDevInfo->prddAllocResDesData);
  828. DeleteResDesDataNode(pdiDevInfo->prddBasicResDesData);
  829. DeleteResDesDataNode(pdiDevInfo->prddBootResDesData);
  830. free(pdiDevInfo);
  831. pdiDevInfo = pdiNextInfoNode;
  832. }
  833. } /* Cleanup */