|
|
/*++
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:
<alias> <date> <comments>
--*/
//
// 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; }
|