windows-nt/Source/XPSP1/NT/windows/winstate/cobra/app/common/common.c
2020-09-26 16:20:57 +08:00

887 lines
21 KiB
C

/*++
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;
}