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.

829 lines
24 KiB

  1. /*++
  2. Copyright Microsoft Corporation, 1996-7, All Rights Reserved.
  3. Module Name:
  4. mkupdate.c
  5. Abstract:
  6. Application for creating the update database file from an
  7. appropriately structured input update file and maintaining
  8. the driver version in the resource file.
  9. Author:
  10. Shivnandan Kaushik
  11. Environment:
  12. User mode
  13. Revision History:
  14. --*/
  15. #include <windows.h>
  16. #include <stdio.h>
  17. #include <winbase.h>
  18. #include <winioctl.h>
  19. #include <fcntl.h>
  20. #include <stdlib.h>
  21. #include <io.h>
  22. #include <string.h>
  23. #include "mkupdate.h"
  24. //
  25. // Globals
  26. //
  27. PUPDATE_ENTRY UpdateTable;
  28. VOID
  29. GenMSHeader(
  30. FILE *file,
  31. CHAR *Filename,
  32. CHAR *Abstract
  33. )
  34. /*++
  35. Routine Description:
  36. Generates the Microsoft recommended header for code files.
  37. Arguments:
  38. File: Output file pointer
  39. FileName: Output file name
  40. Abstract: Description of file
  41. Return Value:
  42. None
  43. --*/
  44. {
  45. fprintf(file,"/*++ \n\nCopyright (c) 1996-7 Microsoft Corporation, ");
  46. fprintf(file,"All Rights Reserved.\n\n");
  47. fprintf(file,"Copyright (c) 1995-2000 Intel Corporation. This update binary code\n");
  48. fprintf(file,"is distributed for the sole purpose of being loaded into Intel\n");
  49. fprintf(file,"Pentium(R) Pro Processor Family and Pentium(R) 4 Family microprocessors.\n");
  50. fprintf(file,"All Rights on the binary code are reserved.\n\n");
  51. fprintf(file,"Module Name:\n\n %s\n\n",Filename);
  52. fprintf(file,"Abstract:\n\n %s\n\n",Abstract);
  53. fprintf(file,"Author:\n\n !!!THIS IS A GENERATED FILE. DO NOT DIRECTLY EDIT!!!\n\n");
  54. fprintf(file,"Revision History:\n\n--*/\n\n");
  55. }
  56. BOOL
  57. GetVerifyPutUpdate(
  58. FILE *OutputFile,
  59. ULONG UpdateNum,
  60. ULONG TotalUpdates
  61. )
  62. /*++
  63. Routine Description:
  64. Read in an update, verify it and write to data file.
  65. Arguments:
  66. OutputFile: output file pointer
  67. UpdateNum: Update number in update list
  68. TotalUpdates: Total number of updates in update list.
  69. Return Value:
  70. TRUE if writes succeeded else FALSE.
  71. --*/
  72. {
  73. FILE *UpdateFile;
  74. CHAR Line[MAX_LINE],UpdateString[MAX_LINE];
  75. CHAR Filename[MAX_PATH];
  76. BOOL BeginFound,EndFound;
  77. ULONG CurrentDword,i,Checksum;
  78. ULONG UpdateBuffer[sizeof(UPDATE)];
  79. PUPDATE CurrentUpdate;
  80. // create the string name of the file to open
  81. strcpy(Filename,UpdateTable[UpdateNum].CpuSigStr);
  82. strcat(Filename,"_");
  83. strcat(Filename,UpdateTable[UpdateNum].UpdateRevStr);
  84. strcat(Filename,".");
  85. strcat(Filename,UpdateTable[UpdateNum].FlagsStr);
  86. UpdateFile = fopen(Filename,"r");
  87. if (UpdateFile == NULL) {
  88. fprintf(stdout,"mkupdate:Unable to open update input file %s\n",Filename);
  89. return(FALSE);
  90. }
  91. //
  92. // Read in each update - scan till beginning of update
  93. // marked by keyword BEGIN_UPDATE
  94. //
  95. BeginFound = FALSE;
  96. while (fgets(Line,MAX_LINE,UpdateFile) != NULL) {
  97. if (sscanf(Line,"%s",&UpdateString)) {
  98. if (strcmp(UpdateString,"BEGIN_UPDATE") == 0) {
  99. BeginFound = TRUE;
  100. break;
  101. }
  102. }
  103. }
  104. if (!BeginFound) {
  105. fprintf(stdout,"mkupdate:BEGIN_UPDATE not found in update file %s\n",Filename);
  106. fclose(UpdateFile);
  107. return(FALSE);
  108. }
  109. //
  110. // scan "update size" forward.
  111. //
  112. EndFound = FALSE;
  113. for (i = 0; i < sizeof(UPDATE)/sizeof(ULONG); i++) {
  114. if (fgets(Line,MAX_LINE,UpdateFile) != NULL) {
  115. if (sscanf(Line,"%lx",&CurrentDword))
  116. UpdateBuffer[i] = CurrentDword;
  117. } else {
  118. EndFound = TRUE;
  119. break;
  120. }
  121. }
  122. if (EndFound) {
  123. fprintf(stdout,"mkupdate:Abnormal termination of update file %s\n",Filename);
  124. fclose(UpdateFile);
  125. return(FALSE);
  126. } else {
  127. if (fgets(Line,MAX_LINE,UpdateFile) != NULL) {
  128. if (sscanf(Line,"%s",&UpdateString)) {
  129. if (strcmp(UpdateString,"END_UPDATE") != 0) {
  130. fprintf(stdout,"mkupdate:Update data size in %s incorrect\n",Filename);
  131. fclose(UpdateFile);
  132. return(FALSE);
  133. }
  134. }
  135. } else {
  136. fprintf(stdout,"mkupdate:Abnormal termination of update file %s\n",Filename);
  137. fclose(UpdateFile);
  138. return(FALSE);
  139. }
  140. }
  141. fclose (UpdateFile);
  142. // Verify Update - Checksum Buffer
  143. Checksum = 0;
  144. for (i = 0; i < sizeof(UPDATE)/sizeof(ULONG); i++) {
  145. Checksum += UpdateBuffer[i];
  146. }
  147. if (Checksum){
  148. fprintf(stdout,"mkupdate:Incorrect update checksum in %s\n",Filename);
  149. return(FALSE);
  150. }
  151. //
  152. // Verify update - check if processor signature, update revision
  153. // and processor flags match that specified in listing file and
  154. // update data file name
  155. //
  156. CurrentUpdate = (PUPDATE) UpdateBuffer;
  157. if ((CurrentUpdate->Processor.u.LongPart !=
  158. UpdateTable[UpdateNum].CpuSignature)){
  159. fprintf(stdout,"mkupdate:incorrect processor signature in %s: ",Filename);
  160. fprintf(stdout,"expected 0x%lx got 0x%lx\n",
  161. UpdateTable[UpdateNum].CpuSignature,
  162. CurrentUpdate->Processor.u.LongPart);
  163. return(FALSE);
  164. }
  165. if (CurrentUpdate->UpdateRevision !=
  166. UpdateTable[UpdateNum].UpdateRevision){
  167. fprintf(stdout,"mkupdate:incorrect update revision in %s: ",Filename);
  168. fprintf(stdout,"expected 0x%lx got 0x%lx\n",
  169. UpdateTable[UpdateNum].UpdateRevision,
  170. CurrentUpdate->UpdateRevision);
  171. return(FALSE);
  172. }
  173. if ((CurrentUpdate->ProcessorFlags.u.LongPart !=
  174. UpdateTable[UpdateNum].ProcessorFlags)){
  175. fprintf(stdout,"mkupdate:incorrect processor flags in %s: ",Filename);
  176. fprintf(stdout,"expected 0x%lx got 0x%lx\n",
  177. UpdateTable[UpdateNum].ProcessorFlags,
  178. CurrentUpdate->ProcessorFlags.u.LongPart);
  179. return(FALSE);
  180. }
  181. //
  182. // Input update validated. Write out validated update
  183. //
  184. fprintf(OutputFile," {\n");
  185. for (i = 0; i < sizeof(UPDATE)/sizeof(ULONG); i++) {
  186. fprintf(OutputFile," 0x%.8x",UpdateBuffer[i]);
  187. if (i == sizeof(UPDATE)/sizeof(ULONG) - 1) {
  188. fprintf(OutputFile,"\n");
  189. } else {
  190. fprintf(OutputFile,",\n");
  191. }
  192. }
  193. fprintf(OutputFile," }");
  194. if (UpdateNum != TotalUpdates-1) {
  195. fprintf(OutputFile,",\n");
  196. }
  197. return(TRUE);
  198. }
  199. VOID
  200. BuildUpdateInfoTable(
  201. FILE *OutputFile,
  202. ULONG TotalUpdates
  203. )
  204. /*++
  205. Routine Description:
  206. Write the CPU Signature and Processor Flags into the
  207. Build Table and adds NULL for the MDL Item.
  208. Arguments:
  209. OutputFile : output file pointer
  210. TotalUpdates : Total number of updates in update list.
  211. Return Value:
  212. None:
  213. --*/
  214. {
  215. ULONG CpuSignature, ProcessorFlags, i;
  216. fprintf(OutputFile, "//\n// Update Info Table containing the CPU Signatures,\n");
  217. fprintf(OutputFile, "// Processor Flags, and MDL Pointers. The MDL Pointers\n");
  218. fprintf(OutputFile, "// are initialized to NULL. They get populated as pages\n");
  219. fprintf(OutputFile, "// corresponding to specific updates are locked in memory.\n");
  220. fprintf(OutputFile, "// This table contains the CPU Signatures and Processor Flags.\n");
  221. fprintf(OutputFile, "// in the same order as in the update database. Therefore,\n");
  222. fprintf(OutputFile, "// the Update Info Table self-indexes to the right update.\n//\n\n");
  223. fprintf(OutputFile, "UPDATE_INFO UpdateInfo[] = {\n");
  224. //
  225. // Add each entry for the info
  226. //
  227. for (i = 0; i < TotalUpdates; i++) {
  228. CpuSignature = strtoul(UpdateTable[i].CpuSigStr, NULL, 16);
  229. ProcessorFlags = strtoul(UpdateTable[i].FlagsStr, NULL, 16);
  230. if (i < (TotalUpdates - 1)) {
  231. fprintf(OutputFile, " {0x%x, 0x%x, NULL},\n", CpuSignature, ProcessorFlags);
  232. } else {
  233. fprintf(OutputFile, " {0x%x, 0x%x, NULL}\n", CpuSignature, ProcessorFlags);
  234. }
  235. }
  236. //
  237. // generate closing code for the update info definition
  238. //
  239. fprintf(OutputFile, "};\n");
  240. return;
  241. }
  242. ULONG
  243. PopulateUpdateList(
  244. CHAR *ListingFile
  245. )
  246. /*++
  247. Routine Description:
  248. Populates the update list with (processor signature, update revision)
  249. pairs included in the update listing file and returns the number of
  250. updates found.
  251. Arguments:
  252. ListingFile
  253. Return Value:
  254. Number of updates in the update list. 0 if no updates found or any
  255. error encountered.
  256. --*/
  257. {
  258. CHAR Line[MAX_LINE],UpdateString[MAX_LINE];
  259. CHAR CpuSigStr[MAX_LINE],UpdateRevStr[MAX_LINE];
  260. CHAR FlagsStr[MAX_LINE];
  261. BOOL BeginFound,EndFound,Error;
  262. FILE *TmpFilePtr;
  263. ULONG NumUpdates,i;
  264. ULONG CpuSignature,UpdateRevision,ProcessorFlags;
  265. #ifdef DEBUG
  266. fprintf(stderr,"listing file %s\n",ListingFile);
  267. #endif
  268. // Open the update listing file
  269. TmpFilePtr = fopen(ListingFile,"r");
  270. if (TmpFilePtr == NULL) {
  271. fprintf(stdout,"mkupdate:Unable to open update listing file %s\n",ListingFile);
  272. return(0);
  273. };
  274. //
  275. // Scan for beginning of the update list marked by
  276. // BEGIN_UPDATE_LIST keyword
  277. //
  278. BeginFound = FALSE;
  279. while ((!BeginFound) && (fgets(Line,MAX_LINE,TmpFilePtr) != NULL)) {
  280. if (sscanf(Line,"%s",&UpdateString)) {
  281. if (strcmp(UpdateString,"BEGIN_UPDATE_LIST") == 0) {
  282. BeginFound = TRUE;
  283. }
  284. }
  285. }
  286. if (!BeginFound) {
  287. fprintf(stdout,"mkupdate:BEGIN_UPDATE_LIST not found in update listing file %s\n",ListingFile);
  288. fclose(TmpFilePtr);
  289. return(0);
  290. };
  291. //
  292. // Scan for end of the update list marked by
  293. // END_UPDATE_LIST keyword and count # updates.
  294. //
  295. NumUpdates = 0;
  296. EndFound = FALSE;
  297. while ((!EndFound) && (fgets(Line,MAX_LINE,TmpFilePtr) != NULL)) {
  298. if (sscanf(Line,"%s",&UpdateString)) {
  299. if (strcmp(UpdateString,"END_UPDATE_LIST") == 0) {
  300. EndFound = TRUE;
  301. } else {
  302. NumUpdates++;
  303. }
  304. }
  305. }
  306. fclose(TmpFilePtr);
  307. if (!EndFound) {
  308. fprintf(stdout,"mkupdate:END_UPDATE_LIST not found in update listing file %s\n",ListingFile);
  309. return(0);
  310. }
  311. //
  312. // If legal file format and non-zero number of updates are found
  313. // then read the processor signatures and update revisions into
  314. // the update list.
  315. //
  316. if (NumUpdates) {
  317. // allocate memory for storing cpu signatures
  318. UpdateTable = (UPDATE_ENTRY *) malloc(NumUpdates*sizeof(UPDATE_ENTRY));
  319. if (UpdateTable == NULL){
  320. fprintf(stdout,"mkupdate:Error: Memory Allocation Error\n");
  321. return(0);
  322. }
  323. TmpFilePtr = fopen(ListingFile,"r");
  324. if (TmpFilePtr == NULL) {
  325. fprintf(stdout,"mkupdate:Unable to open update listing file %s\n",ListingFile);
  326. return(0);
  327. };
  328. while ((fgets(Line,MAX_LINE,TmpFilePtr) != NULL)) {
  329. if (sscanf(Line,"%s",&UpdateString)) {
  330. if (strcmp(UpdateString,"BEGIN_UPDATE_LIST") == 0) {
  331. break;
  332. }
  333. }
  334. }
  335. // Scan the listing file and populate the update table
  336. Error = FALSE;
  337. for (i = 0; i < NumUpdates; i++) {
  338. if (fgets(Line,MAX_LINE,TmpFilePtr) == NULL) {
  339. fprintf(stdout,"mkupdate: Abnormal termination in update listing file %s\n",
  340. ListingFile);
  341. Error = TRUE;
  342. break;
  343. }
  344. if (sscanf(Line,"%s %s %s",&CpuSigStr,&UpdateRevStr,&FlagsStr) != 3) {
  345. fprintf(stdout,"mkupdate: Incorrect format of update listing file %s\n",
  346. ListingFile);
  347. Error = TRUE;
  348. break;
  349. }
  350. #ifdef DEBUG
  351. fprintf(stderr,"CpuSig %s Update Rev %s Processor Flags %s,\n",CpuSigStr,
  352. UpdateRevStr,FlagsStr);
  353. #endif
  354. if (sscanf(CpuSigStr,"%lx",&CpuSignature) != 1) {
  355. fprintf(stdout,"mkupdate: Incorrect Processor Signature in update listing file %s\n",
  356. ListingFile);
  357. Error = TRUE;
  358. break;
  359. }
  360. if (sscanf(UpdateRevStr,"%lx",&UpdateRevision)!= 1) {
  361. fprintf(stdout,"mkupdate: Incorrect Update Revision of update listing file %s\n",
  362. ListingFile);
  363. Error = TRUE;
  364. break;
  365. }
  366. if (sscanf(FlagsStr,"%lx",&ProcessorFlags)!= 1) {
  367. fprintf(stdout,"mkupdate: Incorrect Processor Flags in update listing file %s\n",
  368. ListingFile);
  369. Error = TRUE;
  370. break;
  371. }
  372. #ifdef DEBUG
  373. fprintf(stderr,"CpuSig 0x%lx Update Rev 0x%lx Flags 0x%lx,\n",
  374. CpuSignature,UpdateRevision,ProcessorFlags);
  375. #endif
  376. strcpy(UpdateTable[i].CpuSigStr,CpuSigStr);
  377. UpdateTable[i].CpuSignature = CpuSignature;
  378. strcpy(UpdateTable[i].UpdateRevStr,UpdateRevStr);
  379. UpdateTable[i].UpdateRevision = UpdateRevision;
  380. strcpy(UpdateTable[i].FlagsStr,FlagsStr);
  381. UpdateTable[i].ProcessorFlags = ProcessorFlags;
  382. }
  383. fclose(TmpFilePtr);
  384. if (Error) {
  385. NumUpdates = 0;
  386. free(UpdateTable);
  387. }
  388. }
  389. return(NumUpdates);
  390. }
  391. VOID
  392. CleanupDataFile(
  393. VOID
  394. )
  395. /*++
  396. Routine Description:
  397. If any operation during the creation of the new Data file fails,
  398. then delete it so that the build for the driver will fail.
  399. Arguments:
  400. None
  401. Return Value:
  402. None
  403. --*/
  404. {
  405. DeleteFile(UPDATE_DATA_FILE);
  406. }
  407. BOOL
  408. SanitizeUpdateList(
  409. ULONG NumUpdates
  410. )
  411. /*++
  412. Routine Description:
  413. Sanitizes the update list. Checking for duplicate processor
  414. signatures.
  415. Arguments:
  416. NumUpdates: Number of updates in the update list.
  417. Return Value:
  418. TRUE is list clean else FALSE.
  419. --*/
  420. {
  421. ULONG i,j;
  422. PROCESSOR_FLAGS ProcessorFlags;
  423. //
  424. // Check for garbage values in the update table
  425. //
  426. for (i = 0; i < NumUpdates-1; i++) {
  427. if (UpdateTable[i].CpuSignature == 0) {
  428. fprintf(stdout,"mkupdate: Error: incorrect processor signature in update list.\n");
  429. return(FALSE);
  430. }
  431. if (UpdateTable[i].UpdateRevision == 0) {
  432. fprintf(stdout,"mkupdate: Error: incorrect update revision in update list.\n");
  433. return(FALSE);
  434. }
  435. if (UpdateTable[i].ProcessorFlags != 0) {
  436. // Only a single bit must be set
  437. ProcessorFlags.u.LongPart = UpdateTable[i].ProcessorFlags;
  438. if (((ProcessorFlags.u.hw.Slot1) &&
  439. (ProcessorFlags.u.LongPart & MASK_SLOT1)) ||
  440. ((ProcessorFlags.u.hw.Mobile) &&
  441. (ProcessorFlags.u.LongPart & MASK_MOBILE)) ||
  442. ((ProcessorFlags.u.hw.Slot2) &&
  443. (ProcessorFlags.u.LongPart & MASK_SLOT2)) ||
  444. ((ProcessorFlags.u.hw.MobileModule) &&
  445. (ProcessorFlags.u.LongPart & MASK_MODULE)) ||
  446. ((ProcessorFlags.u.hw.Reserved1) &&
  447. (ProcessorFlags.u.LongPart & MASK_RESERVED1)) ||
  448. ((ProcessorFlags.u.hw.Reserved2) &&
  449. (ProcessorFlags.u.LongPart & MASK_RESERVED2)) ||
  450. ((ProcessorFlags.u.hw.Reserved3) &&
  451. (ProcessorFlags.u.LongPart & MASK_RESERVED3)) ||
  452. ((ProcessorFlags.u.hw.Reserved4) &&
  453. (ProcessorFlags.u.LongPart & MASK_RESERVED4))) {
  454. fprintf(stdout,"mkupdate: Error: incorrect processor flags in update list.\n");
  455. return(FALSE);
  456. }
  457. }
  458. }
  459. for (i = 0; i < NumUpdates-1; i++) {
  460. for (j = i+1; j < NumUpdates; j++) {
  461. if ((UpdateTable[i].CpuSignature == UpdateTable[j].CpuSignature)
  462. && (UpdateTable[i].ProcessorFlags == UpdateTable[j].ProcessorFlags)){
  463. fprintf(stdout,"mkupdate:Error: Duplicate processor entry 0x%lx:0x%lx in update list\n",
  464. UpdateTable[i].CpuSignature,UpdateTable[i].ProcessorFlags);
  465. return(FALSE);
  466. }
  467. }
  468. }
  469. return(TRUE);
  470. }
  471. int
  472. __cdecl main(
  473. int argc,
  474. LPSTR argv[]
  475. )
  476. /*++
  477. Routine Description:
  478. Scans the processor update listing file, pick up the specified
  479. processor updates, verify the updates and generate the update
  480. data file to be used by the update driver. Generates the
  481. version numbers and strings to be included in the
  482. resource definition file.
  483. Arguments:
  484. listing file: list of the processor updates to be included in
  485. the driver.
  486. Return Value:
  487. --*/
  488. {
  489. FILE *DataOut, *RCFile,*VerFile;
  490. ULONG NumUpdates,i;
  491. CHAR Line[MAX_LINE];
  492. CHAR *CurrentDataVersionString;
  493. BOOL VerFileFound;
  494. CHAR VersionFile[MAX_LINE];
  495. CHAR *VersionDirectory;
  496. VersionFile[0] = 0;
  497. if (argc < 2) {
  498. fprintf(stdout,"%s: Usage: %s <patch listing file>\n",argv[0],argv[0]);
  499. exit(0);
  500. }
  501. #ifdef DEBUG
  502. fprintf(stderr,"listing file %s\n",argv[1]);
  503. #endif
  504. // Open generated file UPDATE_DATA_FILE. Delete previous file if any.
  505. DataOut=fopen(UPDATE_DATA_FILE,"w");
  506. if (DataOut == NULL) {
  507. fprintf(stdout,"mkupdate:Unable to open update data file %s\n",UPDATE_DATA_FILE);
  508. exit(0);
  509. }
  510. // Scan listing file and store all the CPU signatures in update table
  511. NumUpdates = PopulateUpdateList(argv[1]);
  512. if (NumUpdates == 0) {
  513. fprintf(stdout,"mkupdate:Listing file %s: Incorrect format or no updates specified.\n",
  514. argv[1]);
  515. fclose(DataOut);
  516. exit(0);
  517. }
  518. //
  519. // Dynamically allocate the size for CurrentDataVersionString
  520. //
  521. CurrentDataVersionString = (CHAR*)malloc(NumUpdates * UPDATE_VER_SIZE);
  522. if (CurrentDataVersionString == NULL) {
  523. fprintf(stdout,"mkupdate:Listing file %s: Failed to allocate memory.\n",
  524. argv[1]);
  525. fclose(DataOut);
  526. exit(0);
  527. }
  528. // Sanitize the update list
  529. if (!SanitizeUpdateList(NumUpdates)) {
  530. fclose(DataOut);
  531. DeleteFile(UPDATE_DATA_FILE);
  532. free(CurrentDataVersionString);
  533. exit(0);
  534. }
  535. // Generate the data file. First generate all headers
  536. GenMSHeader(DataOut,UPDATE_DATA_FILE,"Processor updates.");
  537. // generate the data segment alloc pragmas
  538. fprintf(DataOut,"\n#ifdef ALLOC_DATA_PRAGMA\n");
  539. fprintf(DataOut,"#pragma data_seg(\"PAGELK\")\n");
  540. fprintf(DataOut,"#endif\n\n");
  541. // generate the update table definition
  542. fprintf(DataOut,"//\n// Updates data\n//\n\n");
  543. fprintf(DataOut,"UPDATE UpdateData[] = {\n");
  544. // include each update
  545. for (i=0; i < NumUpdates; i++) {
  546. if (!GetVerifyPutUpdate(DataOut,i,NumUpdates)) {
  547. fprintf(stdout,"mkupdate:Error: processing update data file %s_%s.%s\n",
  548. UpdateTable[i].CpuSigStr,UpdateTable[i].UpdateRevStr,
  549. UpdateTable[i].FlagsStr);
  550. fclose(DataOut);
  551. CleanupDataFile();
  552. free(CurrentDataVersionString);
  553. exit(0);
  554. }
  555. }
  556. // generate closing code for the update table definition
  557. fprintf(DataOut,"\n};\n");
  558. // generate the closing data segment alloc pragmas
  559. fprintf(DataOut,"\n#ifdef ALLOC_DATA_PRAGMA\n");
  560. fprintf(DataOut,"#pragma data_seg()\n");
  561. fprintf(DataOut,"#endif\n\n");
  562. //
  563. // Generate the Update Info Table containing the
  564. // processor signatures, processor flags, and
  565. // pointers to MDLs (initialized to NULL)
  566. //
  567. BuildUpdateInfoTable(DataOut, NumUpdates);
  568. fclose(DataOut);
  569. // Generate the version file. Delete previous file if any.
  570. RCFile = fopen(UPDATE_VERSION_FILE,"w");
  571. if (RCFile == NULL) {
  572. fprintf(stdout,"%s: Unable to open version file %s\n",
  573. argv[0],UPDATE_VERSION_FILE);
  574. free(CurrentDataVersionString);
  575. exit(0);
  576. }
  577. // Generate header
  578. GenMSHeader(RCFile,UPDATE_VERSION_FILE,"Version information for update device driver.");
  579. //
  580. // Open common.ver. If found generate the dataversion string and
  581. // copy everything to our RC file and insert our
  582. // string definitions in the StringFileInfo resource section. We need
  583. // to do this because inclusion of common.ver prevents the addition
  584. // of new string defines in the stringfileinfo block. If common.ver
  585. // is not found in the expected place we only include it expecting the
  586. // appropriate settings in the build environment to locate the file.
  587. //
  588. //
  589. // Generate the common.ver path name
  590. //
  591. //
  592. // Obtain the Drive Name
  593. //
  594. VersionDirectory = getenv( "_NTDRIVE" );
  595. if (VersionDirectory == NULL) {
  596. fprintf(stdout,"%s: Unable to obtain _NTDRIVE ENV variable\n",argv[0]);
  597. fclose(RCFile);
  598. free(CurrentDataVersionString);
  599. exit(0);
  600. }
  601. strcpy(VersionFile, VersionDirectory);
  602. //
  603. // Obtain the Base Directory
  604. //
  605. VersionDirectory = getenv( "_NTROOT" );
  606. if (VersionDirectory == NULL) {
  607. fprintf(stdout,"%s: Unable to obtain _NTROOT ENV variable\n",argv[0]);
  608. fclose(RCFile);
  609. free(CurrentDataVersionString);
  610. exit(0);
  611. }
  612. strcat(VersionFile, VersionDirectory);
  613. strcat(VersionFile, "\\public\\sdk\\inc\\common.ver");
  614. VerFile = fopen(VersionFile,"r");
  615. if (VerFile == NULL) {
  616. fprintf(stdout,"%s: Unable to open version file common.ver\n",argv[0]);
  617. VerFileFound = FALSE;
  618. } else {
  619. VerFileFound = TRUE;
  620. }
  621. if (VerFileFound) {
  622. // Construct data version string from update listing table
  623. strcpy(CurrentDataVersionString,"\"");
  624. for (i=0; i < NumUpdates; i++) {
  625. strcat(CurrentDataVersionString,UpdateTable[i].CpuSigStr);
  626. strcat(CurrentDataVersionString,"-");
  627. strcat(CurrentDataVersionString,UpdateTable[i].FlagsStr);
  628. strcat(CurrentDataVersionString,",");
  629. strcat(CurrentDataVersionString,UpdateTable[i].UpdateRevStr);
  630. if (i != NumUpdates-1)
  631. strcat(CurrentDataVersionString,",");
  632. }
  633. strcat(CurrentDataVersionString,"\"");
  634. #ifdef DEBUG
  635. fprintf(stderr,"DataVersionString %s\n",CurrentDataVersionString);
  636. #endif
  637. fprintf(RCFile,"#define VER_DATAVERSION_STR %s\n",
  638. CurrentDataVersionString);
  639. // Scan till string info block into version file, add our
  640. // definition and scan till end
  641. while (fgets(Line,MAX_LINE,VerFile) != NULL) {
  642. fputs(Line,RCFile);
  643. if (strstr(Line,"VALUE") && strstr(Line,"ProductVersion")
  644. && strstr(Line,"VER_PRODUCTVERSION_STR")){
  645. fprintf(RCFile," VALUE \"DataVersion\", VER_DATAVERSION_STR\n");
  646. }
  647. }
  648. } else {
  649. // version file not found. Cannot define the dataversion
  650. // and codeversion strings. Only include common.ver
  651. fprintf(RCFile,"\n\n#include \"common.ver\"\n");
  652. }
  653. fclose(RCFile);
  654. fclose(VerFile);
  655. free(CurrentDataVersionString);
  656. return(0);
  657. }