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.

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