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.

1173 lines
28 KiB

  1. /*
  2. xx.xx.94 TedM Created.
  3. 10.31.94 JoeHol Added -b switch to help notify of files that
  4. have had bug fixes back-out, eg. since media
  5. build group uses -d switch, we need to know
  6. if a file is now "older" than before so we can
  7. also take the "bad newer" file out of the media.
  8. Also, verifies src and dst by DOS date and time.
  9. 11.01.94 JoeHol -l logs to chk.log, not compress.log.
  10. 12.14.94 JoeHol Make -l work with name of log file, use dcomp.log
  11. if not specified.
  12. 02.07.95 JoeHol -b for bom file. If this is specified we will
  13. check that the files are listed in the bom.
  14. If a file isn't in the bom, we won't add the file
  15. to the list of files to compress.
  16. 06.20.95 JoeHol Since we are changing the location of the files,
  17. lets just compressed all, ie. disable real use of the -b switch
  18. for awhile.
  19. 08.03.95 JoeHol If a file isn't found to compress in a directory, we don't stop, but
  20. continue gracefully displaying an error message.
  21. */
  22. #include <windows.h>
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #include <setupapi.h>
  27. #include <process.h>
  28. typedef struct _SOURCEFILE {
  29. struct _SOURCEFILE *Next;
  30. WIN32_FIND_DATA FileData;
  31. } SOURCEFILE, *PSOURCEFILE;
  32. PSOURCEFILE SourceFileList;
  33. DWORD SourceFileCount;
  34. PSTR SourceSpec,TargetDirectory;
  35. HANDLE NulHandle;
  36. CRITICAL_SECTION SourceListCritSect;
  37. CRITICAL_SECTION ConsoleCritSect;
  38. #define MFL 256
  39. FILE * logFile;
  40. FILE * bomFile;
  41. char logFileName[MFL];
  42. char bomFileName[MFL];
  43. char infFilePath[MFL];
  44. #define MAX_NUMBER_OF_FILES 5000 // let's assume we only have 5000 files max in the product.
  45. #define NAME_SIZE 25 // assume no filename is greater than 25 chars long.
  46. char szFiles[MAX_NUMBER_OF_FILES][NAME_SIZE];
  47. BOOL bVerbose = FALSE;
  48. BOOL bBomChecking = FALSE;
  49. int wRecords=0;
  50. DWORD ThreadCount;
  51. #define MAX_EXCLUDE_EXTENSION 100
  52. PSTR ExcludeExtension[MAX_EXCLUDE_EXTENSION];
  53. unsigned ExcludeExtensionCount;
  54. #define MAX_EXCLUDE_FILEFILTER 100
  55. char ExcludeFileFilter[MAX_EXCLUDE_FILEFILTER][MAX_PATH];
  56. unsigned ExcludeFileFilterCount;
  57. HINF ExcludeFilterHandle[MAX_EXCLUDE_FILEFILTER];
  58. PVOID
  59. MALLOC(
  60. IN DWORD Size
  61. )
  62. {
  63. return((PVOID)LocalAlloc(LMEM_FIXED,Size));
  64. }
  65. VOID
  66. FREE(
  67. IN PVOID Block
  68. )
  69. {
  70. LocalFree((HLOCAL)Block);
  71. }
  72. BOOL
  73. AddExtensionToExclude(
  74. IN PSTR Extension
  75. )
  76. {
  77. //
  78. // Make sure it starts with a dot.
  79. //
  80. if((*Extension != '.') || (lstrlen(Extension) < 2)) {
  81. return(FALSE);
  82. }
  83. if(ExcludeExtensionCount < MAX_EXCLUDE_EXTENSION) {
  84. ExcludeExtension[ExcludeExtensionCount++] = Extension;
  85. } else {
  86. printf("Warning: exclude extension %s ignored (%u max).\n",Extension,MAX_EXCLUDE_EXTENSION);
  87. }
  88. return(TRUE);
  89. }
  90. BOOL
  91. AddFilterToExclude(
  92. IN PSTR FilterName
  93. )
  94. {
  95. DWORD error;
  96. if(!FilterName) {
  97. return(FALSE);
  98. }
  99. if(ExcludeFileFilterCount < MAX_EXCLUDE_EXTENSION) {
  100. ExcludeFilterHandle[ExcludeFileFilterCount] = SetupOpenInfFile(
  101. FilterName,
  102. NULL,
  103. INF_STYLE_WIN4,
  104. &error );
  105. if (ExcludeFilterHandle[ExcludeFileFilterCount] == INVALID_HANDLE_VALUE) {
  106. printf("Warning: couldn't open exclude file filter %s (%d).\n", FilterName , error);
  107. return(FALSE);
  108. }
  109. strcpy( ExcludeFileFilter[ExcludeFileFilterCount], FilterName );
  110. ExcludeFileFilterCount += 1;
  111. return(TRUE);
  112. } else {
  113. printf("Warning: exclude file filter %s ignored (%u max).\n",FilterName,MAX_EXCLUDE_EXTENSION);
  114. }
  115. return(TRUE);
  116. }
  117. BOOL
  118. ParseArguments(
  119. IN int argc,
  120. IN PSTR *argv
  121. )
  122. {
  123. HANDLE FindHandle;
  124. WIN32_FIND_DATA FindData;
  125. while(argc--) {
  126. if((**argv == '-') || (**argv == '/')) {
  127. switch((*argv)[1]) {
  128. case 'b':
  129. case 'B':
  130. strcpy ( infFilePath, &(*argv)[2] );
  131. printf ( "infFilePath: >>>%s<<<\n", &(*argv)[2] );
  132. bBomChecking = TRUE;
  133. break;
  134. case 'l':
  135. case 'L':
  136. strcpy ( logFileName, &(*argv)[2] );
  137. //printf ( ">>>%s<<<\n", &(*argv)[2] );
  138. break;
  139. case 'm':
  140. case 'M':
  141. if(ThreadCount) {
  142. return(FALSE);
  143. }
  144. ThreadCount = (DWORD)atoi((*argv)+2);
  145. if(!ThreadCount) {
  146. return(FALSE);
  147. }
  148. break;
  149. case 'v':
  150. case 'V':
  151. bVerbose = TRUE;
  152. break;
  153. case 'x':
  154. case 'X':
  155. if((argc-- < 1) || !AddExtensionToExclude(*(++argv))) {
  156. return(FALSE);
  157. }
  158. break;
  159. case 'f':
  160. case 'F':
  161. if((argc-- < 1) || !AddFilterToExclude(*(++argv))) {
  162. return(FALSE);
  163. }
  164. break;
  165. default:
  166. return(FALSE);
  167. }
  168. } else {
  169. if(SourceSpec) {
  170. if(TargetDirectory) {
  171. return(FALSE);
  172. } else {
  173. TargetDirectory = *argv;
  174. }
  175. } else {
  176. SourceSpec = *argv;
  177. }
  178. }
  179. argv++;
  180. }
  181. if(!TargetDirectory || !SourceSpec) {
  182. return(FALSE);
  183. }
  184. //
  185. // Make sure target is a directory.
  186. //
  187. FindHandle = FindFirstFile(TargetDirectory,&FindData);
  188. if(FindHandle == INVALID_HANDLE_VALUE) {
  189. return(FALSE);
  190. }
  191. FindClose(FindHandle);
  192. if(!(FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
  193. return(FALSE);
  194. }
  195. return(TRUE);
  196. }
  197. VOID
  198. Usage(
  199. VOID
  200. )
  201. {
  202. printf("DCOMP -llog [-x .ext ...] [-m#] [-d] [-bbom] Source Dest\n\n");
  203. printf(" -x .ext Exclude files with extension .ext.\n");
  204. printf(" -m Force use of # threads.\n");
  205. printf(" -v Verbose.\n" );
  206. printf(" -llog Log filename, dcomp.log default.\n");
  207. printf(" -binfPath your setup\\inf\\win4\\inf path.\n" );
  208. printf(" -f infname Excludes files listed in inf.\n");
  209. printf(" Source Source file specification. Wildcards may be used.\n");
  210. printf(" Destination Specifies directory where renamed compressed files\n");
  211. printf(" will be placed.\n");
  212. }
  213. VOID
  214. DnpGenerateCompressedName(
  215. IN PSTR Filename,
  216. OUT PSTR CompressedName
  217. )
  218. /*++
  219. Routine Description:
  220. Given a filename, generate the compressed form of the name.
  221. The compressed form is generated as follows:
  222. Look backwards for a dot. If there is no dot, append "._" to the name.
  223. If there is a dot followed by 0, 1, or 2 charcaters, append "_".
  224. Otherwise assume there is a 3-character extension and replace the
  225. third character after the dot with "_".
  226. Arguments:
  227. Filename - supplies filename whose compressed form is desired.
  228. CompressedName - receives compressed file name.
  229. Return Value:
  230. None.
  231. --*/
  232. {
  233. PSTR p,q;
  234. strcpy(CompressedName,Filename);
  235. p = strrchr(CompressedName,'.');
  236. q = strrchr(CompressedName,'\\');
  237. if(q < p) {
  238. //
  239. // If there are 0, 1, or 2 characters after the dot, just append
  240. // the underscore. p points to the dot so include that in the length.
  241. //
  242. if(lstrlen(p) < 4) {
  243. lstrcat(CompressedName,"_");
  244. } else {
  245. //
  246. // Assume there are 3 characters in the extension. So replace
  247. // the final one with an underscore.
  248. //
  249. p[3] = '_';
  250. }
  251. } else {
  252. //
  253. // No dot, just add ._.
  254. //
  255. lstrcat(CompressedName,"._");
  256. }
  257. }
  258. BOOL
  259. GetSetTimeStamp(
  260. IN PSTR FileName,
  261. OUT PFILETIME CreateTime,
  262. OUT PFILETIME AccessTime,
  263. OUT PFILETIME WriteTime,
  264. IN BOOL Set
  265. )
  266. {
  267. HANDLE h;
  268. BOOL b;
  269. //
  270. // Open the file.
  271. //
  272. h = CreateFile(
  273. FileName,
  274. Set ? GENERIC_WRITE : GENERIC_READ,
  275. FILE_SHARE_READ,
  276. NULL,
  277. OPEN_EXISTING,
  278. 0,
  279. NULL
  280. );
  281. if(h == INVALID_HANDLE_VALUE) {
  282. return(FALSE);
  283. }
  284. b = Set
  285. ? SetFileTime(h,CreateTime,AccessTime,WriteTime)
  286. : GetFileTime(h,CreateTime,AccessTime,WriteTime);
  287. CloseHandle(h);
  288. return(b);
  289. }
  290. VOID
  291. mprintf(
  292. IN DWORD ThreadSerialNumber,
  293. IN PSTR FormatString,
  294. ...
  295. )
  296. {
  297. CHAR msg[2048];
  298. va_list arglist;
  299. va_start(arglist,FormatString);
  300. vsprintf(msg,FormatString,arglist);
  301. vfprintf(logFile,FormatString,arglist); // print to log file
  302. va_end(arglist);
  303. //EnterCriticalSection(&ConsoleCritSect);
  304. if(ThreadCount == 1) {
  305. printf(msg);
  306. } else {
  307. printf("%u: %s",ThreadSerialNumber,msg);
  308. }
  309. //LeaveCriticalSection(&ConsoleCritSect);
  310. }
  311. VOID
  312. logprintf(
  313. IN PSTR FormatString,
  314. ...
  315. )
  316. {
  317. CHAR msg[2048];
  318. va_list arglist;
  319. va_start(arglist,FormatString);
  320. vsprintf(msg,FormatString,arglist);
  321. vfprintf(logFile,FormatString,arglist); // print to log file
  322. va_end(arglist);
  323. }
  324. // SameDosDateTime returns: TRUE if date/times are same; FALSE otherwise.
  325. //
  326. BOOL
  327. SameDosDateTime(
  328. IN DWORD ThreadSerialNumber,
  329. IN PSTR SourceFileName,
  330. IN PSTR DestFileName,
  331. IN BOOL bDstMustExistNow
  332. )
  333. {
  334. HANDLE h;
  335. FILETIME ftSourceWriteTime;
  336. FILETIME dftDestWriteTime;
  337. FILETIME CreateTime, AccessTime;
  338. FILETIME dCreateTime, dAccessTime;
  339. WORD srcDate, dstDate, srcTime, dstTime; // DOS versions.
  340. //
  341. // Open the source file.
  342. //
  343. h = CreateFile(
  344. SourceFileName,
  345. GENERIC_READ,
  346. FILE_SHARE_READ,
  347. NULL,
  348. OPEN_EXISTING,
  349. 0,
  350. NULL
  351. );
  352. if(h == INVALID_HANDLE_VALUE) {
  353. mprintf ( ThreadSerialNumber, "ERROR CreateFile: %s, gle = %ld\n",
  354. SourceFileName, GetLastError() );
  355. return(FALSE);
  356. }
  357. GetFileTime(h,&CreateTime,&AccessTime,&ftSourceWriteTime);
  358. CloseHandle(h);
  359. FileTimeToDosDateTime ( &ftSourceWriteTime, &srcDate, &srcTime );
  360. //
  361. // Open the destination file.
  362. //
  363. h = CreateFile(
  364. DestFileName,
  365. GENERIC_READ,
  366. FILE_SHARE_READ,
  367. NULL,
  368. OPEN_EXISTING,
  369. 0,
  370. NULL
  371. );
  372. if(h == INVALID_HANDLE_VALUE) {
  373. if ( bDstMustExistNow ) {
  374. // In case we get something like, FILE_NOT_FOUND
  375. //
  376. mprintf ( ThreadSerialNumber,
  377. "ERROR CreateFile: dst %s, gle = %ld\n",
  378. DestFileName,GetLastError());
  379. }
  380. return(FALSE);
  381. }
  382. GetFileTime(h,&dCreateTime,&dAccessTime,&dftDestWriteTime);
  383. CloseHandle(h);
  384. FileTimeToDosDateTime ( &dftDestWriteTime, &dstDate, &dstTime );
  385. // Compare that the DOS date and times are the same.
  386. //
  387. if ( (srcDate != dstDate) || (srcTime != dstTime) ) {
  388. if ( 1 /*bVerbose*/ ) {
  389. mprintf ( ThreadSerialNumber,
  390. "Warning, times different: %s = %x-%x, %s = %x-%x\n",
  391. SourceFileName,
  392. srcDate, srcTime,
  393. DestFileName,
  394. dstDate, dstTime );
  395. }
  396. return (FALSE);
  397. }
  398. return (TRUE); // DOS dates and times are the same.
  399. }
  400. DWORD
  401. WorkerThread(
  402. IN PVOID ThreadParameter
  403. )
  404. {
  405. PSOURCEFILE SourceFile;
  406. DWORD ThreadSerialNumber;
  407. CHAR FullSourceName[2*MAX_PATH];
  408. CHAR FullTargetName[2*MAX_PATH];
  409. CHAR CompressedName[2*MAX_PATH];
  410. CHAR CmdLine[5*MAX_PATH];
  411. PCHAR p;
  412. STARTUPINFO StartupInfo;
  413. PROCESS_INFORMATION ProcessInfo;
  414. BOOL b;
  415. DWORD d;
  416. int i;
  417. ThreadSerialNumber = PtrToUlong(ThreadParameter);
  418. ZeroMemory(&StartupInfo,sizeof(StartupInfo));
  419. StartupInfo.cb = sizeof(STARTUPINFO);
  420. while(1) {
  421. //
  422. // Pluck the next source file off the list.
  423. // If there is no next source file, we're done.
  424. //
  425. EnterCriticalSection(&SourceListCritSect);
  426. SourceFile = SourceFileList;
  427. if(!SourceFile) {
  428. LeaveCriticalSection(&SourceListCritSect);
  429. return(TRUE);
  430. }
  431. SourceFileList = SourceFile->Next;
  432. LeaveCriticalSection(&SourceListCritSect);
  433. //
  434. // Form the source file name.
  435. //
  436. lstrcpy(FullSourceName,SourceSpec);
  437. if(p = strrchr(FullSourceName,'\\')) {
  438. p++;
  439. } else {
  440. p = FullSourceName;
  441. }
  442. lstrcpy(p,SourceFile->FileData.cFileName);
  443. //
  444. // Form full target name.
  445. //
  446. lstrcpy(FullTargetName,TargetDirectory);
  447. i = lstrlen(FullTargetName);
  448. if(FullTargetName[i-1] != '\\') {
  449. FullTargetName[i] = '\\';
  450. FullTargetName[i+1] = 0;
  451. }
  452. lstrcat(FullTargetName,SourceFile->FileData.cFileName);
  453. DnpGenerateCompressedName(FullTargetName,CompressedName);
  454. //
  455. // If the update flag is set, check timestamps.
  456. // If this fails, assume the target file does not exist.
  457. //
  458. if ( !SameDosDateTime ( ThreadSerialNumber,
  459. FullSourceName,
  460. CompressedName, FALSE ) ) {
  461. //
  462. // Form the command line for the child process.
  463. //
  464. sprintf(CmdLine,"diamond /D CompressionType=LZX /D CompressionMemory=21 %s %s",FullSourceName,CompressedName);
  465. if ( 1 /*bVerbose*/ ) {
  466. mprintf(ThreadSerialNumber,
  467. "Start %s ==> %s\n",FullSourceName,CompressedName);
  468. }
  469. //
  470. // Invoke the child process.
  471. //
  472. b = CreateProcess(
  473. NULL,
  474. CmdLine,
  475. NULL,
  476. NULL,
  477. FALSE,
  478. DETACHED_PROCESS,
  479. NULL,
  480. NULL,
  481. &StartupInfo,
  482. &ProcessInfo
  483. );
  484. if(b) {
  485. CloseHandle(ProcessInfo.hThread);
  486. //
  487. // Wait for the child process to terminate and get its
  488. // return code.
  489. //
  490. WaitForSingleObject(ProcessInfo.hProcess,INFINITE);
  491. b = GetExitCodeProcess(ProcessInfo.hProcess,&d);
  492. CloseHandle(ProcessInfo.hProcess);
  493. if(b) {
  494. //
  495. // 'd' value of 0 means success, we've compressed the
  496. // file. Now, set the time stamp on the target file.
  497. //
  498. if(d) {
  499. // 'd' not 0, error occurred.
  500. //
  501. mprintf(ThreadSerialNumber,"ERROR compressing %s to %s.\n",FullSourceName,CompressedName);
  502. } else {
  503. // 'd' is 0, we compressed the file, now time stamp.
  504. //
  505. // First get the source time's stamp.
  506. //
  507. GetSetTimeStamp(
  508. FullSourceName,
  509. &SourceFile->FileData.ftCreationTime,
  510. &SourceFile->FileData.ftLastAccessTime,
  511. &SourceFile->FileData.ftLastWriteTime,
  512. FALSE
  513. );
  514. // Now, set the destination time's stamp.
  515. //
  516. GetSetTimeStamp(
  517. CompressedName,
  518. &SourceFile->FileData.ftCreationTime,
  519. &SourceFile->FileData.ftLastAccessTime,
  520. &SourceFile->FileData.ftLastWriteTime,
  521. TRUE
  522. );
  523. // Double check it is really set.
  524. //
  525. if ( SameDosDateTime ( ThreadSerialNumber,
  526. FullSourceName,
  527. CompressedName,
  528. TRUE ) ) {
  529. if ( bVerbose ) {
  530. mprintf(ThreadSerialNumber,"Compressed %s to %s.\n",FullSourceName,CompressedName);
  531. }
  532. } else {
  533. mprintf(ThreadSerialNumber,"ERROR Compressed %s to %s - time stamps don't match.\n",FullSourceName,CompressedName);
  534. }
  535. }
  536. } else {
  537. mprintf(ThreadSerialNumber,"ERROR Unable to get process \"%s\" termination code.\n",CmdLine);
  538. }
  539. } else {
  540. mprintf(ThreadSerialNumber,"ERROR Unable to invoke \"%s\".\n",CmdLine);
  541. }
  542. } else {
  543. if ( bVerbose ) {
  544. mprintf(ThreadSerialNumber,
  545. "%s is up to date.\n",CompressedName);
  546. }
  547. }
  548. }
  549. }
  550. // FileInBom
  551. // Returns TRUE if fileName is located in the BOM; FALSE otherwise.
  552. //
  553. BOOL FileInBom ( char * fileName ) {
  554. int i;
  555. for ( i = 0; i < wRecords; ++i ) {
  556. if ( _stricmp(fileName, szFiles[i] ) == 0 ) {
  557. return(TRUE);
  558. }
  559. }
  560. return(FALSE);
  561. }
  562. // AddSourceFile
  563. // returns FALSE if an error.
  564. // returns TRUE if no error occrred, but not necesarrily meaning a file
  565. // was added.
  566. BOOL
  567. AddSourceFile(
  568. IN PWIN32_FIND_DATA FindData
  569. )
  570. {
  571. static PSOURCEFILE LastFile = NULL;
  572. PSOURCEFILE SourceFile;
  573. unsigned i;
  574. DWORD ExtensionLength;
  575. DWORD FileNameLength;
  576. INFCONTEXT InfContext;
  577. // If we are doing BOM checking, make sure that this file is
  578. // listed in the BOM. If it is, continue on to the next checking.
  579. // If it is NOT, just return.
  580. //
  581. if ( bBomChecking && !FileInBom(FindData->cFileName) ) {
  582. return(TRUE);
  583. }
  584. //
  585. // Make sure this file is not of a type that is
  586. // supposed to be excluded from the list of files
  587. // we care about.
  588. //
  589. FileNameLength = lstrlen(FindData->cFileName);
  590. for(i=0; i<ExcludeExtensionCount; i++) {
  591. ExtensionLength = lstrlen(ExcludeExtension[i]);
  592. if((FileNameLength > ExtensionLength)
  593. && !lstrcmpi(ExcludeExtension[i],FindData->cFileName+FileNameLength-ExtensionLength)) {
  594. return(TRUE);
  595. }
  596. }
  597. for(i=0; i<ExcludeFileFilterCount; i++) {
  598. if ( SetupFindFirstLine(ExcludeFilterHandle[i],
  599. "Files",
  600. FindData->cFileName,
  601. &InfContext )) {
  602. return(TRUE);
  603. }
  604. }
  605. SourceFile = MALLOC(sizeof(SOURCEFILE));
  606. if(!SourceFile) {
  607. printf("ERROR Insufficient memory.\n");
  608. return(FALSE);
  609. }
  610. SourceFile->FileData = *FindData;
  611. SourceFile->Next = NULL;
  612. if(LastFile) {
  613. LastFile->Next = SourceFile;
  614. } else {
  615. SourceFileList = SourceFile;
  616. }
  617. LastFile = SourceFile;
  618. SourceFileCount++;
  619. return(TRUE);
  620. }
  621. BOOL
  622. FindSourceFiles(
  623. VOID
  624. )
  625. {
  626. WIN32_FIND_DATA FindData;
  627. HANDLE FindHandle;
  628. printf("Building list of source files...\n");
  629. //
  630. // Build a list of source files.
  631. //
  632. FindHandle = FindFirstFile(SourceSpec,&FindData);
  633. if(FindHandle != INVALID_HANDLE_VALUE) {
  634. if(!(FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
  635. if(!AddSourceFile(&FindData)) {
  636. FindClose(FindHandle);
  637. return(FALSE);
  638. }
  639. }
  640. while(FindNextFile(FindHandle,&FindData)) {
  641. if(!(FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
  642. if(!AddSourceFile(&FindData)) {
  643. FindClose(FindHandle);
  644. return(FALSE);
  645. }
  646. }
  647. }
  648. FindClose(FindHandle);
  649. }
  650. if(!SourceFileCount) {
  651. printf("Warning: No files found in: %s.\n",SourceSpec);
  652. }
  653. return(SourceFileCount != 0);
  654. }
  655. VOID
  656. DoIt(
  657. VOID
  658. )
  659. {
  660. SYSTEM_INFO SystemInfo;
  661. PHANDLE ThreadHandles;
  662. DWORD i;
  663. DWORD ThreadId;
  664. //
  665. // Determine number of threads to use.
  666. // This is based on the number of processors.
  667. //
  668. if(!ThreadCount) {
  669. GetSystemInfo(&SystemInfo);
  670. ThreadCount = SystemInfo.dwNumberOfProcessors;
  671. }
  672. ThreadHandles = MALLOC(ThreadCount * sizeof(HANDLE));
  673. if(!ThreadHandles) {
  674. printf("ERROR Insufficient memory.\n");
  675. exit(1);
  676. }
  677. if ( bVerbose ) {
  678. if(ThreadCount == 1) {
  679. printf("Compressing %u files...\n",SourceFileCount);
  680. } else {
  681. printf("Compressing %u files (%u threads)...\n",SourceFileCount,ThreadCount);
  682. }
  683. }
  684. //
  685. // Initialize the source file list critical section.
  686. //
  687. InitializeCriticalSection(&SourceListCritSect);
  688. //
  689. // Create threads.
  690. //
  691. for(i=0; i<ThreadCount; i++) {
  692. ThreadHandles[i] = CreateThread(
  693. NULL,
  694. 0,
  695. WorkerThread,
  696. (PVOID)UlongToPtr(i),
  697. 0,
  698. &ThreadId
  699. );
  700. }
  701. //
  702. // Wait for the threads to terminate.
  703. //
  704. WaitForMultipleObjects(ThreadCount,ThreadHandles,TRUE,INFINITE);
  705. //
  706. // Clean up and exit.
  707. //
  708. for(i=0; i<ThreadCount; i++) {
  709. CloseHandle(ThreadHandles[i]);
  710. }
  711. FREE(ThreadHandles);
  712. }
  713. #define idALL 0
  714. #define idX86 1
  715. #define idMIPS 2
  716. #define idALPHA 3
  717. #define idPPC 4
  718. #define FILE_SECTION_ALL "[SourceDisksFiles]"
  719. #define FILE_SECTION_X86 "[SourceDisksFiles.x86]"
  720. #define FILE_SECTION_MIPS "[SourceDisksFiles.mips]"
  721. #define FILE_SECTION_ALPHA "[SourceDisksFiles.alpha]"
  722. #define FILE_SECTION_PPC "[SourceDisksFiles.ppc]"
  723. #define FILE_SECTION_NOT_USED 0xFFFF
  724. DWORD dwInsideSection = FILE_SECTION_NOT_USED;
  725. DWORD FigureSection ( char * Line ) {
  726. logprintf ( "FigureSection on: %s\n", Line );
  727. if ( strstr ( Line, FILE_SECTION_ALL ) ) {
  728. dwInsideSection = idALL;
  729. }
  730. else
  731. if ( strstr ( Line, FILE_SECTION_X86 ) ) {
  732. dwInsideSection = idX86;
  733. }
  734. else
  735. if ( strstr ( Line, FILE_SECTION_MIPS ) ) {
  736. dwInsideSection = idMIPS;
  737. }
  738. else
  739. if ( strstr ( Line, FILE_SECTION_ALPHA ) ) {
  740. dwInsideSection = idALPHA;
  741. }
  742. else
  743. if ( strstr ( Line, FILE_SECTION_PPC ) ) {
  744. dwInsideSection = idPPC;
  745. }
  746. else {
  747. dwInsideSection = FILE_SECTION_NOT_USED;
  748. }
  749. logprintf ( "dwInsideSection = %x\n", dwInsideSection );
  750. return(dwInsideSection);
  751. }
  752. char * SuckName ( const char * Line ) {
  753. static char szSuckedName[MFL];
  754. DWORD dwIndex = 0;
  755. // The line is in the form: @@:file = 1,2,3,4,5,6,7,8
  756. //
  757. // Skip the first @.
  758. //
  759. if ( *Line == '@' ) {
  760. ++Line;
  761. }
  762. // Skip the 2nd @, w, or s.
  763. //
  764. if ( *Line == '@' || *Line == 'w' || *Line == 's' ) {
  765. ++Line;
  766. }
  767. // Skp the :.
  768. //
  769. if ( *Line == ':' ) {
  770. ++Line;
  771. }
  772. // Copy the file name until a space is encountered.
  773. //
  774. while ( *Line != ' ' ) {
  775. szSuckedName[dwIndex] = *Line;
  776. szSuckedName[dwIndex+1] = '\0';
  777. ++Line;
  778. ++dwIndex;
  779. }
  780. return szSuckedName;
  781. }
  782. void LoadFiles ( const char * infFilePath, const char * infFile ) {
  783. FILE * fHandle;
  784. char Line[MFL];
  785. int i;
  786. sprintf ( bomFileName, "%s%s", infFilePath, infFile );
  787. logprintf ( "bomFileName = %s\n", bomFileName );
  788. fHandle = fopen ( bomFileName, "rt" );
  789. if ( fHandle ) {
  790. dwInsideSection = FILE_SECTION_NOT_USED;
  791. while ( fgets ( Line, sizeof(Line), fHandle ) ) {
  792. if ( Line[0] == '[' ) {
  793. // We have a new section.
  794. //
  795. dwInsideSection = FigureSection ( Line );
  796. continue;
  797. }
  798. // Reasons to ignore this line from further processing.
  799. //
  800. //
  801. // File section not one we process.
  802. //
  803. if ( dwInsideSection == FILE_SECTION_NOT_USED ) {
  804. continue;
  805. }
  806. // Line just contains a non-usefull short string.
  807. //
  808. i = strlen ( Line );
  809. if ( i < 4 ) {
  810. continue;
  811. }
  812. // Line contains just a comment.
  813. //
  814. if ( Line[0] == ';' ) {
  815. continue;
  816. }
  817. switch ( dwInsideSection ) {
  818. case idALL :
  819. case idX86 :
  820. case idMIPS :
  821. case idALPHA :
  822. case idPPC :
  823. sprintf ( szFiles[wRecords], "%s", SuckName ( Line ) );
  824. logprintf ( "file = %s\n", szFiles[wRecords] );
  825. ++wRecords;
  826. break;
  827. default :
  828. // Not inside any section we need files for compressing.
  829. //
  830. break;
  831. }
  832. }
  833. if ( ferror(fHandle) ) {
  834. mprintf ( 0, "FATAL ERROR: reading from: %s\n", bomFileName );
  835. }
  836. fclose ( fHandle );
  837. }
  838. else {
  839. mprintf ( 0, "FATAL ERROR: Can't fopen(%s)\n", bomFileName );
  840. bBomChecking = FALSE;
  841. }
  842. }
  843. int
  844. __cdecl
  845. main(
  846. IN int argc,
  847. IN char *argv[]
  848. )
  849. {
  850. //
  851. // Skip argv[0]
  852. //
  853. argc--;
  854. argv++;
  855. NulHandle = CreateFile(
  856. "nul",
  857. GENERIC_READ | GENERIC_WRITE,
  858. FILE_SHARE_READ | FILE_SHARE_WRITE,
  859. NULL,
  860. OPEN_EXISTING,
  861. 0,
  862. NULL
  863. );
  864. if(NulHandle == INVALID_HANDLE_VALUE) {
  865. printf("ERROR Unable to open \\dev\\nul.\n");
  866. return(1);
  867. }
  868. InitializeCriticalSection(&ConsoleCritSect);
  869. strcpy ( logFileName, "dcomp.log" ); // default log filename.
  870. strcpy ( bomFileName, "bom.txt" ); // default bom filename.
  871. if(ParseArguments(argc,argv)) {
  872. logFile = fopen ( logFileName, "a" );
  873. if ( logFile == NULL ) {
  874. printf ( "ERROR Couldn't open logFile.\n" );
  875. exit(1);
  876. }
  877. if ( bBomChecking ) {
  878. // Load Layout.inx and cairo\Layout.cai, _media.inx doesn't contains files we
  879. // need compressed, as of today.
  880. //
  881. LoadFiles ( infFilePath, "\\Layout.inx" );
  882. mprintf ( 0, "bom loaded records: %d\n", wRecords );
  883. }
  884. if(FindSourceFiles()) {
  885. DoIt();
  886. }
  887. } else {
  888. Usage();
  889. }
  890. CloseHandle(NulHandle);
  891. if ( logFile ) {
  892. fclose ( logFile );
  893. }
  894. return (0);
  895. }