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

720 lines
18 KiB

  1. /*
  2. Modifications:
  3. 01.10.94 Joe Holman Added DISK_TO_START_NUMBERING_AT because
  4. we now have 2 bootdisks, thus we to start
  5. making floppies on disk # 3.
  6. 01.11.94 Joe Holman Change value back to 2.
  7. 05.05.94 Joe Holman Change # to 1.
  8. 06.10.94 Joe Holman Made CD specific changes.
  9. 07.21.94 Joe Holman Added code to check for textmode/gui-mode disk swaps.
  10. */
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #include <windows.h>
  15. #include <time.h>
  16. #include "general.h"
  17. FILE* logFile;
  18. char* product;
  19. int useCdPath;
  20. BOOL bAssigned[15000]; // should put this in Entry struct after Beta.
  21. struct _list {
  22. char name[15]; // name of file
  23. int size;
  24. int csize;
  25. int disk;
  26. int priority;
  27. char nocompress[15];
  28. };
  29. struct _list fileList[15000];
  30. int numFiles;
  31. int totalCompressed=0;
  32. int totalUnCompressed=0;
  33. void Msg ( const char * szFormat, ... ) {
  34. va_list vaArgs;
  35. va_start ( vaArgs, szFormat );
  36. vprintf ( szFormat, vaArgs );
  37. vfprintf ( logFile, szFormat, vaArgs );
  38. va_end ( vaArgs );
  39. }
  40. void Header(argv)
  41. char* argv[];
  42. {
  43. time_t t;
  44. PRINT1("\n=========== MLAYOUT =============\n")
  45. PRINT2("Input BOM: %s\n",argv[2])
  46. PRINT2("Output Layout: %s\n",argv[3])
  47. PRINT2("Product: %s\n",argv[4])
  48. PRINT2("Floppy Size: %s\n",argv[5])
  49. time(&t); PRINT2("Time: %s",ctime(&t))
  50. PRINT1("================================\n\n");
  51. }
  52. void Usage()
  53. {
  54. printf("PURPOSE: Assigns files to disks and generates a layout file.\n");
  55. printf("\n");
  56. printf("PARAMETERS:\n");
  57. printf("\n");
  58. printf("[LogFile] - Path to append a log of actions and errors.\n");
  59. printf("[InBom] - Path of BOM for which a layout is to be made.\n");
  60. printf("[OutLayout] - Path of new layout.\n");
  61. printf("[Product] - Product to lay out.\n");
  62. printf(" NTFLOP = Windows NT on floppy\n");
  63. printf(" LMFLOP = Lan Manager on floppy\n");
  64. printf(" NTCD = Windows NT on CD\n");
  65. printf(" LMCD = Lan Manager on CD\n");
  66. printf(" SDK = Software Development Kit\n");
  67. printf("[FloppySize] - Size in bytes of the second disk.\n\n");
  68. }
  69. int __cdecl PrioritySizeNameCompare(const void*,const void*);
  70. int Same(e1,e2)
  71. Entry* e1;
  72. Entry* e2;
  73. {
  74. char *p1, *p2;
  75. if (useCdPath)
  76. {
  77. p1=e1->cdpath;
  78. p2=e2->cdpath;
  79. }
  80. else
  81. {
  82. p1="x";
  83. p2=p1;
  84. }
  85. return( (!_stricmp(e1->name,e2->name)) &&
  86. (!_stricmp(e1->path,e2->path)) &&
  87. (!_stricmp(e1->source,e2->source)) &&
  88. (!_stricmp(p1,p2)));
  89. }
  90. BOOL FindFile ( char * name ) {
  91. int i;
  92. for ( i = 0; i < numFiles; ++i ) {
  93. if ( _stricmp ( name, fileList[i].name ) == 0 ) {
  94. return TRUE; // found the file in the file list
  95. }
  96. }
  97. return FALSE; // did NOT find the file in the file list.
  98. }
  99. void AddFileToList ( char * name,
  100. int size,
  101. int csize,
  102. int disk,
  103. int priority,
  104. char * nocompress ) {
  105. sprintf ( fileList[numFiles].name, "%s", name );
  106. fileList[numFiles].size = size;
  107. fileList[numFiles].csize = csize;
  108. fileList[numFiles].disk = disk;
  109. fileList[numFiles].priority = priority;
  110. sprintf ( fileList[numFiles].nocompress, "%s", nocompress );
  111. totalUnCompressed += fileList[numFiles].size;
  112. totalCompressed += fileList[numFiles].csize;
  113. //Msg ( "totalUncomp = %d, size = %d,totalComp = %d, csize = %d\n", totalUnCompressed, fileList[numFiles].size, totalCompressed, fileList[numFiles].csize );
  114. if ( fileList[numFiles].size < fileList[numFiles].csize ) {
  115. Msg ( "ER: %s compressed bigger than uncomp\n", fileList[numFiles].name );
  116. }
  117. ++numFiles;
  118. }
  119. // MakeEntries figures out if a file's name is already in the list of
  120. // files to layout. The end result is a list of files, with no duplicates.
  121. //
  122. void MakeEntries ( Entry * e, int records ) {
  123. int i;
  124. BOOL bInList;
  125. int numFiles = 0;
  126. for ( i = 0; i < records; i++ ) {
  127. bInList = FindFile ( e[i].name );
  128. if ( !bInList ) {
  129. AddFileToList ( e[i].name,
  130. e[i].size,
  131. e[i].csize,
  132. e[i].disk,
  133. e[i].priority,
  134. e[i].nocompress );
  135. }
  136. }
  137. }
  138. void ShowEntriesAll ( int records, Entry * e ) {
  139. int i;
  140. Msg ( "\n\n\nShowEntriesAll - show each of the %d file(s) and where it lays...\n\n", records );
  141. for ( i = 0; i < records; ++i ) {
  142. Msg ( "%s,%d,%s,nocomp=%d,comp=%d,priority=%d,disk=%d,%s\n",
  143. e[i].name,
  144. i,
  145. e[i].platform,
  146. e[i].size,
  147. e[i].csize,
  148. e[i].priority,
  149. e[i].disk,
  150. e[i].nocompress );
  151. }
  152. }
  153. void ShowEntries ( void ) {
  154. int i;
  155. totalCompressed=0;
  156. totalUnCompressed=0;
  157. for ( i = 0; i < numFiles; ++i ) {
  158. Msg ( "#%d\t%s,nocomp=%d,comp=%d,priority=%d,disk=%d,%s\n",
  159. i,
  160. fileList[i].name,
  161. fileList[i].size,
  162. fileList[i].csize,
  163. fileList[i].priority,
  164. fileList[i].disk,
  165. fileList[i].nocompress );
  166. totalCompressed+=fileList[i].csize;
  167. totalUnCompressed+=fileList[i].size;
  168. }
  169. Msg ( "totalCompressed = %d, totalUnCompressed = %d\n\n\n",
  170. totalCompressed, totalUnCompressed );
  171. }
  172. //
  173. // Returns TRUE if a file hasn't been assigned a disk #, ie. 0.
  174. // Returns FALSE if all have been assigned.
  175. //
  176. BOOL FileUnAssigned ( void ) {
  177. int i;
  178. for ( i = 0; i < numFiles; ++i ) {
  179. if ( fileList[i].disk == 0 ) {
  180. return TRUE;
  181. }
  182. }
  183. return FALSE;
  184. }
  185. void StuffDiskNumIntoRecords ( int records, Entry * e ) {
  186. int i, j;
  187. // Verify that all entries in the list have a disk # assigned to them.
  188. //
  189. Msg ( "\n\n\nVerifying fileList assignments...\n\n" );
  190. for ( i = 0; i < numFiles; ++i ) {
  191. if ( fileList[i].disk < 1 ) {
  192. Msg ( "ERROR: fileList %s >>> has not been assigned a disk...\n",
  193. fileList[i].name );
  194. }
  195. }
  196. Msg ( "\n\n\nAssigning fileList #s to record #s...\n\n" );
  197. for ( i = 0; i < records; ++i ) {
  198. for ( j = 0; j < numFiles; ++j ) {
  199. if ( _stricmp ( fileList[j].name, e[i].name ) == 0 ) {
  200. e[i].disk = fileList[j].disk;
  201. //Msg ( "disk assignment for: %s #%d\n", e[i].name, e[i].disk );
  202. }
  203. }
  204. }
  205. // Verify that all entries now have a disk # assigned to them.
  206. //
  207. for ( i = 0; i < records; ++i ) {
  208. if ( e[i].disk < 1 ) {
  209. Msg ( "ERROR: %s >>> has not been assigned to a disk...\n",
  210. e[i].name );
  211. }
  212. }
  213. }
  214. void LayoutAssignDisks(e,diskSize,records)
  215. Entry* e;
  216. int diskSize;
  217. int records;
  218. {
  219. //
  220. // Files must always start at disk 1.
  221. //
  222. #define DISK_TO_START_NUMBERING_AT 1
  223. #define CD_TO_START_NUMBERING_AT 1
  224. int disk=DISK_TO_START_NUMBERING_AT;
  225. int freeSpace, i;
  226. int workingPriority = 0;
  227. int firstGuiModeDisk = 666;
  228. #define DMF_CLUSTER_FILES 32
  229. // For DMF, every DMF_CLUSTER_FILES files increases the DMF table by 1 cluster, ie. 2K.
  230. //
  231. int iNumFiles = 1;
  232. //
  233. // Make a entry for each unique file for the product.
  234. // This reduces multiple entries in e due to multiple lines of inf
  235. // information.
  236. //
  237. MakeEntries ( e, records );
  238. //ShowEntries ( );
  239. // Priority values can be from 1-1000;
  240. //
  241. #define FAT_TABLE_GROWTH_FUDGE 2*512 // 1K of extra space.
  242. do {
  243. // Free space left to begin with is the disk size.
  244. //
  245. freeSpace = diskSize - FAT_TABLE_GROWTH_FUDGE;
  246. Msg ( "\n\n\n\n\nInitial Disk #%d freeSpace = %d\n", disk, freeSpace );
  247. // First, find all the files that
  248. // are HARDCODED to go on this disk.
  249. //
  250. //
  251. Msg ( "\n\n\nAnalyze HARDCODED disk #s...\n\n" );
  252. for ( i=0; i < numFiles; i++) {
  253. if ( fileList[i].disk == disk ) {
  254. if ( fileList[i].nocompress[0] == 'x' ||
  255. fileList[i].nocompress[0] == 'X' ) {
  256. freeSpace -= fileList[i].size;
  257. Msg ( "freeSpace(nocomp) = %d, %d, %s, disk #%d, prio = %d, iNumFiles = %d\n",
  258. freeSpace,
  259. fileList[i].size,
  260. fileList[i].name, disk, fileList[i].priority,
  261. iNumFiles );
  262. }
  263. else {
  264. freeSpace -= fileList[i].csize;
  265. Msg ( "freeSpace(comp) = %d, %d, %s, disk #%d, prio = %d, iNumFiles = %d\n",
  266. freeSpace,
  267. fileList[i].csize, fileList[i].name, disk, fileList[i].priority, iNumFiles );
  268. }
  269. ++iNumFiles; // assigned a file.
  270. if ( iNumFiles % DMF_CLUSTER_FILES == 0 ) {
  271. freeSpace -=
  272. (DMF_ALLOCATION_UNIT+DMF_ALLOCATION_UNIT);
  273. Msg ( "WARNING: getting ready for %d more files, DMF_CLUSTER_FILES, freeSpace = %d, iNumFiles=%d\n",
  274. freeSpace, iNumFiles);
  275. }
  276. }
  277. }
  278. // We have a big problem if our freespace is less than 0.
  279. // I.E, too many disks have HARDCODED disk # for this disk.
  280. //
  281. if ( freeSpace < 0 ) {
  282. Msg ( "ERROR: disk #%d freeSpace = %d\n", disk, freeSpace );
  283. Msg ( ">>>> Too many files with HARDCODED disk #%d\n", disk);
  284. }
  285. #define NOT_ASSIGNED_YET 0
  286. #define MAX_GROUPING_NUM 999 // > 999, ie. 1000+ means don't put on floppy.
  287. // Now let's deal with the PRIORITY.
  288. //
  289. Msg ( "\n\n\nAnalyze GROUPINGS...\n\n" );
  290. workingPriority = 0;
  291. do {
  292. for ( i = 0; i < numFiles; ++i ) {
  293. int fileSize;
  294. if ( fileList[i].disk == NOT_ASSIGNED_YET ) {
  295. if ( fileList[i].nocompress[0] == 'x' ||
  296. fileList[i].nocompress[0] == 'X' ) {
  297. fileSize = fileList[i].size;
  298. }
  299. else {
  300. fileSize = fileList[i].csize;
  301. }
  302. // Verify that the file size
  303. // is on a sector boundary.
  304. //
  305. if ( (fileSize % DMF_ALLOCATION_UNIT) != 0 ) {
  306. Msg ( "ERROR: %s, size isn't on DMF_A_U boundary %d\n",
  307. fileList[i].name, fileSize );
  308. }
  309. if ( fileList[i].priority <= workingPriority &&
  310. (freeSpace-fileSize > 0)
  311. ) {
  312. freeSpace -= fileSize;
  313. fileList[i].disk = disk;
  314. Msg ( "freespace(%s) = %d, %s, disk #%d, SIZE=%d, priority = %d, csize=%d,size=%d, iNumFiles = %d\n",
  315. (_stricmp(fileList[i].nocompress,"x")) ? "comp" : "nocomp",
  316. freeSpace,
  317. fileList[i].name, disk, fileSize,
  318. workingPriority,
  319. fileList[i].csize, fileList[i].size, iNumFiles );
  320. ++iNumFiles;
  321. if ( iNumFiles % DMF_CLUSTER_FILES == 0 ) {
  322. freeSpace -=
  323. (DMF_ALLOCATION_UNIT+DMF_ALLOCATION_UNIT);
  324. Msg ( "WARNING: getting ready for %d more files, DMF_CLUSTER_FILES, freeSpace = %d, iNumFiles=%d\n",
  325. freeSpace, iNumFiles);
  326. }
  327. }
  328. }
  329. }
  330. ++workingPriority;
  331. if ( workingPriority > MAX_GROUPING_NUM ) {
  332. break;
  333. }
  334. /**
  335. Msg ( "workingPriority = %d, freeSpace = %d, disk = %d\n",
  336. workingPriority, freeSpace, disk );
  337. **/
  338. } while ( (freeSpace > 0) && FileUnAssigned() );
  339. Msg ( "Disk %d Excess Space: %d\n", disk, freeSpace );
  340. // Increment the disk #.
  341. // Reset the num of files for the cluster information.
  342. //
  343. ++disk;
  344. iNumFiles = 1;
  345. } while ( FileUnAssigned() );
  346. //ShowEntriesAll ( records, e );
  347. StuffDiskNumIntoRecords ( records, e );
  348. // Let's verify that no files are off the textmode/gui mode boundry
  349. // disk.
  350. //
  351. #define FIRST_GUI_MODE_PRIORITY_VALUE 60
  352. // Step #1. Find the floppy with the last textmode file.
  353. //
  354. Msg ( "firstGuiModeDisk: %d\n", firstGuiModeDisk );
  355. for ( i = 0; i < records; ++i ) {
  356. if ( e[i].priority >= FIRST_GUI_MODE_PRIORITY_VALUE ) {
  357. if ( e[i].disk < firstGuiModeDisk ) {
  358. firstGuiModeDisk = e[i].disk;
  359. Msg ( "firstGuiModeDisk: %d (%s,%d)\n", firstGuiModeDisk,
  360. e[i].name, e[i].disk );
  361. }
  362. }
  363. }
  364. // Step #2. Just verify that no textmode files are on any disk
  365. // above 'firstGuiModeDisk'.
  366. for ( i = 0; i < records; ++i ) {
  367. if ( e[i].priority < FIRST_GUI_MODE_PRIORITY_VALUE &&
  368. e[i].disk > firstGuiModeDisk &&
  369. e[i].priority != 0 /* value used if file is HARDCODED on disk*/ ) {
  370. Msg ( "ERROR: We have a disk swap: %d, %d, %s\n", e[i].priority,
  371. e[i].disk,
  372. e[i].name );
  373. }
  374. }
  375. }
  376. void LayoutAssignCD(e,diskSize,records)
  377. Entry* e;
  378. int diskSize;
  379. int records;
  380. {
  381. int freeSpace, i;
  382. int fileSize;
  383. /***
  384. //
  385. // Make a entry for each unique file for the product.
  386. // This reduces multiple entries in e due to multiple lines of inf
  387. // information.
  388. //
  389. MakeEntries ( e, records );
  390. **/
  391. // For CDs, we need to work with each entry in the expanded BOM.
  392. //
  393. //ShowEntriesAll ( records, e );
  394. // Free space left to begin with is the disk size.
  395. //
  396. freeSpace = diskSize;
  397. Msg ( "\nInitial CD freeSpace = %d\n", freeSpace );
  398. for ( i=0; i < records; i++) {
  399. if ( e[i].nocompress[0] == 'x' ||
  400. e[i].nocompress[0] == 'X' ) {
  401. fileSize = e[i].size;
  402. }
  403. else {
  404. fileSize = e[i].csize;
  405. }
  406. freeSpace -= fileSize;
  407. // Force all files on CD to be on disk CD_TO...
  408. //
  409. e[i].disk = CD_TO_START_NUMBERING_AT;
  410. if ( freeSpace < 0 ) {
  411. Msg ( "ERROR: freeSpace = %d, diskSize = %d\n",
  412. freeSpace, diskSize );
  413. }
  414. else {
  415. //Msg ( "%d, %s\n", freeSpace, e[i].name );
  416. }
  417. }
  418. Msg ( "Excess Space: %d\n", freeSpace );
  419. //ShowEntriesAll ( records, e );
  420. }
  421. __cdecl main(argc,argv)
  422. int argc;
  423. char* argv[];
  424. {
  425. FILE *outLayout;
  426. Entry *e;
  427. int records,i,result;
  428. char *buf;
  429. if (argc!=6) { Usage(); return(1); }
  430. if ((logFile=fopen(argv[1],"a"))==NULL)
  431. {
  432. printf("ERROR Couldn't open log file %s\n",argv[1]);
  433. return(1);
  434. }
  435. Header(argv);
  436. LoadFile(argv[2],&buf,&e,&records,argv[4]);
  437. if (MyOpenFile(&outLayout,argv[3],"wb")) return(1);
  438. // Go to the very beginning of the file.
  439. //
  440. result = fseek ( outLayout, SEEK_SET, 0 );
  441. if (result) {
  442. printf("ERROR Unable to seek beginning of file: %s\n", argv[3]);
  443. return(1);
  444. }
  445. if (!_stricmp(argv[4],"ntflop") || !_stricmp(argv[4],"lmflop")) {
  446. useCdPath=0;
  447. }
  448. else {
  449. useCdPath=1;
  450. }
  451. /**
  452. for ( i = 0; i < records; ++i ) {
  453. Msg ( "record #%d, %s, size=%d, csize=%d, disk=%d\n",
  454. i, e[i].name, e[i].size, e[i].csize, e[i].disk );
  455. }
  456. **/
  457. Msg ( "useCdPath = %d\n", useCdPath );
  458. //
  459. // munge the compress flag depending on the product type.
  460. // if we are laying out floppies, then files are always
  461. // compressed unless a special flag is set in the bom.
  462. // X just means don't compress for CD. XFLOPPY means
  463. // don't compress EVEN for FLOPPIES.
  464. // Any other value than xfloppy will compress the file for floppies.
  465. //
  466. // NOTE: from here on out, floppies will use the "" == compress and
  467. // "x" == nocompress. Ie. used in MakeDisk.exe.
  468. //
  469. if(!useCdPath) {
  470. // Just working in the NTFLOP or LMFLOP case, ie. floppies.
  471. //
  472. for (i=0;i<records;i++) {
  473. if(_strnicmp(e[i].nocompress,"xfloppy",7)) {
  474. // Compress this file on floppies.
  475. //
  476. e[i].nocompress[0] = '\0';
  477. e[i].nocompress[1] = '\0';
  478. } else {
  479. // Don't compress this file for floppies.
  480. //
  481. e[i].nocompress[0] = 'x';
  482. e[i].nocompress[1] = '\0';
  483. Msg ( "Forcing NO COMPRESSION on this file for floppies: %s\n", e[i].name );
  484. }
  485. }
  486. }
  487. qsort(e,records,sizeof(Entry),PrioritySizeNameCompare);
  488. if ( useCdPath ) {
  489. LayoutAssignCD ( e, atoi(argv[5]),records);
  490. }
  491. else {
  492. LayoutAssignDisks(e,atoi(argv[5]),records);
  493. }
  494. // Write out the informative column header.
  495. //
  496. i=0; while ((fputc(buf[i++],outLayout))!='\n');
  497. // Write out each line to the layout file.
  498. //
  499. for (i=0;i<records;i++) {
  500. //Msg ( "EntryPrint #%d, %s, size=%d, csize=%d, disk=%d\n",
  501. // i, e[i].name, e[i].size, e[i].csize, e[i].disk );
  502. EntryPrint(&e[i],outLayout);
  503. }
  504. fclose(outLayout);
  505. fclose(logFile);
  506. free(e);
  507. return(0);
  508. }
  509. int __cdecl PrioritySizeNameCompare(const void *v1, const void *v2)
  510. {
  511. int result;
  512. Entry *e1 = (Entry *)v1;
  513. Entry *e2 = (Entry *)v2;
  514. if (e1->priority!=e2->priority)
  515. return(e1->priority-e2->priority);
  516. if (e1->size!=e2->size)
  517. return(e2->size-e1->size);
  518. if (result=_stricmp(e1->name,e2->name))
  519. return(result);
  520. if (useCdPath)
  521. return(_stricmp(e1->cdpath,e2->cdpath));
  522. else
  523. return(0); // always the same for floppies
  524. }