|
|
/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
myapp.c
Abstract:
This module implements functions to access the parsed INF.
Author:
Vijesh Shetty (vijeshs)
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
#include <wild.c>
#define PRINT( msg, param ) \
{ _tprintf( TEXT(msg), param ); \ if(g_Display == Default ){ \ _tprintf( TEXT("\n")); \ }else if(g_Display == FileOnly ){ \ _tprintf( TEXT(" - ")); }\ }
#define ERROROUT \
{ g_Pass = FALSE; \ OutputFileInfo( LayoutInformation, FileName, g_Display ); \ return TRUE;} #define MAX_BOOTFLOPPY 7
extern BOOL Verbose;
extern DWORD LoadInfFile( IN LPCTSTR Filename, IN BOOL OemCodepage, OUT PVOID *InfHandle, DWORD Phase );
BOOL CALLBACK MyCallback( IN PLAYOUT_CONTEXT Context, IN PCTSTR FileName, IN PFILE_LAYOUTINFORMATION LayoutInformation, IN PVOID ExtraData, IN UINT ExtraDataSize, IN OUT DWORD_PTR Param );
typedef enum _DISPLAYOPTIONS{ Default, FileOnly } DISPLAYOPTIONS, *PDISPLAYOPTIONS;
typedef enum _CHECKSUITE{ Deflt, Build } CHECKSUITE, *PCHECKSUITE;
DISPLAYOPTIONS g_Display = Default; CHECKSUITE g_CheckSuite = Deflt; TCHAR g_LayoutFileName[MAX_PATH]; DWORD g_Platform=LAYOUTPLATFORMS_COMMON; BOOLEAN g_Warning = FALSE; BOOLEAN g_Pass = TRUE; DWORD g_Phase = TEXTMODE_PHASE; PLAYOUTENUMCALLBACK g_Callback = (PLAYOUTENUMCALLBACK) MyCallback;
BOOLEAN IsNameInExpressionPrivate ( IN PCTSTR Expression, IN PCTSTR Name );
void OutputFileInfo( PFILE_LAYOUTINFORMATION LayoutInformation, PCTSTR FileName, DISPLAYOPTIONS DispType );
/*******************************************************************************/
// Validation Check Functions
//
BOOL Validate8Dot3( IN PCTSTR FileName ) /*
Function to check if a file satisfies 8.3 Arguments: FileName - Filename to validate Return value: TRUE - Passes validation FALSE - Fails validation */ {
//
// Check for 8.3 validation
//
if( (g_Platform & LAYOUTPLATFORMS_IA64) || (g_Platform & LAYOUTPLATFORMS_AMD64) ) return TRUE;
if( FileName && (lstrlen(FileName) > 12)){ PRINT( "%s : Error E0000 : !!! - Filename too long (8.3 required)", g_LayoutFileName ); return FALSE; }
return TRUE;
}
BOOL ValidateMissingDirCodes( IN PFILE_LAYOUTINFORMATION LayoutInformation ) /*
Function to check if a file is missing Directory Information when it is needed by textmode Arguments: LayoutInformation - Pointer to PFILE_LAYOUTINFORMATION structure for file Return value: TRUE - Passes validation FALSE - Fails validation */ {
//
// Check for Directory codes
//
if( ((LayoutInformation->CleanInstallDisposition <= 2) || (LayoutInformation->UpgradeDisposition <= 2)) && !(*LayoutInformation->Directory)){ PRINT( "%s : Error E0000 : !!! - Missing directory for textmode setup", g_LayoutFileName ); return FALSE; }
return TRUE;
}
BOOL ValidateBootMediaFields( IN PFILE_LAYOUTINFORMATION LayoutInformation ) /*
Function to check if the Boot Media fields are set right Arguments: LayoutInformation - Pointer to PFILE_LAYOUTINFORMATION structure for file Return value: TRUE - Passes validation FALSE - Fails validation */ {
if( (LayoutInformation->BootMediaNumber < 0) || (LayoutInformation->BootMediaNumber > MAX_BOOTFLOPPY) || (LayoutInformation->BootMediaNumber == -1) ){
PRINT( "%s : Error E0000 : !!! - Bad Boot media number", g_LayoutFileName ); return FALSE; }
return TRUE;
}
BOOL ValidateSingleInstance( IN PFILE_LAYOUTINFORMATION LayoutInformation ) /*
Function to check if there is only a single instance of this file Arguments: LayoutInformation - Pointer to PFILE_LAYOUTINFORMATION structure for file Return value: TRUE - Passes validation FALSE - Fails validation */ {
if( LayoutInformation->Count > 1 ){ PRINT( "%s : Error E0000 : !!! - Filename present in more than one place", g_LayoutFileName ); return FALSE; }
return TRUE;
}
BOOL CheckForTurdDirCodes( IN PFILE_LAYOUTINFORMATION LayoutInformation ) /*
Function to check if the dir code is present but doesn't make sense with respect to dispositions Arguments: LayoutInformation - Pointer to PFILE_LAYOUTINFORMATION structure for file Return value: TRUE - Not a Turd FALSE - Presence of a turd */ {
if( ((LayoutInformation->CleanInstallDisposition == 3) && (LayoutInformation->UpgradeDisposition == 3)) \ && (*LayoutInformation->Directory)){ PRINT( "%s : Warning W0000 : !!! - Directory code specified but not used", g_LayoutFileName ); return FALSE; }
return TRUE;
}
/***********End Validation Check Functions*****************************************/
/***********Callback Routines*************************************/
BOOL CALLBACK MyCallback( IN PLAYOUT_CONTEXT Context, IN PCTSTR FileName, IN PFILE_LAYOUTINFORMATION LayoutInformation, IN PVOID ExtraData, IN UINT ExtraDataSize, IN OUT DWORD_PTR Param ) { BOOL Error=FALSE;
// Check for missing filename
if( !FileName || !(*FileName) ){ PRINT( "%s : Error E0000 :!!! - Line missing filename\n", FileName ); ERROROUT; }
//
// Check for 8.3 validation
//
if( !Validate8Dot3( FileName )) ERROROUT;
//
// Check for Directory codes
//
if( !ValidateMissingDirCodes( LayoutInformation)) ERROROUT;
//
// Check for Boot Media validity
//
if (!ValidateBootMediaFields( LayoutInformation)) ERROROUT;
//
// Check for duplicates
//
if (!ValidateSingleInstance( LayoutInformation )) ERROROUT;
if( g_Warning ){ if( !CheckForTurdDirCodes( LayoutInformation )) OutputFileInfo( LayoutInformation, FileName, g_Display );
}
return( TRUE );
}
CALLBACK BuildCheckCallback( IN PLAYOUT_CONTEXT Context, IN PCTSTR FileName, IN PFILE_LAYOUTINFORMATION LayoutInformation, IN PVOID ExtraData, IN UINT ExtraDataSize, IN OUT DWORD_PTR Param ) { BOOL Error=FALSE;
// Check for missing filename
if( !FileName || !(*FileName) ){ PRINT( "%s : Error E0000 :!!! - Line missing filename\n", FileName ); ERROROUT; }
//
// Check for 8.3 validation
//
if( !Validate8Dot3( FileName )) ERROROUT;
//
// Check for Directory codes
//
if( !ValidateMissingDirCodes( LayoutInformation)) ERROROUT;
//
// Check for Boot Media validity
//
if (!ValidateBootMediaFields( LayoutInformation)) ERROROUT;
//
// Check for duplicates
//
if (!ValidateSingleInstance( LayoutInformation )) ERROROUT;
if( g_Warning ){ if( !CheckForTurdDirCodes( LayoutInformation )) OutputFileInfo( LayoutInformation, FileName, g_Display );
}
return( TRUE );
}
/******************End Callback Routines**********************************************/
void FindSingleFile( PLAYOUT_CONTEXT LayoutContext, PCTSTR FileName ) {
BOOL ret=FALSE; FILE_LAYOUTINFORMATION LayoutInformation; MEDIA_INFO MediaInfo;
ret = FindFileInLayoutInf( LayoutContext, FileName, &LayoutInformation, NULL, NULL, &MediaInfo);
if (ret) OutputFileInfo( &LayoutInformation, FileName, Default ); else _ftprintf(stderr, TEXT("\nError: File Not Found\n"));
return;
}
void OutputFileInfo( PFILE_LAYOUTINFORMATION LayoutInformation, PCTSTR FileName, DISPLAYOPTIONS DispType ) { TCHAR Disposition[][50]={ TEXT("Always Copy"), TEXT("Copy if present"), TEXT("Copy if not present"), TEXT("Never copy - Copied via INF")
};
if( DispType == FileOnly ) _tprintf(TEXT("%s\n"),FileName); else _tprintf(TEXT("Filename - %s\n"),FileName);
if( DispType == FileOnly ) return;
_tprintf(TEXT("Dir Name - %s(%d)\n"), LayoutInformation->Directory, LayoutInformation->Directory_Code);
_tprintf(TEXT("On Upgrade - %s(%d)\n"), Disposition[LayoutInformation->UpgradeDisposition], LayoutInformation->UpgradeDisposition); _tprintf(TEXT("On Clean Install - %s(%d)\n"), Disposition[LayoutInformation->CleanInstallDisposition], LayoutInformation->CleanInstallDisposition);
_tprintf(TEXT("Media Tag ID - %s\n"),LayoutInformation->Media_tagID);
if( *(LayoutInformation->TargetFileName)) _tprintf(TEXT("Target Filename - %s\n"),LayoutInformation->TargetFileName); if( LayoutInformation->BootMediaNumber && (LayoutInformation->BootMediaNumber != -1)) _tprintf(TEXT("Boot Media - %d\n"),LayoutInformation->BootMediaNumber); if( !LayoutInformation->Compression ) _tprintf(TEXT("No Compression\n"));
if( DispType != FileOnly ) _tprintf( TEXT("\n"));
return;
}
BOOL ProcessCommandLine( int ArgCount, TCHAR *ArgArray[] ) /*
Function to process the command line and seperate out options into tokens */ {
int i; LPTSTR Arg;
if( ArgCount >= 1) lstrcpy( g_LayoutFileName, ArgArray[1] );
if( !_tcsrchr( g_LayoutFileName, TEXT('\\'))){ GetCurrentDirectory( MAX_PATH, g_LayoutFileName ); MyConcatenatePaths(g_LayoutFileName,ArgArray[1],MAX_PATH);
}
for ( i=2;i < ArgCount;i++ ){ //Go through each directive
Arg = ArgArray[i];
if( (Arg[0] != TEXT('/')) && (Arg[0] != TEXT('-'))) continue;
if(_istlower(Arg[1])) Arg[1] = _toupper(Arg[1]);
switch( Arg[1] ){
case TEXT('F'): g_Display = FileOnly; break;
case TEXT('A'): g_Platform |= LAYOUTPLATFORMS_AMD64; break;
case TEXT('I'): g_Platform |= LAYOUTPLATFORMS_X86; break;
case TEXT('M'): g_Platform |= LAYOUTPLATFORMS_IA64; break;
case TEXT('W'): g_Warning = TRUE; break;
case TEXT('V'): if( _ttoi(Arg+2) == BRIEF ) Verbose = BRIEF; else if(_ttoi(Arg+2) == DETAIL ) Verbose = DETAIL; else Verbose = BRIEF; break;
case TEXT('D'): g_Phase = WINNT32_PHASE; break;
case TEXT('L'): g_Phase = LOADER_PHASE; break;
case TEXT('T'): g_Phase = TEXTMODE_PHASE; break;
case TEXT('B'): g_CheckSuite = Build; break;
default: break; }
}// for
return( TRUE );
}
void BuildValidations( void ) /*
Main processing routine while using the /B - Build switch Runs the suite of validations for this situation
*/ { BOOL LayoutInf = FALSE; PLAYOUT_CONTEXT LayoutContext; PVOID InfHandle; DWORD Error;
// Set the globals accordingly
g_Display = FileOnly;
// We set LayoutInf if we are validating it. In the build case
// we only validate layout info for layout.inf. All others should be only
// syntax checks.
if(_tcsstr( g_LayoutFileName, TEXT("layout.inf"))) LayoutInf = TRUE;
// Run the sematic validation tests only for layout.inf in the build case
if( LayoutInf ){
g_Phase = 0; LayoutContext = BuildLayoutInfContext( g_LayoutFileName, g_Platform, 0); if( !LayoutContext ){ g_Pass = FALSE; _tprintf(TEXT("%s : Error E0000 : Could not build Layout Inf context\n"), g_LayoutFileName); return; }
//Callback will set the right value of g_pass on error.
EnumerateLayoutInf( LayoutContext, BuildCheckCallback, 0 ); CloseLayoutInfContext( LayoutContext );
if(!ValidateTextmodeDirCodesSection( g_LayoutFileName, TEXT("WinntDirectories") )) g_Pass = FALSE;
} if (g_Phase & TEXTMODE_PHASE){
_tprintf( TEXT("Checking %s for compliance with the textmode setup INF parser\n"),g_LayoutFileName); if( (Error=LoadInfFile(g_LayoutFileName,FALSE,&InfHandle,TEXTMODE_PHASE)) != NO_ERROR ){ _tprintf( TEXT("%s : Error E0000 : Not compliant with Textmode Setup's parser - %i\n"), g_LayoutFileName, Error ); g_Pass = FALSE; }else _tprintf( TEXT("Compliant with Textmode Setup's Parser\n"), Error ); } if (g_Phase & LOADER_PHASE){
_tprintf( TEXT("Checking %s for compliance with the Loader's INF parser\n\n"),g_LayoutFileName); if( (Error=LoadInfFile(g_LayoutFileName,FALSE,&InfHandle,LOADER_PHASE)) != NO_ERROR ){ _tprintf( TEXT("%s : Error E0000 : Not compliant with Loader's parser - %i\n"), g_LayoutFileName, Error ); g_Pass = FALSE; }else _tprintf( TEXT("Compliant with Loader's Parser\n"), Error );
} if (g_Phase & WINNT32_PHASE) {
_tprintf( TEXT("Checking %s for compliance with the Winnt32 INF parser\n\n"),g_LayoutFileName); if( (Error=LoadInfFile(g_LayoutFileName,FALSE,&InfHandle,WINNT32_PHASE)) != NO_ERROR ){ _tprintf( TEXT("%s : Error E0000 : Not compliant with Winnt32's parser - %i\n"), g_LayoutFileName, Error ); g_Pass = FALSE; }else _tprintf( TEXT("Compliant with Winnt32's Parser\n"), Error );
}
}
void DefaultValidations( void ) /*
Main processing routine while using the /B - Build switch Runs the suite of validations for this situation
*/ { BOOL TxtSetupSif = FALSE; PLAYOUT_CONTEXT LayoutContext; PVOID InfHandle; DWORD Error;
// We set TxtSetupSif if we are validating it. That is the only case where we need to
// do syntax checks with loader and textmode along with Layout validation.
if(_tcsstr( g_LayoutFileName, TEXT("txtsetup.sif")) || _tcsstr( g_LayoutFileName, TEXT("layout.inf"))){ TxtSetupSif = TRUE; }
if( TxtSetupSif ){ // Run the semantic validation tests
LayoutContext = BuildLayoutInfContext( g_LayoutFileName, g_Platform, 0); if( !LayoutContext ){ g_Pass = FALSE; _tprintf(TEXT("\nError - Could not build Layout Inf context\n")); return; } //Callback will set the right value of g_pass on error.
EnumerateLayoutInf( LayoutContext, MyCallback, 0 ); CloseLayoutInfContext( LayoutContext );
if(!ValidateTextmodeDirCodesSection( g_LayoutFileName, TEXT("WinntDirectories") )) g_Pass = FALSE;
}
if ((g_Phase & TEXTMODE_PHASE) || TxtSetupSif){
_ftprintf( stderr, TEXT("\nChecking %s for compliance with the textmode setup INF parser\n\n"),g_LayoutFileName); if( (Error=LoadInfFile(g_LayoutFileName,FALSE,&InfHandle,TEXTMODE_PHASE)) != NO_ERROR ){ _tprintf( TEXT("%s : Not compliant with Textmode Setup's parser - %i\n"), g_LayoutFileName, Error ); g_Pass = FALSE; }else _tprintf( TEXT("Compliant with Textmode Setup's Parser\n"), Error ); } if (g_Phase & LOADER_PHASE || TxtSetupSif){
_ftprintf( stderr, TEXT("\nChecking %s for compliance with the Loader's INF parser\n\n"),g_LayoutFileName); if( (Error=LoadInfFile(g_LayoutFileName,FALSE,&InfHandle,LOADER_PHASE)) != NO_ERROR ){ _tprintf( TEXT("%s : Not compliant with Loader's parser - %i\n"), g_LayoutFileName, Error ); g_Pass = FALSE; }else _tprintf( TEXT("Compliant with Loader's Parser\n"), Error );
} if (g_Phase & WINNT32_PHASE) {
_ftprintf( stderr, TEXT("\nChecking %s for compliance with the Winnt32 INF parser\n\n"),g_LayoutFileName); if( (Error=LoadInfFile(g_LayoutFileName,FALSE,&InfHandle,WINNT32_PHASE)) != NO_ERROR ){ _tprintf( TEXT("%s : Not compliant with Winnt32's parser - %i\n"), g_LayoutFileName, Error ); g_Pass = FALSE; }else _tprintf( TEXT("Compliant with Winnt32's Parser\n"), Error );
}
}
_cdecl _tmain( int argc, TCHAR *argv[ ], char *envp[ ] ) { LPWSTR *CmdlineV; int CmdlineC;
if(!pSetupInitializeUtils()) { return 1; }
//
// Check Params.
//
if( (argc < 2) || !_tcscmp(argv[1],TEXT("/?")) ) { _tprintf(TEXT("Program to validate/verify the given layout inf file\n\n") TEXT("Usage: %s <Inf Filename> [options]\n") TEXT("<Inf Filename> - Layout File to examine\n") TEXT("Options for layout.inf and txtsetup.sif (automatically checks loader and textmode syntax):-\n") TEXT("/W - Enable warnings too\n\n") TEXT("Checking of Platform specific SourceDisksFiles section\n") TEXT("/F - Display only filenames\n") TEXT("/I - Process for Intel i386\n") TEXT("/A - Process for AMD AMD64\n") TEXT("/M - Process for Intel IA64\n") TEXT("By default the parser will check for compliance with the textmode setup parser\n\n") TEXT("The below checks only perform a syntax check and don't check semantics.\n") TEXT("/D - Checks for compliance with winnt32 parser - use with dosnet.inf,mblclean.inf etc.\n") TEXT("/L - Checks for compliance with the loader - use for infs used by loader - biosinfo.inf, migrate.inf etc.\n") TEXT("/T - Checks for compliance with the textmode setup - use for hive*.inf etc.\n\n") TEXT("/B - Does the layout information checks for setup infs and uses build.exe compliant error reporting\n\n") , argv[0] ); goto cleanup; }
if( !ProcessCommandLine( argc, argv ) ) { g_Pass = FALSE; goto cleanup; }
switch( g_CheckSuite ){ case Build: BuildValidations(); break;
case Deflt: DefaultValidations(); break;
default: //Shouldn't get here as g_CheckSuite is initialized to Default
_tprintf( TEXT("\nUnexpected error \n")); g_Pass=FALSE; break;
}
if( g_Pass ) _tprintf( TEXT("\nNo problems found with %s\n"), g_LayoutFileName); else _tprintf( TEXT("\nErrors were encountered with %s.\n"), g_LayoutFileName); cleanup:
pSetupUninitializeUtils();
return (g_Pass ? 0:1); }
|