887 lines
21 KiB
C
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;
|
|
}
|
|
|