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.

464 lines
12 KiB

  1. #include <windows.h>
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <setupapi.h>
  5. #include <crt\string.h>
  6. #include <sputils.h>
  7. #include <tchar.h>
  8. /*
  9. ============================================================================
  10. Compute the disk space requirements for all OC components.
  11. ============================================================================
  12. */
  13. //
  14. // String Macros
  15. //
  16. #define AS(x) ( sizeof(x) / sizeof(x[0]) )
  17. #define LSTRCPY(x,y) ( lstrcpyn(x, y, AS(x)) )
  18. #define LSTRCAT(x,y) ( lstrcpyn(x + lstrlen(x), y, AS(x) - lstrlen(x)) )
  19. //
  20. // Handle to the inf we're operating on.
  21. //
  22. HINF hInputinf;
  23. HINF hLayoutinf;
  24. //
  25. // Initialize input parameters.
  26. //
  27. BOOL Verbose = FALSE;
  28. TCHAR InfPath[MAX_PATH];
  29. PCWSTR InputInf = NULL;
  30. PCWSTR LayoutPath = NULL;
  31. //
  32. // backward-compatible SetupGetInfSections
  33. //
  34. #undef SetupGetInfSections
  35. BOOL
  36. SetupGetInfSections (
  37. IN HINF InfHandle,
  38. OUT PTSTR Buffer, OPTIONAL
  39. IN UINT Size, OPTIONAL
  40. OUT UINT *SizeNeeded OPTIONAL
  41. );
  42. //
  43. // ============================================================================
  44. //
  45. // Find out what the user wants us to do.
  46. //
  47. // ============================================================================
  48. //
  49. BOOL GetParams(
  50. int argc,
  51. char *argv[ ]
  52. )
  53. {
  54. char *p;
  55. int i;
  56. PTSTR tstr_ptr = NULL;
  57. for( i = 0; i < argc; i++ ) {
  58. if( *argv[i] == '-' ) {
  59. p = argv[i];
  60. //
  61. // Verbose?
  62. //
  63. if( !_strcmpi( p, "-v" ) ) {
  64. Verbose = TRUE;
  65. continue;
  66. }
  67. //
  68. // Inf file?
  69. //
  70. if( !_strnicmp( p, "-inf:", 5 ) ) {
  71. p = p + 5;
  72. InputInf = pSetupAnsiToUnicode(p);
  73. //
  74. // Now extract the path for this inf.
  75. //
  76. lstrcpy( InfPath, InputInf );
  77. tstr_ptr = wcsrchr( InfPath, TEXT( '\\' ) );
  78. if( tstr_ptr ) {
  79. *tstr_ptr = 0;
  80. }
  81. continue;
  82. }
  83. //
  84. // Files location location?
  85. //
  86. if( !_strnicmp( p, "-layout:", 8 ) ) {
  87. p = p + 8;
  88. LayoutPath = pSetupAnsiToUnicode(p);
  89. continue;
  90. }
  91. }
  92. }
  93. //
  94. // Check Params.
  95. //
  96. if( InfPath == NULL ) {
  97. return FALSE;
  98. }
  99. if( LayoutPath == NULL ) {
  100. return FALSE;
  101. }
  102. return TRUE;
  103. }
  104. //
  105. // ============================================================================
  106. //
  107. // Tell the user how to use us.
  108. //
  109. // ============================================================================
  110. //
  111. void Usage( )
  112. {
  113. printf( "Compute disk space requirements for files listed in an inf\n" );
  114. printf( "\n" );
  115. printf( "\n" );
  116. printf( " -inf:<path> This is the path to the inf (including the\n" );
  117. printf( " inf file name). E.g. -inf:c:\\dosnet.inf\n" );
  118. printf( "\n" );
  119. printf( " -layout:<path> This is the path to layout.inf (including the\n" );
  120. printf( " inf file name). E.g. -inf:c:\\layout.inf\n" );
  121. printf( "\n" );
  122. printf( " -v Run in verbose mode.\n" );
  123. printf( "\n" );
  124. printf( "\n" );
  125. }
  126. //
  127. // ============================================================================
  128. //
  129. // Process a single section in the inf.
  130. //
  131. // ============================================================================
  132. //
  133. VOID
  134. ProcessInf(
  135. HINF hInputinf,
  136. PTSTR TargetInfPath
  137. )
  138. /*
  139. Process the inf. Look at each section and ask SetupApi to give us the
  140. disk space requirements for installing this section. If we get input
  141. back from setupapi, then update the SizeApproximation entry in this
  142. section.
  143. */
  144. {
  145. DWORD SizeNeeded = 0;
  146. PTSTR Sections,CurrentSection;
  147. HDSKSPC hDiskSpace;
  148. BOOL b;
  149. TCHAR CurrentDrive[MAX_PATH];
  150. LONGLONG SpaceRequired;
  151. DWORD dwError;
  152. //
  153. // get a list of all the sections in this inf.
  154. //
  155. if( !SetupGetInfSections(hInputinf, NULL, 0, &SizeNeeded) ) {
  156. fprintf( stderr, "Unable to get section names, ec=0x%08x\n", GetLastError());
  157. return;
  158. }
  159. if( SizeNeeded == 0 ) {
  160. fprintf( stderr, "There are no sections in this file.\n");
  161. return;
  162. }
  163. Sections = pSetupMalloc (SizeNeeded + 1);
  164. if (!Sections) {
  165. fprintf( stderr, "Unable to allocate memory, ec=0x%08x\n", GetLastError());
  166. return;
  167. }
  168. if(!SetupGetInfSections(hInputinf, Sections, SizeNeeded, NULL) ) {
  169. fprintf( stderr, "Unable to get section names, ec=0x%08x\n", GetLastError());
  170. return;
  171. }
  172. if( Verbose ) {
  173. fprintf( stderr, "\nProcessing inf file: %ws.\n", TargetInfPath );
  174. }
  175. //
  176. // Now process each section.
  177. //
  178. CurrentSection = Sections;
  179. while( *CurrentSection ) {
  180. if( Verbose ) {
  181. fprintf( stderr, "\tProcessing Section: %ws.\n", CurrentSection );
  182. }
  183. //
  184. // Get a diskspace structure.
  185. //
  186. hDiskSpace = SetupCreateDiskSpaceList( NULL, 0, SPDSL_IGNORE_DISK );
  187. if( !hDiskSpace ) {
  188. fprintf( stderr, "\t\tUnable to allocate a DiskSpace structure. ec=0x%08x\n", GetLastError());
  189. continue;
  190. }
  191. b = SetupAddInstallSectionToDiskSpaceList( hDiskSpace,
  192. hInputinf,
  193. hLayoutinf,
  194. CurrentSection,
  195. 0,
  196. 0 );
  197. if( b ) {
  198. //
  199. // There must have been a copyfile section and we got some info.
  200. //
  201. //
  202. // Figure out which drive we're running on. we're going to
  203. // assume that this disk has a reasonable cluster-size and just
  204. // use it.
  205. //
  206. if( !GetWindowsDirectory( CurrentDrive, MAX_PATH ) ) {
  207. fprintf( stderr, "\t\tUnable to retrieve current directory. ec=0x%08x\n", GetLastError());
  208. continue;
  209. }
  210. CurrentDrive[2] = 0;
  211. if( Verbose ) {
  212. fprintf( stderr, "\t\tChecking space requirements on drive %ws.\n", CurrentDrive );
  213. }
  214. //
  215. // Now query the disk space requirements against this drive.
  216. //
  217. SpaceRequired = 0;
  218. b = SetupQuerySpaceRequiredOnDrive( hDiskSpace,
  219. CurrentDrive,
  220. &SpaceRequired,
  221. NULL,
  222. 0 );
  223. if( !b ) {
  224. //
  225. // This probably happened because there was no CopyFiles section.
  226. //
  227. dwError = GetLastError();
  228. if( dwError != ERROR_INVALID_DRIVE ) {
  229. fprintf( stderr, "\t\tUnable to query space requirements. ec=0x%08x\n", GetLastError());
  230. } else {
  231. if( Verbose ) {
  232. fprintf( stderr, "\t\tI don't think this section has a CopyFiles entry.\n");
  233. }
  234. }
  235. }
  236. //
  237. // We got the space requirements. now all we have to do is spew them into the inf.
  238. //
  239. if( Verbose ) {
  240. fprintf( stderr, "\t\tRequired space: %I64d\n", SpaceRequired );
  241. }
  242. if( SpaceRequired > 0 ) {
  243. swprintf( CurrentDrive, TEXT("%I64d"), SpaceRequired );
  244. b = WritePrivateProfileString( CurrentSection,
  245. TEXT("SizeApproximation"),
  246. CurrentDrive,
  247. TargetInfPath );
  248. if( !b ) {
  249. fprintf( stderr, "\t\tUnable to write space requirements to %ws. ec=0x%08x\n", InfPath, GetLastError());
  250. continue;
  251. }
  252. }
  253. }
  254. //
  255. // Free that diskspace structure.
  256. //
  257. SetupDestroyDiskSpaceList( hDiskSpace );
  258. CurrentSection += lstrlen(CurrentSection) + 1;
  259. }
  260. pSetupFree( Sections );
  261. }
  262. int
  263. __cdecl
  264. main( int argc, char *argv[ ], char *envp[ ] )
  265. {
  266. INFCONTEXT InputContext;
  267. LONG i, LineCount;
  268. BOOL b;
  269. TCHAR TargetInfPath[MAX_PATH];
  270. TCHAR FileName[MAX_INF_STRING_LENGTH];
  271. HINF hTargetInf;
  272. int Result = 1;
  273. //
  274. // Check Params.
  275. //
  276. if(!pSetupInitializeUtils()) {
  277. fprintf( stderr, "Initialization failed\n" );
  278. return 1;
  279. }
  280. if( !GetParams( argc, argv ) ) {
  281. Usage();
  282. Result = 1;
  283. goto cleanup;
  284. }
  285. //
  286. // Open the inf file.
  287. //
  288. hInputinf = SetupOpenInfFileW( InputInf, NULL, INF_STYLE_WIN4, NULL );
  289. if( hInputinf == INVALID_HANDLE_VALUE ) {
  290. if( Verbose ) {
  291. fprintf( stderr, "The file %ws was not opened!\n", InputInf );
  292. }
  293. Result = 1;
  294. goto cleanup;
  295. }
  296. //
  297. // Open the specified layout.inf file.
  298. //
  299. hLayoutinf = SetupOpenInfFileW( LayoutPath, NULL, INF_STYLE_WIN4, NULL );
  300. if( hLayoutinf == INVALID_HANDLE_VALUE ) {
  301. if( Verbose ) {
  302. fprintf( stderr, "The file %ws was not opened!\n", LayoutPath );
  303. }
  304. Result = 1;
  305. goto cleanup;
  306. }
  307. //
  308. // Now loop through all the entries in the "components"
  309. // section and process their infs.
  310. //
  311. LineCount = SetupGetLineCount( hInputinf,
  312. TEXT("Components") );
  313. for( i = 0; i < LineCount; i++ ) {
  314. //
  315. // Get this line.
  316. //
  317. b = SetupGetLineByIndex( hInputinf,
  318. TEXT("Components"),
  319. i,
  320. &InputContext );
  321. if( b ) {
  322. //
  323. // got it. Get the inf name for this component (there
  324. // may not be one).
  325. //
  326. if(SetupGetStringField(&InputContext, 3,FileName,MAX_INF_STRING_LENGTH,NULL) &&
  327. FileName[0] != TEXT('\0')) {
  328. //
  329. // Yep, there's an inf that we need to look at.
  330. // Build a path to it and open a handle to it.
  331. //
  332. LSTRCPY( TargetInfPath, InfPath );
  333. LSTRCAT( TargetInfPath, TEXT("\\") );
  334. LSTRCAT( TargetInfPath, FileName );
  335. hTargetInf = SetupOpenInfFileW( TargetInfPath, NULL, INF_STYLE_WIN4, NULL );
  336. if( hTargetInf == INVALID_HANDLE_VALUE ) {
  337. if( Verbose ) {
  338. fprintf( stderr, "The file %ws was not opened!\n", TargetInfPath );
  339. }
  340. continue;
  341. }
  342. //
  343. // Now process it.
  344. //
  345. ProcessInf( hTargetInf, TargetInfPath );
  346. } else {
  347. //
  348. // There must not have been an inf in this
  349. // line.
  350. //
  351. if( Verbose ) {
  352. fprintf( stderr, "I didn't find an inf entry on this line.\n");
  353. }
  354. }
  355. }
  356. }
  357. SetupCloseInfFile( hInputinf );
  358. SetupCloseInfFile( hLayoutinf );
  359. Result = 0;
  360. cleanup:
  361. pSetupUninitializeUtils();
  362. return Result;
  363. }