Windows NT 4.0 source code leak
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.

1765 lines
47 KiB

4 years ago
  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. rlogconf.c
  5. Abstract:
  6. This module contains the server-side logical configuration APIs.
  7. PNP_AddEmptyLogConf
  8. PNP_FreeLogConf
  9. PNP_GetFirstLogConf
  10. PNP_GetNextLogConf
  11. Author:
  12. Paula Tomlinson (paulat) 9-27-1995
  13. Environment:
  14. User-mode only.
  15. Revision History:
  16. 27-Sept-1995 paulat
  17. Creation and initial implementation.
  18. --*/
  19. //
  20. // includes
  21. //
  22. #include "precomp.h"
  23. #include "umpnpdat.h"
  24. //
  25. // Prototypes used in this routine and in rresdes.c
  26. //
  27. CONFIGRET
  28. GetLogConfData(
  29. IN HKEY hKey,
  30. IN ULONG ulLogConfType,
  31. OUT PULONG pulRegDataType,
  32. OUT LPWSTR pszValueName,
  33. OUT LPBYTE *ppBuffer,
  34. OUT PULONG pulBufferSize
  35. );
  36. PCM_FULL_RESOURCE_DESCRIPTOR
  37. AdvanceResourcePtr(
  38. IN PCM_FULL_RESOURCE_DESCRIPTOR pRes
  39. );
  40. PIO_RESOURCE_LIST
  41. AdvanceRequirementsPtr(
  42. IN PIO_RESOURCE_LIST pReq
  43. );
  44. BOOL
  45. FindLogConf(
  46. IN PVOID pList,
  47. OUT PVOID *ppLogConf,
  48. IN ULONG RegDataType,
  49. IN ULONG ulTag,
  50. OUT PULONG pulIndex
  51. );
  52. //
  53. // private prototypes
  54. //
  55. BOOL
  56. InitLogConfRes(
  57. IN OUT PCM_FULL_RESOURCE_DESCRIPTOR pRes,
  58. IN ULONG ulPriority,
  59. IN ULONG ulTag
  60. );
  61. BOOL
  62. InitLogConfReq(
  63. IN OUT PIO_RESOURCE_LIST pReq,
  64. IN ULONG ulPriority,
  65. IN ULONG ulTag
  66. );
  67. BOOL
  68. InitReqList(
  69. IN OUT PIO_RESOURCE_REQUIREMENTS_LIST pReqList,
  70. IN ULONG ulReqSize
  71. );
  72. ULONG
  73. GetFreeLogConfTag(
  74. IN ULONG RegDataType,
  75. IN LPBYTE pList
  76. );
  77. ULONG
  78. LC_RES_TAG(
  79. IN PCM_FULL_RESOURCE_DESCRIPTOR pRes
  80. );
  81. ULONG
  82. LC_REQ_TAG(
  83. IN PIO_RESOURCE_LIST pReq
  84. );
  85. ULONG
  86. LC_RES_PRIORITY(
  87. IN PCM_FULL_RESOURCE_DESCRIPTOR pRes
  88. );
  89. ULONG
  90. LC_REQ_PRIORITY(
  91. IN PIO_RESOURCE_LIST pReq
  92. );
  93. BYTE
  94. CmToNtPriority(
  95. IN ULONG CmPriority
  96. );
  97. ULONG
  98. NtToCmPriority(
  99. IN BYTE NtPriority
  100. );
  101. BOOL
  102. MigrateObsoleteDetectionInfo(
  103. IN LPWSTR pszDeviceID,
  104. IN HKEY hLogConfKey
  105. );
  106. //
  107. // global data
  108. //
  109. CONFIGRET
  110. PNP_AddEmptyLogConf(
  111. IN handle_t hBinding,
  112. IN LPWSTR pDeviceID,
  113. IN ULONG ulPriority,
  114. OUT PULONG pulTag,
  115. IN ULONG ulFlags
  116. )
  117. /*++
  118. Routine Description:
  119. This the server-side of an RPC remote call. This routine adds
  120. an empty logical configuration.
  121. Arguments:
  122. hBinding Not used.
  123. pDeviceID Null-terminated device instance id string.
  124. ulPriority Priority for new log conf.
  125. pulTag Returns tag that identifies which log config this is.
  126. ulFlags Describes type of log conf to add.
  127. Return Value:
  128. If the specified device instance is valid, it returns CR_SUCCESS,
  129. otherwise it returns CR_ error code.
  130. --*/
  131. {
  132. CONFIGRET Status = CR_SUCCESS;
  133. HKEY hKey = NULL;
  134. WCHAR szValueName[64];
  135. LPBYTE pList = NULL, pLogConf = NULL, pTemp = NULL, pNext = NULL;
  136. ULONG Index = 0, ulListSize = 0, ulAddListSize = 0, ulSize = 0;
  137. ULONG RegDataType = 0;
  138. UNREFERENCED_PARAMETER(hBinding);
  139. //------------------------------------------------------------------
  140. // NOTE: The log confs are stored in priority order in the registry.
  141. // The BOOT, ALLOC, and FORCED config types are stored in a registry
  142. // value name of the format XxxConfig and the BASIC, FILTERED, and
  143. // OVERRIDE configs are stored in a registr value name of the format
  144. // XxxConfigVector. XxxConfig values contain the actual resource
  145. // description (REG_RESOURCE_LIST, CM_RESOURCE_LIST) while
  146. // XxxConfigVector values contain a list of resource requirements
  147. // (REG_RESOURCE_REQUIREMENTS_LIST, IO_RESOURCE_REQUIREMENTS_LIST).
  148. //
  149. // The policy for using the log conf and res des APIs is:
  150. // - BOOT, ALLOC, and FORCED are defined to only have one log conf.
  151. // You can add additional log confs, but only the first (highest
  152. // priority log conf will ever be used internally).
  153. // - Although callers always specify a complete XXX_RESOURCE type
  154. // structure for the data when adding resource descriptors to
  155. // a log conf, I will ignore the resource specific portion of
  156. // the XXX_DES structure for FILTERED, BASIC, and OVERRIDE.
  157. // Likewise I will ignore any XXX_RANGE structures for ALLOC,
  158. // BOOT or FORCED log config types.
  159. //------------------------------------------------------------------
  160. try {
  161. //
  162. // make sure original caller didn't specify root devnode
  163. //
  164. if (IsRootDeviceID(pDeviceID)) {
  165. Status = CR_INVALID_DEVNODE;
  166. goto Clean0;
  167. }
  168. //
  169. // open a key to the device's LogConf subkey
  170. //
  171. Status = OpenLogConfKey(pDeviceID, &hKey);
  172. if (Status != CR_SUCCESS) {
  173. goto Clean0;
  174. }
  175. MigrateObsoleteDetectionInfo(pDeviceID, hKey);
  176. //
  177. // Retrieve log conf data from the registry
  178. //
  179. Status = GetLogConfData(hKey, ulFlags & LOG_CONF_BITS,
  180. &RegDataType, szValueName,
  181. &pList, &ulListSize);
  182. //-----------------------------------------------------------
  183. // Specified log conf type contains Resource Data only
  184. //-----------------------------------------------------------
  185. if (RegDataType == REG_RESOURCE_LIST) {
  186. if (Status != CR_SUCCESS || ulListSize == 0) {
  187. //
  188. // If this is the first log conf of this type, create a new
  189. // log conf list structure with a single empty log conf entry
  190. //
  191. PCM_RESOURCE_LIST pResList = NULL;
  192. Status = CR_SUCCESS;
  193. ulListSize = sizeof(CM_RESOURCE_LIST) -
  194. sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
  195. pList = malloc(ulListSize);
  196. if (pList == NULL) {
  197. Status = CR_OUT_OF_MEMORY;
  198. goto Clean0;
  199. }
  200. //
  201. // initialize the config list header info
  202. //
  203. *pulTag = 0;
  204. memset(pList, 0, ulListSize);
  205. pResList = (PCM_RESOURCE_LIST)pList;
  206. pResList->Count = 1;
  207. InitLogConfRes(&pResList->List[0], ulPriority, *pulTag);
  208. } else {
  209. //
  210. // There is already at least one log conf of this type, so add
  211. // a new empty log conf to the log conf list (in priority order)
  212. //
  213. PCM_RESOURCE_LIST pResList = (PCM_RESOURCE_LIST)pList;
  214. PCM_FULL_RESOURCE_DESCRIPTOR pRes = (PCM_FULL_RESOURCE_DESCRIPTOR)pLogConf;
  215. //
  216. // verify there is room for another log conf
  217. //
  218. if (pResList->Count >= MAX_LOG_CONF-1) {
  219. Status = CR_NO_MORE_LOG_CONF;
  220. goto Clean0;
  221. }
  222. *pulTag = GetFreeLogConfTag(RegDataType, pList);
  223. if (*pulTag == MAX_LOGCONF_TAG) {
  224. Status = CR_NO_MORE_LOG_CONF; // no more available log confs
  225. goto Clean0;
  226. }
  227. //
  228. // realloc the existing log conf list structs to hold another
  229. // log conf
  230. //
  231. ulAddListSize = sizeof(CM_FULL_RESOURCE_DESCRIPTOR) -
  232. sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
  233. pResList = (PCM_RESOURCE_LIST)realloc(pResList,
  234. ulListSize + ulAddListSize);
  235. if (pResList == NULL) {
  236. Status = CR_OUT_OF_MEMORY;
  237. goto Clean0;
  238. }
  239. pList = (LPBYTE)pResList;
  240. //
  241. // walk the Resource data looking for where the new log conf
  242. // fits in the list of log confs in terms of priority.
  243. //
  244. pRes = (PCM_FULL_RESOURCE_DESCRIPTOR)(&pResList->List[0]); // first lc
  245. Index = 0;
  246. while (Index < pResList->Count) {
  247. if ((LC_RES_PRIORITY(pRes) > ulPriority) ||
  248. ((LC_RES_PRIORITY(pRes) == ulPriority) &&
  249. ((ulFlags & PRIORITY_BIT) == PRIORITY_EQUAL_FIRST))) {
  250. break; // this is the spot
  251. }
  252. pRes = AdvanceResourcePtr(pRes); // next lc
  253. Index++;
  254. }
  255. if (Index != pResList->Count) {
  256. //
  257. // we're going to insert the new log conf somewhere besides
  258. // at the end, so move any remaining log confs down one
  259. // spot in the list to make room for the new log conf at
  260. // this spot
  261. //
  262. ulSize = ulListSize - ((DWORD)pRes - (DWORD)pResList);
  263. pTemp = malloc(ulSize);
  264. if (pTemp == NULL) {
  265. Status = CR_OUT_OF_MEMORY;
  266. goto Clean0;
  267. }
  268. pNext = (LPBYTE)((LPBYTE)pRes + ulAddListSize);
  269. memcpy(pTemp, pRes, ulSize); // save in temp buffer
  270. memcpy(pNext, pTemp, ulSize); // copy to next lc
  271. }
  272. //
  273. // initialize the new empty log config
  274. //
  275. pResList->Count++;
  276. InitLogConfRes(pRes, ulPriority, *pulTag);
  277. }
  278. }
  279. //-----------------------------------------------------------
  280. // Specified log conf type contains requirements data only
  281. //-----------------------------------------------------------
  282. else if (RegDataType == REG_RESOURCE_REQUIREMENTS_LIST) {
  283. if (Status != CR_SUCCESS || ulListSize == 0) {
  284. //
  285. // If this is the first log conf of this type, create a new
  286. // log conf list structure with a single empty log conf entry
  287. //
  288. PIO_RESOURCE_REQUIREMENTS_LIST pReqList = NULL;
  289. Status = CR_SUCCESS;
  290. ulListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) -
  291. sizeof(IO_RESOURCE_DESCRIPTOR);
  292. pList = malloc(ulListSize);
  293. if (pList == NULL) {
  294. Status = CR_OUT_OF_MEMORY;
  295. goto Clean0;
  296. }
  297. //
  298. // initialize the config list header info
  299. //
  300. *pulTag = 0;
  301. memset(pList, 0, ulListSize);
  302. pReqList = (PIO_RESOURCE_REQUIREMENTS_LIST)pList;
  303. InitReqList(pReqList, ulListSize);
  304. pReqList->AlternativeLists = 1;
  305. InitLogConfReq(&pReqList->List[0], ulPriority, *pulTag);
  306. } else {
  307. //
  308. // There is already at least one log conf of this type, so add
  309. // a new empty log conf to the log conf list (in priority order)
  310. //
  311. PIO_RESOURCE_REQUIREMENTS_LIST pReqList = (PIO_RESOURCE_REQUIREMENTS_LIST)pList;
  312. PIO_RESOURCE_LIST pReq = (PIO_RESOURCE_LIST)pLogConf;
  313. //
  314. // verify there is room for another log conf
  315. //
  316. if (pReqList->AlternativeLists >= MAX_LOG_CONF-1) {
  317. Status = CR_NO_MORE_LOG_CONF;
  318. goto Clean0;
  319. }
  320. *pulTag = GetFreeLogConfTag(RegDataType, pList);
  321. if (*pulTag == MAX_LOGCONF_TAG) {
  322. Status = CR_NO_MORE_LOG_CONF; // no more available log confs
  323. goto Clean0;
  324. }
  325. //
  326. // realloc the existing log conf list structs to hold another
  327. // log conf
  328. //
  329. ulAddListSize = sizeof(IO_RESOURCE_LIST) -
  330. sizeof(IO_RESOURCE_DESCRIPTOR);
  331. pReqList = (PIO_RESOURCE_REQUIREMENTS_LIST)realloc(pReqList,
  332. ulListSize + ulAddListSize);
  333. if (pReqList == NULL) {
  334. Status = CR_OUT_OF_MEMORY;
  335. goto Clean0;
  336. }
  337. pList = (LPBYTE)pReqList;
  338. //
  339. // walk the pReqList struct (it contains priority value), looking
  340. // for where the new log conf fits in the list of log confs in
  341. // terms of priority.
  342. //
  343. pReq = (PIO_RESOURCE_LIST)(&pReqList->List[0]); // first lc
  344. Index = 0;
  345. while (Index < pReqList->AlternativeLists) {
  346. if ((LC_REQ_PRIORITY(pReq) > ulPriority) ||
  347. ((LC_REQ_PRIORITY(pReq) == ulPriority) &&
  348. ((ulFlags & PRIORITY_BIT) == PRIORITY_EQUAL_FIRST))) {
  349. break; // this is the spot
  350. }
  351. pReq = AdvanceRequirementsPtr(pReq); // next lc
  352. Index++;
  353. }
  354. if (Index != pReqList->AlternativeLists) {
  355. //
  356. // we're going to insert the new log conf somewhere besides
  357. // at the end, so move any remaining log confs down one
  358. // spot in the list to make room for the new log conf at
  359. // this spot
  360. //
  361. ulSize = ulListSize - ((DWORD)pReq - (DWORD)pReqList);
  362. pTemp = malloc(ulSize);
  363. if (pTemp == NULL) {
  364. Status = CR_OUT_OF_MEMORY;
  365. goto Clean0;
  366. }
  367. pNext = (LPBYTE)((LPBYTE)pReq + ulAddListSize);
  368. memcpy(pTemp, pReq, ulSize); // save in temp buffer
  369. memcpy(pNext, pTemp, ulSize); // copy to next lc
  370. }
  371. //
  372. // initialize the new empty log config
  373. //
  374. InitLogConfReq(pReq, ulPriority, *pulTag);
  375. pReqList->AlternativeLists++;
  376. pReqList->ListSize = ulListSize + ulAddListSize;
  377. }
  378. } else {
  379. Status = CR_FAILURE;
  380. goto Clean0;
  381. }
  382. //
  383. // Write out the new/updated log conf list to the registry
  384. //
  385. if (RegSetValueEx(hKey, szValueName, 0, RegDataType,
  386. pList, ulListSize + ulAddListSize)
  387. != ERROR_SUCCESS) {
  388. Status = CR_REGISTRY_ERROR;
  389. goto Clean0;
  390. }
  391. Clean0:
  392. ;
  393. } except(EXCEPTION_EXECUTE_HANDLER) {
  394. Status = CR_FAILURE;
  395. }
  396. if (hKey != NULL) {
  397. RegCloseKey(hKey);
  398. }
  399. if (pList != NULL) {
  400. free(pList);
  401. }
  402. if (pTemp != NULL) {
  403. free(pTemp);
  404. }
  405. return Status;
  406. } // PNP_AddEmptyLogConf
  407. CONFIGRET
  408. PNP_FreeLogConf(
  409. IN handle_t hBinding,
  410. IN LPWSTR pDeviceID,
  411. IN ULONG ulType,
  412. IN ULONG ulTag,
  413. IN ULONG ulFlags
  414. )
  415. /*++
  416. Routine Description:
  417. This the server-side of an RPC remote call. This routine frees a
  418. logical configuration.
  419. Arguments:
  420. hBinding Not used.
  421. pDeviceID Null-terminated device instance id string.
  422. ulType Identifies which type of log conf is requested.
  423. ulTag Identifies which log conf from the specified type
  424. of log conf we want.
  425. ulFlags Not used.
  426. Return Value:
  427. If the specified device instance is valid, it returns CR_SUCCESS,
  428. otherwise it returns CR_ error code.
  429. --*/
  430. {
  431. CONFIGRET Status = CR_SUCCESS;
  432. HKEY hKey = NULL;
  433. WCHAR szValueName[64];
  434. LPBYTE pList = NULL, pLogConf = NULL, pTemp = NULL, pNext = NULL;
  435. ULONG RegDataType = 0, ulIndex = 0, ulListSize = 0, ulSize = 0;
  436. UNREFERENCED_PARAMETER(hBinding);
  437. UNREFERENCED_PARAMETER(ulFlags);
  438. try {
  439. //
  440. // make sure original caller didn't specify root devnode (this
  441. // can't happen but Win95 does the check anyway)
  442. //
  443. if (IsRootDeviceID(pDeviceID)) {
  444. Status = CR_INVALID_DEVNODE;
  445. goto Clean0;
  446. }
  447. //
  448. // Validate the specified tag
  449. //
  450. if (ulTag >= MAX_LOGCONF_TAG) {
  451. Status = CR_INVALID_LOG_CONF;
  452. goto Clean0;
  453. }
  454. //
  455. // open a key to the device's LogConf subkey
  456. //
  457. Status = OpenLogConfKey(pDeviceID, &hKey);
  458. if (Status != CR_SUCCESS) {
  459. //
  460. // if the device id or LogConf subkey is not in registry,
  461. // that's okay, by definition the log conf is freed since it
  462. // doesn't exist
  463. //
  464. goto Clean0;
  465. }
  466. //
  467. // Retrieve log conf data from the registry
  468. //
  469. Status = GetLogConfData(hKey, ulType,
  470. &RegDataType, szValueName,
  471. &pList, &ulListSize);
  472. if (Status != CR_SUCCESS) {
  473. Status = CR_INVALID_LOG_CONF;
  474. goto Clean0;
  475. }
  476. //
  477. // If the log conf to free is the one and only log conf of this
  478. // type then delete the corresponding registry values
  479. //
  480. if ((RegDataType == REG_RESOURCE_LIST &&
  481. ((PCM_RESOURCE_LIST)pList)->Count <= 1) ||
  482. (RegDataType == REG_RESOURCE_REQUIREMENTS_LIST &&
  483. ((PIO_RESOURCE_REQUIREMENTS_LIST)pList)->AlternativeLists <= 1)) {
  484. RegDeleteValue(hKey, szValueName);
  485. goto Clean0;
  486. }
  487. //
  488. // There are other log confs besides the one to delete, so I'll
  489. // have to remove the log conf from the data structs and resave
  490. // to the registry
  491. //
  492. //
  493. // Seek to the log conf that matches the log conf tag
  494. //
  495. if (!FindLogConf(pList, &pLogConf, RegDataType, ulTag, &ulIndex)) {
  496. Status = CR_INVALID_LOG_CONF;
  497. goto Clean0;
  498. }
  499. //
  500. // Specified log conf type contains Resource Data only
  501. //
  502. if (RegDataType == REG_RESOURCE_LIST) {
  503. PCM_RESOURCE_LIST pResList = (PCM_RESOURCE_LIST)pList;
  504. PCM_FULL_RESOURCE_DESCRIPTOR pRes = (PCM_FULL_RESOURCE_DESCRIPTOR)pLogConf;
  505. if (ulIndex == pResList->Count-1) {
  506. //
  507. // If deleting the last log conf in the list, just truncate it
  508. //
  509. ulListSize = (ULONG)pRes - (ULONG)pResList;
  510. } else {
  511. //
  512. // Shift remaining log confs (after the log conf to be deleted)
  513. // up in the list, writing over the log conf to be deleted
  514. //
  515. pNext = (LPBYTE)AdvanceResourcePtr(pRes);
  516. ulSize = ulListSize - ((DWORD)pNext - (DWORD)pResList);
  517. pTemp = malloc(ulSize);
  518. if (pTemp == NULL) {
  519. Status = CR_OUT_OF_MEMORY;
  520. goto Clean0;
  521. }
  522. memcpy(pTemp, pNext, ulSize); // save in temp buffer
  523. memcpy(pRes, pTemp, ulSize); // copy to deleted lc
  524. ulListSize -= ((DWORD)pNext - (DWORD)pRes);
  525. }
  526. //
  527. // update the log conf list header
  528. //
  529. pResList->Count--;
  530. }
  531. //
  532. // Specified log conf type contains requirements data only
  533. //
  534. else if (RegDataType == REG_RESOURCE_REQUIREMENTS_LIST) {
  535. PIO_RESOURCE_REQUIREMENTS_LIST pReqList = (PIO_RESOURCE_REQUIREMENTS_LIST)pList;
  536. PIO_RESOURCE_LIST pReq = (PIO_RESOURCE_LIST)pLogConf;
  537. if (ulIndex == pReqList->AlternativeLists-1) {
  538. //
  539. // If deleting the last log conf in the list, just truncate it
  540. //
  541. ulListSize = (ULONG)pReq - (ULONG)pReqList;
  542. }
  543. else {
  544. //
  545. // Shift remaining log confs (after the log conf to be deleted)
  546. // up in the list, writing over the log conf to be deleted
  547. //
  548. pNext = (LPBYTE)AdvanceRequirementsPtr(pReq);
  549. ulSize = ulListSize - ((DWORD)pNext - (DWORD)pReqList);
  550. pTemp = malloc(ulSize);
  551. if (pTemp == NULL) {
  552. Status = CR_OUT_OF_MEMORY;
  553. goto Clean0;
  554. }
  555. memcpy(pTemp, pNext, ulSize); // save in temp buffer
  556. memcpy(pReq, pTemp, ulSize); // copy to deleted lc
  557. ulListSize -= ((DWORD)pNext - (DWORD)pReq);
  558. }
  559. //
  560. // update the log conf list header
  561. //
  562. pReqList->AlternativeLists--;
  563. pReqList->ListSize = ulListSize;
  564. }
  565. //
  566. // Write out the updated log conf list to the registry
  567. //
  568. if (RegSetValueEx(hKey, szValueName, 0, RegDataType, pList,
  569. ulListSize) != ERROR_SUCCESS) {
  570. Status = CR_REGISTRY_ERROR;
  571. goto Clean0;
  572. }
  573. Clean0:
  574. ;
  575. } except(EXCEPTION_EXECUTE_HANDLER) {
  576. Status = CR_FAILURE;
  577. }
  578. if (hKey != NULL) {
  579. RegCloseKey(hKey);
  580. }
  581. if (pList != NULL) {
  582. free(pList);
  583. }
  584. if (pTemp != NULL) {
  585. free(pTemp);
  586. }
  587. return Status;
  588. } // PNP_FreeLogConf
  589. CONFIGRET
  590. PNP_GetFirstLogConf(
  591. IN handle_t hBinding,
  592. IN LPWSTR pDeviceID,
  593. IN ULONG ulType,
  594. OUT PULONG pulTag,
  595. IN ULONG ulFlags
  596. )
  597. /*++
  598. Routine Description:
  599. This the server-side of an RPC remote call. This routine finds the
  600. first log conf of this type for this devnode.
  601. Arguments:
  602. hBinding Not used.
  603. pDeviceID Null-terminated device instance id string.
  604. ulType Describes the type of log conf to find.
  605. pulTag Returns tag that identifies which log config this is.
  606. ulFlags Not used.
  607. Return Value:
  608. If the specified device instance is valid, it returns CR_SUCCESS,
  609. otherwise it returns CR_ error code.
  610. --*/
  611. {
  612. CONFIGRET Status = CR_SUCCESS;
  613. HKEY hKey = NULL;
  614. LPBYTE pList = NULL;
  615. WCHAR szValueName[64];
  616. ULONG RegDataType = 0, ulListSize = 0;
  617. UNREFERENCED_PARAMETER(hBinding);
  618. UNREFERENCED_PARAMETER(ulFlags);
  619. try {
  620. //
  621. // Initialize output parameters
  622. //
  623. *pulTag = MAX_LOGCONF_TAG;
  624. //
  625. // open a key to the device's LogConf subkey. If the device id is not
  626. // in the registry, the devnode doesn't exist and therefore neither
  627. // does the log conf
  628. //
  629. Status = OpenLogConfKey(pDeviceID, &hKey);
  630. if (Status != CR_SUCCESS) {
  631. Status = CR_NO_MORE_LOG_CONF;
  632. goto Clean0;
  633. }
  634. //
  635. // Migrate any log conf data that might have been written to
  636. // registry by NT 4.0 Beta I code.
  637. //
  638. MigrateObsoleteDetectionInfo(pDeviceID, hKey);
  639. //
  640. // Retrieve log conf data from the registry
  641. //
  642. Status = GetLogConfData(hKey, ulType,
  643. &RegDataType, szValueName,
  644. &pList, &ulListSize);
  645. if (Status != CR_SUCCESS) {
  646. Status = CR_NO_MORE_LOG_CONF;
  647. goto Clean0;
  648. }
  649. //
  650. // Specified log conf type contains Resource Data only
  651. //
  652. if (RegDataType == REG_RESOURCE_LIST) {
  653. //
  654. // retrieve log conf tag value
  655. //
  656. *pulTag = LC_RES_TAG(&((PCM_RESOURCE_LIST)pList)->List[0]);
  657. }
  658. //
  659. // Specified log conf type contains requirements data only
  660. //
  661. else if (RegDataType == REG_RESOURCE_REQUIREMENTS_LIST) {
  662. //
  663. // retreive log conf tag value
  664. //
  665. *pulTag = LC_REQ_TAG(&((PIO_RESOURCE_REQUIREMENTS_LIST)pList)->List[0]);
  666. }
  667. Clean0:
  668. ;
  669. } except(EXCEPTION_EXECUTE_HANDLER) {
  670. Status = CR_FAILURE;
  671. }
  672. if (hKey != NULL) {
  673. RegCloseKey(hKey);
  674. }
  675. if (pList != NULL) {
  676. free(pList);
  677. }
  678. return Status;
  679. } // PNP_GetFirstLogConf
  680. CONFIGRET
  681. PNP_GetNextLogConf(
  682. IN handle_t hBinding,
  683. IN LPWSTR pDeviceID,
  684. IN ULONG ulType,
  685. IN ULONG ulCurrentTag,
  686. OUT PULONG pulNextTag,
  687. IN ULONG ulFlags
  688. )
  689. /*++
  690. Routine Description:
  691. This the server-side of an RPC remote call. This routine finds the
  692. next log conf of this type for this devnode.
  693. Arguments:
  694. hBinding Not used.
  695. pDeviceID Null-terminated device instance id string.
  696. ulType Specifies what type of log conf to retrieve.
  697. ulCurrent Specifies current log conf in the enumeration.
  698. pulNext Returns next log conf of this type for this device id.
  699. ulFlags Not used.
  700. Return Value:
  701. If the specified device instance is valid, it returns CR_SUCCESS,
  702. otherwise it returns CR_ error code.
  703. --*/
  704. {
  705. CONFIGRET Status = CR_SUCCESS;
  706. HKEY hKey = NULL;
  707. WCHAR szValueName[64];
  708. ULONG RegDataType = 0, ulListSize = 0, ulIndex = 0;
  709. LPBYTE pList = NULL, pLogConf = NULL;
  710. UNREFERENCED_PARAMETER(hBinding);
  711. UNREFERENCED_PARAMETER(ulFlags);
  712. try {
  713. //
  714. // Initialize output parameters
  715. //
  716. *pulNextTag = MAX_LOGCONF_TAG;
  717. //
  718. // open a key to the device's LogConf subkey. If the device id is not
  719. // in the registry, the devnode doesn't exist and therefore neither
  720. // does the log conf
  721. //
  722. Status = OpenLogConfKey(pDeviceID, &hKey);
  723. if (Status != CR_SUCCESS) {
  724. Status = CR_INVALID_LOG_CONF;
  725. goto Clean0;
  726. }
  727. //
  728. // Retrieve log conf data from the registry
  729. //
  730. Status = GetLogConfData(hKey, ulType,
  731. &RegDataType, szValueName,
  732. &pList, &ulListSize);
  733. if (Status != CR_SUCCESS) {
  734. Status = CR_NO_MORE_LOG_CONF;
  735. goto Clean0;
  736. }
  737. //
  738. // Seek to the log conf that matches the "current" tag
  739. //
  740. if (!FindLogConf(pList, &pLogConf, RegDataType, ulCurrentTag, &ulIndex)) {
  741. Status = CR_INVALID_LOG_CONF;
  742. goto Clean0;
  743. }
  744. //
  745. // Specified log conf type contains Resource Data only
  746. //
  747. if (RegDataType == REG_RESOURCE_LIST) {
  748. PCM_RESOURCE_LIST pResList = (PCM_RESOURCE_LIST)pList;
  749. PCM_FULL_RESOURCE_DESCRIPTOR pRes = (PCM_FULL_RESOURCE_DESCRIPTOR)pLogConf;
  750. //
  751. // Is the "current" log conf the last log conf?
  752. //
  753. if (ulIndex == pResList->Count - 1) {
  754. Status = CR_NO_MORE_LOG_CONF;
  755. goto Clean0;
  756. }
  757. //
  758. // Skip to the "next" log conf and return the tag for that log conf
  759. //
  760. pRes = AdvanceResourcePtr(pRes); // next lc
  761. *pulNextTag = LC_RES_TAG(pRes);
  762. }
  763. //
  764. // Specified log conf type contains requirements data only
  765. //
  766. else if (RegDataType == REG_RESOURCE_REQUIREMENTS_LIST) {
  767. PIO_RESOURCE_REQUIREMENTS_LIST pReqList = (PIO_RESOURCE_REQUIREMENTS_LIST)pList;
  768. PIO_RESOURCE_LIST pReq = (PIO_RESOURCE_LIST)pLogConf;
  769. //
  770. // Is the "current" log conf the last log conf?
  771. //
  772. if (ulIndex == pReqList->AlternativeLists - 1) {
  773. Status = CR_NO_MORE_LOG_CONF;
  774. goto Clean0;
  775. }
  776. //
  777. // Skip to the "next" log conf and return the tag for that log conf
  778. //
  779. pReq = AdvanceRequirementsPtr(pReq); // next lc
  780. *pulNextTag = LC_REQ_TAG(pReq);
  781. }
  782. Clean0:
  783. ;
  784. } except(EXCEPTION_EXECUTE_HANDLER) {
  785. Status = CR_FAILURE;
  786. }
  787. if (hKey != NULL) {
  788. RegCloseKey(hKey);
  789. }
  790. if (pList != NULL) {
  791. free(pList);
  792. }
  793. return Status;
  794. } // PNP_GetNextLogConf
  795. //------------------------------------------------------------------------
  796. // Private Utility Routines
  797. //------------------------------------------------------------------------
  798. CONFIGRET
  799. GetLogConfData(
  800. IN HKEY hKey,
  801. IN ULONG ulLogConfType,
  802. OUT PULONG pulRegDataType,
  803. OUT LPWSTR pszValueName,
  804. OUT LPBYTE *ppBuffer,
  805. OUT PULONG pulBufferSize
  806. )
  807. {
  808. switch (ulLogConfType) {
  809. //
  810. // BOOT, ALLOC, FORCED only have a Config value
  811. //
  812. case BOOT_LOG_CONF:
  813. lstrcpy(pszValueName, pszRegValueBootConfig);
  814. *pulRegDataType = REG_RESOURCE_LIST;
  815. break;
  816. case ALLOC_LOG_CONF:
  817. lstrcpy(pszValueName, pszRegValueAllocConfig);
  818. *pulRegDataType = REG_RESOURCE_LIST;
  819. break;
  820. case FORCED_LOG_CONF:
  821. lstrcpy(pszValueName, pszRegValueForcedConfig);
  822. *pulRegDataType = REG_RESOURCE_LIST;
  823. break;
  824. //
  825. // FILTERED, BASIC, OVERRIDE only have a Vector value
  826. //
  827. case FILTERED_LOG_CONF:
  828. lstrcpy(pszValueName, pszRegValueFilteredVector);
  829. *pulRegDataType = REG_RESOURCE_REQUIREMENTS_LIST;
  830. break;
  831. case BASIC_LOG_CONF:
  832. lstrcpy(pszValueName, pszRegValueBasicVector);
  833. *pulRegDataType = REG_RESOURCE_REQUIREMENTS_LIST;
  834. break;
  835. case OVERRIDE_LOG_CONF:
  836. lstrcpy(pszValueName, pszRegValueOverrideVector);
  837. *pulRegDataType = REG_RESOURCE_REQUIREMENTS_LIST;
  838. break;
  839. default:
  840. return CR_FAILURE;
  841. }
  842. //
  843. // retrieve the Log Conf registry data
  844. //
  845. if (RegQueryValueEx(hKey, pszValueName, NULL, NULL, NULL,
  846. pulBufferSize) != ERROR_SUCCESS) {
  847. return CR_INVALID_LOG_CONF;
  848. }
  849. *ppBuffer = malloc(*pulBufferSize);
  850. if (*ppBuffer == NULL) {
  851. return CR_OUT_OF_MEMORY;
  852. }
  853. if (RegQueryValueEx(hKey, pszValueName, NULL, NULL,
  854. (LPBYTE)*ppBuffer, pulBufferSize) != ERROR_SUCCESS) {
  855. return CR_INVALID_LOG_CONF;
  856. }
  857. return CR_SUCCESS;
  858. } // GetLogConfData
  859. PCM_FULL_RESOURCE_DESCRIPTOR
  860. AdvanceResourcePtr(
  861. IN PCM_FULL_RESOURCE_DESCRIPTOR pRes
  862. )
  863. {
  864. // Given a resource pointer, this routine advances to the beginning
  865. // of the next resource and returns a pointer to it. I assume that
  866. // at least one more resource exists in the resource list.
  867. LPBYTE p = NULL;
  868. ULONG LastResIndex = 0;
  869. if (pRes == NULL) {
  870. return NULL;
  871. }
  872. //
  873. // account for the size of the CM_FULL_RESOURCE_DESCRIPTOR
  874. // (includes the header plus a single imbedded
  875. // CM_PARTIAL_RESOURCE_DESCRIPTOR struct)
  876. //
  877. p = (LPBYTE)pRes + sizeof(CM_FULL_RESOURCE_DESCRIPTOR);
  878. //
  879. // account for any resource descriptors in addition to the single
  880. // imbedded one I've already accounted for (if there aren't any,
  881. // then I'll end up subtracting off the extra imbedded descriptor
  882. // from the previous step)
  883. //
  884. p += (pRes->PartialResourceList.Count - 1) *
  885. sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
  886. //
  887. // finally, account for any extra device specific data at the end of
  888. // the last partial resource descriptor (if any)
  889. //
  890. if (pRes->PartialResourceList.Count > 0) {
  891. LastResIndex = pRes->PartialResourceList.Count - 1;
  892. if (pRes->PartialResourceList.PartialDescriptors[LastResIndex].Type ==
  893. CmResourceTypeDeviceSpecific) {
  894. p += pRes->PartialResourceList.PartialDescriptors[LastResIndex].
  895. u.DeviceSpecificData.DataSize;
  896. }
  897. }
  898. return (PCM_FULL_RESOURCE_DESCRIPTOR)p;
  899. } // AdvanceResourcePtr
  900. PIO_RESOURCE_LIST
  901. AdvanceRequirementsPtr(
  902. IN PIO_RESOURCE_LIST pReq
  903. )
  904. {
  905. LPBYTE p = NULL;
  906. if (pReq == NULL) {
  907. return NULL;
  908. }
  909. //
  910. // account for the size of the IO_RESOURCE_LIST (includes header plus
  911. // a single imbedded IO_RESOURCE_DESCRIPTOR struct)
  912. //
  913. p = (LPBYTE)pReq + sizeof(IO_RESOURCE_LIST);
  914. //
  915. // account for any requirements descriptors in addition to the single
  916. // imbedded one I've already accounted for (if there aren't any,
  917. // then I'll end up subtracting off the extra imbedded descriptor
  918. // from the previous step)
  919. //
  920. p += (pReq->Count - 1) * sizeof(IO_RESOURCE_DESCRIPTOR);
  921. return (PIO_RESOURCE_LIST)p;
  922. } // AdvanceRequirementsPtr
  923. BOOL
  924. FindLogConf(
  925. IN LPBYTE pList,
  926. OUT LPBYTE *ppLogConf,
  927. IN ULONG RegDataType,
  928. IN ULONG ulTag,
  929. OUT PULONG pulIndex
  930. )
  931. {
  932. ULONG Index = 0, i = 0;
  933. //
  934. // Input data is a Resource List
  935. //
  936. if (RegDataType == REG_RESOURCE_LIST) {
  937. PCM_RESOURCE_LIST pResList = (PCM_RESOURCE_LIST)pList;
  938. PCM_FULL_RESOURCE_DESCRIPTOR pRes = NULL;
  939. //
  940. // seek to the log conf that matches the log conf tag
  941. // Req first.
  942. //
  943. pRes = (PCM_FULL_RESOURCE_DESCRIPTOR)(&pResList->List[0]); // first lc
  944. while ((Index < pResList->Count) &&
  945. (ulTag != LC_RES_TAG(pRes))) {
  946. Index++;
  947. if (Index < pResList->Count) {
  948. pRes = AdvanceResourcePtr(pRes); // next lc
  949. }
  950. }
  951. if (Index >= pResList->Count) {
  952. *ppLogConf = NULL;
  953. return FALSE; // tag not found
  954. }
  955. //
  956. // return index if specified
  957. //
  958. if (pulIndex) {
  959. *pulIndex = Index;
  960. }
  961. *ppLogConf = (LPBYTE)pRes;
  962. }
  963. //
  964. // Input data is a Requirments List
  965. //
  966. else if (RegDataType == REG_RESOURCE_REQUIREMENTS_LIST) {
  967. PIO_RESOURCE_REQUIREMENTS_LIST pReqList = (PIO_RESOURCE_REQUIREMENTS_LIST)pList;
  968. PIO_RESOURCE_LIST pReq = NULL;
  969. //
  970. // seek to the log conf that matches the log conf tag
  971. // Req first.
  972. //
  973. pReq = (PIO_RESOURCE_LIST)(&pReqList->List[0]); // first lc
  974. while ((Index < pReqList->AlternativeLists) &&
  975. (ulTag != LC_REQ_TAG(pReq))) {
  976. Index++;
  977. if (Index < pReqList->AlternativeLists) {
  978. pReq = AdvanceRequirementsPtr(pReq); // next lc
  979. }
  980. }
  981. if (Index >= pReqList->AlternativeLists) {
  982. *ppLogConf = NULL;
  983. return FALSE; // tag not found
  984. }
  985. //
  986. // return index if specified
  987. //
  988. if (pulIndex) {
  989. *pulIndex = Index;
  990. }
  991. *ppLogConf = (LPBYTE)pReq;
  992. } else {
  993. return FALSE;
  994. }
  995. return TRUE;
  996. } // FindLogConf
  997. BOOL
  998. InitLogConfRes(
  999. IN OUT PCM_FULL_RESOURCE_DESCRIPTOR pRes,
  1000. IN ULONG ulPriority,
  1001. IN ULONG ulTag
  1002. )
  1003. {
  1004. pRes->InterfaceType = Isa; // BUGBUG
  1005. pRes->BusNumber = 0; // BUGBUG
  1006. pRes->PartialResourceList.Version = 1;
  1007. pRes->PartialResourceList.Revision =
  1008. (USHORT)MAKEWORD(ulTag, CmToNtPriority(ulPriority));
  1009. pRes->PartialResourceList.Count = 0;
  1010. return TRUE;
  1011. } // InitLogConfRes
  1012. BOOL
  1013. InitLogConfReq(
  1014. IN OUT PIO_RESOURCE_LIST pReq,
  1015. IN ULONG ulPriority,
  1016. IN ULONG ulTag
  1017. )
  1018. {
  1019. pReq->Version = 1;
  1020. pReq->Revision = (USHORT)MAKEWORD(ulTag, CmToNtPriority(ulPriority));
  1021. pReq->Count = 0;
  1022. return TRUE;
  1023. } // InitLogConfReq
  1024. BOOL
  1025. InitReqList(
  1026. IN OUT PIO_RESOURCE_REQUIREMENTS_LIST pReqList,
  1027. IN ULONG ulReqSize
  1028. )
  1029. {
  1030. pReqList->ListSize = ulReqSize;
  1031. pReqList->InterfaceType = Isa; // BUGBUG
  1032. pReqList->BusNumber = 0; // BUGBUG
  1033. pReqList->SlotNumber = 0; // BUGBUG
  1034. pReqList->Reserved[0] = 0;
  1035. pReqList->Reserved[1] = 0;
  1036. pReqList->Reserved[2] = 0;
  1037. pReqList->AlternativeLists = 0;
  1038. return TRUE;
  1039. } // InitReqList
  1040. ULONG
  1041. GetFreeLogConfTag(
  1042. IN ULONG RegDataType,
  1043. IN LPBYTE pList
  1044. )
  1045. {
  1046. ULONG ulTag = 0, i = 0;
  1047. //
  1048. // Input data is a Resource List
  1049. //
  1050. if (RegDataType == REG_RESOURCE_LIST) {
  1051. PCM_RESOURCE_LIST pResList = (PCM_RESOURCE_LIST)pList;
  1052. PCM_FULL_RESOURCE_DESCRIPTOR pRes = NULL;
  1053. //
  1054. // find an unused log conf tag value
  1055. //
  1056. while (ulTag < MAX_LOGCONF_TAG) {
  1057. for (i = 0; i < pResList->Count; i++) { // check each rd
  1058. if (i == 0) {
  1059. pRes = (PCM_FULL_RESOURCE_DESCRIPTOR)(&pResList->List[0]);
  1060. } else {
  1061. pRes = AdvanceResourcePtr(pRes); // next lc
  1062. }
  1063. if (ulTag == LC_RES_TAG(pRes)) {
  1064. goto NextResTag; // match, try next tag
  1065. }
  1066. }
  1067. break; // made it thru whole list without a hit, use this tag
  1068. NextResTag:
  1069. ulTag++;
  1070. }
  1071. }
  1072. //
  1073. // Input data is a Requirments List
  1074. //
  1075. else if (RegDataType == REG_RESOURCE_REQUIREMENTS_LIST) {
  1076. PIO_RESOURCE_REQUIREMENTS_LIST pReqList = (PIO_RESOURCE_REQUIREMENTS_LIST)pList;
  1077. PIO_RESOURCE_LIST pReq = NULL;
  1078. //
  1079. // find an unused log conf tag value
  1080. //
  1081. while (ulTag < MAX_LOGCONF_TAG) {
  1082. for (i = 0; i < pReqList->AlternativeLists; i++) { // check each rd
  1083. if (i == 0) {
  1084. pReq = (PIO_RESOURCE_LIST)(&pReqList->List[0]); // first lc
  1085. } else {
  1086. pReq = AdvanceRequirementsPtr(pReq); // next lc
  1087. }
  1088. if (ulTag == LC_REQ_TAG(pReq)) {
  1089. goto NextReqTag; // match, try next tag
  1090. }
  1091. }
  1092. break; // made it thru whole list without a hit, use this tag
  1093. NextReqTag:
  1094. ulTag++;
  1095. }
  1096. } else {
  1097. ulTag = MAX_LOGCONF_TAG;
  1098. }
  1099. return ulTag;
  1100. } // GetFreeLogConfTag
  1101. ULONG
  1102. LC_RES_TAG(
  1103. IN PCM_FULL_RESOURCE_DESCRIPTOR pRes
  1104. )
  1105. {
  1106. //
  1107. // Abstract the notion of where the tag value is stored
  1108. //
  1109. if (pRes != NULL) {
  1110. return (ULONG)LOBYTE(pRes->PartialResourceList.Revision);
  1111. } else {
  1112. return MAX_LOGCONF_TAG;
  1113. }
  1114. } // LC_RES_TAG
  1115. ULONG
  1116. LC_REQ_TAG(
  1117. IN PIO_RESOURCE_LIST pReq
  1118. )
  1119. {
  1120. //
  1121. // Abstract the notion of where the tag value is stored
  1122. //
  1123. if (pReq != NULL) {
  1124. return (ULONG)LOBYTE(pReq->Revision);
  1125. } else {
  1126. return MAX_LOGCONF_TAG;
  1127. }
  1128. } // LC_REQ_TAG
  1129. ULONG
  1130. LC_RES_PRIORITY(
  1131. IN PCM_FULL_RESOURCE_DESCRIPTOR pRes
  1132. )
  1133. {
  1134. //
  1135. // Abstract the notion of where the priority value is stored
  1136. //
  1137. if (pRes != NULL) {
  1138. return NtToCmPriority(HIBYTE(pRes->PartialResourceList.Revision));
  1139. } else {
  1140. return 0;
  1141. }
  1142. } // LC_RES_PRIORITY
  1143. ULONG
  1144. LC_REQ_PRIORITY(
  1145. IN PIO_RESOURCE_LIST pReq
  1146. )
  1147. {
  1148. //
  1149. // Abstract the notion of where the priority value is stored
  1150. //
  1151. if (pReq != NULL) {
  1152. return NtToCmPriority(HIBYTE(pReq->Revision));
  1153. } else {
  1154. return 0;
  1155. }
  1156. } // LC_REQ_PRIORITY
  1157. BYTE
  1158. CmToNtPriority(
  1159. IN ULONG CmPriority
  1160. )
  1161. {
  1162. switch (CmPriority) {
  1163. case LCPRI_FORCECONFIG:
  1164. return NT_FORCECONFIG;
  1165. case LCPRI_BOOTCONFIG:
  1166. return NT_BOOTCONFIG;
  1167. case LCPRI_DESIRED:
  1168. return NT_DESIRED;
  1169. case LCPRI_NORMAL:
  1170. return NT_NORMAL;
  1171. case LCPRI_LASTBESTCONFIG:
  1172. return NT_LASTBESTCONFIG;
  1173. case LCPRI_SUBOPTIMAL:
  1174. return NT_SUBOPTIMAL;
  1175. case LCPRI_LASTSOFTCONFIG:
  1176. return NT_LASTSOFTCONFIG;
  1177. case LCPRI_RESTART:
  1178. return NT_RESTART;
  1179. case LCPRI_REBOOT:
  1180. return NT_REBOOT;
  1181. case LCPRI_POWEROFF:
  1182. return NT_POWEROFF;
  1183. case LCPRI_HARDRECONFIG:
  1184. return NT_HARDRECONFIG;
  1185. case LCPRI_HARDWIRED:
  1186. return NT_HARDWIRED;
  1187. case LCPRI_IMPOSSIBLE:
  1188. return NT_IMPOSSIBLE;
  1189. case LCPRI_DISABLED:
  1190. return NT_DISABLED;
  1191. default:
  1192. return NT_NORMAL;
  1193. }
  1194. } // CmToNtPriority
  1195. ULONG
  1196. NtToCmPriority(
  1197. IN BYTE NtPriority
  1198. )
  1199. {
  1200. switch (NtPriority) {
  1201. case NT_FORCECONFIG:
  1202. return LCPRI_FORCECONFIG;
  1203. case NT_BOOTCONFIG:
  1204. return LCPRI_BOOTCONFIG;
  1205. case NT_DESIRED:
  1206. return LCPRI_DESIRED;
  1207. case NT_NORMAL:
  1208. return LCPRI_NORMAL;
  1209. case NT_LASTBESTCONFIG:
  1210. return LCPRI_LASTBESTCONFIG;
  1211. case NT_SUBOPTIMAL:
  1212. return LCPRI_SUBOPTIMAL;
  1213. case NT_LASTSOFTCONFIG:
  1214. return LCPRI_LASTSOFTCONFIG;
  1215. case NT_RESTART:
  1216. return LCPRI_RESTART;
  1217. case NT_REBOOT:
  1218. return LCPRI_REBOOT;
  1219. case NT_POWEROFF:
  1220. return LCPRI_POWEROFF;
  1221. case NT_HARDRECONFIG:
  1222. return LCPRI_HARDRECONFIG;
  1223. case NT_HARDWIRED:
  1224. return LCPRI_HARDWIRED;
  1225. case NT_IMPOSSIBLE:
  1226. return LCPRI_IMPOSSIBLE;
  1227. case NT_DISABLED:
  1228. return LCPRI_DISABLED;
  1229. default:
  1230. return LCPRI_NORMAL;
  1231. }
  1232. } // NtToCmPriority
  1233. BOOL
  1234. MigrateObsoleteDetectionInfo(
  1235. IN LPWSTR pszDeviceID,
  1236. IN HKEY hLogConfKey
  1237. )
  1238. {
  1239. LONG RegStatus = ERROR_SUCCESS;
  1240. WCHAR RegStr[MAX_PATH];
  1241. HKEY hKey = NULL;
  1242. ULONG ulSize = 0;
  1243. LPBYTE ptr = NULL;
  1244. PCM_RESOURCE_LIST pResList = NULL;
  1245. IO_RESOURCE_REQUIREMENTS_LIST ReqList;
  1246. PPrivate_Log_Conf pDetectData = NULL;
  1247. //
  1248. // First, delete any of the log conf pairs that aren't valid any more
  1249. //
  1250. RegDeleteValue(hLogConfKey, TEXT("BootConfigVector"));
  1251. RegDeleteValue(hLogConfKey, TEXT("AllocConfigVector"));
  1252. RegDeleteValue(hLogConfKey, TEXT("ForcedConfigVector"));
  1253. RegDeleteValue(hLogConfKey, TEXT("BasicConfig"));
  1254. RegDeleteValue(hLogConfKey, TEXT("FilteredConfig"));
  1255. RegDeleteValue(hLogConfKey, TEXT("OverrideConfig"));
  1256. //
  1257. // open the device instance key in the registry
  1258. //
  1259. wsprintf(RegStr, TEXT("%s\\%s"),
  1260. pszRegPathEnum,
  1261. pszDeviceID);
  1262. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, RegStr, 0,
  1263. KEY_READ | KEY_WRITE, &hKey) != ERROR_SUCCESS) {
  1264. goto Clean0; // nothing to migrate
  1265. }
  1266. //
  1267. // If there is already a boot log config value then we can't
  1268. // migrate any old detect info
  1269. //
  1270. RegStatus = RegQueryValueEx(hLogConfKey, pszRegValueBootConfig,
  1271. NULL, NULL, NULL, &ulSize);
  1272. if (RegStatus == ERROR_SUCCESS && ulSize > 0) {
  1273. goto Clean0; // can't migrate
  1274. }
  1275. //
  1276. // retrieve any old detect signature info
  1277. //
  1278. RegStatus = RegQueryValueEx(hKey, pszRegValueDetectSignature,
  1279. NULL, NULL, NULL, &ulSize);
  1280. if ((RegStatus != ERROR_SUCCESS) || (ulSize == 0)) {
  1281. goto Clean0; // nothing to migrate
  1282. }
  1283. pDetectData = (PPrivate_Log_Conf)malloc(ulSize);
  1284. if (pDetectData == NULL) {
  1285. goto Clean0; // insufficient memory
  1286. }
  1287. RegStatus = RegQueryValueEx(hKey, pszRegValueDetectSignature,
  1288. NULL, NULL, (LPBYTE)pDetectData, &ulSize);
  1289. if ((RegStatus != ERROR_SUCCESS) || (ulSize == 0)) {
  1290. goto Clean0; // nothing to migrate
  1291. }
  1292. //
  1293. // Create an empty boot log conf and add this class specific data
  1294. // to it
  1295. //
  1296. ulSize = pDetectData->LC_CS.CS_Header.CSD_SignatureLength +
  1297. pDetectData->LC_CS.CS_Header.CSD_LegacyDataSize +
  1298. sizeof(GUID);
  1299. pResList = malloc(sizeof(CM_RESOURCE_LIST) + ulSize);
  1300. if (pResList == NULL) {
  1301. goto Clean0; // insufficient memory
  1302. }
  1303. //
  1304. // initialize resource list
  1305. //
  1306. memset(pResList, 0, ulSize);
  1307. pResList->Count = 1;
  1308. pResList->List[0].InterfaceType = Isa; // BUGBUG
  1309. pResList->List[0].BusNumber = 0; // BUGBUG
  1310. pResList->List[0].PartialResourceList.Version = 1;
  1311. pResList->List[0].PartialResourceList.Revision =
  1312. (USHORT)pDetectData->LC_Priority;
  1313. pResList->List[0].PartialResourceList.Count = 1;
  1314. pResList->List[0].PartialResourceList.PartialDescriptors[0].Type =
  1315. CmResourceTypeDeviceSpecific;
  1316. pResList->List[0].PartialResourceList.PartialDescriptors[0].ShareDisposition =
  1317. CmResourceShareUndetermined;
  1318. pResList->List[0].PartialResourceList.PartialDescriptors[0].Flags =
  1319. (USHORT)pDetectData->LC_CS.CS_Header.CSD_Flags;
  1320. pResList->List[0].PartialResourceList.PartialDescriptors[0].
  1321. u.DeviceSpecificData.DataSize = ulSize;
  1322. pResList->List[0].PartialResourceList.PartialDescriptors[0].
  1323. u.DeviceSpecificData.Reserved1 =
  1324. pDetectData->LC_CS.CS_Header.CSD_LegacyDataSize;
  1325. pResList->List[0].PartialResourceList.PartialDescriptors[0].
  1326. u.DeviceSpecificData.Reserved2 =
  1327. pDetectData->LC_CS.CS_Header.CSD_SignatureLength;
  1328. //
  1329. // copy the legacy and class-specific signature data
  1330. //
  1331. ptr = (LPBYTE)(&pResList->List[0].PartialResourceList.PartialDescriptors[1]);
  1332. memcpy(ptr,
  1333. pDetectData->LC_CS.CS_Header.CSD_Signature +
  1334. pDetectData->LC_CS.CS_Header.CSD_LegacyDataOffset,
  1335. pDetectData->LC_CS.CS_Header.CSD_LegacyDataSize); // legacy data
  1336. ptr += pDetectData->LC_CS.CS_Header.CSD_LegacyDataSize;
  1337. memcpy(ptr,
  1338. pDetectData->LC_CS.CS_Header.CSD_Signature,
  1339. pDetectData->LC_CS.CS_Header.CSD_SignatureLength); // signature
  1340. ptr += pDetectData->LC_CS.CS_Header.CSD_SignatureLength;
  1341. memcpy(ptr,
  1342. &pDetectData->LC_CS.CS_Header.CSD_ClassGuid,
  1343. sizeof(GUID)); // GUID
  1344. //
  1345. // Write out the new/updated log conf list to the registry
  1346. //
  1347. RegSetValueEx(hLogConfKey, pszRegValueBootConfig, 0,
  1348. REG_RESOURCE_LIST, (LPBYTE)pResList,
  1349. ulSize + sizeof(CM_RESOURCE_LIST));
  1350. //
  1351. // Delete the old detect signature info
  1352. //
  1353. RegDeleteValue(hKey, pszRegValueDetectSignature);
  1354. Clean0:
  1355. if (hKey != NULL) {
  1356. RegCloseKey(hKey);
  1357. }
  1358. if (pDetectData != NULL) {
  1359. free(pDetectData);
  1360. }
  1361. if (pResList != NULL) {
  1362. free(pResList);
  1363. }
  1364. return TRUE;
  1365. } // MigrateObsoleteDetectionInfo