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.

833 lines
20 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. myapp.c
  5. Abstract:
  6. This module implements functions to access the parsed INF.
  7. Author:
  8. Vijesh Shetty (vijeshs)
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. #include <wild.c>
  14. #define PRINT( msg, param ) \
  15. { _tprintf( TEXT(msg), param ); \
  16. if(g_Display == Default ){ \
  17. _tprintf( TEXT("\n")); \
  18. }else if(g_Display == FileOnly ){ \
  19. _tprintf( TEXT(" - ")); }\
  20. }
  21. #define ERROROUT \
  22. { g_Pass = FALSE; \
  23. OutputFileInfo( LayoutInformation, FileName, g_Display ); \
  24. return TRUE;}
  25. #define MAX_BOOTFLOPPY 7
  26. extern BOOL Verbose;
  27. extern DWORD
  28. LoadInfFile(
  29. IN LPCTSTR Filename,
  30. IN BOOL OemCodepage,
  31. OUT PVOID *InfHandle,
  32. DWORD Phase
  33. );
  34. BOOL
  35. CALLBACK
  36. MyCallback(
  37. IN PLAYOUT_CONTEXT Context,
  38. IN PCTSTR FileName,
  39. IN PFILE_LAYOUTINFORMATION LayoutInformation,
  40. IN PVOID ExtraData,
  41. IN UINT ExtraDataSize,
  42. IN OUT DWORD_PTR Param
  43. );
  44. typedef enum _DISPLAYOPTIONS{
  45. Default,
  46. FileOnly
  47. } DISPLAYOPTIONS, *PDISPLAYOPTIONS;
  48. typedef enum _CHECKSUITE{
  49. Deflt,
  50. Build
  51. } CHECKSUITE, *PCHECKSUITE;
  52. DISPLAYOPTIONS g_Display = Default;
  53. CHECKSUITE g_CheckSuite = Deflt;
  54. TCHAR g_LayoutFileName[MAX_PATH];
  55. DWORD g_Platform=LAYOUTPLATFORMS_COMMON;
  56. BOOLEAN g_Warning = FALSE;
  57. BOOLEAN g_Pass = TRUE;
  58. DWORD g_Phase = TEXTMODE_PHASE;
  59. PLAYOUTENUMCALLBACK g_Callback = (PLAYOUTENUMCALLBACK) MyCallback;
  60. BOOLEAN
  61. IsNameInExpressionPrivate (
  62. IN PCTSTR Expression,
  63. IN PCTSTR Name
  64. );
  65. void
  66. OutputFileInfo( PFILE_LAYOUTINFORMATION LayoutInformation,
  67. PCTSTR FileName,
  68. DISPLAYOPTIONS DispType );
  69. /*******************************************************************************/
  70. // Validation Check Functions
  71. //
  72. BOOL
  73. Validate8Dot3(
  74. IN PCTSTR FileName )
  75. /*
  76. Function to check if a file satisfies 8.3
  77. Arguments:
  78. FileName - Filename to validate
  79. Return value:
  80. TRUE - Passes validation
  81. FALSE - Fails validation
  82. */
  83. {
  84. //
  85. // Check for 8.3 validation
  86. //
  87. if( (g_Platform & LAYOUTPLATFORMS_IA64) ||
  88. (g_Platform & LAYOUTPLATFORMS_AMD64) )
  89. return TRUE;
  90. if( FileName && (lstrlen(FileName) > 12)){
  91. PRINT( "%s : Error E0000 : !!! - Filename too long (8.3 required)", g_LayoutFileName );
  92. return FALSE;
  93. }
  94. return TRUE;
  95. }
  96. BOOL
  97. ValidateMissingDirCodes(
  98. IN PFILE_LAYOUTINFORMATION LayoutInformation )
  99. /*
  100. Function to check if a file is missing Directory Information when it is needed by textmode
  101. Arguments:
  102. LayoutInformation - Pointer to PFILE_LAYOUTINFORMATION structure for file
  103. Return value:
  104. TRUE - Passes validation
  105. FALSE - Fails validation
  106. */
  107. {
  108. //
  109. // Check for Directory codes
  110. //
  111. if( ((LayoutInformation->CleanInstallDisposition <= 2) || (LayoutInformation->UpgradeDisposition <= 2))
  112. && !(*LayoutInformation->Directory)){
  113. PRINT( "%s : Error E0000 : !!! - Missing directory for textmode setup", g_LayoutFileName );
  114. return FALSE;
  115. }
  116. return TRUE;
  117. }
  118. BOOL
  119. ValidateBootMediaFields(
  120. IN PFILE_LAYOUTINFORMATION LayoutInformation )
  121. /*
  122. Function to check if the Boot Media fields are set right
  123. Arguments:
  124. LayoutInformation - Pointer to PFILE_LAYOUTINFORMATION structure for file
  125. Return value:
  126. TRUE - Passes validation
  127. FALSE - Fails validation
  128. */
  129. {
  130. if( (LayoutInformation->BootMediaNumber < 0) || (LayoutInformation->BootMediaNumber > MAX_BOOTFLOPPY)
  131. || (LayoutInformation->BootMediaNumber == -1) ){
  132. PRINT( "%s : Error E0000 : !!! - Bad Boot media number", g_LayoutFileName );
  133. return FALSE;
  134. }
  135. return TRUE;
  136. }
  137. BOOL
  138. ValidateSingleInstance(
  139. IN PFILE_LAYOUTINFORMATION LayoutInformation )
  140. /*
  141. Function to check if there is only a single instance of this file
  142. Arguments:
  143. LayoutInformation - Pointer to PFILE_LAYOUTINFORMATION structure for file
  144. Return value:
  145. TRUE - Passes validation
  146. FALSE - Fails validation
  147. */
  148. {
  149. if( LayoutInformation->Count > 1 ){
  150. PRINT( "%s : Error E0000 : !!! - Filename present in more than one place", g_LayoutFileName );
  151. return FALSE;
  152. }
  153. return TRUE;
  154. }
  155. BOOL
  156. CheckForTurdDirCodes(
  157. IN PFILE_LAYOUTINFORMATION LayoutInformation )
  158. /*
  159. Function to check if the dir code is present but doesn't make sense with respect to dispositions
  160. Arguments:
  161. LayoutInformation - Pointer to PFILE_LAYOUTINFORMATION structure for file
  162. Return value:
  163. TRUE - Not a Turd
  164. FALSE - Presence of a turd
  165. */
  166. {
  167. if( ((LayoutInformation->CleanInstallDisposition == 3) && (LayoutInformation->UpgradeDisposition == 3)) \
  168. && (*LayoutInformation->Directory)){
  169. PRINT( "%s : Warning W0000 : !!! - Directory code specified but not used", g_LayoutFileName );
  170. return FALSE;
  171. }
  172. return TRUE;
  173. }
  174. /***********End Validation Check Functions*****************************************/
  175. /***********Callback Routines*************************************/
  176. BOOL
  177. CALLBACK
  178. MyCallback(
  179. IN PLAYOUT_CONTEXT Context,
  180. IN PCTSTR FileName,
  181. IN PFILE_LAYOUTINFORMATION LayoutInformation,
  182. IN PVOID ExtraData,
  183. IN UINT ExtraDataSize,
  184. IN OUT DWORD_PTR Param
  185. )
  186. {
  187. BOOL Error=FALSE;
  188. // Check for missing filename
  189. if( !FileName || !(*FileName) ){
  190. PRINT( "%s : Error E0000 :!!! - Line missing filename\n", FileName );
  191. ERROROUT;
  192. }
  193. //
  194. // Check for 8.3 validation
  195. //
  196. if( !Validate8Dot3( FileName ))
  197. ERROROUT;
  198. //
  199. // Check for Directory codes
  200. //
  201. if( !ValidateMissingDirCodes( LayoutInformation))
  202. ERROROUT;
  203. //
  204. // Check for Boot Media validity
  205. //
  206. if (!ValidateBootMediaFields( LayoutInformation))
  207. ERROROUT;
  208. //
  209. // Check for duplicates
  210. //
  211. if (!ValidateSingleInstance( LayoutInformation ))
  212. ERROROUT;
  213. if( g_Warning ){
  214. if( !CheckForTurdDirCodes( LayoutInformation ))
  215. OutputFileInfo( LayoutInformation, FileName, g_Display );
  216. }
  217. return( TRUE );
  218. }
  219. CALLBACK
  220. BuildCheckCallback(
  221. IN PLAYOUT_CONTEXT Context,
  222. IN PCTSTR FileName,
  223. IN PFILE_LAYOUTINFORMATION LayoutInformation,
  224. IN PVOID ExtraData,
  225. IN UINT ExtraDataSize,
  226. IN OUT DWORD_PTR Param
  227. )
  228. {
  229. BOOL Error=FALSE;
  230. // Check for missing filename
  231. if( !FileName || !(*FileName) ){
  232. PRINT( "%s : Error E0000 :!!! - Line missing filename\n", FileName );
  233. ERROROUT;
  234. }
  235. //
  236. // Check for 8.3 validation
  237. //
  238. if( !Validate8Dot3( FileName ))
  239. ERROROUT;
  240. //
  241. // Check for Directory codes
  242. //
  243. if( !ValidateMissingDirCodes( LayoutInformation))
  244. ERROROUT;
  245. //
  246. // Check for Boot Media validity
  247. //
  248. if (!ValidateBootMediaFields( LayoutInformation))
  249. ERROROUT;
  250. //
  251. // Check for duplicates
  252. //
  253. if (!ValidateSingleInstance( LayoutInformation ))
  254. ERROROUT;
  255. if( g_Warning ){
  256. if( !CheckForTurdDirCodes( LayoutInformation ))
  257. OutputFileInfo( LayoutInformation, FileName, g_Display );
  258. }
  259. return( TRUE );
  260. }
  261. /******************End Callback Routines**********************************************/
  262. void
  263. FindSingleFile( PLAYOUT_CONTEXT LayoutContext,
  264. PCTSTR FileName )
  265. {
  266. BOOL ret=FALSE;
  267. FILE_LAYOUTINFORMATION LayoutInformation;
  268. MEDIA_INFO MediaInfo;
  269. ret = FindFileInLayoutInf( LayoutContext,
  270. FileName,
  271. &LayoutInformation,
  272. NULL,
  273. NULL,
  274. &MediaInfo);
  275. if (ret)
  276. OutputFileInfo( &LayoutInformation, FileName, Default );
  277. else
  278. _ftprintf(stderr, TEXT("\nError: File Not Found\n"));
  279. return;
  280. }
  281. void
  282. OutputFileInfo( PFILE_LAYOUTINFORMATION LayoutInformation,
  283. PCTSTR FileName,
  284. DISPLAYOPTIONS DispType
  285. )
  286. {
  287. TCHAR Disposition[][50]={ TEXT("Always Copy"),
  288. TEXT("Copy if present"),
  289. TEXT("Copy if not present"),
  290. TEXT("Never copy - Copied via INF")
  291. };
  292. if( DispType == FileOnly )
  293. _tprintf(TEXT("%s\n"),FileName);
  294. else
  295. _tprintf(TEXT("Filename - %s\n"),FileName);
  296. if( DispType == FileOnly )
  297. return;
  298. _tprintf(TEXT("Dir Name - %s(%d)\n"), LayoutInformation->Directory, LayoutInformation->Directory_Code);
  299. _tprintf(TEXT("On Upgrade - %s(%d)\n"), Disposition[LayoutInformation->UpgradeDisposition], LayoutInformation->UpgradeDisposition);
  300. _tprintf(TEXT("On Clean Install - %s(%d)\n"), Disposition[LayoutInformation->CleanInstallDisposition], LayoutInformation->CleanInstallDisposition);
  301. _tprintf(TEXT("Media Tag ID - %s\n"),LayoutInformation->Media_tagID);
  302. if( *(LayoutInformation->TargetFileName))
  303. _tprintf(TEXT("Target Filename - %s\n"),LayoutInformation->TargetFileName);
  304. if( LayoutInformation->BootMediaNumber && (LayoutInformation->BootMediaNumber != -1))
  305. _tprintf(TEXT("Boot Media - %d\n"),LayoutInformation->BootMediaNumber);
  306. if( !LayoutInformation->Compression )
  307. _tprintf(TEXT("No Compression\n"));
  308. if( DispType != FileOnly )
  309. _tprintf( TEXT("\n"));
  310. return;
  311. }
  312. BOOL
  313. ProcessCommandLine( int ArgCount, TCHAR *ArgArray[] )
  314. /*
  315. Function to process the command line and seperate out options into tokens
  316. */
  317. {
  318. int i;
  319. LPTSTR Arg;
  320. if( ArgCount >= 1)
  321. lstrcpy( g_LayoutFileName, ArgArray[1] );
  322. if( !_tcsrchr( g_LayoutFileName, TEXT('\\'))){
  323. GetCurrentDirectory( MAX_PATH, g_LayoutFileName );
  324. MyConcatenatePaths(g_LayoutFileName,ArgArray[1],MAX_PATH);
  325. }
  326. for ( i=2;i < ArgCount;i++ ){ //Go through each directive
  327. Arg = ArgArray[i];
  328. if( (Arg[0] != TEXT('/')) && (Arg[0] != TEXT('-')))
  329. continue;
  330. if(_istlower(Arg[1]))
  331. Arg[1] = _toupper(Arg[1]);
  332. switch( Arg[1] ){
  333. case TEXT('F'):
  334. g_Display = FileOnly;
  335. break;
  336. case TEXT('A'):
  337. g_Platform |= LAYOUTPLATFORMS_AMD64;
  338. break;
  339. case TEXT('I'):
  340. g_Platform |= LAYOUTPLATFORMS_X86;
  341. break;
  342. case TEXT('M'):
  343. g_Platform |= LAYOUTPLATFORMS_IA64;
  344. break;
  345. case TEXT('W'):
  346. g_Warning = TRUE;
  347. break;
  348. case TEXT('V'):
  349. if( _ttoi(Arg+2) == BRIEF )
  350. Verbose = BRIEF;
  351. else if(_ttoi(Arg+2) == DETAIL )
  352. Verbose = DETAIL;
  353. else
  354. Verbose = BRIEF;
  355. break;
  356. case TEXT('D'):
  357. g_Phase = WINNT32_PHASE;
  358. break;
  359. case TEXT('L'):
  360. g_Phase = LOADER_PHASE;
  361. break;
  362. case TEXT('T'):
  363. g_Phase = TEXTMODE_PHASE;
  364. break;
  365. case TEXT('B'):
  366. g_CheckSuite = Build;
  367. break;
  368. default:
  369. break;
  370. }
  371. }// for
  372. return( TRUE );
  373. }
  374. void
  375. BuildValidations( void )
  376. /*
  377. Main processing routine while using the /B - Build switch
  378. Runs the suite of validations for this situation
  379. */
  380. {
  381. BOOL LayoutInf = FALSE;
  382. PLAYOUT_CONTEXT LayoutContext;
  383. PVOID InfHandle;
  384. DWORD Error;
  385. // Set the globals accordingly
  386. g_Display = FileOnly;
  387. // We set LayoutInf if we are validating it. In the build case
  388. // we only validate layout info for layout.inf. All others should be only
  389. // syntax checks.
  390. if(_tcsstr( g_LayoutFileName, TEXT("layout.inf")))
  391. LayoutInf = TRUE;
  392. // Run the sematic validation tests only for layout.inf in the build case
  393. if( LayoutInf ){
  394. g_Phase = 0;
  395. LayoutContext = BuildLayoutInfContext( g_LayoutFileName, g_Platform, 0);
  396. if( !LayoutContext ){
  397. g_Pass = FALSE;
  398. _tprintf(TEXT("%s : Error E0000 : Could not build Layout Inf context\n"), g_LayoutFileName);
  399. return;
  400. }
  401. //Callback will set the right value of g_pass on error.
  402. EnumerateLayoutInf( LayoutContext, BuildCheckCallback, 0 );
  403. CloseLayoutInfContext( LayoutContext );
  404. if(!ValidateTextmodeDirCodesSection( g_LayoutFileName, TEXT("WinntDirectories") ))
  405. g_Pass = FALSE;
  406. }
  407. if (g_Phase & TEXTMODE_PHASE){
  408. _tprintf( TEXT("Checking %s for compliance with the textmode setup INF parser\n"),g_LayoutFileName);
  409. if( (Error=LoadInfFile(g_LayoutFileName,FALSE,&InfHandle,TEXTMODE_PHASE)) != NO_ERROR ){
  410. _tprintf( TEXT("%s : Error E0000 : Not compliant with Textmode Setup's parser - %i\n"), g_LayoutFileName, Error );
  411. g_Pass = FALSE;
  412. }else
  413. _tprintf( TEXT("Compliant with Textmode Setup's Parser\n"), Error );
  414. }
  415. if (g_Phase & LOADER_PHASE){
  416. _tprintf( TEXT("Checking %s for compliance with the Loader's INF parser\n\n"),g_LayoutFileName);
  417. if( (Error=LoadInfFile(g_LayoutFileName,FALSE,&InfHandle,LOADER_PHASE)) != NO_ERROR ){
  418. _tprintf( TEXT("%s : Error E0000 : Not compliant with Loader's parser - %i\n"), g_LayoutFileName, Error );
  419. g_Pass = FALSE;
  420. }else
  421. _tprintf( TEXT("Compliant with Loader's Parser\n"), Error );
  422. }
  423. if (g_Phase & WINNT32_PHASE) {
  424. _tprintf( TEXT("Checking %s for compliance with the Winnt32 INF parser\n\n"),g_LayoutFileName);
  425. if( (Error=LoadInfFile(g_LayoutFileName,FALSE,&InfHandle,WINNT32_PHASE)) != NO_ERROR ){
  426. _tprintf( TEXT("%s : Error E0000 : Not compliant with Winnt32's parser - %i\n"), g_LayoutFileName, Error );
  427. g_Pass = FALSE;
  428. }else
  429. _tprintf( TEXT("Compliant with Winnt32's Parser\n"), Error );
  430. }
  431. }
  432. void
  433. DefaultValidations( void )
  434. /*
  435. Main processing routine while using the /B - Build switch
  436. Runs the suite of validations for this situation
  437. */
  438. {
  439. BOOL TxtSetupSif = FALSE;
  440. PLAYOUT_CONTEXT LayoutContext;
  441. PVOID InfHandle;
  442. DWORD Error;
  443. // We set TxtSetupSif if we are validating it. That is the only case where we need to
  444. // do syntax checks with loader and textmode along with Layout validation.
  445. if(_tcsstr( g_LayoutFileName, TEXT("txtsetup.sif"))
  446. || _tcsstr( g_LayoutFileName, TEXT("layout.inf"))){
  447. TxtSetupSif = TRUE;
  448. }
  449. if( TxtSetupSif ){
  450. // Run the semantic validation tests
  451. LayoutContext = BuildLayoutInfContext( g_LayoutFileName, g_Platform, 0);
  452. if( !LayoutContext ){
  453. g_Pass = FALSE;
  454. _tprintf(TEXT("\nError - Could not build Layout Inf context\n"));
  455. return;
  456. }
  457. //Callback will set the right value of g_pass on error.
  458. EnumerateLayoutInf( LayoutContext, MyCallback, 0 );
  459. CloseLayoutInfContext( LayoutContext );
  460. if(!ValidateTextmodeDirCodesSection( g_LayoutFileName, TEXT("WinntDirectories") ))
  461. g_Pass = FALSE;
  462. }
  463. if ((g_Phase & TEXTMODE_PHASE) || TxtSetupSif){
  464. _ftprintf( stderr, TEXT("\nChecking %s for compliance with the textmode setup INF parser\n\n"),g_LayoutFileName);
  465. if( (Error=LoadInfFile(g_LayoutFileName,FALSE,&InfHandle,TEXTMODE_PHASE)) != NO_ERROR ){
  466. _tprintf( TEXT("%s : Not compliant with Textmode Setup's parser - %i\n"), g_LayoutFileName, Error );
  467. g_Pass = FALSE;
  468. }else
  469. _tprintf( TEXT("Compliant with Textmode Setup's Parser\n"), Error );
  470. }
  471. if (g_Phase & LOADER_PHASE || TxtSetupSif){
  472. _ftprintf( stderr, TEXT("\nChecking %s for compliance with the Loader's INF parser\n\n"),g_LayoutFileName);
  473. if( (Error=LoadInfFile(g_LayoutFileName,FALSE,&InfHandle,LOADER_PHASE)) != NO_ERROR ){
  474. _tprintf( TEXT("%s : Not compliant with Loader's parser - %i\n"), g_LayoutFileName, Error );
  475. g_Pass = FALSE;
  476. }else
  477. _tprintf( TEXT("Compliant with Loader's Parser\n"), Error );
  478. }
  479. if (g_Phase & WINNT32_PHASE) {
  480. _ftprintf( stderr, TEXT("\nChecking %s for compliance with the Winnt32 INF parser\n\n"),g_LayoutFileName);
  481. if( (Error=LoadInfFile(g_LayoutFileName,FALSE,&InfHandle,WINNT32_PHASE)) != NO_ERROR ){
  482. _tprintf( TEXT("%s : Not compliant with Winnt32's parser - %i\n"), g_LayoutFileName, Error );
  483. g_Pass = FALSE;
  484. }else
  485. _tprintf( TEXT("Compliant with Winnt32's Parser\n"), Error );
  486. }
  487. }
  488. _cdecl _tmain( int argc, TCHAR *argv[ ], char *envp[ ] )
  489. {
  490. LPWSTR *CmdlineV;
  491. int CmdlineC;
  492. if(!pSetupInitializeUtils()) {
  493. return 1;
  494. }
  495. //
  496. // Check Params.
  497. //
  498. if( (argc < 2) || !_tcscmp(argv[1],TEXT("/?")) ) {
  499. _tprintf(TEXT("Program to validate/verify the given layout inf file\n\n")
  500. TEXT("Usage: %s <Inf Filename> [options]\n")
  501. TEXT("<Inf Filename> - Layout File to examine\n")
  502. TEXT("Options for layout.inf and txtsetup.sif (automatically checks loader and textmode syntax):-\n")
  503. TEXT("/W - Enable warnings too\n\n")
  504. TEXT("Checking of Platform specific SourceDisksFiles section\n")
  505. TEXT("/F - Display only filenames\n")
  506. TEXT("/I - Process for Intel i386\n")
  507. TEXT("/A - Process for AMD AMD64\n")
  508. TEXT("/M - Process for Intel IA64\n")
  509. TEXT("By default the parser will check for compliance with the textmode setup parser\n\n")
  510. TEXT("The below checks only perform a syntax check and don't check semantics.\n")
  511. TEXT("/D - Checks for compliance with winnt32 parser - use with dosnet.inf,mblclean.inf etc.\n")
  512. TEXT("/L - Checks for compliance with the loader - use for infs used by loader - biosinfo.inf, migrate.inf etc.\n")
  513. TEXT("/T - Checks for compliance with the textmode setup - use for hive*.inf etc.\n\n")
  514. TEXT("/B - Does the layout information checks for setup infs and uses build.exe compliant error reporting\n\n")
  515. , argv[0] );
  516. goto cleanup;
  517. }
  518. if( !ProcessCommandLine( argc, argv ) ) {
  519. g_Pass = FALSE;
  520. goto cleanup;
  521. }
  522. switch( g_CheckSuite ){
  523. case Build:
  524. BuildValidations();
  525. break;
  526. case Deflt:
  527. DefaultValidations();
  528. break;
  529. default:
  530. //Shouldn't get here as g_CheckSuite is initialized to Default
  531. _tprintf( TEXT("\nUnexpected error \n"));
  532. g_Pass=FALSE;
  533. break;
  534. }
  535. if( g_Pass )
  536. _tprintf( TEXT("\nNo problems found with %s\n"), g_LayoutFileName);
  537. else
  538. _tprintf( TEXT("\nErrors were encountered with %s.\n"), g_LayoutFileName);
  539. cleanup:
  540. pSetupUninitializeUtils();
  541. return (g_Pass ? 0:1);
  542. }