/*++ Copyright (c) 1999 Microsoft Corporation Module Name: common.c Abstract: Implements code common to two or more apps. Author: Jim Schmidt (jimschm) 17-Oct-2000 Revision History: --*/ // // Includes // #include "pch.h" #include "ism.h" #include "modules.h" #include "trans.h" #include "common.h" // // Strings // // none // // Constants // #define LOG_VERBOSE_BIT 0x01 #define LOG_UNUSED_BIT 0x02 // for v1 compatibility, do not use #define LOG_STATUS_BIT 0x04 #define LOG_DEBUGGER_BIT 0x08 #define LOG_UPDATE_BIT 0x10 // // Macros // // none // // Types // // none // // Globals // // none // // Macro expansion list // #define REQUIRED_INFS \ DEFMAC(OSFILES, TEXT("USMTDef.inf")) \ // // Private function prototypes // // none // // Macro expansion definition // // this is the structure used for handling required infs typedef struct { PCTSTR InfId; PCTSTR InfName; } REQUIREDINF_STRUCT, *PREQUIREDINF_STRUCT; // declare a global array of required infs #define DEFMAC(infid,infname) {TEXT(#infid),infname}, static REQUIREDINF_STRUCT g_RequiredInfs[] = { REQUIRED_INFS {NULL, NULL} }; #undef DEFMAC // // Code // VOID InitAppCommon ( VOID ) { InfGlobalInit (FALSE); RegInitialize(); } VOID TerminateAppCommon ( VOID ) { RegTerminate(); InfGlobalInit (FALSE); } HINF InitRequiredInfs ( IN PCTSTR AppPath, IN PCSTR FailMsgId ) { PCTSTR fullPath; HINF result = INVALID_HANDLE_VALUE; PREQUIREDINF_STRUCT p = g_RequiredInfs; while (p->InfId) { fullPath = JoinPaths (AppPath, p->InfName); if (DoesFileExist (fullPath)) { if (result == INVALID_HANDLE_VALUE) { result = SetupOpenInfFile (fullPath, NULL, INF_STYLE_WIN4 | INF_STYLE_OLDNT, NULL); if (result == INVALID_HANDLE_VALUE) { LOG ((LOG_ERROR, FailMsgId, p->InfId, fullPath)); } } else { if (!SetupOpenAppendInfFile (fullPath, result, NULL)) { LOG ((LOG_ERROR, FailMsgId, p->InfId, fullPath)); } } } else { LOG ((LOG_ERROR, FailMsgId, p->InfId, fullPath)); } FreePathString (fullPath); p++; } return result; } VOID PrintMsgOnConsole ( IN UINT MsgId ) { PCTSTR msg; msg = GetStringResource (MsgId); if (msg) { _tprintf (TEXT("%s"), msg); FreeStringResource (msg); } } VOID UploadEnvVars ( IN MIG_PLATFORMTYPEID Platform ) { PCTSTR envVars = NULL; MULTISZ_ENUM e; PTSTR envString; PTSTR p; // // we are going to write here all defined environment variables // envVars = (PCTSTR) GetEnvironmentStrings(); if (envVars) { if (EnumFirstMultiSz (&e, envVars)) { do { envString = DuplicatePathString (e.CurrentString, 0); p = _tcschr (envString, TEXT('=')); // // Get rid of empty environment strings or the dummy env string starting // with '=' // if (!p || p == envString) { FreePathString (envString); continue; } *p = 0; p = _tcsinc (p); if (p) { IsmSetEnvironmentString (Platform, S_SYSENVVAR_GROUP, envString, p); } FreePathString (envString); } while (EnumNextMultiSz (&e)); } } } VOID SetLogVerbosity ( IN INT VerboseLevel ) { LOG_LEVEL logBitmap = 0; if (VerboseLevel < 0) { VerboseLevel = 0; } // Always ON logBitmap = LL_FATAL_ERROR | LL_MODULE_ERROR | LL_ERROR; // ON for VERBOSE_BIT if (VerboseLevel & LOG_VERBOSE_BIT) { logBitmap |= LL_WARNING | LL_INFORMATION; } // ON for STATUS_BIT if (VerboseLevel & LOG_STATUS_BIT) { logBitmap |= LL_STATUS; } // ON for UPDATE_BIT if (VerboseLevel & LOG_UPDATE_BIT) { logBitmap |= LL_UPDATE; } #ifdef PRERELEASE LogSetVerboseBitmap ( logBitmap, LL_FATAL_ERROR|LL_MODULE_ERROR|LL_ERROR|LL_WARNING|LL_INFORMATION|LL_STATUS|LL_UPDATE, VerboseLevel & LOG_DEBUGGER_BIT ); #else LogSetVerboseBitmap ( logBitmap, LL_FATAL_ERROR|LL_MODULE_ERROR|LL_ERROR|LL_WARNING|LL_INFORMATION, VerboseLevel & LOG_DEBUGGER_BIT ); #endif } BOOL GetFilePath ( IN PCTSTR UserSpecifiedFile, OUT PTSTR Buffer, IN UINT BufferTchars ) { PTSTR tempBuffer = NULL; TCHAR infDir[MAX_MBCHAR_PATH]; TCHAR modulePath[MAX_MBCHAR_PATH]; TCHAR currentDir[MAX_MBCHAR_PATH]; PTSTR p; PCTSTR userFile = NULL; PTSTR dontCare; __try { // // Locate the file using the full path specified by the user, or // if only a file spec was given, use the following priorities: // // 1. Current directory // 2. Directory where the tool is // 3. INF directory // // In all cases, return the full path to the file. // if (Buffer) { *Buffer = 0; } else { __leave; } tempBuffer = AllocText (BufferTchars); *tempBuffer = 0; if (!_tcsrchr (UserSpecifiedFile, TEXT('\\'))) { // // Compute INF directory, module directory and current directory // if (!GetWindowsDirectory (infDir, ARRAYSIZE(infDir) - 5)) { MYASSERT (FALSE); __leave; } StringCat (infDir, TEXT("\\inf")); if (!GetModuleFileName (NULL, modulePath, ARRAYSIZE(modulePath))) { MYASSERT (FALSE); __leave; } p = _tcsrchr (modulePath, TEXT('\\')); if (p) { *p = 0; } else { MYASSERT (FALSE); __leave; } if (!GetCurrentDirectory (ARRAYSIZE(currentDir), currentDir)) { MYASSERT (FALSE); __leave; } // // Let's see if it's in the current dir // userFile = JoinPaths (currentDir, UserSpecifiedFile); if (DoesFileExist (userFile)) { GetFullPathName ( userFile, BufferTchars, tempBuffer, &dontCare ); } else { // // Let's try the module dir // FreePathString (userFile); userFile = JoinPaths (modulePath, UserSpecifiedFile); if (DoesFileExist (userFile)) { GetFullPathName ( userFile, BufferTchars, tempBuffer, &dontCare ); } else { // // Let's try the INF dir // FreePathString (userFile); userFile = JoinPaths (infDir, UserSpecifiedFile); if (DoesFileExist (userFile)) { GetFullPathName ( userFile, BufferTchars, tempBuffer, &dontCare ); } } } } else { // // Use the full path that the user specified // GetFullPathName ( UserSpecifiedFile, BufferTchars, tempBuffer, &dontCare ); if (*tempBuffer && !DoesFileExist (tempBuffer)) { *tempBuffer = 0; } } // // Transfer output into caller's buffer. Note the TCHAR conversion. // StringCopy (Buffer, tempBuffer); } __finally { if (userFile) { FreePathString (userFile); } if (tempBuffer) { FreeText (tempBuffer); } } return (Buffer && (*Buffer != 0)); } VOID WriteAppStatus ( IN PCTSTR AppJournal, IN DWORD Status ) { HANDLE appJrnHandle; if (AppJournal && AppJournal [0]) { appJrnHandle = BfOpenFile (AppJournal); if (!appJrnHandle) { appJrnHandle = BfCreateFile (AppJournal); } if (appJrnHandle) { if (BfSetFilePointer (appJrnHandle, 0)) { BfWriteFile (appJrnHandle, (PBYTE)(&Status), sizeof (DWORD)); } FlushFileBuffers (appJrnHandle); CloseHandle (appJrnHandle); } } } DWORD ReadAppStatus ( IN PCTSTR AppJournal ) { HANDLE appJrnHandle; DWORD result = 0; if (AppJournal && AppJournal [0]) { appJrnHandle = BfOpenReadFile (AppJournal); if (appJrnHandle) { if (BfSetFilePointer (appJrnHandle, 0)) { if (!BfReadFile (appJrnHandle, (PBYTE)(&result), sizeof (DWORD))) { result = 0; } } CloseHandle (appJrnHandle); } } return result; } VOID SelectComponentsViaInf ( IN HINF Inf ) { INFSTRUCT is = INITINFSTRUCT_GROWBUFFER; PCTSTR data; // // Enable or disable components based on the unlocalized tag name, // or by the localized string // if (InfFindFirstLine (Inf, TEXT("Disabled Components"), NULL, &is)) { do { data = InfGetStringField (&is, 1); if (data) { if (!IsmSelectComponent (data, 0, FALSE)) { IsmSelectComponent (data, COMPONENT_NAME, FALSE); } } } while (InfFindNextLine (&is)); } if (InfFindFirstLine (Inf, TEXT("Enabled Components"), NULL, &is)) { do { data = InfGetStringField (&is, 1); if (data) { if (!IsmSelectComponent (data, 0, TRUE)) { IsmSelectComponent (data, COMPONENT_NAME, TRUE); } } } while (InfFindNextLine (&is)); } } PARSERESULT ParseToolCmdLine ( IN BOOL ScanState, OUT PTOOLARGS Args, IN INT Argc, IN PCTSTR Argv[] ) { INT i; PCTSTR infFileFromCmdLine; TCHAR fullInfPath[MAX_TCHAR_PATH]; MULTISZ_ENUM e; HANDLE h; BOOL logCreated = FALSE; BOOL everythingOn = TRUE; BOOL xSwitch = FALSE; #ifdef PRERELEASE DWORD tagSize; #endif ZeroMemory (Args, sizeof (TOOLARGS)); Args->VerboseLevel = -1; Args->TransportName = S_RELIABLE_STORAGE_TRANSPORT; #ifdef PRERELEASE tagSize = ARRAYSIZE(Args->Tag); GetUserName (Args->Tag, &tagSize); #endif for (i = 1 ; i < Argc ; i++) { if (Argv[i][0] == TEXT('-') || Argv[i][0] == '/') { switch ((CHARTYPE) _totlower ((CHARTYPE) _tcsnextc (&Argv[i][1]))) { case TEXT('i'): if (Argv[i][2] == TEXT('x') && !Argv[i][3]) { if (ScanState) { return PARSE_OTHER_ERROR; } if (Args->NoScanStateInfs) { return PARSE_OTHER_ERROR; } Args->NoScanStateInfs = TRUE; break; } if (Argv[i][2] == TEXT(':')) { infFileFromCmdLine = &Argv[i][3]; } else if (i + 1 < Argc) { i++; infFileFromCmdLine = Argv[i]; } else { return PARSE_OTHER_ERROR; } if (!GetFilePath (infFileFromCmdLine, fullInfPath, ARRAYSIZE(fullInfPath))) { GbMultiSzAppend (&Args->BadInfs, infFileFromCmdLine); break; } // // Make sure fullInfPath was not already specified // if (Args->InputInf.End) { if (EnumFirstMultiSz (&e, (PCTSTR) Args->InputInf.Buf)) { do { if (StringIMatch (e.CurrentString, fullInfPath)) { GbMultiSzAppend (&Args->MultiInfs, infFileFromCmdLine); *fullInfPath = 0; break; } } while (EnumNextMultiSz (&e)); } if (*fullInfPath == 0) { break; } } // // INF file is valid // GbMultiSzAppend (&Args->InputInf, fullInfPath); break; case TEXT('l'): if (Args->LogFile) { return PARSE_MULTI_LOG; } if (Argv[i][2] == TEXT(':')) { Args->LogFile = &(Argv[i][3]); } else if (i + 1 < Argc) { i++; Args->LogFile = Argv[i]; } else { return PARSE_OTHER_ERROR; } h = BfCreateFile (Args->LogFile); if (!h) { return PARSE_BAD_LOG; } CloseHandle (h); logCreated = TRUE; break; case TEXT('v'): if (Args->VerboseLevel >= 0) { return PARSE_MULTI_VERBOSE; } if (Argv[i][2] == TEXT(':')) { _stscanf (&(Argv[i][3]), TEXT("%d"), &Args->VerboseLevel); } else if (i + 1 < Argc) { if (_tcsnextc (Argv[i + 1]) >= TEXT('0') && _tcsnextc (Argv[i + 1]) <= TEXT('9') ) { i++; _stscanf (Argv[i], TEXT("%d"), &Args->VerboseLevel); } else { Args->VerboseLevel = 1; } } else { return PARSE_OTHER_ERROR; } #ifndef PRERELEASE if (Args->VerboseLevel > 7) { #else Args->VerboseLevel |= LOG_UPDATE_BIT; if (Args->VerboseLevel > 0x1F) { #endif return PARSE_OTHER_ERROR; } break; case TEXT('x'): if (xSwitch) { return PARSE_OTHER_ERROR; } if (Argv[i][2]) { return PARSE_OTHER_ERROR; } everythingOn = FALSE; xSwitch = TRUE; break; case TEXT('s'): if (Args->SystemOn) { return PARSE_OTHER_ERROR; } if (Argv[i][2]) { return PARSE_OTHER_ERROR; } Args->SystemOn = TRUE; everythingOn = FALSE; break; case TEXT('u'): if (Args->UserOn) { return PARSE_OTHER_ERROR; } if (Argv[i][2]) { return PARSE_OTHER_ERROR; } Args->UserOn = TRUE; everythingOn = FALSE; break; case TEXT('f'): if (Args->FilesOn) { return PARSE_OTHER_ERROR; } if (Argv[i][2]) { return PARSE_OTHER_ERROR; } Args->FilesOn = TRUE; everythingOn = FALSE; break; case TEXT('q'): if (ScanState) { Args->OverwriteImage = TRUE; Args->TestMode = TRUE; } else { Args->CurrentUser = TRUE; } break; case TEXT('o'): if (!ScanState) { return PARSE_OTHER_ERROR; } if (Args->OverwriteImage) { return PARSE_OTHER_ERROR; } if (Argv[i][2]) { return PARSE_OTHER_ERROR; } Args->OverwriteImage = TRUE; break; case TEXT('c'): if (Argv[i][2]) { return PARSE_OTHER_ERROR; } if (ScanState) { if (Args->ContinueOnError) { return PARSE_OTHER_ERROR; } Args->ContinueOnError = TRUE; } else { return PARSE_OTHER_ERROR; } break; case TEXT('d'): if (ScanState) { return PARSE_OTHER_ERROR; } if (Args->DelayedOpsOn) { return PARSE_OTHER_ERROR; } if (Argv[i][2]) { return PARSE_OTHER_ERROR; } Args->DelayedOpsOn = TRUE; break; #ifdef PRERELEASE case TEXT('t'): switch ((CHARTYPE) _totlower (Argv[i][2])) { case TEXT('f'): if (Argv[i][3]) { return PARSE_OTHER_ERROR; } if (Args->FullTransport) { return PARSE_OTHER_ERROR; } Args->FullTransport = TRUE; break; case TEXT('c'): if (Argv[i][3]) { return PARSE_OTHER_ERROR; } if (Args->Capabilities & CAPABILITY_COMPRESSED) { return PARSE_OTHER_ERROR; } Args->Capabilities |= CAPABILITY_COMPRESSED; break; case TEXT('a'): if (Argv[i][3]) { return PARSE_OTHER_ERROR; } if (Args->Capabilities & CAPABILITY_AUTOMATED) { return PARSE_OTHER_ERROR; } Args->Capabilities |= CAPABILITY_AUTOMATED; break; case TEXT('i'): if (Argv[i][3] != TEXT(':')) { return PARSE_OTHER_ERROR; } StackStringCopy (Args->Tag, &Argv[i][4]); break; case 0: case TEXT(':'): if (Args->TransportNameSpecified) { return PARSE_OTHER_ERROR; } Args->TransportNameSpecified = TRUE; if (Argv[i][2]) { if (!Argv[i][3]) { return PARSE_OTHER_ERROR; } Args->TransportName = &Argv[i][3]; } else { if (i + 1 >= Argc) { return PARSE_OTHER_ERROR; } else { i++; Args->TransportName = Argv[i]; } } break; default: return PARSE_OTHER_ERROR; } break; case TEXT('r'): if (ScanState) { return PARSE_OTHER_ERROR; } if (Args->Recovery) { return PARSE_OTHER_ERROR; } if (Argv[i][2]) { return PARSE_OTHER_ERROR; } Args->Recovery = TRUE; break; #endif default: return PARSE_OTHER_ERROR; } } else if (!Args->StoragePath) { Args->StoragePath = Argv[i]; } else { return PARSE_OTHER_ERROR; } } if (!Args->StoragePath) { if (!Args->DelayedOpsOn) { return PARSE_MISSING_STORAGE_PATH; } } if (everythingOn) { Args->SystemOn = TRUE; Args->UserOn = TRUE; Args->FilesOn = TRUE; } if (Args->InputInf.Buf) { GbMultiSzAppend (&Args->InputInf, TEXT("")); } return PARSE_SUCCESS; }