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.

613 lines
18 KiB

  1. #include <windows.h>
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <setupapi.h>
  5. #include <crt\string.h>
  6. #define PULONGLONG PDWORDLONG
  7. #include <spapip.h>
  8. /*
  9. ============================================================================
  10. Compute the disk space requirements for the product.
  11. The program runs in 2 modes:
  12. 1. Compute disk space requirements to the %windir% (run with -w)
  13. Computed by adding up the sizes for all files in layout.inf. Note
  14. that the files should be uncompressed.
  15. 2. Compute disk space requirements for the local source (run with -l)
  16. Computed by adding up the sizes for all the files in dosnet.inf. Note
  17. that the files should be compressed.
  18. For each of these modes, the various size requirements for cluster size
  19. are generated.
  20. ============================================================================
  21. */
  22. //
  23. // Initialize final space requirements.
  24. //
  25. ULONG Running_RawSize = 0;
  26. ULONG Running_512 = 0;
  27. ULONG Running_1K = 0;
  28. ULONG Running_2K = 0;
  29. ULONG Running_4K = 0;
  30. ULONG Running_8K = 0;
  31. ULONG Running_16K = 0;
  32. ULONG Running_32K = 0;
  33. ULONG Running_64K = 0;
  34. ULONG Running_128K = 0;
  35. ULONG Running_256K = 0;
  36. ULONG LineCount = 0;
  37. ULONG MissedFiles = 0;
  38. //
  39. // This structure will be used to hold link lists
  40. // of file names, section names, or whatever. It's
  41. // just a linked list of strings.
  42. //
  43. typedef struct _NAMES {
  44. struct _NAMES *Next;
  45. PCWSTR String;
  46. } NAMES;
  47. //
  48. // Initialize input parameters.
  49. //
  50. BOOL LocalSource = FALSE;
  51. BOOL Windir = FALSE;
  52. BOOL Verbose = FALSE;
  53. PCWSTR InfPath = NULL;
  54. NAMES SectionNames;
  55. NAMES FilePath;
  56. ULONG Slop = 0;
  57. //
  58. // ============================================================================
  59. //
  60. // Add a string to the end of our NAMES linked list.
  61. //
  62. // ============================================================================
  63. //
  64. BOOL AddName(
  65. char *IncomingString,
  66. NAMES *NamesStruct
  67. )
  68. {
  69. NAMES *Names = NamesStruct;
  70. //
  71. // The very first entry may be free.
  72. //
  73. if( Names->String ) {
  74. //
  75. // Get to the end of the list.
  76. //
  77. while( Names->Next != NULL ) {
  78. Names = Names->Next;
  79. }
  80. //
  81. // make room for a new entry.
  82. //
  83. Names->Next = MyMalloc(sizeof(NAMES));
  84. if( Names->Next == NULL ) {
  85. printf( "AddName - Out of memory!\n" );
  86. return FALSE;
  87. }
  88. Names = Names->Next;
  89. }
  90. //
  91. // Assign
  92. //
  93. Names->Next = NULL;
  94. Names->String = AnsiToUnicode(IncomingString);
  95. return TRUE;
  96. }
  97. //
  98. // ============================================================================
  99. //
  100. // Find out what the user wants us to do.
  101. //
  102. // ============================================================================
  103. //
  104. BOOL GetParams(
  105. int argc,
  106. char *argv[ ]
  107. )
  108. {
  109. char *p;
  110. int i;
  111. for( i = 0; i < argc; i++ ) {
  112. if( *argv[i] == '-' ) {
  113. p = argv[i];
  114. //
  115. // local source?
  116. //
  117. if( !_strcmpi( p, "-l" ) ) {
  118. LocalSource = TRUE;
  119. if( Windir ) {
  120. return FALSE;
  121. }
  122. continue;
  123. }
  124. //
  125. // windir?
  126. //
  127. if( !_strcmpi( p, "-w" ) ) {
  128. Windir = TRUE;
  129. if( LocalSource ) {
  130. return FALSE;
  131. }
  132. continue;
  133. }
  134. //
  135. // Verbose?
  136. //
  137. if( !_strcmpi( p, "-v" ) ) {
  138. Verbose = TRUE;
  139. continue;
  140. }
  141. //
  142. // Slop (in Mbytes)?
  143. //
  144. if( !_strnicmp( p, "-slop:", 6 ) ) {
  145. p = p + 6;
  146. Slop = atoi(p);
  147. Slop = Slop * (1024*1024);
  148. continue;
  149. }
  150. //
  151. // Inf file?
  152. //
  153. if( !_strnicmp( p, "-inf:", 5 ) ) {
  154. p = p + 5;
  155. InfPath = AnsiToUnicode(p);
  156. continue;
  157. }
  158. //
  159. // Inf section?
  160. //
  161. if( !_strnicmp( p, "-section:", 9 ) ) {
  162. p = p + 9;
  163. if( AddName( p, &SectionNames ) ) {
  164. continue;
  165. } else {
  166. return FALSE;
  167. }
  168. }
  169. //
  170. // Files location location?
  171. //
  172. if( !_strnicmp( p, "-files:", 7 ) ) {
  173. p = p + 7;
  174. if( AddName( p, &FilePath ) ) {
  175. continue;
  176. } else {
  177. return FALSE;
  178. }
  179. }
  180. }
  181. }
  182. //
  183. // Check Params.
  184. //
  185. if( !(LocalSource || Windir) ){
  186. return FALSE;
  187. }
  188. if( InfPath == NULL ) {
  189. return FALSE;
  190. }
  191. if( SectionNames.String == NULL ) {
  192. return FALSE;
  193. }
  194. if( FilePath.String == NULL ) {
  195. return FALSE;
  196. }
  197. return TRUE;
  198. }
  199. //
  200. // ============================================================================
  201. //
  202. // Tell the user how to use us.
  203. //
  204. // ============================================================================
  205. //
  206. void Usage( )
  207. {
  208. printf( "Compute disk space requirements for files listed in an inf\n" );
  209. printf( "\n" );
  210. printf( " -[l|w] l indicates we're computing space requirements\n" );
  211. printf( " for the local source directory, inwhich case\n" );
  212. printf( " we'll be processing dosnet.inf and computing\n" );
  213. printf( " file sizes for compressed files.\n" );
  214. printf( " w indicates we're computing space requirements\n" );
  215. printf( " for the %windir%, inwhich case we'll be\n" );
  216. printf( " processing layout.inf and computing file\n" );
  217. printf( " sizes for uncompressed files.\n" );
  218. printf( "\n" );
  219. printf( " -v Execute in Verbose mode.\n" );
  220. printf( "\n" );
  221. printf( " -slop:<num> This is the error (in Mb) that should be added onto\n" );
  222. printf( " the final disk space requirements.\n" );
  223. printf( "\n" );
  224. printf( " -inf:<path> This is the path to the inf (including the\n" );
  225. printf( " inf file name). E.g. -inf:c:\\dosnet.inf\n" );
  226. printf( "\n" );
  227. printf( " -section:<inf_section_name> This is the section name in the inf\n" );
  228. printf( " that needs to be processed. The user may specify\n" );
  229. printf( " this parameter multiple times inorder to have multiple\n" );
  230. printf( " sections processed.\n" );
  231. printf( "\n" );
  232. printf( " -files:<path> Path to the source files (e.g. install sharepoint or\n" );
  233. printf( " CD). The user may specify multiple paths here, and\n" );
  234. printf( " they will be checked in the order given.\n" );
  235. printf( "\n" );
  236. printf( "\n" );
  237. }
  238. //
  239. // ============================================================================
  240. //
  241. // Round to the nearest clustersize.
  242. //
  243. // ============================================================================
  244. //
  245. ULONG
  246. RoundIt(
  247. ULONG FileSize,
  248. ULONG ClusterSize
  249. )
  250. {
  251. if( FileSize <= ClusterSize ) {
  252. return( ClusterSize );
  253. } else {
  254. return( ClusterSize * ((FileSize / ClusterSize) + 1) );
  255. }
  256. }
  257. //
  258. // ============================================================================
  259. //
  260. // Compute file sizes. Note that we keep track of how much space
  261. // the file will require for a variety of different clusters.
  262. //
  263. // ============================================================================
  264. //
  265. VOID
  266. ComputeSizes(
  267. PCWSTR FileName,
  268. ULONG FileSize
  269. )
  270. {
  271. Running_RawSize += FileSize;
  272. Running_512 += RoundIt( FileSize, 512 );
  273. Running_1K += RoundIt( FileSize, (1 * 1024) );
  274. Running_2K += RoundIt( FileSize, (2 * 1024) );
  275. Running_4K += RoundIt( FileSize, (4 * 1024) );
  276. Running_8K += RoundIt( FileSize, (8 * 1024) );
  277. Running_16K += RoundIt( FileSize, (16 * 1024) );
  278. Running_32K += RoundIt( FileSize, (32 * 1024) );
  279. Running_64K += RoundIt( FileSize, (64 * 1024) );
  280. Running_128K += RoundIt( FileSize, (128 * 1024) );
  281. Running_256K += RoundIt( FileSize, (256 * 1024) );
  282. //
  283. // HACK.
  284. //
  285. // If the file is an inf, then we'll be creating an .pnf file
  286. // during gui-mode setup. The .pnf file is going to take about
  287. // 2X the original file size, so we need to fudge this
  288. //
  289. if( wcsstr( FileName, L".inf" ) && Windir ) {
  290. //
  291. // It's an inf. Add in size for .pnf file too.
  292. //
  293. Running_RawSize += FileSize;
  294. Running_512 += RoundIt( FileSize*2, 512 );
  295. Running_1K += RoundIt( FileSize*2, (1 * 1024) );
  296. Running_2K += RoundIt( FileSize*2, (2 * 1024) );
  297. Running_4K += RoundIt( FileSize*2, (4 * 1024) );
  298. Running_8K += RoundIt( FileSize*2, (8 * 1024) );
  299. Running_16K += RoundIt( FileSize*2, (16 * 1024) );
  300. Running_32K += RoundIt( FileSize*2, (32 * 1024) );
  301. Running_64K += RoundIt( FileSize*2, (64 * 1024) );
  302. Running_128K += RoundIt( FileSize*2, (128 * 1024) );
  303. Running_256K += RoundIt( FileSize*2, (256 * 1024) );
  304. }
  305. if( Verbose ) {
  306. //
  307. // Print data for each file.
  308. //
  309. printf( "%15ws %10d %10d %10d %10d %10d %10d %10d %10d %10d %10d %10d\n",
  310. FileName,
  311. FileSize,
  312. RoundIt( FileSize, 512 ),
  313. RoundIt( FileSize, (1 * 1024) ),
  314. RoundIt( FileSize, (2 * 1024) ),
  315. RoundIt( FileSize, (4 * 1024) ),
  316. RoundIt( FileSize, (8 * 1024) ),
  317. RoundIt( FileSize, (16 * 1024) ),
  318. RoundIt( FileSize, (32 * 1024) ),
  319. RoundIt( FileSize, (64 * 1024) ),
  320. RoundIt( FileSize, (128 * 1024) ),
  321. RoundIt( FileSize, (256 * 1024) ) );
  322. }
  323. }
  324. //
  325. // ============================================================================
  326. //
  327. // Process a single section in the inf.
  328. //
  329. // ============================================================================
  330. //
  331. DoSection(
  332. HINF hInputinf,
  333. PCWSTR SectionName
  334. )
  335. {
  336. #define GOT_IT() { \
  337. ComputeSizes( FileName, FindData.nFileSizeLow ); \
  338. FindClose( tmpHandle ); \
  339. Found = TRUE; \
  340. }
  341. INFCONTEXT InputContext;
  342. PCWSTR Inputval = NULL;
  343. BOOL Found;
  344. NAMES *FileLocations;
  345. WCHAR CompleteFilePath[MAX_PATH*2];
  346. PCWSTR FileName;
  347. WCHAR LastChar;
  348. WIN32_FIND_DATAW FindData;
  349. HANDLE tmpHandle;
  350. if( SetupFindFirstLineW( hInputinf, SectionName, NULL, &InputContext ) ) {
  351. do {
  352. LineCount++;
  353. fprintf( stderr, "\b\b\b\b\b%5d", LineCount );
  354. //
  355. // Cast the return value from pSetupGetField to PCWSTR, since we're linking
  356. // with the UNICODE version of the Setup APIs, but this app doesn't have
  357. // UNICODE defined (thus the PCTSTR return value becomes a PCSTR).
  358. //
  359. // Note that if we're doing LocalSource, then we're processing
  360. // dosnet, which means we want the second field. If we're doing
  361. // windir, then we're processing layout, which means we want the 1st
  362. // field.
  363. //
  364. if(FileName = (PCWSTR)pSetupGetField(&InputContext, LocalSource ? 2 : 0)) {
  365. //
  366. // We're ready to actually look for the file.
  367. // Look in each path specified.
  368. //
  369. Found = FALSE;
  370. FileLocations = &FilePath;
  371. while( FileLocations && !Found ) {
  372. wcscpy( CompleteFilePath, FileLocations->String );
  373. wcscat( CompleteFilePath, L"\\" );
  374. wcscat( CompleteFilePath, FileName );
  375. //
  376. // Try compressed name first.
  377. //
  378. LastChar = CompleteFilePath[lstrlenW(CompleteFilePath)-1];
  379. CompleteFilePath[lstrlenW(CompleteFilePath)-1] = L'_';
  380. tmpHandle = FindFirstFileW(CompleteFilePath, &FindData);
  381. if( tmpHandle != INVALID_HANDLE_VALUE ) {
  382. GOT_IT();
  383. } else {
  384. //
  385. // We missed. Try the uncompressed name.
  386. //
  387. CompleteFilePath[wcslen(CompleteFilePath)-1] = LastChar;
  388. tmpHandle = FindFirstFileW(CompleteFilePath, &FindData);
  389. if( tmpHandle != INVALID_HANDLE_VALUE ) {
  390. GOT_IT();
  391. } else {
  392. //
  393. // Missed again. This may be a file with a funky
  394. // extension (not 8.3).
  395. //
  396. //
  397. // Try and find entries that are of the form
  398. // 8.<less-than-3>
  399. //
  400. wcscat( CompleteFilePath, L"_" );
  401. tmpHandle = FindFirstFileW(CompleteFilePath, &FindData);
  402. if( tmpHandle != INVALID_HANDLE_VALUE ) {
  403. GOT_IT();
  404. } else {
  405. //
  406. // Try and find entries with no extension.
  407. //
  408. CompleteFilePath[wcslen(CompleteFilePath)-1] = 0;
  409. wcscat( CompleteFilePath, L"._" );
  410. tmpHandle = FindFirstFileW(CompleteFilePath, &FindData);
  411. if( tmpHandle != INVALID_HANDLE_VALUE ) {
  412. GOT_IT();
  413. } else {
  414. //
  415. // Give up...
  416. //
  417. }
  418. }
  419. }
  420. }
  421. if( Verbose ) {
  422. if( Found ) {
  423. printf( "Processed file: %ws\n", CompleteFilePath );
  424. } else {
  425. printf( "Couldn't find %ws in path %s\n", FileName, FileLocations->String );
  426. }
  427. }
  428. FileLocations = FileLocations->Next;
  429. } // while( FileLocations && !Found )
  430. if( Found == FALSE ) {
  431. //
  432. // We missed the file! Error.
  433. //
  434. printf( " ERROR: Couldn't find %ws\n", FileName );
  435. MissedFiles++;
  436. }
  437. }
  438. } while( SetupFindNextLine(&InputContext, &InputContext) );
  439. } else {
  440. fprintf(stderr,"Section %ws is empty or missing\n", SectionName);
  441. return(FALSE);
  442. }
  443. return(TRUE);
  444. }
  445. int
  446. __cdecl
  447. main( int argc, char *argv[ ], char *envp[ ] )
  448. {
  449. NAMES *Sections = &SectionNames;
  450. char *char_ptr;
  451. HINF hInputinf;
  452. ULONG i;
  453. //
  454. // Check Params.
  455. //
  456. if( !GetParams( argc, argv ) ) {
  457. Usage();
  458. return 1;
  459. }
  460. LineCount = 0;
  461. fprintf( stderr, "Files processed: " );
  462. //
  463. // Open the inf file.
  464. //
  465. hInputinf = SetupOpenInfFileW( InfPath, NULL, INF_STYLE_WIN4, NULL );
  466. if( hInputinf == INVALID_HANDLE_VALUE ) {
  467. printf( "The file %s was not opened!\n", InfPath );
  468. return 1;
  469. }
  470. //
  471. // For each section the user specified...
  472. //
  473. while( Sections ) {
  474. DoSection( hInputinf, Sections->String );
  475. //
  476. // Now process the next section.
  477. //
  478. Sections = Sections->Next;
  479. }
  480. SetupCloseInfFile( hInputinf );
  481. //
  482. // Print totals.
  483. //
  484. printf( "\n\n==================================================\n\n" );
  485. printf( "%d files processed\n", LineCount );
  486. if( MissedFiles > 0 ) {
  487. printf( "%d files were not found\n", MissedFiles );
  488. }
  489. if( LocalSource ) {
  490. char_ptr = "TempDirSpace";
  491. //
  492. // TempDirSpace is given in bytes.
  493. //
  494. i = 1;
  495. } else {
  496. char_ptr = "WinDirSpace";
  497. //
  498. // WinDir space is given in KBytes.
  499. //
  500. i = 1024;
  501. }
  502. printf( "Raw size: %12d\n", Running_RawSize+Slop );
  503. printf( "%s512 = %12d\n", char_ptr, (Running_512+Slop)/i );
  504. printf( "%s1K = %12d\n", char_ptr, (Running_1K+Slop)/i );
  505. printf( "%s2K = %12d\n", char_ptr, (Running_2K+Slop)/i );
  506. printf( "%s4K = %12d\n", char_ptr, (Running_4K+Slop)/i );
  507. printf( "%s8K = %12d\n", char_ptr, (Running_8K+Slop)/i );
  508. printf( "%s16K = %12d\n", char_ptr, (Running_16K+Slop)/i );
  509. printf( "%s32K = %12d\n", char_ptr, (Running_32K+Slop)/i );
  510. printf( "%s64K = %12d\n", char_ptr, (Running_64K+Slop)/i );
  511. printf( "%s128K = %12d\n", char_ptr, (Running_128K+Slop)/i );
  512. printf( "%s256K = %12d\n", char_ptr, (Running_256K+Slop)/i );
  513. return 0;
  514. }