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.

1942 lines
52 KiB

  1. #include <iostream.h>
  2. #include <windows.h>
  3. #include <winbase.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <ctype.h>
  8. #include <tchar.h>
  9. #include <wchar.h>
  10. #include "CheckINF.h"
  11. #include "hcttools.h"
  12. #include "logutils.h"
  13. // The master INF is opened first
  14. // Then all the infs that are pointed to in the master are opened
  15. // Then all the infs that are pointed to in the subcomp infs are opened
  16. // All these things make a big open INF file
  17. // bunch of section names
  18. const PTSTR tszOptionalComponents = TEXT("Optional Components");
  19. const PTSTR tszComponents = TEXT("Components");
  20. const PTSTR tszLayoutFile = TEXT("LayoutFile");
  21. const PTSTR tszIconIndex = TEXT("IconIndex");
  22. /*++
  23. Routine description:
  24. Check the validity of a set of INF files
  25. used by OC Manager
  26. Argument:
  27. Standard main argument
  28. Return Value:
  29. None
  30. --*/
  31. VOID __cdecl main(INT argc,
  32. TCHAR *argv[])
  33. {
  34. TCHAR tszMsg[MaxStringSize];
  35. const PTSTR tszFunctionName = TEXT("main");
  36. if (argc < 2) {
  37. _stprintf(tszMsg,
  38. TEXT("Correct Usage: %s INFFileNameToCheck [/l] [/m]"),
  39. argv[0]);
  40. MessageBox(NULL,
  41. tszMsg,
  42. TEXT("Incorrect argument"),
  43. MB_ICONERROR | MB_OK);
  44. return;
  45. }
  46. g_bUseLog = FALSE;
  47. g_bUseMsgBox = FALSE;
  48. g_bUseConsole = TRUE;
  49. g_bMasterInf = TRUE;
  50. // Parse the argument and set global variables
  51. for (INT i = 1; i < argc; i++) {
  52. if (_tcscmp(argv[i], TEXT("/m")) == 0 ||
  53. _tcscmp(argv[i], TEXT("/M")) == 0 ||
  54. _tcscmp(argv[i], TEXT("-m")) == 0 ||
  55. _tcscmp(argv[i], TEXT("-M")) == 0 ) {
  56. g_bUseMsgBox = TRUE;
  57. }
  58. if (_tcscmp(argv[i], TEXT("/l")) == 0 ||
  59. _tcscmp(argv[i], TEXT("/L")) == 0 ||
  60. _tcscmp(argv[i], TEXT("-l")) == 0 ||
  61. _tcscmp(argv[i], TEXT("-L")) == 0 ) {
  62. g_bUseLog = TRUE;
  63. }
  64. }
  65. // we will see if there is any path seperator in the filename
  66. // if there is, we assume it is the full path
  67. // if there is not, we assume it is in the current directory
  68. PTSTR tszFilename = argv[1];
  69. while (*tszFilename) {
  70. if (*tszFilename == TEXT('\\')) {
  71. break;
  72. }
  73. tszFilename++;
  74. }
  75. // Let's initialize the log
  76. if (g_bUseLog) {
  77. InitLog(TEXT("checkinf.log"), TEXT("Inf File Check Log"), TRUE);
  78. }
  79. TCHAR tszDir[MaxStringSize];
  80. if (!*tszFilename) {
  81. // Get the currect path
  82. GetCurrentDirectory(MaxBufferSize, tszDir);
  83. if (tszDir[_tcslen(tszDir)-1] != TEXT('\\')) {
  84. tszDir[_tcslen(tszDir)+1] = 0;
  85. tszDir[_tcslen(tszDir)] = TEXT('\\');
  86. }
  87. CheckINF(tszDir, argv[1]);
  88. }
  89. else {
  90. CheckINF(NULL, argv[1]);
  91. }
  92. if (g_bUseLog) {
  93. ExitLog();
  94. }
  95. return;
  96. }
  97. /*++
  98. Routine description:
  99. Check the validity of an INF file
  100. Argument:
  101. TCHAR *tszDir : Where the Inf files are
  102. TCHAR *tszFilename : file name of the inf file to check
  103. Return value:
  104. FALSE means there is something wrong
  105. TRUE means everything going well
  106. --*/
  107. BOOL CheckINF(IN TCHAR *tszDir,
  108. IN TCHAR *tszFilename)
  109. {
  110. UINT uiError;
  111. HINF hinfHandle;
  112. TCHAR tszMsg[256];
  113. TCHAR tszSubINFName[256][MaxStringSize];
  114. UINT uiNumComponents;
  115. INFCONTEXT infContext;
  116. BOOL bSuccess;
  117. const PTSTR tszFunctionName = TEXT("CheckINF");
  118. // Open the INF Files
  119. if (tszDir && *tszDir) {
  120. _stprintf(tszMsg, TEXT("%s%s"), tszDir, tszFilename);
  121. hinfHandle = SetupOpenInfFile(tszMsg,
  122. NULL,
  123. INF_STYLE_WIN4,
  124. &uiError);
  125. }
  126. else {
  127. hinfHandle = SetupOpenInfFile(tszFilename,
  128. NULL,
  129. INF_STYLE_WIN4,
  130. &uiError);
  131. }
  132. if (hinfHandle == INVALID_HANDLE_VALUE) {
  133. // If the openning failed, try the system default path
  134. if (!tszDir) {
  135. hinfHandle = SetupOpenInfFile(tszFilename,
  136. NULL,
  137. INF_STYLE_WIN4,
  138. &uiError);
  139. if (hinfHandle != INVALID_HANDLE_VALUE) {
  140. LogError(TEXT("File openned in system path"),
  141. INFO,
  142. tszFunctionName);
  143. }
  144. }
  145. if (hinfHandle == INVALID_HANDLE_VALUE) {
  146. _stprintf(tszMsg,
  147. TEXT("Error opeing INF file %s"),
  148. tszFilename);
  149. MessageBox(NULL, tszMsg, tszFunctionName, MB_OK);
  150. return FALSE;
  151. }
  152. }
  153. _stprintf(tszMsg, TEXT("%s opened"), tszFilename);
  154. LogError(tszMsg, INFO, tszFunctionName);
  155. bSuccess = SetupFindFirstLine(hinfHandle,
  156. tszComponents,
  157. NULL,
  158. &infContext);
  159. if (!bSuccess) {
  160. // This is not a master inf file
  161. g_bMasterInf = FALSE;
  162. LogError(TEXT("[Components] section not found."),
  163. INFO,
  164. tszFunctionName);
  165. }
  166. else {
  167. // in the [Components] section, get all the INF file names
  168. // and using SetupOpenAppendFile to append to the current handle
  169. uiNumComponents = SetupGetLineCount(hinfHandle, tszComponents);
  170. if (uiNumComponents < 1) {
  171. LogError(TEXT("Too few components in the [Components] section"),
  172. SEV2,
  173. tszFunctionName);
  174. return TRUE;
  175. }
  176. for (UINT i = 0; i < uiNumComponents; i++) {
  177. UINT uiNumFieldCount;
  178. uiNumFieldCount = SetupGetFieldCount(&infContext);
  179. if (uiNumFieldCount < 3) {
  180. tszSubINFName[i][0] = 0;
  181. SetupFindNextLine(&infContext, &infContext);
  182. continue;
  183. }
  184. SetupGetStringField(&infContext,
  185. 3,
  186. tszSubINFName[i],
  187. MaxBufferSize,
  188. NULL);
  189. SetupFindNextLine(&infContext, &infContext);
  190. }
  191. // It is assumed that the master INF doesn't contain path
  192. for (UINT j = 0; j < uiNumComponents; j++) {
  193. if (tszSubINFName[j][0]) {
  194. _stprintf(tszMsg, TEXT("%s%s"), tszDir, tszSubINFName[j]);
  195. bSuccess = SetupOpenAppendInfFile(tszMsg, hinfHandle, NULL);
  196. if (!bSuccess) {
  197. _stprintf(tszMsg, TEXT("Error opening %s"), tszMsg);
  198. LogError(tszMsg, SEV2, tszFunctionName);
  199. }
  200. else {
  201. _stprintf(tszMsg, TEXT("%s opened"), tszMsg);
  202. LogError(tszMsg, INFO, tszFunctionName);
  203. }
  204. }
  205. }
  206. }
  207. // Now the file is opened
  208. ComponentList clList;
  209. FillList(hinfHandle, &clList, tszDir);
  210. CheckIconIndex(hinfHandle, &clList);
  211. CheckNeedRelationship(&clList);
  212. CheckExcludeRelationship(&clList);
  213. CheckParentRelationship(&clList);
  214. CheckCopyFiles(hinfHandle, &clList);
  215. CheckSuspicious(hinfHandle, &clList);
  216. CheckSameId(&clList);
  217. CheckDescription(hinfHandle, &clList);
  218. CheckModes(hinfHandle, &clList);
  219. SetupCloseInfFile(hinfHandle);
  220. if (g_bMasterInf) {
  221. CheckLayoutFile(tszSubINFName, uiNumComponents, tszDir);
  222. }
  223. else{
  224. _tcscpy(tszSubINFName[0], tszFilename);
  225. CheckLayoutFile(tszSubINFName, 1, tszDir);
  226. }
  227. return TRUE;
  228. }
  229. /*++
  230. Routine Description:
  231. This routine creates the component list
  232. and fill the relation list of each component on the list
  233. Argument:
  234. HINF hinfHandle : a handle to the Inf file
  235. Component *pclList : a pointer to the component list
  236. TCHAR *tszDir : current working directory
  237. Return Value:
  238. The return value is not used
  239. --*/
  240. BOOL FillList(IN OUT HINF hinfHandle,
  241. IN OUT ComponentList *pclList,
  242. IN TCHAR *tszDir)
  243. {
  244. INFCONTEXT infContext;
  245. BOOL bSuccess;
  246. UINT uiNumComponents;
  247. TCHAR tszMsg[MaxStringSize];
  248. const PTSTR tszFunctionName = TEXT("FillList");
  249. bSuccess = SetupFindFirstLine(hinfHandle,
  250. tszOptionalComponents,
  251. NULL,
  252. &infContext);
  253. if (!bSuccess) {
  254. LogError(TEXT("There is no [Optional Components] section"),
  255. SEV2,
  256. tszFunctionName);
  257. return FALSE;
  258. }
  259. // Get the number of components in this INF file
  260. uiNumComponents = SetupGetLineCount(hinfHandle, tszOptionalComponents);
  261. if (uiNumComponents <= 0) {
  262. LogError(TEXT("There is no optional component"),
  263. SEV2,
  264. tszFunctionName);
  265. return FALSE;
  266. }
  267. // Build a array of all the component names listed
  268. TCHAR Components[256][MaxStringSize];
  269. UINT count = 0;
  270. for (UINT l = 0; l < uiNumComponents; l++) {
  271. bSuccess = SetupGetStringField(&infContext,
  272. 0,
  273. Components[count],
  274. MaxBufferSize,
  275. NULL);
  276. if (bSuccess) {
  277. SetupFindNextLine(&infContext, &infContext);
  278. count++;
  279. }
  280. else {
  281. LogError(TEXT("Error getting component name"),
  282. SEV2,
  283. tszFunctionName);
  284. return TRUE;
  285. }
  286. }
  287. // For each component listed here
  288. // There should be a section with the same name
  289. // otherwise there is an error
  290. Component *pcNewComponent;
  291. for (UINT i = 0; i < uiNumComponents; i++) {
  292. bSuccess = SetupFindFirstLine(hinfHandle,
  293. Components[i],
  294. NULL,
  295. &infContext);
  296. if (!bSuccess) {
  297. _stprintf(tszMsg,
  298. TEXT("Can't find the section [%s]"),
  299. Components[i]);
  300. LogError(tszMsg, SEV2, tszFunctionName);
  301. return FALSE;
  302. }
  303. // add the component to the list
  304. pcNewComponent = pclList->AddComponent(Components[i]);
  305. // Figure out the parent id from the INF File
  306. pcNewComponent->GetParentIdFromINF(hinfHandle);
  307. }
  308. // Now go through the list and fill the prlChildrenList
  309. // of each component
  310. Component *pcComponent;
  311. pclList->ResetList();
  312. while (!pclList->Done()) {
  313. pcComponent = pclList->GetNext();
  314. pcComponent->BuildChildrenList(pclList);
  315. }
  316. // Now go through the INF for a second time
  317. // This time the need and exclude relationlist is filled
  318. TCHAR tszId[MaxStringSize];
  319. for (UINT k = 0; k < uiNumComponents; k++) {
  320. bSuccess = SetupFindFirstLine(hinfHandle,
  321. Components[k],
  322. NULL,
  323. &infContext);
  324. if (!bSuccess) {
  325. _stprintf(tszMsg,
  326. TEXT("Can't find the section [%s]"),
  327. Components[k]);
  328. LogError(tszMsg, SEV2, tszFunctionName);
  329. return TRUE;
  330. }
  331. // Get the needs= line
  332. bSuccess = SetupFindFirstLine(hinfHandle,
  333. Components[k],
  334. TEXT("Needs"),
  335. &infContext);
  336. if (bSuccess) {
  337. UINT uiNumNeeds = SetupGetFieldCount(&infContext);
  338. if (uiNumNeeds == 0) {
  339. _stprintf(tszMsg,
  340. TEXT("Too few field for the Needs key in [%s]"),
  341. Components[k]);
  342. LogError(tszMsg, SEV2, tszFunctionName);
  343. }
  344. for (UINT j = 1; j <= uiNumNeeds; j++) {
  345. SetupGetStringField(&infContext,
  346. j,
  347. tszId,
  348. MaxBufferSize,
  349. NULL);
  350. Component *pcTemp = pclList->LookupComponent(Components[k]);
  351. if (!pcTemp) {
  352. // Can't find Components[k]
  353. // This can only happen if there is something wrong
  354. // in the code
  355. LogError(TEXT("Something wrong in the code"),
  356. SEV2,
  357. tszFunctionName);
  358. return TRUE;
  359. }
  360. else {
  361. pcTemp->GetNeedList()->AddRelation(tszId);
  362. }
  363. }
  364. }
  365. // Get the exclude
  366. bSuccess = SetupFindFirstLine(hinfHandle,
  367. Components[k],
  368. TEXT("Exclude"),
  369. &infContext);
  370. if (bSuccess) {
  371. UINT uiNumExcludes = SetupGetFieldCount(&infContext);
  372. if (uiNumExcludes == 0) {
  373. _stprintf(tszMsg,
  374. TEXT("Too few field for Exclude= in section [%s]"),
  375. Components[k]);
  376. LogError(tszMsg, SEV2, tszFunctionName);
  377. }
  378. for (UINT l = 1; l <= uiNumExcludes; l++) {
  379. SetupGetStringField(&infContext,
  380. l,
  381. tszId,
  382. MaxBufferSize,
  383. NULL);
  384. Component *pcTmp = NULL;
  385. pcTmp = pclList->LookupComponent(tszId);
  386. if (!pcTmp) {
  387. _stprintf(tszMsg,
  388. TEXT("Unknown component %s in section [%s]"),
  389. tszId, Components[k]);
  390. LogError(tszMsg, SEV2, tszFunctionName);
  391. }
  392. else {
  393. pcTmp->GetExcludeList()->AddRelation(Components[k]);
  394. pcTmp = pclList->LookupComponent(Components[k]);
  395. pcTmp->GetExcludeList()->AddRelation(tszId);
  396. }
  397. }
  398. }
  399. }
  400. return TRUE;
  401. }
  402. /*++
  403. Routine Description:
  404. Routine to check the IconIndex key of each component
  405. Argument:
  406. HINF hinfHandle : A handle to the Inf file
  407. ComponentList *pclList : A pointer to the component list
  408. Return Value:
  409. The return value is not used
  410. --*/
  411. BOOL CheckIconIndex(IN HINF hinfHandle,
  412. IN ComponentList *pclList)
  413. {
  414. // Go through each of the component in the list
  415. PTSTR tszId;
  416. TCHAR tszMsg[MaxStringSize];
  417. BOOL bSuccess;
  418. INFCONTEXT infContext;
  419. INT nIconIndex;
  420. TCHAR tszTemp[MaxStringSize];
  421. const PTSTR tszFunctionName = TEXT("CheckIconIndex");
  422. pclList->ResetList();
  423. while (!pclList->Done()) {
  424. tszId = pclList->GetNext()->GetComponentId();
  425. bSuccess = SetupFindFirstLine(hinfHandle,
  426. tszId,
  427. tszIconIndex,
  428. &infContext);
  429. if (!bSuccess) {
  430. _stprintf(tszMsg,
  431. TEXT("IconIndex not present for component %s"),
  432. tszId);
  433. LogError(tszMsg, SEV2, tszFunctionName);
  434. continue;
  435. }
  436. UINT uiNumField = SetupGetFieldCount(&infContext);
  437. if (uiNumField < 1) {
  438. _stprintf(tszMsg,
  439. TEXT("%s has less than 2 fields for component %s"),
  440. tszIconIndex,
  441. tszId);
  442. LogError(tszMsg, SEV2, tszFunctionName);
  443. }
  444. else if (uiNumField > 1) {
  445. _stprintf(tszMsg,
  446. TEXT("%s has more than 2 fields for component %s"),
  447. tszIconIndex,
  448. tszId);
  449. LogError(tszMsg, SEV2, tszFunctionName);
  450. }
  451. else {
  452. bSuccess = SetupGetIntField(&infContext, 1, &nIconIndex);
  453. if (bSuccess) {
  454. // Check the range of the iconindex returned
  455. if (nIconIndex < 0 || nIconIndex > 66) {
  456. _stprintf(tszMsg,
  457. TEXT("Invalid icon index %d for component %s"),
  458. nIconIndex,
  459. tszId);
  460. LogError(tszMsg, SEV2, tszFunctionName);
  461. }
  462. else if (nIconIndex == 12 ||
  463. nIconIndex == 13 ||
  464. nIconIndex == 25) {
  465. _stprintf(tszMsg,
  466. TEXT("Component %s is using icon index %d"),
  467. tszId,
  468. nIconIndex);
  469. LogError(tszMsg, SEV2, tszFunctionName);
  470. }
  471. }
  472. else {
  473. bSuccess = SetupGetStringField(&infContext,
  474. 1,
  475. tszTemp,
  476. MaxBufferSize,
  477. NULL);
  478. if (!bSuccess) {
  479. _stprintf(tszMsg,
  480. TEXT("Error reading the value of %s in [%s]"),
  481. tszIconIndex, tszId);
  482. LogError(tszMsg, SEV2, tszFunctionName);
  483. }
  484. else {
  485. if (_tcscmp(tszTemp, TEXT("*")) != 0 ) {
  486. _stprintf(tszMsg,
  487. TEXT("Invalid value of %s in [%s]"),
  488. tszIconIndex, tszId);
  489. LogError(tszMsg, SEV2, tszFunctionName);
  490. }
  491. }
  492. }
  493. }
  494. }
  495. return TRUE;
  496. }
  497. /*++
  498. Routine Description:
  499. Routine that checks the need relationship amond component
  500. Argument:
  501. ComponentList *pclList : A pointer to the list of component
  502. Return Value:
  503. The return value is not used
  504. --*/
  505. BOOL CheckNeedRelationship(IN ComponentList *pclList)
  506. {
  507. Component *pcComponent;
  508. TCHAR tszMsg[MaxStringSize];
  509. BOOL bNonExist = FALSE;
  510. const PTSTR tszFunctionName = TEXT("CheckNeedRelationship");
  511. // First thing to check
  512. // There should not be a component that needs
  513. // a categorical component
  514. pclList->ResetList();
  515. while (!pclList->Done()) {
  516. pcComponent = pclList->GetNext();
  517. if (pcComponent->IsParentOfOthers() &&
  518. pcComponent->IsNeededByOthers(pclList)) {
  519. _stprintf(tszMsg,
  520. TEXT("%s has subcomponent and is needed by others"),
  521. pcComponent->GetComponentId());
  522. LogError(tszMsg, SEV2, tszFunctionName);
  523. }
  524. }
  525. // Second thing to check
  526. // There should not be a categorical component
  527. // that needs another component
  528. pclList->ResetList();
  529. while (!pclList->Done()) {
  530. pcComponent = pclList->GetNext();
  531. if (pcComponent->IsParentOfOthers() &&
  532. pcComponent->NeedOthers() != NULL) {
  533. _stprintf(tszMsg,
  534. TEXT("%s has subcomponent, and needs another component"),
  535. pcComponent->GetComponentId());
  536. LogError(tszMsg, SEV2, tszFunctionName);
  537. }
  538. }
  539. // Third thing to check
  540. // There should not be Need and Exclude at the same time
  541. pclList->ResetList();
  542. while (!pclList->Done()) {
  543. pcComponent = pclList->GetNext();
  544. if (pcComponent->NeedAndExcludeAtSameTime(pclList)) {
  545. _stprintf(tszMsg,
  546. TEXT("%s is needed and excluded by the same component"),
  547. pcComponent->GetComponentId());
  548. LogError(tszMsg, SEV2, tszFunctionName);
  549. }
  550. }
  551. // Fouth thing to check
  552. // Every component should need an existent component
  553. // if the argument is a master inf file
  554. Relation *prNeed;
  555. if (g_bMasterInf) {
  556. pclList->ResetList();
  557. while (!pclList->Done()) {
  558. pcComponent = pclList->GetNext();
  559. pcComponent->GetNeedList()->ResetList();
  560. while (!pcComponent->GetNeedList()->Done()) {
  561. prNeed = pcComponent->GetNeedList()->GetNext();
  562. if (!pclList->LookupComponent(prNeed->GetComponentId())) {
  563. _stprintf(tszMsg,
  564. TEXT("%s needs %s, which is not in the list"),
  565. pcComponent->GetComponentId(),
  566. prNeed->GetComponentId());
  567. LogError(tszMsg, SEV2, tszFunctionName);
  568. bNonExist = TRUE;
  569. }
  570. }
  571. }
  572. }
  573. // Fifth thing to check
  574. // There should not be cycles
  575. if (g_bMasterInf && !bNonExist) {
  576. pclList->ResetList();
  577. while (!pclList->Done()) {
  578. pcComponent = pclList->GetNext();
  579. // Recursive calls to find the cycle
  580. CheckNeedCycles(pcComponent, pclList);
  581. }
  582. }
  583. return TRUE;
  584. }
  585. /*++
  586. Routine Description:
  587. Routine that checks the exclude relation among components
  588. Argument:
  589. ComponentList *pclList : A pointer to the component list
  590. Return Value:
  591. The return value is not used
  592. --*/
  593. BOOL CheckExcludeRelationship(IN ComponentList *pclList)
  594. {
  595. TCHAR tszMsg[MaxStringSize];
  596. Component *pcComponent;
  597. const PTSTR tszFunctionName = TEXT("CheckExcludeRelationship");
  598. // Can't exclude a categorical component
  599. // a categorical component can't exclude another component
  600. pclList->ResetList();
  601. while (!pclList->Done()) {
  602. pcComponent = pclList->GetNext();
  603. if (pcComponent->IsParentOfOthers() &&
  604. pcComponent->IsExcludedByOthers(pclList)) {
  605. _stprintf(tszMsg,
  606. TEXT("%s has subcomponent and is excluded by other componennts"),
  607. pcComponent->GetComponentId());
  608. LogError(tszMsg, SEV2, tszFunctionName);
  609. }
  610. if (pcComponent->IsParentOfOthers() &&
  611. pcComponent->ExcludeOthers() != NULL) {
  612. _stprintf(tszMsg,
  613. TEXT("%s has subcomponent and excludes other components"),
  614. pcComponent->GetComponentId());
  615. LogError(tszMsg, SEV2, tszFunctionName);
  616. }
  617. }
  618. // Component should exclude an existent component
  619. Relation *prExclude;
  620. if (g_bMasterInf) {
  621. pclList->ResetList();
  622. while (!pclList->Done()) {
  623. pcComponent = pclList->GetNext();
  624. pcComponent->GetExcludeList()->ResetList();
  625. while (!pcComponent->GetExcludeList()->Done()) {
  626. prExclude = pcComponent->GetExcludeList()->GetNext();
  627. if (!pclList->LookupComponent(prExclude->GetComponentId())) {
  628. _stprintf(tszMsg,
  629. TEXT("%s excludes %s, which is not in the list"),
  630. pcComponent->GetComponentId(),
  631. prExclude->GetComponentId());
  632. LogError(tszMsg, SEV2, tszFunctionName);
  633. }
  634. }
  635. }
  636. }
  637. return TRUE;
  638. }
  639. /*++
  640. Routine Description:
  641. Routine that checks the parent relationship among components
  642. Argument:
  643. ComponentList *pclList : A pointer to the component list
  644. Return Value:
  645. The return value is not used
  646. --*/
  647. BOOL CheckParentRelationship(IN ComponentList *pclList)
  648. {
  649. TCHAR tszMsg[MaxStringSize];
  650. Component *pcComponent;
  651. BOOL bNonExist = FALSE;
  652. const PTSTR tszFunctionName = TEXT("CheckParentRelationship");
  653. // The child should always be valid
  654. // otherwise there is something seriously wrong in the code
  655. // I will add this checking code in anyway
  656. Relation *prChild;
  657. if (g_bMasterInf) {
  658. pclList->ResetList();
  659. while (!pclList->Done()) {
  660. pcComponent = pclList->GetNext();
  661. pcComponent->GetChildrenList()->ResetList();
  662. while (!pcComponent->GetChildrenList()->Done()) {
  663. prChild = pcComponent->GetChildrenList()->GetNext();
  664. if (!pclList->LookupComponent(prChild->GetComponentId())) {
  665. _stprintf(tszMsg,
  666. TEXT("%s is parent of %s, which is not in the list"),
  667. pcComponent->GetComponentId(),
  668. prChild->GetComponentId());
  669. LogError(tszMsg, SEV2, tszFunctionName);
  670. bNonExist = TRUE;
  671. }
  672. }
  673. }
  674. }
  675. // There should not be any cycles
  676. if (!bNonExist && g_bMasterInf) {
  677. pclList->ResetList();
  678. while (!pclList->Done()) {
  679. pcComponent = pclList->GetNext();
  680. CheckParentCycles(pcComponent, pclList);
  681. }
  682. }
  683. return TRUE;
  684. }
  685. /*++
  686. Routine Description:
  687. Routine that makes sure categorical component doesn't have a
  688. CopyFiles key
  689. Argument:
  690. HINF hinfHandle : A handle to the open Inf file
  691. ComponentList *pclList : A pointer to the component list
  692. Return Value:
  693. The return value is not used
  694. --*/
  695. BOOL CheckCopyFiles(IN HINF hinfHandle,
  696. IN ComponentList *pclList)
  697. {
  698. Component *pcComponent = NULL;
  699. BOOL bSuccess;
  700. INFCONTEXT infContext;
  701. TCHAR tszMsg[MaxStringSize];
  702. const PTSTR tszFunctionName = TEXT("CheckCopyFiles");
  703. // A categorical component can't have a [CopyFiles] section
  704. pclList->ResetList();
  705. while (!pclList->Done()) {
  706. pcComponent = pclList->GetNext();
  707. if (pcComponent->IsParentOfOthers()) {
  708. bSuccess = SetupFindFirstLine(hinfHandle,
  709. pcComponent->GetComponentId(),
  710. TEXT("CopyFiles"),
  711. &infContext);
  712. if (bSuccess) {
  713. _stprintf(tszMsg,
  714. TEXT("%s has subcomponent, and has copyfiles section"),
  715. pcComponent->GetComponentId());
  716. LogError(tszMsg, SEV2, tszFunctionName);
  717. }
  718. }
  719. }
  720. return TRUE;
  721. }
  722. /*++
  723. Routine Description:
  724. Routine that checks for suspicious keys in the component section
  725. Argument:
  726. HINF hinfHandle : A handle to the open Inf file
  727. ComponentList *pclList : A pointer to the component list
  728. Return Value:
  729. The return value is not used
  730. --*/
  731. BOOL CheckSuspicious(IN HINF hinfHandle,
  732. IN ComponentList *pclList)
  733. {
  734. // A categorical component can't have any code
  735. // associated with it, which includes add registry
  736. // register services, etc.
  737. // Go through all the component that has subcomponent
  738. // read the lines in its section, looking for anything suspicious
  739. INFCONTEXT infContext;
  740. BOOL bSuccess;
  741. Component *pcComponent;
  742. TCHAR tszMsg[MaxStringSize];
  743. UINT uiNumLineCount;
  744. TCHAR tszTemp[MaxStringSize];
  745. const PTSTR tszFunctionName = TEXT("CheckSuspicious");
  746. pclList->ResetList();
  747. while (!pclList->Done()) {
  748. pcComponent = pclList->GetNext();
  749. if (pcComponent->IsParentOfOthers()) {
  750. // This component has children
  751. bSuccess = SetupFindFirstLine(hinfHandle,
  752. pcComponent->GetComponentId(),
  753. NULL,
  754. &infContext);
  755. if (!bSuccess) {
  756. _stprintf(tszMsg,
  757. TEXT("Unable to locate the component %s in Inf file"),
  758. pcComponent->GetComponentId());
  759. LogError(tszMsg, SEV2, tszFunctionName);
  760. }
  761. uiNumLineCount = SetupGetLineCount(hinfHandle,
  762. pcComponent->GetComponentId());
  763. if (uiNumLineCount < 1) {
  764. _stprintf(tszMsg,
  765. TEXT("%s has too few lines in its section"),
  766. pcComponent->GetComponentId());
  767. LogError(tszMsg, SEV2, tszFunctionName);
  768. }
  769. for (UINT i = 0; i < uiNumLineCount; i++) {
  770. // Go through each line
  771. // see if there is something we don't know
  772. SetupGetStringField(&infContext,
  773. 0,
  774. tszTemp,
  775. MaxBufferSize,
  776. NULL);
  777. // We only understand: OptionDesc, Tip, IconIndex,
  778. // Parent, Needs, Excludes, SubCompInf, Modes
  779. if (_tcscmp(tszTemp, TEXT("OptionDesc")) != 0 &&
  780. _tcscmp(tszTemp, TEXT("Tip")) != 0 &&
  781. _tcscmp(tszTemp, TEXT("IconIndex")) != 0 &&
  782. _tcscmp(tszTemp, TEXT("Parent")) != 0 &&
  783. _tcscmp(tszTemp, TEXT("SubCompInf")) != 0 &&
  784. _tcscmp(tszTemp, TEXT("ExtraSetupFiles")) != 0) {
  785. // Hit something we don't understand
  786. _stprintf(tszMsg,
  787. TEXT("In section [%s], I don't understand key %s"),
  788. pcComponent->GetComponentId(),
  789. tszTemp);
  790. LogError(tszMsg, SEV2, tszFunctionName);
  791. }
  792. SetupFindNextLine(&infContext,
  793. &infContext);
  794. }
  795. }
  796. }
  797. return TRUE;
  798. }
  799. /*++
  800. Routine Description:
  801. Routine that checks if there is any need relation cycles
  802. among components (not implemented)
  803. Argument:
  804. Component *pcComponent : A pointer to the component to check
  805. ComponentList *pclList : A pointer to the component list
  806. Return Value:
  807. The return value is not used
  808. --*/
  809. BOOL CheckNeedCycles(IN Component *pcComponent,
  810. IN ComponentList *pclList)
  811. {
  812. const PTSTR tszFunctionName = TEXT("CheckNeedCycles");
  813. // We can't change the value of pclList,
  814. // or we will mess up the CheckNeedRelationship function
  815. RelationList *prlStack = new RelationList();
  816. RecursiveCheckNeedCycles(pcComponent, pclList, prlStack);
  817. delete prlStack;
  818. return TRUE;
  819. }
  820. /*++
  821. Routine Description:
  822. Routine that is to be called recursively to determine if
  823. there is any cycles in the need relationship
  824. Argument:
  825. Component *pcComponent : A pointer to the component to check
  826. ComponentList *pclList : A pointer to the component list
  827. RelationList *prlStack : A list of nodes that have been visited
  828. Return Value:
  829. The return value is not used
  830. --*/
  831. BOOL RecursiveCheckNeedCycles(IN Component *pcComponent,
  832. IN ComponentList *pclList,
  833. IN RelationList *prlStack)
  834. {
  835. Component *pcNeeded;
  836. const PTSTR tszFunctionName = TEXT("RecursiveCheckNeedCycles");
  837. Relation *prNeed = NULL;
  838. TCHAR tszMsg[MaxStringSize];
  839. pcComponent->GetNeedList()->ResetList();
  840. while (!pcComponent->GetNeedList()->Done()) {
  841. prNeed = pcComponent->GetNeedList()->GetNext();
  842. pcNeeded = pclList->LookupComponent(prNeed->GetComponentId());
  843. if (!pcNeeded) {
  844. _stprintf(tszMsg,
  845. TEXT("%s needs component %s, which is not in the list"),
  846. pcComponent->GetComponentId(),
  847. prNeed->GetComponentId());
  848. LogError(tszMsg, SEV2, tszFunctionName);
  849. return TRUE;
  850. }
  851. // if pcNeeded is already in the stack,
  852. // state the error and returns
  853. // Otherwise add pcNeeded to the stack,
  854. // call CheckNeedCycles with pcNeeded and pclList
  855. prlStack->ResetList();
  856. while (!prlStack->Done()) {
  857. if (_tcscmp(prlStack->GetNext()->GetComponentId(),
  858. pcNeeded->GetComponentId()) == 0) {
  859. _stprintf(tszMsg,
  860. TEXT("need relation cycle exists starting from %s"),
  861. pcNeeded->GetComponentId());
  862. LogError(tszMsg, SEV2, tszFunctionName);
  863. return TRUE;
  864. }
  865. }
  866. prlStack->AddRelation(pcNeeded->GetComponentId());
  867. RecursiveCheckNeedCycles(pcNeeded, pclList, prlStack);
  868. }
  869. // Before returning from this function
  870. // pop out the node added into the stack
  871. pcComponent->GetNeedList()->ResetList();
  872. while (!pcComponent->GetNeedList()->Done()) {
  873. prNeed = pcComponent->GetNeedList()->GetNext();
  874. prlStack->RemoveRelation(prNeed->GetComponentId());
  875. }
  876. return TRUE;
  877. }
  878. /*++
  879. Routine Description:
  880. Routine that checks if there is any parent relation cycles
  881. among components (not implemented)
  882. Argument:
  883. Component *pcComponent : A pointer to the component to check
  884. ComponentList *pclList : A pointer to the component list
  885. Return Value:
  886. The return value is not used
  887. --*/
  888. BOOL CheckParentCycles(IN Component *pcComponent,
  889. IN ComponentList *pclList)
  890. {
  891. const PTSTR tszFunctionName = TEXT("CheckParentCycles");
  892. RelationList *prlStack = new RelationList();
  893. RecursiveCheckParentCycles(pcComponent, pclList, prlStack);
  894. delete prlStack;
  895. return TRUE;
  896. }
  897. /*++
  898. Routine Description:
  899. Routine that is to be called recursively to determine if
  900. there is any cycles in the parent relationship
  901. Argument:
  902. Component *pcComponent : A pointer to the component to check
  903. ComponentList *pclList : A pointer to the component list
  904. RelationList *prlStack : A list of nodes that have been visited
  905. Return Value:
  906. The return value is not used
  907. --*/
  908. BOOL RecursiveCheckParentCycles(IN Component *pcComponent,
  909. IN ComponentList *pclList,
  910. IN RelationList *prlStack)
  911. {
  912. Component *pcChild;
  913. const PTSTR tszFunctionName = TEXT("RecursiveCheckParentCycles");
  914. Relation *prChild = NULL;
  915. TCHAR tszMsg[MaxStringSize];
  916. pcComponent->GetChildrenList()->ResetList();
  917. while (!pcComponent->GetChildrenList()->Done()) {
  918. prChild = pcComponent->GetChildrenList()->GetNext();
  919. pcChild = pclList->LookupComponent(prChild->GetComponentId());
  920. if (!pcChild) {
  921. _stprintf(tszMsg,
  922. TEXT("%s has component %s as child, which is not in the list"),
  923. pcComponent->GetComponentId(),
  924. prChild->GetComponentId());
  925. LogError(tszMsg, SEV2, tszFunctionName);
  926. return TRUE;
  927. }
  928. // if pcChild is already in the stack,
  929. // state the error and returns
  930. // Otherwise add pcChild to the stack,
  931. // call CheckNeedCycles with pcNeeded and pclList
  932. prlStack->ResetList();
  933. while (!prlStack->Done()) {
  934. if (_tcscmp(prlStack->GetNext()->GetComponentId(),
  935. pcChild->GetComponentId()) == 0) {
  936. _stprintf(tszMsg,
  937. TEXT("Parent relation cycle exists starting from %s"),
  938. pcChild->GetComponentId());
  939. LogError(tszMsg, SEV2, tszFunctionName);
  940. return TRUE;
  941. }
  942. }
  943. prlStack->AddRelation(pcChild->GetComponentId());
  944. RecursiveCheckParentCycles(pcChild, pclList, prlStack);
  945. }
  946. pcComponent->GetChildrenList()->ResetList();
  947. while (!pcComponent->GetChildrenList()->Done()) {
  948. prChild = pcComponent->GetChildrenList()->GetNext();
  949. prlStack->RemoveRelation(prChild->GetComponentId());
  950. }
  951. return TRUE;
  952. }
  953. /*++
  954. Routine Description:
  955. Routine that checks if there are components with the same ID
  956. Argument:
  957. ComponentList *pclList : A pointer to the component list
  958. Return Value:
  959. The return value is not used
  960. --*/
  961. BOOL CheckSameId(IN ComponentList *pclList)
  962. {
  963. const PTSTR tszFunctionName = TEXT("CheckSameId");
  964. pclList->ResetList();
  965. Component *pcComponent;
  966. while (!pclList->Done()) {
  967. pcComponent = pclList->GetNext();
  968. pcComponent->IsThereSameId(pclList);
  969. }
  970. return TRUE;
  971. }
  972. /*++
  973. Routine Description:
  974. Routine that checks if the top level components are the ones
  975. that are listed in the master INF file
  976. Argument:
  977. HINF hinfHandle : A handle to the open Inf file
  978. ComponentList *pclList : A pointer to the component list
  979. Return Value:
  980. The return value is not used
  981. --*/
  982. BOOL CheckTopLevelComponent(IN HINF hinfHandle,
  983. IN ComponentList *pclList)
  984. {
  985. const PTSTR tszFunctionName = TEXT("CheckTopLevelComponent");
  986. Component *pcComponent;
  987. BOOL bSuccess;
  988. INFCONTEXT infContext;
  989. TCHAR tszMsg[MaxStringSize];
  990. pclList->ResetList();
  991. while (!pclList->Done()) {
  992. pcComponent = pclList->GetNext();
  993. if (pcComponent->IsTopLevelComponent()) {
  994. // Check if this component exists in the [Components] section
  995. bSuccess = SetupFindFirstLine(hinfHandle,
  996. tszComponents,
  997. pcComponent->GetComponentId(),
  998. &infContext);
  999. if (!bSuccess) {
  1000. _stprintf(tszMsg,
  1001. TEXT("Component %s doesn't have a parent, but it is not listed in the [Components] section"),
  1002. pcComponent->GetComponentId());
  1003. LogError(tszMsg, SEV2, tszFunctionName);
  1004. }
  1005. }
  1006. }
  1007. return TRUE;
  1008. }
  1009. /*++
  1010. Routine Description:
  1011. Routine that checks if every component has a description
  1012. and tip, and that no two components have the same
  1013. description if they share a common parent
  1014. Argument:
  1015. HINF hinfHandle : A handle to the open Inf file
  1016. ComponentList *pclList : A pointer to the component list
  1017. Return Value:
  1018. The return value is not used
  1019. --*/
  1020. BOOL CheckDescription(IN HINF hinfHandle,
  1021. IN ComponentList *pclList)
  1022. {
  1023. const PTSTR tszFunctionName = TEXT("CheckDescription");
  1024. Component *pcComponent;
  1025. BOOL bSuccess;
  1026. TCHAR tszMsg[MaxStringSize];
  1027. INFCONTEXT infContext;
  1028. pclList->ResetList();
  1029. while (!pclList->Done()) {
  1030. pcComponent = pclList->GetNext();
  1031. // We probably have to add two members to the class
  1032. // but let's how this works out
  1033. // Allocate a new structure for this node
  1034. pcComponent->pDescAndTip = new DescAndTip;
  1035. // Get the data from the inf file
  1036. bSuccess = SetupFindFirstLine(hinfHandle,
  1037. pcComponent->GetComponentId(),
  1038. TEXT("OptionDesc"),
  1039. &infContext);
  1040. if (!bSuccess) {
  1041. _stprintf(tszMsg,
  1042. TEXT("Unable to find OptionDesc for component %s"),
  1043. pcComponent->GetComponentId());
  1044. LogError(tszMsg, SEV2, tszFunctionName);
  1045. }
  1046. else {
  1047. bSuccess = SetupGetStringField(&infContext, 1,
  1048. pcComponent->pDescAndTip->tszDesc,
  1049. MaxBufferSize,
  1050. NULL);
  1051. if (!bSuccess) {
  1052. _stprintf(tszMsg,
  1053. TEXT("Unable to read OptionDesc field of component %s"),
  1054. pcComponent->GetComponentId());
  1055. LogError(tszMsg, SEV2, tszFunctionName);
  1056. }
  1057. // Now see if it is a real description or a string
  1058. if (pcComponent->pDescAndTip->tszDesc[0] == TEXT('%')) {
  1059. bSuccess = SetupFindFirstLine(hinfHandle,
  1060. TEXT("Strings"),
  1061. Strip(pcComponent->pDescAndTip->tszDesc),
  1062. NULL);
  1063. if (!bSuccess) {
  1064. _stprintf(tszMsg,
  1065. TEXT("Unable to find key %s in [Strings] section"),
  1066. pcComponent->pDescAndTip->tszDesc);
  1067. LogError(tszMsg, SEV2, tszFunctionName);
  1068. }
  1069. else {
  1070. bSuccess = SetupGetStringField(&infContext,
  1071. 1,
  1072. pcComponent->pDescAndTip->tszDesc,
  1073. MaxBufferSize,
  1074. NULL);
  1075. }
  1076. }
  1077. else {
  1078. // Do nothing
  1079. }
  1080. }
  1081. // Now Get the tip stuff, it is basically the same as desc
  1082. bSuccess = SetupFindFirstLine(hinfHandle,
  1083. pcComponent->GetComponentId(),
  1084. TEXT("Tip"),
  1085. &infContext);
  1086. if (!bSuccess) {
  1087. _stprintf(tszMsg,
  1088. TEXT("Unable to find Tip key for component %s"),
  1089. pcComponent->GetComponentId());
  1090. LogError(tszMsg, SEV2, tszFunctionName);
  1091. }
  1092. else {
  1093. bSuccess = SetupGetStringField(&infContext, 1,
  1094. pcComponent->pDescAndTip->tszTip,
  1095. MaxBufferSize,
  1096. NULL);
  1097. if (!bSuccess) {
  1098. _stprintf(tszMsg,
  1099. TEXT("Unable to read Tip field for component %s"),
  1100. pcComponent->GetComponentId());
  1101. LogError(tszMsg, SEV2, tszFunctionName);
  1102. }
  1103. // Now see if it is a real description or a string
  1104. if (pcComponent->pDescAndTip->tszTip[0] == TEXT('%')) {
  1105. bSuccess = SetupFindFirstLine(hinfHandle,
  1106. TEXT("Strings"),
  1107. Strip(pcComponent->pDescAndTip->tszTip),
  1108. NULL);
  1109. if (!bSuccess) {
  1110. _stprintf(tszMsg,
  1111. TEXT("Unable to find key %s in [Strings] section"),
  1112. pcComponent->pDescAndTip->tszTip);
  1113. LogError(tszMsg, SEV2, tszFunctionName);
  1114. }
  1115. else {
  1116. bSuccess = SetupGetStringField(&infContext,
  1117. 1,
  1118. pcComponent->pDescAndTip->tszTip,
  1119. MaxBufferSize,
  1120. NULL);
  1121. }
  1122. }
  1123. else {
  1124. // Do nothing
  1125. }
  1126. }
  1127. }
  1128. // Now all the tip and desc thing is filled
  1129. // Loop through the component, see if there are two components with
  1130. // the same description
  1131. pclList->ResetList();
  1132. while (!pclList->Done()) {
  1133. pcComponent = pclList->GetNext();
  1134. pcComponent->IsThereSameDesc(pclList);
  1135. }
  1136. // Now go through the list and delete the field
  1137. pclList->ResetList();
  1138. while (!pclList->Done()) {
  1139. pcComponent = pclList->GetNext();
  1140. delete (pcComponent->pDescAndTip);
  1141. }
  1142. return TRUE;
  1143. }
  1144. /*++
  1145. Routine Description:
  1146. Routine that checks if every component has the correct mode value
  1147. Toplevel component should not have Modes= line, and the modes value
  1148. should only be 0 through 3
  1149. Argument:
  1150. HINF hinfHandle : A handle to the open Inf file
  1151. ComponentList *pclList : A pointer to the component list
  1152. Return Value:
  1153. The return value is not used
  1154. --*/
  1155. BOOL CheckModes(IN HINF hinfHandle,
  1156. IN ComponentList *pclList)
  1157. {
  1158. // Go through each component, two things to check
  1159. // a component with children should not have a mode line
  1160. // the value of the fields should be between 0 and 3
  1161. //SETUPMODE_MINIMAL = 0;
  1162. //SETUPMODE_TYPICAL = 1;
  1163. //SETUPMODE_LAPTOP = 2;
  1164. //SETUPMODE_CUSTOM = 3;
  1165. TCHAR tszMsg[MaxStringSize];
  1166. INFCONTEXT infContext;
  1167. BOOL bSuccess;
  1168. UINT uiNumFields;
  1169. const PTSTR tszFunctionName = TEXT("CheckModes");
  1170. INT nMode;
  1171. Component *pcComponent;
  1172. pclList->ResetList();
  1173. while (!pclList->Done()) {
  1174. pcComponent = pclList->GetNext();
  1175. bSuccess = SetupFindFirstLine(hinfHandle,
  1176. pcComponent->GetComponentId(),
  1177. TEXT("Modes"),
  1178. &infContext);
  1179. if (bSuccess) {
  1180. // Found the mode line
  1181. // first check if this a component with children
  1182. if (pcComponent->IsParentOfOthers()) {
  1183. _stprintf(tszMsg,
  1184. TEXT("%s has subcomponent, and has Modes = line"),
  1185. pcComponent->GetComponentId());
  1186. LogError(tszMsg, SEV2, tszFunctionName);
  1187. }
  1188. else {
  1189. // Check the validity of the fields
  1190. uiNumFields = SetupGetFieldCount(&infContext);
  1191. if (uiNumFields < 1 || uiNumFields > 4) {
  1192. _stprintf(tszMsg,
  1193. TEXT("Invalid number of fields in section [%s]"),
  1194. pcComponent->GetComponentId());
  1195. LogError(tszMsg, SEV2, tszFunctionName);
  1196. }
  1197. for (UINT i = 1; i <= uiNumFields; i++) {
  1198. bSuccess = SetupGetIntField(&infContext, i, &nMode);
  1199. if (!bSuccess) {
  1200. _stprintf(tszMsg,
  1201. TEXT("Failed to get Mode value in section [%s]"),
  1202. pcComponent->GetComponentId());
  1203. LogError(tszMsg, SEV2, tszFunctionName);
  1204. }
  1205. if (nMode < 0 || nMode > 3) {
  1206. _stprintf(tszMsg,
  1207. TEXT("Invalid mode value %d in section [%s]"),
  1208. nMode,
  1209. pcComponent->GetComponentId());
  1210. LogError(tszMsg, SEV2, tszFunctionName);
  1211. }
  1212. }
  1213. }
  1214. }
  1215. }
  1216. return TRUE;
  1217. }
  1218. /*++
  1219. Routine Description:
  1220. Routine that checks if the every INF file has a line
  1221. LayoutFile = layout.inf No file should ever use
  1222. [SourceDisksFiles] or [SourceDisksNames] section
  1223. Argument:
  1224. HINF hinfHandle : A handle to the open Inf file
  1225. ComponentList *pclList : A pointer to the component list
  1226. Return Value:
  1227. The return value is not used
  1228. --*/
  1229. BOOL CheckLayoutFile(IN TCHAR tszSubINFName[MaxStringSize][MaxStringSize],
  1230. IN UINT uiNumComponents,
  1231. IN TCHAR *tszDir)
  1232. {
  1233. TCHAR tszMsg[MaxStringSize];
  1234. BOOL bSuccess;
  1235. HINF hinfHandle;
  1236. INFCONTEXT infContext;
  1237. UINT uiError;
  1238. TCHAR tszLine[MaxStringSize];
  1239. const PTSTR tszFunctionName = TEXT("CheckLayoutFile");
  1240. // Now check the LayoutFile in each INF file
  1241. for (UINT m = 0; m < uiNumComponents; m++) {
  1242. if (tszSubINFName[m][0]) {
  1243. _stprintf(tszMsg, TEXT("%s%s"), tszDir, tszSubINFName[m]);
  1244. hinfHandle = SetupOpenInfFile(tszMsg,
  1245. NULL,
  1246. INF_STYLE_WIN4,
  1247. &uiError);
  1248. // We assume the hinf handle is valid
  1249. bSuccess = SetupFindFirstLine(hinfHandle,
  1250. TEXT("Version"),
  1251. tszLayoutFile,
  1252. &infContext);
  1253. if (!bSuccess) {
  1254. _stprintf(tszMsg,
  1255. TEXT("LayoutFile not found in file %s"),
  1256. tszSubINFName[m]);
  1257. LogError(tszMsg, SEV2, tszFunctionName);
  1258. SetupCloseInfFile(hinfHandle);
  1259. continue;
  1260. }
  1261. // Check if the value of the key is Layout.inf
  1262. TCHAR tszLayoutFileName[MaxStringSize];
  1263. bSuccess = SetupGetStringField(&infContext,
  1264. 1,
  1265. tszLayoutFileName,
  1266. MaxBufferSize,
  1267. NULL);
  1268. if (!bSuccess) {
  1269. _stprintf(tszMsg,
  1270. TEXT("Error reading the value of the %s in %s"),
  1271. tszLayoutFile,
  1272. tszSubINFName[m]);
  1273. }
  1274. if ( _tcsicmp(tszLayoutFileName, TEXT("Layout.inf")) != 0 ) {
  1275. _stprintf(tszMsg,
  1276. TEXT("The value of LayoutFile= %s in %s is invalid"),
  1277. tszLayoutFileName,
  1278. tszSubINFName[m]);
  1279. }
  1280. if (!bSuccess ||
  1281. _tcsicmp(tszLayoutFileName, TEXT("Layout.inf")) != 0 ) {
  1282. LogError(tszMsg, SEV2, tszFunctionName);
  1283. }
  1284. // Now check that we should not have SourceDisksNames
  1285. // or SourceDisksFiles sections
  1286. bSuccess = SetupFindFirstLine(hinfHandle,
  1287. TEXT("SourceDisksNames"),
  1288. NULL,
  1289. &infContext);
  1290. if (bSuccess) {
  1291. _stprintf(tszMsg,
  1292. TEXT("[SourceDisksNames] section presents in %s"),
  1293. tszSubINFName[m]);
  1294. LogError(tszMsg, SEV2, tszFunctionName);
  1295. }
  1296. bSuccess = SetupFindFirstLine(hinfHandle,
  1297. TEXT("SourceDisksFiles"),
  1298. NULL,
  1299. &infContext);
  1300. if (bSuccess) {
  1301. _stprintf(tszMsg,
  1302. TEXT("[SourceDisksFiles] section presents in %s"),
  1303. tszSubINFName[m]);
  1304. LogError(tszMsg, SEV2, tszFunctionName);
  1305. }
  1306. SetupCloseInfFile(hinfHandle);
  1307. }
  1308. }
  1309. return TRUE;
  1310. }
  1311. /*++
  1312. Routine Description:
  1313. Routine that logs an error depending on the ways some
  1314. global variables are set
  1315. Argument:
  1316. TCHAR *tszMsg: Error Message to log
  1317. DWORD dwErrorLevel: How serious the error is
  1318. TCHAR *tszFunctionName: the function name this error is detected
  1319. Return Value:
  1320. The return value is not used
  1321. --*/
  1322. VOID LogError(IN TCHAR *tszMsg,
  1323. IN DWORD dwErrorLevel,
  1324. IN TCHAR *tszFunctionName)
  1325. {
  1326. double fn = 1.00;
  1327. if (g_bUseLog) {
  1328. Log(fn, dwErrorLevel, tszMsg);
  1329. }
  1330. if (g_bUseMsgBox) {
  1331. if (dwErrorLevel == INFO) {
  1332. // We will not put up anything
  1333. }
  1334. else {
  1335. MessageBox(NULL, tszMsg, tszFunctionName, MB_ICONERROR | MB_OK);
  1336. }
  1337. }
  1338. if (g_bUseConsole) {
  1339. TCHAR tszContent[MaxStringSize];
  1340. _tcscpy(tszContent, tszMsg);
  1341. _tcscat(tszContent, TEXT("\n"));
  1342. _ftprintf(stdout, tszContent);
  1343. }
  1344. }
  1345. /*++
  1346. Routine Description:
  1347. Routine that gets rid of the first and last char of a string
  1348. Argument:
  1349. TCHAR *tszString: Error Message to log
  1350. Return Value:
  1351. The return value is not used
  1352. --*/
  1353. TCHAR *Strip(TCHAR *tszString)
  1354. {
  1355. TCHAR tszTemp[MaxStringSize];
  1356. _tcscpy(tszTemp, (tszString+1));
  1357. tszTemp[_tcslen(tszTemp)-1] = 0;
  1358. _tcscpy(tszString, tszTemp);
  1359. return tszString;
  1360. }