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.

1468 lines
45 KiB

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <windows.h>
  5. #include <tchar.h>
  6. #include <assert.h>
  7. #include "dbghelp.h"
  8. #include "strsafe.h"
  9. #define X86INF 200
  10. #define ALPHAINF 201
  11. // Prototypes
  12. typedef struct _COMMAND_ARGS {
  13. DWORD dwCabSize; // Default size of cab
  14. LPTSTR szInputFileName; // Name of the list of files to put into cabs
  15. LPTSTR szOutDir; // Directory to place the makefile and DDF's
  16. LPTSTR szDDFHeader; // Header for the DDF
  17. LPTSTR szSymDir; // Root of symbols directory
  18. LPTSTR szCabDir; // Directory to write cabs to
  19. LPTSTR szInfDir; // Directory to write infs to
  20. LPTSTR szSymCabName; // Symbol cab name
  21. BOOL MergeIntoOne; // Will cabs all be merged into one cab?
  22. } COM_ARGS, *PCOM_ARGS;
  23. typedef struct _SYM_FILE {
  24. TCHAR szCabName [_MAX_FNAME + 1]; // Final destination cab for this file
  25. TCHAR szTmpCabName [_MAX_FNAME + 1]; // Original cab this file is in before it
  26. // is combined into a bigger cab
  27. TCHAR szExeName [_MAX_PATH + 1];
  28. TCHAR szSymName [_MAX_PATH + 1];
  29. TCHAR szSymReName [_MAX_PATH + 1];
  30. TCHAR szSymSrcPath [_MAX_PATH + 1];
  31. TCHAR szInstallPath [_MAX_PATH + 1];
  32. TCHAR szInstallPathX [_MAX_PATH + 1]; // This is the install path with
  33. // the /'s changed to .'s
  34. BOOL Duplicate; // Duplicate File, ignore it
  35. BOOL ReName; // Two different files have the same
  36. // name. Example, exe\dcpromo.dbg,
  37. // dll\dcpromo.dbg
  38. DWORD dwCabNumber; // Number of the cab in symbols.inf
  39. } SYM_FILE, *PSYM_FILE;
  40. typedef struct _SYM_LIST {
  41. DWORD dwSize; // Number of Entries
  42. PSYM_FILE* pSymList; // list of symbol files
  43. } SYM_LIST, *PSYM_LIST;
  44. BOOL PrintFullSymbolPath(
  45. IN FILE* OutputFile,
  46. IN OPTIONAL LPTSTR SymbolRoot,
  47. IN LPTSTR SymbolPath
  48. );
  49. PCOM_ARGS GetCommandLineArgs(
  50. int argc,
  51. char **argv
  52. );
  53. PSYM_LIST
  54. GetList(
  55. LPTSTR szFileName
  56. );
  57. VOID
  58. Usage (
  59. VOID
  60. );
  61. int __cdecl
  62. SymComp(
  63. const void *e1,
  64. const void *e2
  65. );
  66. int __cdecl
  67. SymSortBySymbolName(
  68. const void *e1,
  69. const void *e2
  70. );
  71. int __cdecl
  72. SymSortByInstallPath(
  73. const void *e1,
  74. const void *e2
  75. );
  76. int __cdecl
  77. SymSortByCabNumber(
  78. const void *e1,
  79. const void *e2
  80. );
  81. BOOL
  82. ComputeCabNames(
  83. PSYM_LIST pList,
  84. DWORD dwCabSize,
  85. LPTSTR szSymCabName
  86. );
  87. BOOL
  88. CreateMakefile(
  89. PSYM_LIST pList,
  90. LPTSTR szOutDir,
  91. LPTSTR szSymDir,
  92. LPTSTR szCabDir
  93. );
  94. BOOL
  95. CreateDDFs(
  96. PSYM_LIST pList,
  97. LPTSTR szOutDir, // Directory to write the DDFs to
  98. LPTSTR szSymDir, // Root of the symbols tree
  99. LPTSTR szCabDir // Directory where cabs are written to
  100. );
  101. BOOL
  102. CreateCDF(
  103. PSYM_LIST pList,
  104. LPTSTR szOutDir, // Directory to write the CDF to
  105. LPTSTR szSymDir, // Root of the symbols tree
  106. LPTSTR szSymCabName,
  107. LPTSTR szInfDir // Destination for the CAT file
  108. );
  109. BOOL
  110. CreateCabList(
  111. PSYM_LIST pList,
  112. LPTSTR szOutDir
  113. );
  114. BOOL
  115. FindDuplicatesAndFilesToReName(
  116. PSYM_LIST pList
  117. );
  118. BOOL
  119. RenameAllTheFiles(
  120. PSYM_LIST pList
  121. );
  122. BOOL
  123. ComputeFinalCabNames(
  124. PSYM_LIST pList,
  125. LPTSTR szSymCabName,
  126. BOOL MergeIntoOne
  127. );
  128. BOOL
  129. CreateInf(
  130. PSYM_LIST pList,
  131. LPTSTR szInfDir,
  132. LPTSTR szSymCabName
  133. );
  134. BOOL FreePList(PSYM_LIST pList);
  135. int
  136. _cdecl
  137. main( int argc, char **argv)
  138. {
  139. PCOM_ARGS pArgs;
  140. PSYM_LIST pList;
  141. DWORD i;
  142. pArgs = GetCommandLineArgs(argc, argv);
  143. pList = GetList(pArgs->szInputFileName);
  144. if (pList)
  145. {
  146. if ( pList->dwSize < 1 ) {
  147. FreePList(pList);
  148. exit(1);
  149. }
  150. // First, sort the list by Symbol name
  151. qsort( (void*)pList->pSymList, (size_t)pList->dwSize,
  152. (size_t)sizeof(PSYM_FILE), SymSortBySymbolName );
  153. FindDuplicatesAndFilesToReName(pList);
  154. RenameAllTheFiles(pList);
  155. // Compute Temporary cab names ...
  156. // Make a bunch of small cabs and then combine them to
  157. // make symbol cabbing more efficient.
  158. // all functions must return TRUE
  159. if ( ComputeCabNames(pList, pArgs->dwCabSize, pArgs->szSymCabName) &&
  160. CreateMakefile( pList, pArgs->szOutDir, pArgs->szSymDir, pArgs->szCabDir) &&
  161. CreateCabList( pList, pArgs->szOutDir ) &&
  162. CreateDDFs( pList, pArgs->szOutDir, pArgs->szSymDir, pArgs->szCabDir) &&
  163. CreateCDF( pList, pArgs->szOutDir, pArgs->szSymDir, pArgs->szSymCabName,
  164. pArgs->szInfDir ) &&
  165. ComputeFinalCabNames(pList, pArgs->szSymCabName, pArgs->MergeIntoOne) &&
  166. // Creates symbols.inf that is used to install the symbols
  167. CreateInf(pList, pArgs->szInfDir, pArgs->szSymCabName) ) {
  168. return(0);
  169. } else {
  170. return(1);
  171. }
  172. }
  173. return 0;
  174. }
  175. VOID
  176. Usage (
  177. VOID
  178. )
  179. {
  180. printf("\n");
  181. printf("Usage: symmake [/m] /c CabName /d DDFHeader /i InfFile /o OutDir \n");
  182. printf(" /s CabSize /t SymbolPath\n");
  183. printf(" /c cabname Name to give the cabs\n");
  184. printf(" /d DDFHeader File with common DDF header formatting\n");
  185. printf(" /i InfFile File with list of symbol files to copy\n");
  186. printf(" /m Merge Merge the cabs into one cab\n");
  187. printf(" /o OutDir Directory to place DDF files and makefile\n");
  188. printf(" /s CabSize Number of files per cab\n");
  189. printf(" /t SymPath Root of the symbol tree (i.e., d:\\binaries)\n");
  190. printf(" SymPath is ignored if the symbol path in InfFile\n");
  191. printf(" is already fully qualified.\n");
  192. printf(" /x CabDest Full destination path for the cabs\n");
  193. printf(" /y InfDest Full destination for the infs\n");
  194. printf("\n");
  195. exit(1);
  196. }
  197. PCOM_ARGS
  198. GetCommandLineArgs(
  199. int argc,
  200. char **argv
  201. )
  202. {
  203. PCOM_ARGS pArgs;
  204. int i,cur,length;
  205. TCHAR c;
  206. BOOL NeedSecond = FALSE;
  207. if (argc == 1) Usage();
  208. pArgs = (PCOM_ARGS)malloc(sizeof(COM_ARGS));
  209. if ( pArgs == NULL ) {
  210. printf("Not enough memory to allocate pArgs\n");
  211. exit(1);
  212. }
  213. memset( pArgs, 0, sizeof(COM_ARGS) );
  214. pArgs->MergeIntoOne = FALSE;
  215. pArgs->szSymDir = NULL; // expect this to be NULL or a valid string
  216. for (i=1; i<argc; i++) {
  217. if (!NeedSecond) {
  218. if ( (argv[i][0] == '/') || (argv[i][0] == '-') ) {
  219. length = _tcslen(argv[i]) -1;
  220. for (cur=1; cur <= length; cur++) {
  221. c = argv[i][cur];
  222. switch (c) {
  223. case 'c': NeedSecond = TRUE;
  224. break;
  225. case 'd': NeedSecond = TRUE;
  226. break;
  227. case 'i': NeedSecond = TRUE;
  228. break;
  229. case 'm': NeedSecond = FALSE;
  230. pArgs->MergeIntoOne = TRUE;
  231. break;
  232. case 'o': NeedSecond = TRUE;
  233. break;
  234. case 's': NeedSecond = TRUE;
  235. break;
  236. case 't': NeedSecond = TRUE;
  237. break;
  238. case 'x': NeedSecond = TRUE;
  239. break;
  240. case 'y': NeedSecond = TRUE;
  241. break;
  242. default: Usage();
  243. }
  244. }
  245. }
  246. }
  247. else {
  248. NeedSecond = FALSE;
  249. switch (c) {
  250. case 'c': pArgs->szSymCabName = argv[i];
  251. break;
  252. case 'd': pArgs->szDDFHeader = argv[i];
  253. break;
  254. case 'i': pArgs->szInputFileName = argv[i];
  255. break;
  256. case 'o': pArgs->szOutDir = argv[i];
  257. break;
  258. case 's': pArgs->dwCabSize = atoi(argv[i]);
  259. break;
  260. case 't': pArgs->szSymDir = argv[i];
  261. break;
  262. case 'x': pArgs->szCabDir = argv[i];
  263. break;
  264. case 'y': pArgs->szInfDir = argv[i];
  265. break;
  266. default: Usage();
  267. }
  268. }
  269. }
  270. return (pArgs);
  271. }
  272. PSYM_LIST
  273. GetList(
  274. LPTSTR szFileName
  275. )
  276. {
  277. PSYM_LIST pList;
  278. FILE *fFile;
  279. DWORD i;
  280. TCHAR szEntry[_MAX_PATH * 4];
  281. TCHAR *token, *c, *x;
  282. LPTSTR seps=_T(",");
  283. PTCHAR pCh;
  284. pList = (PSYM_LIST)malloc(sizeof(SYM_LIST));
  285. if (pList == NULL )
  286. {
  287. return NULL;
  288. }
  289. if ( (fFile = _tfopen(szFileName,_T("r") )) == NULL )
  290. {
  291. printf( "Cannot open the symbol inf input file %s\n",szFileName );
  292. free(pList);
  293. return NULL;
  294. }
  295. // Figure out the number of entries and allocate the list accordingly
  296. pList->dwSize = 0;
  297. while ( _fgetts(szEntry,_MAX_FNAME,fFile) )
  298. {
  299. (pList->dwSize)++;
  300. }
  301. // Go back to the beginning of the file and read the entries in
  302. if ( fseek(fFile,0,0) != 0 )
  303. {
  304. free(pList);
  305. pList = NULL;
  306. }
  307. else
  308. {
  309. pList->pSymList = NULL;
  310. pList->pSymList = (PSYM_FILE*)malloc( sizeof(PSYM_FILE) *
  311. (pList->dwSize));
  312. if (pList->pSymList == NULL)
  313. {
  314. free(pList);
  315. pList = NULL;
  316. }
  317. else
  318. {
  319. for (i=0; i<pList->dwSize; i++)
  320. {
  321. // Allocate the List element
  322. pList->pSymList[i] = (PSYM_FILE)malloc( sizeof(SYM_FILE) );
  323. if (pList->pSymList[i] == NULL)
  324. {
  325. pList->dwSize=i;
  326. FreePList(pList);
  327. pList = NULL;
  328. break;
  329. }
  330. memset(pList->pSymList[i],0,sizeof(SYM_FILE) );
  331. // Get the next list element from input file
  332. memset(szEntry,0,_MAX_PATH*4);
  333. if ( _fgetts(szEntry,_MAX_PATH*4,fFile) == NULL )
  334. {
  335. FreePList(pList);
  336. pList = NULL;
  337. break;
  338. }
  339. _tcslwr(szEntry);
  340. // Replace the \n with \0
  341. c = NULL;
  342. c = _tcschr(szEntry, '\n');
  343. if ( c != NULL )
  344. {
  345. *c = _T('\0');
  346. }
  347. // Fill in the four entry values
  348. token = _tcstok( szEntry, seps);
  349. if (token)
  350. {
  351. StringCbCopy(pList->pSymList[i]->szExeName, sizeof(pList->pSymList[i]->szExeName), token);
  352. }
  353. token = _tcstok( NULL, seps);
  354. if (token)
  355. {
  356. StringCbCopy(pList->pSymList[i]->szSymName, sizeof(pList->pSymList[i]->szSymName), token);
  357. }
  358. token = _tcstok( NULL, seps);
  359. if (token)
  360. {
  361. StringCbCopy(pList->pSymList[i]->szSymSrcPath, sizeof(pList->pSymList[i]->szSymSrcPath), token);
  362. }
  363. token = _tcstok( NULL, seps);
  364. if (token)
  365. {
  366. StringCbCopy(pList->pSymList[i]->szInstallPath, sizeof(pList->pSymList[i]->szInstallPath), token);
  367. // Create an install path that has any /'s changed to .'s
  368. StringCbCopy(pList->pSymList[i]->szInstallPathX, sizeof(pList->pSymList[i]->szInstallPathX), token);
  369. while ( (pCh = _tcschr(pList->pSymList[i]->szInstallPathX,'\\')) != NULL) {
  370. *pCh = '.';
  371. }
  372. }
  373. // Initialize other fields to NULL
  374. StringCbCopy(pList->pSymList[i]->szSymReName, sizeof(pList->pSymList[i]->szSymReName), _T("") );
  375. }
  376. }
  377. }
  378. fclose(fFile);
  379. return (pList);
  380. }
  381. int __cdecl
  382. SymComp(
  383. const void *e1,
  384. const void *e2
  385. )
  386. {
  387. PSYM_FILE p1;
  388. PSYM_FILE p2;
  389. int rc;
  390. p1 = *((PSYM_FILE*)e1);
  391. p2 = *((PSYM_FILE*)e2);
  392. rc = _tcsicmp(p1->szCabName,p2->szCabName);
  393. if ( rc == 0 ) {
  394. rc = _tcsicmp(p1->szExeName, p2->szExeName);
  395. if (rc == 0) {
  396. rc = _tcsicmp(p1->szSymName, p2->szSymName);
  397. }
  398. }
  399. return ( rc );
  400. }
  401. int __cdecl
  402. SymSortBySymbolName(
  403. const void *e1,
  404. const void *e2
  405. )
  406. {
  407. PSYM_FILE p1;
  408. PSYM_FILE p2;
  409. int rc;
  410. p1 = *((PSYM_FILE*)e1);
  411. p2 = *((PSYM_FILE*)e2);
  412. rc = _tcsicmp(p1->szSymName, p2->szSymName);
  413. if (rc == 0) {
  414. rc = _tcsicmp(p1->szSymSrcPath, p2->szSymSrcPath);
  415. }
  416. return ( rc );
  417. }
  418. int __cdecl
  419. SymSortByInstallPath(
  420. const void *e1,
  421. const void *e2
  422. )
  423. {
  424. PSYM_FILE p1;
  425. PSYM_FILE p2;
  426. int rc;
  427. p1 = *((PSYM_FILE*)e1);
  428. p2 = *((PSYM_FILE*)e2);
  429. rc = _tcsicmp(p1->szInstallPath, p2->szInstallPath);
  430. if (rc == 0) {
  431. rc = _tcsicmp(p1->szSymName, p2->szSymName);
  432. }
  433. return ( rc );
  434. }
  435. int __cdecl
  436. SymSortByCabNumber(
  437. const void *e1,
  438. const void *e2
  439. )
  440. {
  441. PSYM_FILE p1;
  442. PSYM_FILE p2;
  443. int rc;
  444. p1 = *((PSYM_FILE*)e1);
  445. p2 = *((PSYM_FILE*)e2);
  446. if ( p1->dwCabNumber < p2->dwCabNumber) return(-1);
  447. if ( p1->dwCabNumber > p2->dwCabNumber) return(1);
  448. rc = _tcsicmp(p1->szSymName, p2->szSymName);
  449. return ( rc );
  450. }
  451. BOOL
  452. ComputeCabNames(
  453. PSYM_LIST pList,
  454. DWORD dwCabSize,
  455. LPTSTR szSymCabName
  456. )
  457. {
  458. // This divides the files into cabs of dwCabSize files.
  459. // It appends a number to the end of each cab so they all
  460. // have different names
  461. // szTmpCabName is the name of the cab that each file is in
  462. // originally. These may get combined into bigger cabs later.
  463. // If they do, then the final cab name is in szCabName.
  464. TCHAR szCurCabName[_MAX_PATH];
  465. TCHAR szCurAppend[10];
  466. DWORD i,dwCurCount,dwCurAppend;
  467. if (dwCabSize <= 0 ) return 1;
  468. if (szSymCabName == NULL) return FALSE;
  469. // Get the Cab name of the first one
  470. StringCbCopy(szCurCabName, sizeof(szCurCabName), szSymCabName );
  471. StringCbCat( szCurCabName, sizeof(szCurCabName), _T("1") );
  472. StringCbCopy(pList->pSymList[0]->szTmpCabName, sizeof(pList->pSymList[0]->szTmpCabName), szCurCabName);
  473. dwCurCount = 1; // Number of files in this cab so far
  474. dwCurAppend = 1; // Current number to append to the cab name
  475. for ( i=1; i<pList->dwSize; i++ ) {
  476. // Always put symbols for the same exe in the same cab
  477. if ( (_tcsicmp( pList->pSymList[i-1]->szExeName,
  478. pList->pSymList[i]->szExeName ) != 0) &&
  479. (dwCurCount >= dwCabSize) ) {
  480. dwCurAppend++;
  481. dwCurCount = 0;
  482. _itot(dwCurAppend, szCurAppend, 10);
  483. StringCbCopy(szCurCabName, sizeof(szCurCabName), szSymCabName );
  484. StringCbCat (szCurCabName, sizeof(szCurCabName), szCurAppend );
  485. }
  486. // Add the file to the current cab
  487. StringCbCopy(pList->pSymList[i]->szTmpCabName, sizeof(pList->pSymList[i]->szTmpCabName), szCurCabName);
  488. dwCurCount++;
  489. }
  490. return TRUE;
  491. }
  492. BOOL
  493. ComputeFinalCabNames(
  494. PSYM_LIST pList,
  495. LPTSTR szSymCabName,
  496. BOOL MergeIntoOne
  497. )
  498. {
  499. DWORD i;
  500. DWORD dwCabNumber, dwSkip;
  501. // For right now, the final cab name is the same as the
  502. // temporary cab name.
  503. for ( i=0; i<pList->dwSize; i++ ) {
  504. // Get the final cab name and number
  505. if (MergeIntoOne) {
  506. StringCbCopy(pList->pSymList[i]->szCabName, sizeof(pList->pSymList[i]->szCabName), szSymCabName);
  507. pList->pSymList[i]->dwCabNumber = 1;
  508. } else {
  509. StringCbCopy(pList->pSymList[i]->szCabName,
  510. sizeof(pList->pSymList[i]->szCabName),
  511. pList->pSymList[i]->szTmpCabName);
  512. // Also, get the number of the cab
  513. dwSkip = _tcslen( szSymCabName );
  514. dwCabNumber = atoi(pList->pSymList[i]->szTmpCabName + dwSkip);
  515. pList->pSymList[i]->dwCabNumber = dwCabNumber;
  516. }
  517. }
  518. return TRUE;
  519. }
  520. BOOL
  521. CreateMakefile(
  522. PSYM_LIST pList,
  523. LPTSTR szOutDir,
  524. LPTSTR szSymDir,
  525. LPTSTR szCabDir
  526. )
  527. {
  528. FILE *fFile;
  529. TCHAR buf[_MAX_PATH * 2];
  530. TCHAR buf2[_MAX_PATH];
  531. BOOL newcab,rc;
  532. DWORD i;
  533. PCHAR ch;
  534. if (szOutDir == NULL) return FALSE;
  535. rc = TRUE;
  536. StringCbCopy(buf, sizeof(buf), szOutDir);
  537. MakeSureDirectoryPathExists(szOutDir);
  538. StringCbCat(buf, sizeof(buf), "\\");
  539. StringCbCat(buf, sizeof(buf), "makefile");
  540. if ( (fFile = _tfopen(buf, _T("w") )) == NULL ) {
  541. printf( "Cannot open the makefile %s for writing.\n",buf);
  542. return (FALSE);
  543. }
  544. if (pList->dwSize <= 0 ) {
  545. rc = FALSE;
  546. goto cleanup;
  547. }
  548. // Print the lists for the individual cabs
  549. newcab = TRUE;
  550. for (i=0; i<pList->dwSize; i++) {
  551. // Test for printing a new cab to the makefile
  552. if ( newcab) {
  553. StringCbPrintf(buf, sizeof(buf), "%s\\%s.cab:",
  554. szCabDir,
  555. pList->pSymList[i]->szTmpCabName);
  556. _fputts(buf, fFile);
  557. }
  558. // Print the file, print the continuation mark first
  559. if ( !(pList->pSymList[i]->Duplicate) ) {
  560. _fputts("\t\\\n\t", fFile);
  561. PrintFullSymbolPath(fFile, szSymDir, pList->pSymList[i]->szSymSrcPath);
  562. }
  563. // Decide if this is the end of this cab
  564. if ( (i != pList->dwSize-1) &&
  565. (_tcsicmp(pList->pSymList[i]->szTmpCabName,
  566. pList->pSymList[i+1]->szTmpCabName) == 0) ) {
  567. newcab = FALSE;
  568. }
  569. else {
  570. newcab = TRUE;
  571. StringCbPrintf(buf, sizeof(buf), "\n\t!echo $?>>%s.txt\n\n",
  572. pList->pSymList[i]->szTmpCabName);
  573. _fputts(buf, fFile);
  574. }
  575. }
  576. cleanup:
  577. fflush(fFile);
  578. fclose(fFile);
  579. return rc;
  580. }
  581. BOOL
  582. CreateDDFs(
  583. PSYM_LIST pList,
  584. LPTSTR szOutDir, // Directory to write the DDFs to
  585. LPTSTR szSymDir,
  586. LPTSTR szCabDir
  587. )
  588. {
  589. BOOL newddf;
  590. FILE *fFile;
  591. TCHAR szCabName[_MAX_PATH*2];
  592. TCHAR buf[_MAX_PATH*2];
  593. DWORD i;
  594. if (szOutDir == NULL) return FALSE;
  595. newddf = TRUE;
  596. for (i=0; i<pList->dwSize; i++) {
  597. if (newddf) {
  598. newddf = FALSE;
  599. StringCbCopy(szCabName, sizeof(szCabName), szOutDir);
  600. StringCbCat(szCabName, sizeof(szCabName), _T("\\") );
  601. StringCbCat(szCabName, sizeof(szCabName), pList->pSymList[i]->szTmpCabName);
  602. StringCbCat(szCabName, sizeof(szCabName), _T(".ddf") );
  603. if ( (fFile = _tfopen(szCabName, _T("w") )) == NULL ) {
  604. printf( "Cannot open the ddf file %s for writing.\n",szCabName);
  605. return FALSE;
  606. }
  607. //
  608. // Write the header
  609. //
  610. // .option explicit will complain if you make a spelling error
  611. // in any of the other .set commands
  612. _fputts(".option explicit\n", fFile);
  613. // Tell what directory to write the cabs to:
  614. StringCbPrintf(buf, sizeof(buf), ".Set DiskDirectoryTemplate=%s\n", szCabDir);
  615. _fputts(buf, fFile);
  616. _fputts(".Set RptFileName=nul\n", fFile);
  617. _fputts(".Set InfFileName=nul\n", fFile);
  618. StringCbPrintf(buf, sizeof(buf), ".Set CabinetNameTemplate=%s.cab\n",
  619. pList->pSymList[i]->szTmpCabName);
  620. _fputts(buf, fFile);
  621. _fputts(".Set CompressionType=MSZIP\n", fFile);
  622. _fputts(".Set MaxDiskSize=CDROM\n", fFile);
  623. _fputts(".Set ReservePerCabinetSize=0\n", fFile);
  624. _fputts(".Set Compress=on\n", fFile);
  625. _fputts(".Set CompressionMemory=21\n", fFile);
  626. _fputts(".Set Cabinet=ON\n", fFile);
  627. _fputts(".Set MaxCabinetSize=999999999\n", fFile);
  628. _fputts(".Set FolderSizeThreshold=1000000\n", fFile);
  629. }
  630. // Write the file to the DDF
  631. if ( !pList->pSymList[i]->Duplicate) {
  632. fputs("\"",fFile); // begin quote
  633. PrintFullSymbolPath(fFile, szSymDir, pList->pSymList[i]->szSymSrcPath);
  634. fputs("\"",fFile); // end quote
  635. // optional rename and \n
  636. if ( pList->pSymList[i]->ReName) {
  637. StringCbPrintf( buf, sizeof(buf), " \"%s\"\n",
  638. pList->pSymList[i]->szSymReName);
  639. } else {
  640. StringCbPrintf(buf, sizeof(buf), "\n");
  641. }
  642. _fputts(buf, fFile);
  643. }
  644. // Check if this is the end of this DDF
  645. if ( i == pList->dwSize-1) {
  646. fflush(fFile);
  647. fclose(fFile);
  648. break;
  649. }
  650. // See if the next file in the list starts a new DDF
  651. if ( _tcsicmp(pList->pSymList[i]->szTmpCabName,
  652. pList->pSymList[i+1]->szTmpCabName) != 0 ) {
  653. fflush(fFile);
  654. fclose(fFile);
  655. newddf = TRUE;
  656. }
  657. }
  658. return TRUE;
  659. }
  660. BOOL
  661. CreateCDF(
  662. PSYM_LIST pList,
  663. LPTSTR szOutDir, // Directory to write the CDF to
  664. LPTSTR szSymDir, // Root of the symbols tree
  665. LPTSTR szSymCabName,
  666. LPTSTR szInfDir
  667. )
  668. {
  669. FILE *fFile;
  670. FILE *fFile2;
  671. TCHAR buf[_MAX_PATH*2];
  672. DWORD i;
  673. TCHAR szCDFName[_MAX_PATH];
  674. TCHAR szCDFMakefile[_MAX_PATH];
  675. if (szOutDir == NULL) return FALSE;
  676. if (szSymCabName == NULL) return FALSE;
  677. StringCbCopy(szCDFName, sizeof(szCDFName), szOutDir);
  678. StringCbCat( szCDFName, sizeof(szCDFName), _T("\\") );
  679. StringCbCat( szCDFName, sizeof(szCDFName), szSymCabName);
  680. // Create a makefile for this, so we can do incremental
  681. // adds to the CAT file.
  682. StringCbCopy(szCDFMakefile, sizeof(szCDFMakefile), szCDFName);
  683. StringCbCat( szCDFMakefile, sizeof(szCDFMakefile), _T(".CDF.makefile") );
  684. StringCbCat( szCDFName, sizeof(szCDFName), _T(".CDF.noheader") );
  685. if ( (fFile = _tfopen(szCDFName, _T("w") )) == NULL ) {
  686. printf( "Cannot open the CDF file %s for writing.\n",szCDFName);
  687. return FALSE;
  688. }
  689. if ( (fFile2 = _tfopen(szCDFMakefile, _T("w") )) == NULL ) {
  690. printf( "Cannot open the CDF file %s for writing.\n",szCDFMakefile);
  691. return FALSE;
  692. }
  693. // Write the first line of the makefile for the Catalog
  694. StringCbPrintf( buf, sizeof(buf), "%s\\%s.CAT:", szInfDir, szSymCabName );
  695. _fputts( buf, fFile2);
  696. for (i=0; i<pList->dwSize; i++) {
  697. // Write the file to the DDF
  698. if ( !pList->pSymList[i]->Duplicate) {
  699. _fputts("<HASH>", fFile );
  700. PrintFullSymbolPath(fFile, szSymDir, pList->pSymList[i]->szSymSrcPath);
  701. _fputts( "=", fFile);
  702. PrintFullSymbolPath(fFile, szSymDir, pList->pSymList[i]->szSymSrcPath);
  703. _fputts("\n", fFile);
  704. _fputts( " \\\n ", fFile2 );
  705. PrintFullSymbolPath(fFile2, szSymDir, pList->pSymList[i]->szSymSrcPath);
  706. }
  707. }
  708. // Write the last line of the makefile
  709. StringCbPrintf(buf, sizeof(buf), "\n\t!echo $? >> %s\\%s.update\n",
  710. szOutDir,
  711. szSymCabName );
  712. _fputts( buf, fFile2 );
  713. fflush(fFile);
  714. fclose(fFile);
  715. fflush(fFile2);
  716. fclose(fFile2);
  717. return TRUE;
  718. }
  719. BOOL
  720. CreateCabList(
  721. PSYM_LIST pList,
  722. LPTSTR szOutDir
  723. )
  724. {
  725. FILE *fFile;
  726. TCHAR buf[_MAX_PATH*2];
  727. DWORD i;
  728. BOOL rc;
  729. rc = TRUE;
  730. if (szOutDir == NULL) return FALSE;
  731. StringCbCopy(buf, sizeof(buf), szOutDir);
  732. MakeSureDirectoryPathExists(szOutDir);
  733. StringCbCat( buf, sizeof(buf), "\\");
  734. StringCbCat( buf, sizeof(buf), "symcabs.txt");
  735. if ( (fFile = _tfopen(buf, _T("w") )) == NULL ) {
  736. printf( "Cannot open %s for writing.\n",buf);
  737. return(FALSE);
  738. }
  739. if (pList->dwSize <= 0 ) {
  740. rc = FALSE;
  741. goto cleanup;
  742. }
  743. // First, print a list of all the targets
  744. StringCbPrintf(buf, sizeof(buf), "%s.cab\n",
  745. pList->pSymList[0]->szTmpCabName);
  746. _fputts(buf, fFile);
  747. for (i=1; i<pList->dwSize; i++) {
  748. if ( _tcsicmp(pList->pSymList[i]->szTmpCabName,
  749. pList->pSymList[i-1]->szTmpCabName) != 0 ) {
  750. StringCbPrintf(buf,sizeof(buf), "%s.cab\n",
  751. pList->pSymList[i]->szTmpCabName);
  752. _fputts(buf, fFile);
  753. }
  754. }
  755. cleanup:
  756. fflush(fFile);
  757. fclose(fFile);
  758. return (rc);
  759. }
  760. BOOL
  761. RenameAllTheFiles(
  762. PSYM_LIST pList
  763. )
  764. {
  765. DWORD i;
  766. PTCHAR pCh;
  767. // Rename all the files so that there is consistency in
  768. // file naming. This will help the transition to building
  769. // slip-streamed service packs.
  770. for (i=0; i<pList->dwSize; i++) {
  771. pList->pSymList[i]->ReName = TRUE;
  772. StringCbCopy(pList->pSymList[i]->szSymReName,
  773. sizeof(pList->pSymList[i]->szSymReName),
  774. pList->pSymList[i]->szSymName);
  775. StringCbCat(pList->pSymList[i]->szSymReName,
  776. sizeof(pList->pSymList[i]->szSymReName),
  777. _T("."));
  778. StringCbCat(pList->pSymList[i]->szSymReName,
  779. sizeof(pList->pSymList[i]->szSymReName),
  780. pList->pSymList[i]->szInstallPathX);
  781. }
  782. return (TRUE);
  783. }
  784. BOOL
  785. FindDuplicatesAndFilesToReName(
  786. PSYM_LIST pList
  787. )
  788. {
  789. DWORD i;
  790. PTCHAR pCh;
  791. // Its a duplicate if the symbol file has the same name and its
  792. // exe has the same extension (i.e., it has the same cab name
  793. pList->pSymList[0]->Duplicate = FALSE;
  794. pList->pSymList[0]->ReName = FALSE;
  795. for (i=1; i<pList->dwSize; i++) {
  796. // See if file name is duplicate
  797. if ( _tcsicmp(pList->pSymList[i]->szSymName,
  798. pList->pSymList[i-1]->szSymName) == 0) {
  799. // These two symbol files have the same name. See if
  800. // they get installed to the same directory.
  801. if (_tcsicmp(pList->pSymList[i]->szInstallPath,
  802. pList->pSymList[i-1]->szInstallPath) == 0) {
  803. // We will ignore this file later
  804. pList->pSymList[i]->Duplicate = TRUE;
  805. } else {
  806. // There are two versions of this file, but they
  807. // are each different and get installed to different
  808. // directories. One of them will need to be renamed
  809. // since the names inside cabs and infs need to be
  810. // unique.
  811. pList->pSymList[i]->ReName = TRUE;
  812. StringCbCopy(pList->pSymList[i]->szSymReName,
  813. sizeof(pList->pSymList[i]->szSymReName),
  814. pList->pSymList[i]->szSymName);
  815. StringCbCat( pList->pSymList[i]->szSymReName,
  816. sizeof(pList->pSymList[i]->szSymReName),
  817. _T("."));
  818. StringCbCat( pList->pSymList[i]->szSymReName,
  819. sizeof(pList->pSymList[i]->szSymReName),
  820. pList->pSymList[i]->szInstallPathX);
  821. }
  822. }
  823. else {
  824. pList->pSymList[i]->Duplicate = FALSE;
  825. pList->pSymList[i]->ReName = FALSE;
  826. }
  827. }
  828. return (TRUE);
  829. }
  830. //
  831. // defines and structure for CreateInf
  832. //
  833. #define _MAX_STRING 40 // max length for strings
  834. #define INSTALL_SECTION_COUNT 6 // number of install sections
  835. typedef struct _INSTALL_SECTION_INFO {
  836. CHAR SectionName[ _MAX_STRING+1]; // required
  837. CHAR CustomDestination[_MAX_STRING+1]; // required
  838. CHAR BeginPrompt[ _MAX_STRING+1]; // optional
  839. CHAR EndPrompt[ _MAX_STRING+1]; // optional
  840. } INSTALL_SECTION_INFO;
  841. BOOL
  842. CreateInf(
  843. PSYM_LIST pList,
  844. LPTSTR szInfDir,
  845. LPTSTR szSymCabName
  846. )
  847. {
  848. FILE *fFile;
  849. TCHAR buf[_MAX_PATH*2];
  850. TCHAR szCurInstallPathX[_MAX_PATH+1];
  851. DWORD i, dwCurDisk;
  852. INSTALL_SECTION_INFO InstallSections[INSTALL_SECTION_COUNT];
  853. INT iLoop;
  854. if (szInfDir == NULL) return FALSE;
  855. if (szSymCabName == NULL) return FALSE;
  856. // make all strings empty by default
  857. ZeroMemory(InstallSections, sizeof(InstallSections));
  858. // setup the variable data for each section
  859. StringCbCopy(InstallSections[0].SectionName, sizeof(InstallSections[0].SectionName), "DefaultInstall");
  860. StringCbCopy(InstallSections[0].CustomDestination, sizeof(InstallSections[0].CustomDestination), "CustDest");
  861. StringCbCopy(InstallSections[0].BeginPrompt, sizeof(InstallSections[0].BeginPrompt), "BeginPromptSection");
  862. StringCbCopy(InstallSections[0].EndPrompt, sizeof(InstallSections[0].EndPrompt), "EndPromptSection");
  863. StringCbCopy(InstallSections[1].SectionName, sizeof(InstallSections[1].SectionName), "DefaultInstall.Quiet");
  864. StringCbCopy(InstallSections[1].CustomDestination, sizeof(InstallSections[1].CustomDestination), "CustDest.2");
  865. StringCbCopy(InstallSections[2].SectionName, sizeof(InstallSections[2].SectionName), "DefaultInstall.Chained.1");
  866. StringCbCopy(InstallSections[2].CustomDestination, sizeof(InstallSections[2].CustomDestination), "CustDest");
  867. StringCbCopy(InstallSections[2].BeginPrompt, sizeof(InstallSections[2].BeginPrompt), "BeginPromptSection");
  868. StringCbCopy(InstallSections[3].SectionName, sizeof(InstallSections[3].SectionName), "DefaultInstall.Chained.1.Quiet");
  869. StringCbCopy(InstallSections[3].CustomDestination, sizeof(InstallSections[3].CustomDestination), "CustDest.2");
  870. StringCbCopy(InstallSections[4].SectionName, sizeof(InstallSections[4].SectionName), "DefaultInstall.Chained.2");
  871. StringCbCopy(InstallSections[4].CustomDestination, sizeof(InstallSections[4].CustomDestination), "CustDest.2");
  872. StringCbCopy(InstallSections[4].EndPrompt, sizeof(InstallSections[4].EndPrompt), "EndPromptSection");
  873. StringCbCopy(InstallSections[5].SectionName, sizeof(InstallSections[5].SectionName), "DefaultInstall.Chained.2.Quiet");
  874. StringCbCopy(InstallSections[5].CustomDestination, sizeof(InstallSections[5].CustomDestination), "CustDest.2");
  875. StringCbCopy(buf, sizeof(buf), szInfDir);
  876. MakeSureDirectoryPathExists(szInfDir);
  877. // Get the name of the inf ... name it the same as the cabs
  878. // with an .inf extension
  879. StringCbCat(buf, sizeof(buf), _T("\\"));
  880. StringCbCat(buf, sizeof(buf), szSymCabName);
  881. StringCbCat(buf, sizeof(buf), _T(".inf") );
  882. if ( (fFile = _tfopen(buf, _T("w") )) == NULL ) {
  883. printf( "Cannot open %s for writing.\n",buf);
  884. return FALSE;
  885. }
  886. // Write the header for the inf
  887. _fputts("[Version]\n", fFile);
  888. _fputts("AdvancedInf= 2.5\n", fFile);
  889. _fputts("Signature= \"$CHICAGO$\"\n", fFile);
  890. StringCbPrintf(buf, sizeof(buf), "CatalogFile= %s.CAT\n", szSymCabName);
  891. _fputts(buf, fFile);
  892. _fputts("\n", fFile);
  893. //
  894. // Do the default installs
  895. // This inf has options for how it will be called. It has
  896. // provision for a chained incremental install.
  897. //
  898. // DefaultInstall -- standalone install.
  899. // DefaultInstall.Quiet -- standalone with no UI intervention
  900. // DefaultInstall.Chained.1 -- first part of a chained install
  901. // DefaultInstall.Chained.1.Quiet -- first part of a chained install with no UI intervention
  902. // DefaultInstall.Chained.2 -- second part of a chained install
  903. // DefaultInstall.Chained.2.Quiet -- second part of a chained install with no UI intervention
  904. //
  905. //
  906. // Do the install sections
  907. //
  908. for (iLoop = 0; iLoop < INSTALL_SECTION_COUNT; iLoop++) {
  909. fprintf(fFile, "[%s]\n" , InstallSections[iLoop].SectionName);
  910. fprintf(fFile, "CustomDestination=%s\n", InstallSections[iLoop].CustomDestination);
  911. // BeginPrompt is optional
  912. if (strlen(InstallSections[iLoop].BeginPrompt) > 0) {
  913. fprintf(fFile, "BeginPrompt=%s\n", InstallSections[iLoop].BeginPrompt);
  914. }
  915. // EndPrompt is optional
  916. if (strlen(InstallSections[iLoop].EndPrompt) > 0) {
  917. fprintf(fFile, "EndPrompt=%s\n", InstallSections[iLoop].EndPrompt);
  918. }
  919. // from here to end of loop, output is identical for all sections
  920. _fputts("AddReg= RegVersion\n", fFile);
  921. _fputts("RequireEngine= Setupapi;\n", fFile);
  922. //
  923. // Print the Copyfiles line
  924. //
  925. _fputts("CopyFiles= ", fFile);
  926. // First, sort the list by Install Path
  927. qsort( (void*)pList->pSymList, (size_t)pList->dwSize,
  928. (size_t)sizeof(PSYM_FILE), SymSortByInstallPath);
  929. // Print the files sections that need to be installed
  930. StringCbPrintf( buf, sizeof(buf), "Files.%s",
  931. pList->pSymList[0]->szInstallPathX);
  932. _fputts(buf, fFile);
  933. StringCbCopy(szCurInstallPathX, sizeof(szCurInstallPathX), pList->pSymList[0]->szInstallPathX);
  934. for (i=0; i<pList->dwSize; i++) {
  935. if ( pList->pSymList[i]->Duplicate) continue;
  936. // See if we have a new files section
  937. if ( _tcsicmp( pList->pSymList[i]->szInstallPathX,
  938. szCurInstallPathX) != 0 ) {
  939. // Print the files sections
  940. StringCbPrintf(buf, sizeof(buf), ", Files.%s",
  941. pList->pSymList[i]->szInstallPathX);
  942. _fputts(buf, fFile);
  943. StringCbCopy(szCurInstallPathX, sizeof(szCurInstallPathX), pList->pSymList[i]->szInstallPathX);
  944. }
  945. }
  946. _fputts("\n\n", fFile);
  947. } // end of install sections loop
  948. // Print the Default Uninstall line
  949. //
  950. _fputts("[DefaultUninstall]\n", fFile);
  951. _fputts("CustomDestination= CustDest\n", fFile);
  952. _fputts("BeginPrompt= DelBeginPromptSection\n", fFile);
  953. _fputts("DelFiles= ", fFile);
  954. // Print the files sections that need to be installed
  955. StringCbPrintf(buf, sizeof(buf), "Files.%s", pList->pSymList[0]->szInstallPathX);
  956. _fputts(buf, fFile);
  957. StringCbCopy(szCurInstallPathX, sizeof(szCurInstallPathX), pList->pSymList[0]->szInstallPathX);
  958. for (i=0; i<pList->dwSize; i++) {
  959. if ( pList->pSymList[i]->Duplicate) continue;
  960. // See if we have a new files section
  961. if ( _tcsicmp( pList->pSymList[i]->szInstallPathX,
  962. szCurInstallPathX) != 0 ) {
  963. // Print the files sections
  964. StringCbPrintf(buf, sizeof(buf), ", Files.%s",
  965. pList->pSymList[i]->szInstallPathX);
  966. _fputts(buf, fFile);
  967. StringCbCopy(szCurInstallPathX, sizeof(szCurInstallPathX), pList->pSymList[i]->szInstallPathX);
  968. }
  969. }
  970. _fputts("\n", fFile);
  971. _fputts("DelDirs= DelDirsSection\n", fFile);
  972. _fputts("DelReg= RegVersion\n", fFile);
  973. _fputts("EndPrompt= DelEndPromptSection\n", fFile);
  974. _fputts("RequireEngine= Setupapi;\n\n", fFile);
  975. //
  976. // Print the [BeginPromptSection]
  977. //
  978. _fputts("[BeginPromptSection]\n", fFile);
  979. _fputts("Title= \"Microsoft Windows Symbols\"\n", fFile);
  980. _fputts("\n", fFile);
  981. //
  982. // Print the [DelBeginPromptSection]
  983. //
  984. _fputts("[DelBeginPromptSection]\n", fFile);
  985. _fputts("Title= \"Microsoft Windows Symbol Uninstall\"\n", fFile);
  986. _fputts("ButtonType= YESNO\n", fFile);
  987. _fputts("Prompt= \"Do you want to remove Microsoft Windows Symbols?\"\n", fFile);
  988. _fputts("\n", fFile);
  989. //
  990. // Print the [EndPromptSection]
  991. //
  992. _fputts("[EndPromptSection]\n", fFile);
  993. _fputts("Title= \"Microsoft Windows Symbols\"\n", fFile);
  994. _fputts("Prompt= \"Installation is complete\"\n", fFile);
  995. _fputts("\n", fFile);
  996. //
  997. // Print the [DelEndPromptSection]
  998. //
  999. _fputts("[DelEndPromptSection]\n", fFile);
  1000. _fputts("Prompt= \"Uninstall is complete\"\n", fFile);
  1001. _fputts("\n", fFile);
  1002. //
  1003. // Print the [RegVersion] Section
  1004. //
  1005. _fputts("[RegVersion]\n", fFile);
  1006. _fputts("\"HKLM\",\"SOFTWARE\\Microsoft\\Symbols\\Directories\",\"Symbol Dir\",0,\"%49100%\"\n", fFile);
  1007. _fputts("\"HKCU\",\"SOFTWARE\\Microsoft\\Symbols\\Directories\",\"Symbol Dir\",0,\"%49100%\"\n", fFile);
  1008. _fputts("\"HKCU\",\"SOFTWARE\\Microsoft\\Symbols\\SymbolInstall\",\"Symbol Install\",,\"1\"\n", fFile);
  1009. _fputts(";\"HKLM\",\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Symbols\",\"DisplayName\",,\"Microsoft Windows Symbols\"\n", fFile);
  1010. _fputts(";\"HKLM\",\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Symbols\",\"UninstallString\",,\"RunDll32.exe advpack.dll,LaunchINFSection symusa.inf,DefaultUninstall\"\n", fFile);
  1011. _fputts(";\"HKLM\",\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Symbols\",\"RequiresIESysFile\",,\"4.71\"\n", fFile);
  1012. _fputts("\n", fFile);
  1013. //
  1014. // Print the Custom Destination Section
  1015. //
  1016. _fputts("[SymCust]\n", fFile);
  1017. _fputts("\"HKCU\", \"Software\\Microsoft\\Symbols\\Directories\",\"Symbol Dir\",\"Symbols install directory\",\"%25%\\Symbols\"\n", fFile);
  1018. _fputts("\n", fFile);
  1019. //
  1020. // Print the CustDest section
  1021. //
  1022. _fputts("[CustDest]\n", fFile);
  1023. _fputts("49100=SymCust,1\n", fFile);
  1024. _fputts("\n", fFile);
  1025. //
  1026. // Print the CustDest section
  1027. // Don't prompt the user for where to install, just read
  1028. // it out of the registry
  1029. //
  1030. _fputts("[CustDest.2]\n", fFile);
  1031. _fputts("49100=SymCust,5\n", fFile);
  1032. _fputts("\n", fFile);
  1033. //
  1034. // Print the DestinationDirs section
  1035. //
  1036. StringCbCopy(szCurInstallPathX, sizeof(szCurInstallPathX), "");
  1037. _fputts("[DestinationDirs]\n", fFile);
  1038. _fputts(";49100 is %systemroot%\\symbols\n", fFile);
  1039. _fputts("\n", fFile);
  1040. _fputts("Files.inf\t\t\t= 17\n", fFile);
  1041. _fputts("Files.system32\t\t\t= 11\n", fFile);
  1042. for (i=0; i<pList->dwSize; i++) {
  1043. if ( pList->pSymList[i]->Duplicate) continue;
  1044. // See if we have a new files section
  1045. if ( _tcsicmp( pList->pSymList[i]->szInstallPathX,
  1046. szCurInstallPathX) != 0 ) {
  1047. // Print the files sections
  1048. StringCbPrintf(buf, sizeof(buf), "Files.%s\t\t\t= 49100,\"%s\"\n",
  1049. pList->pSymList[i]->szInstallPathX,
  1050. pList->pSymList[i]->szInstallPath
  1051. );
  1052. _fputts(buf, fFile);
  1053. StringCbCopy(szCurInstallPathX, sizeof(szCurInstallPathX), pList->pSymList[i]->szInstallPathX);
  1054. }
  1055. }
  1056. _fputts("\n", fFile);
  1057. //
  1058. // Print the DelDirsSection
  1059. //
  1060. StringCbCopy(szCurInstallPathX, sizeof(szCurInstallPathX), pList->pSymList[0]->szInstallPathX);
  1061. _fputts("[DelDirsSection]\n", fFile);
  1062. for (i=0; i<pList->dwSize; i++) {
  1063. if ( pList->pSymList[i]->Duplicate) continue;
  1064. // See if we have a new files section
  1065. if ( _tcsicmp( pList->pSymList[i]->szInstallPathX,
  1066. szCurInstallPathX) != 0 ) {
  1067. // Print the files sections
  1068. _fputts("%49100%\\", fFile);
  1069. _fputts(pList->pSymList[i]->szInstallPath, fFile);
  1070. _fputts("\n", fFile);
  1071. StringCbCopy(szCurInstallPathX, sizeof(szCurInstallPathX), pList->pSymList[i]->szInstallPathX);
  1072. }
  1073. }
  1074. _fputts("%49100%\n\n", fFile);
  1075. //
  1076. // Print the files section
  1077. //
  1078. _fputts("[Files.inf]\n", fFile);
  1079. StringCbPrintf(buf, sizeof(buf), "%s.inf,,,4\n\n", szSymCabName);
  1080. _fputts(buf, fFile);
  1081. _fputts("[Files.system32.x86]\n", fFile);
  1082. _fputts("advpack.dll,,,96\n\n", fFile);
  1083. _fputts("[Files.system32.alpha]\n", fFile);
  1084. _fputts("advpack.dll, advpacka.dll,,96\n\n", fFile);
  1085. StringCbPrintf(buf, sizeof(buf), "[Files.%s]\n", pList->pSymList[0]->szInstallPathX);
  1086. _fputts(buf, fFile);
  1087. StringCbCopy(szCurInstallPathX, sizeof(szCurInstallPathX), pList->pSymList[0]->szInstallPathX);
  1088. for (i=0; i<pList->dwSize; i++) {
  1089. if ( pList->pSymList[i]->Duplicate) continue;
  1090. // See if we have a new files section
  1091. if ( _tcsicmp( pList->pSymList[i]->szInstallPathX,
  1092. szCurInstallPathX) != 0 ) {
  1093. // Print the files sections
  1094. StringCbPrintf(buf, sizeof(buf), "\n[Files.%s]\n",
  1095. pList->pSymList[i]->szInstallPathX);
  1096. _fputts(buf, fFile);
  1097. StringCbCopy(szCurInstallPathX, sizeof(szCurInstallPathX), pList->pSymList[i]->szInstallPathX);
  1098. }
  1099. // Print the file name inside the cab
  1100. StringCbPrintf(buf, sizeof(buf), "%s,%s,,4\n", pList->pSymList[i]->szSymName,
  1101. pList->pSymList[i]->szSymReName);
  1102. _fputts(buf, fFile);
  1103. }
  1104. // Print the SourceDisksNames section
  1105. // First sort the list by the final cab name
  1106. qsort( (void*)pList->pSymList, (size_t)pList->dwSize,
  1107. (size_t)sizeof(PSYM_FILE), SymSortByCabNumber);
  1108. _fputts("\n[SourceDisksNames]\n", fFile);
  1109. dwCurDisk = -1;
  1110. // Print the SourceDisks section
  1111. for (i=0; i<pList->dwSize; i++) {
  1112. if ( pList->pSymList[i]->dwCabNumber != dwCurDisk ) {
  1113. // New cab name
  1114. dwCurDisk = pList->pSymList[i]->dwCabNumber;
  1115. StringCbPrintf(buf, sizeof(buf), "%1d=\"%s.cab\",%s.cab,0\n",
  1116. dwCurDisk,
  1117. pList->pSymList[i]->szCabName,
  1118. pList->pSymList[i]->szCabName);
  1119. _fputts(buf, fFile);
  1120. }
  1121. }
  1122. // Print the SourceDisksFiles section
  1123. _fputts("\n[SourceDisksFiles]\n", fFile);
  1124. for (i=0; i<pList->dwSize; i++) {
  1125. if ( pList->pSymList[i]->ReName ) {
  1126. StringCbPrintf(buf, sizeof(buf), "%s=%1d\n",
  1127. pList->pSymList[i]->szSymReName,
  1128. pList->pSymList[i]->dwCabNumber );
  1129. } else {
  1130. StringCbPrintf(buf, sizeof(buf), "%s=%1d\n",
  1131. pList->pSymList[i]->szSymName,
  1132. pList->pSymList[i]->dwCabNumber );
  1133. }
  1134. _fputts(buf, fFile);
  1135. }
  1136. fflush(fFile);
  1137. fclose(fFile);
  1138. return TRUE;
  1139. }
  1140. BOOL FreePList(
  1141. PSYM_LIST pList
  1142. )
  1143. {
  1144. DWORD i;
  1145. if ( pList==NULL ) return TRUE;
  1146. if ( pList->pSymList == NULL ) {
  1147. free(pList);
  1148. return (TRUE);
  1149. }
  1150. for (i=0; i<pList->dwSize; i++) {
  1151. free(pList->pSymList[i]);
  1152. }
  1153. free(pList->pSymList);
  1154. free(pList);
  1155. return (TRUE);
  1156. }
  1157. /* ------------------------------------------------------------------------------------------------
  1158. Prints the fully qualified path to a symbol using the following logic:
  1159. - if SymbolRoot is NULL, assume SymbolPath is a fully qualified path and print it
  1160. - if SymbolPath begins with "%c:\" or "\\", assume SymbolPath is fully qualified and print it
  1161. - assume the concatenation "SymbolRoot\\SymbolPath" is the fully qualified path and print it
  1162. ------------------------------------------------------------------------------------------------ */
  1163. BOOL PrintFullSymbolPath(IN FILE* OutputFile, IN OPTIONAL LPTSTR SymbolRoot, IN LPTSTR SymbolPath) {
  1164. if ( (OutputFile == NULL) || (SymbolPath == NULL) ) {
  1165. return(FALSE);
  1166. }
  1167. if (SymbolRoot == NULL) {
  1168. fprintf(OutputFile, "%s", SymbolPath);
  1169. } else if (isalpha(SymbolPath[0]) && SymbolPath[1] == ':' && SymbolPath[2] == '\\') {
  1170. fprintf(OutputFile, "%s", SymbolPath);
  1171. } else if (SymbolPath[0] == '\\' && SymbolPath[1] == '\\') {
  1172. fprintf(OutputFile, "%s", SymbolPath);
  1173. } else {
  1174. fprintf(OutputFile, "%s\\%s", SymbolRoot, SymbolPath);
  1175. }
  1176. return(TRUE);
  1177. }