You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1030 lines
29 KiB
1030 lines
29 KiB
/*++
|
|
|
|
Copyright (c) 1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
scanstate.c
|
|
|
|
Abstract:
|
|
|
|
Implements the app layer of the v1 compatibility app.
|
|
|
|
Author:
|
|
|
|
Jim Schmidt (jimschm) 14-Mar-2000
|
|
|
|
Revision History:
|
|
|
|
<alias> <date> <comments>
|
|
|
|
--*/
|
|
|
|
//
|
|
// Includes
|
|
//
|
|
|
|
#include "pch.h"
|
|
#include "ism.h"
|
|
#include "modules.h"
|
|
#include "trans.h"
|
|
#include "v2app.h"
|
|
#include <lm.h>
|
|
#ifdef DEBUG
|
|
#include <shellapi.h>
|
|
#endif
|
|
#include "logmsg.h"
|
|
#include "common.h"
|
|
|
|
#define DBG_SCANSTATE "ScanState"
|
|
|
|
//
|
|
// 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
|
|
|
|
#define SCANSTATE_SAVE 0x00000001
|
|
#define SCANSTATE_COMPLETED 0x00000002
|
|
|
|
#define RETURN_SUCCESS 0
|
|
#define RETURN_FATAL_ERROR 1
|
|
#define RETURN_ERROR 2
|
|
#define RETURN_IGNORED_ERROR 3
|
|
|
|
//
|
|
// Macros
|
|
//
|
|
|
|
// None
|
|
|
|
//
|
|
// Types
|
|
//
|
|
|
|
typedef NET_API_STATUS(WINAPI NETWKSTAGETINFO)(PWSTR, DWORD, PBYTE *);
|
|
typedef NETWKSTAGETINFO *PNETWKSTAGETINFO;
|
|
|
|
typedef NET_API_STATUS(WINAPI NETAPIBUFFERFREE)(PVOID);
|
|
typedef NETAPIBUFFERFREE *PNETAPIBUFFERFREE;
|
|
|
|
//
|
|
// Globals
|
|
//
|
|
|
|
BOOL g_OverwriteImage = FALSE;
|
|
BOOL g_ContinueOnError = FALSE;
|
|
DWORD g_ReturnCode = RETURN_SUCCESS;
|
|
TCHAR g_JournalPath[MAX_PATH_PLUS_NUL];
|
|
BOOL g_Break;
|
|
BOOL g_TestMode;
|
|
|
|
//
|
|
// Macro expansion list
|
|
//
|
|
|
|
#define REQUIRED_INFS \
|
|
DEFMAC(OSFILES, TEXT("USMTDef.inf")) \
|
|
|
|
//
|
|
// Private function prototypes
|
|
//
|
|
|
|
#ifdef PRERELEASE
|
|
MESSAGECALLBACK pSaveMsgCallback;
|
|
#endif
|
|
|
|
//
|
|
// Macro expansion definition
|
|
//
|
|
|
|
//
|
|
// This is the structure used for 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
|
|
pHelpAndExit (
|
|
VOID
|
|
)
|
|
{
|
|
PrintMsgOnConsole (MSG_HELP);
|
|
|
|
#ifdef PRERELEASE
|
|
printf ("\nAdditional PRERELEASE options:\n\n"
|
|
"/tf Uses full transport instead of v1 transport\n"
|
|
"/tc Enable compression\n"
|
|
"/ta Enable automatic capability (for homenet transport)\n"
|
|
"/ti:<tag> Specify an identity tag for the homenet transport\n"
|
|
" Default is user name\n"
|
|
"/t:<name> Specifies transport to use\n"
|
|
);
|
|
#endif
|
|
|
|
TerminateAppCommon();
|
|
UtTerminate ();
|
|
exit (1);
|
|
}
|
|
|
|
|
|
VOID
|
|
pCleanUpApp (
|
|
VOID
|
|
)
|
|
{
|
|
IsmTerminate();
|
|
|
|
if (g_JournalPath[0]) {
|
|
DeleteFile (g_JournalPath);
|
|
g_JournalPath[0] = 0;
|
|
}
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
CtrlCRoutine (
|
|
IN DWORD ControlSignal
|
|
)
|
|
{
|
|
PrintMsgOnConsole (MSG_EXITING);
|
|
|
|
LOG ((LOG_WARNING, (PCSTR) MSG_TOOL_STOPPED));
|
|
|
|
g_Break = TRUE;
|
|
|
|
IsmSetCancel();
|
|
while (IsmCurrentlyExecuting()) {
|
|
Sleep (1000);
|
|
}
|
|
|
|
pCleanUpApp();
|
|
|
|
printf ("\n");
|
|
exit (1);
|
|
}
|
|
|
|
|
|
ULONG_PTR
|
|
pSaveMsgCallback (
|
|
UINT Message,
|
|
ULONG_PTR Arg
|
|
)
|
|
{
|
|
PTRANSCOPY_ERROR transCopyError;
|
|
#ifdef PRERELEASE
|
|
PRMEDIA_EXTRADATA extraData;
|
|
#endif
|
|
|
|
switch (Message) {
|
|
|
|
case TRANSPORTMESSAGE_IMAGE_EXISTS:
|
|
return g_OverwriteImage;
|
|
|
|
case TRANSPORTMESSAGE_SRC_COPY_ERROR:
|
|
transCopyError = (PTRANSCOPY_ERROR) Arg;
|
|
if (transCopyError) {
|
|
if (StringIMatch (transCopyError->ObjectType, TEXT("File"))) {
|
|
if ((transCopyError->Error == ERROR_FILE_NOT_FOUND) ||
|
|
(transCopyError->Error == ERROR_PATH_NOT_FOUND) ||
|
|
(transCopyError->Error == ERROR_ACCESS_DENIED) ||
|
|
(transCopyError->Error == ERROR_INVALID_NAME)
|
|
) {
|
|
return APPRESPONSE_IGNORE;
|
|
}
|
|
if ((transCopyError->Error == ERROR_FILENAME_EXCED_RANGE) && g_ContinueOnError) {
|
|
return APPRESPONSE_IGNORE;
|
|
}
|
|
}
|
|
}
|
|
return APPRESPONSE_FAIL;
|
|
|
|
#ifdef PRERELEASE
|
|
case TRANSPORTMESSAGE_RMEDIA_SAVE:
|
|
extraData = (PRMEDIA_EXTRADATA) Arg;
|
|
if (!extraData) {
|
|
return (MessageBox (
|
|
NULL,
|
|
TEXT("Please insert the next media in your drive."),
|
|
TEXT("ScanState"),
|
|
MB_OKCANCEL
|
|
) == IDOK);
|
|
}
|
|
if (extraData->MediaNumber == 1) {
|
|
switch (extraData->LastError) {
|
|
case RMEDIA_ERR_NOERROR:
|
|
return TRUE;
|
|
case RMEDIA_ERR_WRONGMEDIA:
|
|
return (MessageBox (
|
|
NULL,
|
|
TEXT("You have inserted the wrong media.\n\nPlease insert the first media in your drive."),
|
|
TEXT("ScanState"),
|
|
MB_OKCANCEL
|
|
) == IDOK);
|
|
case RMEDIA_ERR_DISKFULL:
|
|
return (MessageBox (
|
|
NULL,
|
|
TEXT("The media you inserted does not have enough free space.\n\nPlease insert the first media in your drive."),
|
|
TEXT("ScanState"),
|
|
MB_OKCANCEL
|
|
) == IDOK);
|
|
case RMEDIA_ERR_WRITEPROTECT:
|
|
return (MessageBox (
|
|
NULL,
|
|
TEXT("The media you inserted is write protected.\n\nPlease insert the first media in your drive."),
|
|
TEXT("ScanState"),
|
|
MB_OKCANCEL
|
|
) == IDOK);
|
|
case RMEDIA_ERR_NOTREADY:
|
|
return (MessageBox (
|
|
NULL,
|
|
TEXT("The drive is not ready for use. Please check the drive and make sure that a disk is inserted and that the drive door is closed."),
|
|
TEXT("ScanState"),
|
|
MB_OKCANCEL
|
|
) == IDOK);
|
|
case RMEDIA_ERR_CRITICAL:
|
|
return FALSE;
|
|
default:
|
|
return (MessageBox (
|
|
NULL,
|
|
TEXT("Your media is toast.\n\nPlease insert the first media in your drive."),
|
|
TEXT("ScanState"),
|
|
MB_OKCANCEL
|
|
) == IDOK);
|
|
}
|
|
} else {
|
|
switch (extraData->LastError) {
|
|
case RMEDIA_ERR_NOERROR:
|
|
return TRUE;
|
|
case RMEDIA_ERR_WRONGMEDIA:
|
|
return (MessageBox (
|
|
NULL,
|
|
TEXT("You have inserted the wrong media.\n\nPlease insert the next media in your drive."),
|
|
TEXT("ScanState"),
|
|
MB_OKCANCEL
|
|
) == IDOK);
|
|
case RMEDIA_ERR_DISKFULL:
|
|
return (MessageBox (
|
|
NULL,
|
|
TEXT("The media you inserted does not have enough free space.\n\nPlease insert the next media in your drive."),
|
|
TEXT("ScanState"),
|
|
MB_OKCANCEL
|
|
) == IDOK);
|
|
case RMEDIA_ERR_WRITEPROTECT:
|
|
return (MessageBox (
|
|
NULL,
|
|
TEXT("The media you inserted is write protected.\n\nPlease insert the next media in your drive."),
|
|
TEXT("ScanState"),
|
|
MB_OKCANCEL
|
|
) == IDOK);
|
|
case RMEDIA_ERR_NOTREADY:
|
|
return (MessageBox (
|
|
NULL,
|
|
TEXT("The drive is not ready for use. Please check the drive and make sure that a disk is inserted and that the drive door is closed."),
|
|
TEXT("ScanState"),
|
|
MB_OKCANCEL
|
|
) == IDOK);
|
|
case RMEDIA_ERR_CRITICAL:
|
|
return FALSE;
|
|
default:
|
|
return (MessageBox (
|
|
NULL,
|
|
TEXT("Your media is toast.\n\nPlease insert the next media in your drive."),
|
|
TEXT("ScanState"),
|
|
MB_OKCANCEL
|
|
) == IDOK);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
VOID
|
|
pMyLogCallback (
|
|
IN PLOGARG LogArg
|
|
)
|
|
{
|
|
if (LogArg->Debug) {
|
|
DEBUGDIRECT (LogArg->Type, LogArg->FormattedMessage);
|
|
} else {
|
|
if (StringIMatchA (LogArg->Type, LOG_ERROR)) {
|
|
if (g_ReturnCode == RETURN_SUCCESS) {
|
|
g_ReturnCode = g_ContinueOnError?RETURN_IGNORED_ERROR:RETURN_ERROR;
|
|
}
|
|
if (g_ReturnCode == RETURN_IGNORED_ERROR) {
|
|
g_ReturnCode = g_ContinueOnError?RETURN_IGNORED_ERROR:RETURN_ERROR;
|
|
}
|
|
if (!g_ContinueOnError) {
|
|
IsmSetCancel();
|
|
}
|
|
} else if (StringIMatchA (LogArg->Type, LOG_FATAL_ERROR) ||
|
|
StringIMatchA (LogArg->Type, LOG_MODULE_ERROR)) {
|
|
g_ReturnCode = RETURN_FATAL_ERROR;
|
|
}
|
|
LOGDIRECT (LogArg->Type, LogArg->FormattedMessage);
|
|
}
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
VOID
|
|
pStopAndDisplayInfs (
|
|
IN PGROWBUFFER InputInfs,
|
|
IN BOOL Begin
|
|
)
|
|
{
|
|
MULTISZ_ENUM infEnum;
|
|
|
|
if (MessageBox (
|
|
NULL,
|
|
TEXT("ScanState stopped. Do you want to display all loaded INFs?"),
|
|
Begin?TEXT("ScanState-Begin"):TEXT("ScanState-End"),
|
|
MB_YESNO
|
|
) == IDYES) {
|
|
//
|
|
// now let's open append all INF files and pass the HINF to
|
|
// everybody.
|
|
//
|
|
if (EnumFirstMultiSz (&infEnum, (PCTSTR)InputInfs->Buf)) {
|
|
do {
|
|
ShellExecute (NULL, TEXT("open"), infEnum.CurrentString, NULL, NULL, SW_SHOWNORMAL);
|
|
} while (EnumNextMultiSz (&infEnum));
|
|
}
|
|
MessageBox (NULL, TEXT("Press OK to continue..."), TEXT("ScanState-Begin"), MB_OK);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
BOOL
|
|
pIsIE4Installed (
|
|
VOID
|
|
)
|
|
{
|
|
LONG hResult;
|
|
REGSAM prevMode;
|
|
HKEY ieKey = NULL;
|
|
DWORD valueType = REG_SZ;
|
|
DWORD valueSize = 0;
|
|
PTSTR valueData = NULL;
|
|
PTSTR numPtr = NULL;
|
|
PTSTR dotPtr = NULL;
|
|
INT major = 0;
|
|
INT minor = 0;
|
|
TCHAR saved;
|
|
BOOL result = FALSE;
|
|
|
|
prevMode = SetRegOpenAccessMode (KEY_READ);
|
|
|
|
ieKey = OpenRegKeyStr (TEXT("HKLM\\Software\\Microsoft\\Internet Explorer"));
|
|
|
|
SetRegOpenAccessMode (prevMode);
|
|
|
|
if (ieKey) {
|
|
hResult = RegQueryValueEx (ieKey, TEXT("Version"), NULL, &valueType, NULL, &valueSize);
|
|
if ((hResult == ERROR_SUCCESS) || (hResult == ERROR_MORE_DATA)) {
|
|
valueData = (PTSTR)HeapAlloc (GetProcessHeap (), 0, valueSize * 2);
|
|
if (valueData) {
|
|
hResult = RegQueryValueEx (ieKey, TEXT("Version"), NULL, &valueType, (PBYTE)valueData, &valueSize);
|
|
if ((hResult == ERROR_SUCCESS) && (valueType == REG_SZ)) {
|
|
// let's see if it the version is the correct one
|
|
numPtr = valueData;
|
|
dotPtr = _tcschr (numPtr, TEXT('.'));
|
|
if (dotPtr) {
|
|
saved = *dotPtr;
|
|
*dotPtr = 0;
|
|
major = _ttoi (numPtr);
|
|
*dotPtr = saved;
|
|
} else {
|
|
major = _ttoi (numPtr);
|
|
}
|
|
if (dotPtr) {
|
|
numPtr = _tcsinc (dotPtr);
|
|
dotPtr = _tcschr (numPtr, TEXT('.'));
|
|
if (dotPtr) {
|
|
saved = *dotPtr;
|
|
*dotPtr = 0;
|
|
minor = _ttoi (numPtr);
|
|
*dotPtr = saved;
|
|
} else {
|
|
minor = _ttoi (numPtr);
|
|
}
|
|
}
|
|
if ((major >= 5) ||
|
|
((major == 4) && (minor >= 71))
|
|
) {
|
|
result = TRUE;
|
|
}
|
|
}
|
|
HeapFree (GetProcessHeap (), 0, valueData);
|
|
valueData = NULL;
|
|
}
|
|
}
|
|
CloseRegKey (ieKey);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
BOOL
|
|
pCheckSystemRequirements (
|
|
VOID
|
|
)
|
|
{
|
|
HKEY domainLogonKey;
|
|
PDWORD data;
|
|
BOOL result = TRUE;
|
|
TCHAR userName[MAX_USER_NAME];
|
|
DWORD size;
|
|
NET_API_STATUS rc;
|
|
PWKSTA_INFO_102 buffer;
|
|
HANDLE netApi32Lib;
|
|
PNETWKSTAGETINFO netWkstaGetInfo;
|
|
PNETAPIBUFFERFREE netApiBufferFree;
|
|
BYTE sid[256];
|
|
DWORD sidSize = 256;
|
|
WCHAR domain[256];
|
|
DWORD domainSize = 256;
|
|
SID_NAME_USE use;
|
|
|
|
if (!ISNT()) {
|
|
//
|
|
// Require the Log On To Domain setting to be checked
|
|
//
|
|
|
|
SetLastError (ERROR_SUCCESS);
|
|
|
|
domainLogonKey = OpenRegKeyStr (TEXT("HKLM\\Network\\Logon"));
|
|
if (!domainLogonKey) {
|
|
LOG ((LOG_ERROR, (PCSTR) MSG_NETWORK_LOGON_KEY));
|
|
return FALSE;
|
|
}
|
|
|
|
data = (PDWORD) GetRegValueBinary (domainLogonKey, TEXT("LMLogon"));
|
|
if (!data) {
|
|
data = (PDWORD) GetRegValueDword (domainLogonKey, TEXT("LMLogon"));
|
|
if (!data) {
|
|
LOG ((LOG_ERROR, (PCSTR) MSG_NETWORK_LMLOGON_KEY));
|
|
result = FALSE;
|
|
} else {
|
|
if (!(*data)) {
|
|
LOG ((LOG_ERROR, (PCSTR) MSG_NO_DOMAIN_LOGON));
|
|
result = FALSE;
|
|
}
|
|
FreeAlloc (data);
|
|
}
|
|
} else {
|
|
if (!(*data)) {
|
|
LOG ((LOG_ERROR, (PCSTR) MSG_NO_DOMAIN_LOGON));
|
|
result = FALSE;
|
|
}
|
|
FreeAlloc (data);
|
|
}
|
|
|
|
CloseRegKey (domainLogonKey);
|
|
|
|
} else {
|
|
//
|
|
// Require domain membership
|
|
//
|
|
|
|
netApi32Lib = LoadLibrary (TEXT("netapi32.dll"));
|
|
if (netApi32Lib) {
|
|
netWkstaGetInfo = (PNETWKSTAGETINFO) GetProcAddress (netApi32Lib, "NetWkstaGetInfo");
|
|
netApiBufferFree = (PNETAPIBUFFERFREE) GetProcAddress (netApi32Lib, "NetApiBufferFree");
|
|
} else {
|
|
netWkstaGetInfo = NULL;
|
|
netApiBufferFree = NULL;
|
|
}
|
|
|
|
if (!netWkstaGetInfo || !netApiBufferFree) {
|
|
LOG ((LOG_ERROR, (PCSTR) MSG_CANT_LOAD_NETAPI32));
|
|
result = FALSE;
|
|
} else {
|
|
|
|
rc = netWkstaGetInfo (NULL, 102, (PBYTE *) &buffer);
|
|
|
|
if (rc == NO_ERROR) {
|
|
result = buffer->wki102_langroup && (buffer->wki102_langroup[0] != 0);
|
|
if (result) {
|
|
DEBUGMSGW ((DBG_SCANSTATE, "Getting account type of %s", buffer->wki102_langroup));
|
|
|
|
sidSize = ARRAYSIZE(sid);
|
|
domainSize = ARRAYSIZE(domain);
|
|
|
|
result = LookupAccountNameW (
|
|
NULL,
|
|
buffer->wki102_langroup,
|
|
sid,
|
|
&sidSize,
|
|
domain,
|
|
&domainSize,
|
|
&use
|
|
);
|
|
DEBUGMSG ((DBG_SCANSTATE, "Account type result is %u (use=%u)", result, use));
|
|
|
|
LOG_IF ((!result, LOG_ERROR, (PCSTR) MSG_NOT_JOINED_TO_DOMAIN));
|
|
|
|
}
|
|
ELSE_DEBUGMSG ((DBG_SCANSTATE, "No langroup specified"));
|
|
|
|
netApiBufferFree (buffer);
|
|
} else {
|
|
LOG ((LOG_ERROR, (PCSTR) MSG_CANT_GET_WORKSTATION_PROPS));
|
|
result = FALSE;
|
|
}
|
|
}
|
|
|
|
if (netApi32Lib) {
|
|
FreeLibrary (netApi32Lib);
|
|
}
|
|
}
|
|
|
|
// let's check to see if IE4 is installed on this machine
|
|
if (result && !pIsIE4Installed ()) {
|
|
LOG ((LOG_ERROR, (PCSTR) MSG_NEED_IE4));
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Make sure a user name is specified
|
|
//
|
|
|
|
if (result) {
|
|
size = ARRAYSIZE(userName);
|
|
if (!GetUserName (userName, &size)) {
|
|
result = FALSE;
|
|
} else if (*userName == 0) {
|
|
result = FALSE;
|
|
}
|
|
|
|
LOG_IF ((!result, LOG_ERROR, (PCSTR) MSG_LOGGED_ON_USER_REQUIRED));
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
VOID
|
|
__cdecl
|
|
_tmain (
|
|
IN INT Argc,
|
|
IN PCTSTR Argv[]
|
|
)
|
|
{
|
|
TCHAR appPath[MAX_PATH_PLUS_NUL];
|
|
TCHAR ismPath[MAX_PATH_PLUS_NUL];
|
|
PCTSTR commandLine = NULL;
|
|
PTSTR p;
|
|
MIG_TRANSPORTID transportId;
|
|
MIG_TRANSPORTSTORAGEID transportStorageId;
|
|
MULTISZ_ENUM infEnum;
|
|
HINF infHandle = INVALID_HANDLE_VALUE;
|
|
ENVENTRY_STRUCT infHandleStruct;
|
|
INT numInfs = 0;
|
|
PTSTR buffer;
|
|
MULTISZ_ENUM e;
|
|
DWORD appStatus;
|
|
BOOL skipExecute = FALSE;
|
|
BOOL storagePathIsValid = FALSE;
|
|
BOOL imageExists = FALSE;
|
|
BOOL terminateIsm = FALSE;
|
|
BOOL logEnabled = FALSE;
|
|
PCTSTR msg;
|
|
#ifdef UNICODE
|
|
PCSTR ansimsg;
|
|
#endif
|
|
PCTSTR argArray[1];
|
|
TOOLARGS args;
|
|
BOOL fail;
|
|
|
|
ZeroMemory (&args, sizeof (args));
|
|
|
|
SET_RESETLOG();
|
|
UtInitialize (NULL);
|
|
InitAppCommon();
|
|
|
|
SuppressAllLogPopups (TRUE);
|
|
|
|
// this part is for matching thread's locale to the console code page
|
|
CallSetThreadUILanguage ();
|
|
|
|
PrintMsgOnConsole (MSG_RUNNING);
|
|
|
|
// initialize app journal path
|
|
g_JournalPath[0] = 0;
|
|
if (GetWindowsDirectory (g_JournalPath, ARRAYSIZE (g_JournalPath))) {
|
|
StringCopy (AppendWack (g_JournalPath), TEXT("SCANSTATE.JRN"));
|
|
}
|
|
|
|
GetModuleFileName (NULL, appPath, ARRAYSIZE(appPath));
|
|
p = _tcsrchr (appPath, TEXT('\\'));
|
|
if (p) {
|
|
*p = 0;
|
|
}
|
|
|
|
//
|
|
// Parse the command line
|
|
//
|
|
|
|
fail = TRUE;
|
|
|
|
switch (ParseToolCmdLine (TRUE, &args, Argc, Argv)) {
|
|
|
|
case PARSE_SUCCESS:
|
|
fail = FALSE;
|
|
break;
|
|
|
|
case PARSE_MULTI_LOG:
|
|
PrintMsgOnConsole (MSG_MULTI_LOG);
|
|
g_ReturnCode = RETURN_FATAL_ERROR;
|
|
goto END;
|
|
|
|
case PARSE_BAD_LOG:
|
|
argArray[0] = args.LogFile;
|
|
msg = ParseMessageID (MSG_CANT_OPEN_LOG, argArray);
|
|
if (msg) {
|
|
#ifdef UNICODE
|
|
ansimsg = ConvertWtoA (msg);
|
|
printf ("%s", ansimsg);
|
|
FreeConvertedStr (ansimsg);
|
|
#else
|
|
printf ("%s", msg);
|
|
#endif
|
|
FreeStringResource (msg);
|
|
}
|
|
|
|
g_ReturnCode = RETURN_FATAL_ERROR;
|
|
goto END;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (fail) {
|
|
pHelpAndExit();
|
|
}
|
|
|
|
g_TestMode = args.TestMode;
|
|
g_OverwriteImage = args.OverwriteImage;
|
|
g_ContinueOnError = args.ContinueOnError;
|
|
|
|
#ifdef DEBUG
|
|
{
|
|
if (DoesFileExist (TEXT("C:\\SCANSTATE.BEGIN"))) {
|
|
pStopAndDisplayInfs (&args.InputInf, TRUE);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
LogReInit (NULL, NULL, (args.LogFile ? args.LogFile : TEXT("scanstate.log")), NULL);
|
|
logEnabled = TRUE;
|
|
|
|
// Let's log the command line that was used
|
|
commandLine = GetCommandLine ();
|
|
if (commandLine) {
|
|
LOG ((LOG_INFORMATION, (PCSTR)MSG_COMMAND_LINE_USED, commandLine));
|
|
}
|
|
|
|
//
|
|
// Check requirements
|
|
//
|
|
|
|
if (args.BadInfs.End || args.MultiInfs.End) {
|
|
SetLastError (ERROR_BAD_COMMAND);
|
|
|
|
if (EnumFirstMultiSz (&e, (PCTSTR) args.BadInfs.Buf)) {
|
|
do {
|
|
LOG ((LOG_ERROR, (PCSTR) MSG_INF_FILE_NOT_FOUND, e.CurrentString));
|
|
} while (EnumNextMultiSz (&e));
|
|
}
|
|
|
|
if (EnumFirstMultiSz (&e, (PCTSTR) args.MultiInfs.Buf)) {
|
|
do {
|
|
LOG ((LOG_ERROR, (PCSTR) MSG_INF_SPECIFIED_MORE_THAN_ONE, e.CurrentString));
|
|
} while (EnumNextMultiSz (&e));
|
|
}
|
|
|
|
g_ReturnCode = RETURN_FATAL_ERROR;
|
|
LOG ((LOG_FATAL_ERROR, (PCSTR) MSG_CMD_LINE_ERROR));
|
|
goto END;
|
|
}
|
|
|
|
if (!GetFilePath (TEXT("migism.inf"), ismPath, ARRAYSIZE(ismPath))) {
|
|
g_ReturnCode = RETURN_FATAL_ERROR;
|
|
LOG ((LOG_FATAL_ERROR, (PCSTR) MSG_ISM_INF_MISSING));
|
|
goto END;
|
|
}
|
|
|
|
if (!g_TestMode) {
|
|
if (!pCheckSystemRequirements()) {
|
|
g_ReturnCode = RETURN_FATAL_ERROR;
|
|
goto END;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Initialize ISM
|
|
//
|
|
|
|
if (!IsmInitialize (ismPath, pSaveMsgCallback, pMyLogCallback)) {
|
|
g_ReturnCode = RETURN_FATAL_ERROR;
|
|
LOG ((LOG_FATAL_ERROR, (PCSTR) MSG_CANT_START_ISM));
|
|
goto END;
|
|
}
|
|
|
|
terminateIsm = TRUE;
|
|
SetLogVerbosity (args.VerboseLevel);
|
|
|
|
SetConsoleCtrlHandler (CtrlCRoutine, TRUE);
|
|
|
|
IsmSetPlatform (PLATFORM_SOURCE);
|
|
|
|
// upload environment variables
|
|
UploadEnvVars (PLATFORM_SOURCE);
|
|
|
|
infHandle = InitRequiredInfs (appPath, (PCSTR) MSG_CANT_OPEN_REQUIRED_FILE);
|
|
|
|
if (args.InputInf.Buf) {
|
|
IsmSetEnvironmentData (
|
|
PLATFORM_SOURCE,
|
|
NULL,
|
|
S_INF_FILE_MULTISZ,
|
|
args.InputInf.Buf,
|
|
(WORD) args.InputInf.End
|
|
);
|
|
|
|
//
|
|
// now let's open append all INF files and pass the HINF to
|
|
// everybody.
|
|
//
|
|
if (EnumFirstMultiSz (&infEnum, (PCTSTR)args.InputInf.Buf)) {
|
|
buffer = DuplicateTextEx (NULL, S_INF_OBJECT_NAME, 2, &p); // Up to 2 digits of numbers
|
|
do {
|
|
if (infHandle == INVALID_HANDLE_VALUE) {
|
|
infHandle = SetupOpenInfFile (infEnum.CurrentString, NULL, INF_STYLE_WIN4 | INF_STYLE_OLDNT, NULL);
|
|
if (infHandle == INVALID_HANDLE_VALUE) {
|
|
LOG ((LOG_ERROR, (PCSTR) MSG_CANT_OPEN_FILE, infEnum.CurrentString));
|
|
}
|
|
} else {
|
|
if (!SetupOpenAppendInfFile (infEnum.CurrentString, infHandle, NULL)) {
|
|
LOG ((LOG_ERROR, (PCSTR) MSG_CANT_OPEN_FILE, infEnum.CurrentString));
|
|
}
|
|
}
|
|
|
|
// Save Inf for right side use
|
|
if (numInfs < 100) {
|
|
numInfs++;
|
|
_stprintf(p, TEXT("%d"), numInfs);
|
|
IsmAddControlFile (buffer, infEnum.CurrentString);
|
|
}
|
|
} while (EnumNextMultiSz (&infEnum));
|
|
FreeText (buffer);
|
|
}
|
|
}
|
|
|
|
if (infHandle != INVALID_HANDLE_VALUE) {
|
|
infHandleStruct.Type = ENVENTRY_BINARY;
|
|
infHandleStruct.EnvBinaryData = (PVOID)(&infHandle);
|
|
infHandleStruct.EnvBinaryDataSize = sizeof (HINF);
|
|
IsmSetEnvironmentValue (PLATFORM_SOURCE, NULL, S_GLOBAL_INF_HANDLE, &infHandleStruct);
|
|
}
|
|
|
|
if (args.UserOn) {
|
|
IsmSetEnvironmentFlag (PLATFORM_SOURCE, NULL, S_ENV_HKCU_V1);
|
|
IsmSetEnvironmentFlag (PLATFORM_SOURCE, NULL, S_ENV_HKCU_ON);
|
|
}
|
|
|
|
if (args.FilesOn) {
|
|
IsmSetEnvironmentFlag (PLATFORM_SOURCE, NULL, S_ENV_ALL_FILES);
|
|
}
|
|
|
|
//
|
|
// Start ETM modules
|
|
//
|
|
|
|
if (!IsmStartEtmModules ()) {
|
|
if (!IsmCheckCancel()) {
|
|
LOG ((LOG_FATAL_ERROR, (PCSTR) MSG_CANT_START_ETMS));
|
|
}
|
|
goto END;
|
|
}
|
|
|
|
//
|
|
// Initialize transport
|
|
//
|
|
|
|
if (!IsmStartTransport ()) {
|
|
if (!IsmCheckCancel()) {
|
|
LOG ((LOG_FATAL_ERROR, "Can't start the transport."));
|
|
}
|
|
goto END;
|
|
}
|
|
|
|
transportStorageId = IsmRegisterTransport (args.TransportName);
|
|
|
|
if (args.FullTransport) {
|
|
transportId = IsmSelectTransport (transportStorageId, TRANSPORTTYPE_FULL, args.Capabilities);
|
|
} else {
|
|
transportId = IsmSelectTransport (transportStorageId, TRANSPORTTYPE_LIGHT, args.Capabilities);
|
|
}
|
|
|
|
if (!args.TransportNameSpecified) {
|
|
BfCreateDirectory (args.StoragePath);
|
|
}
|
|
|
|
if (!transportId) {
|
|
LOG ((LOG_FATAL_ERROR, (PCSTR) MSG_TRANSPORT_UNAVAILABLE));
|
|
goto END;
|
|
}
|
|
|
|
#ifdef PRERELEASE
|
|
|
|
IsmSetEnvironmentString (PLATFORM_SOURCE, NULL, TRANSPORT_ENVVAR_HOMENET_TAG, args.Tag);
|
|
|
|
#endif
|
|
|
|
if (!IsmSetTransportStorage (
|
|
PLATFORM_SOURCE,
|
|
transportId,
|
|
transportStorageId,
|
|
args.Capabilities,
|
|
args.StoragePath,
|
|
&storagePathIsValid,
|
|
&imageExists
|
|
) || storagePathIsValid == FALSE
|
|
) {
|
|
|
|
if (!IsmCheckCancel()) {
|
|
LOG ((LOG_FATAL_ERROR, (PCSTR) MSG_TRANSPORT_STORAGE_INVALID, args.StoragePath));
|
|
}
|
|
|
|
goto END;
|
|
}
|
|
|
|
#ifdef PRERELEASE
|
|
if (args.Capabilities & CAPABILITY_AUTOMATED) {
|
|
if (!imageExists) {
|
|
LOG ((
|
|
LOG_FATAL_ERROR,
|
|
"Can't select %s as the transport; need to run loadstate first.",
|
|
args.TransportName
|
|
));
|
|
goto END;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
appStatus = ReadAppStatus (g_JournalPath);
|
|
|
|
if (appStatus == SCANSTATE_SAVE) {
|
|
skipExecute = IsmResumeSave ();
|
|
}
|
|
|
|
if (!skipExecute) {
|
|
|
|
//
|
|
// Execute the preparsing to populate the components
|
|
//
|
|
|
|
if (IsmExecute (args.FullTransport?EXECUTETYPE_EXECUTESOURCE_PARSING:EXECUTETYPE_VIRTUALCOMPUTER_PARSING)) {
|
|
|
|
IsmSelectMasterGroup (MASTERGROUP_ALL, TRUE);
|
|
|
|
if (!args.SystemOn) {
|
|
IsmSelectMasterGroup (MASTERGROUP_SYSTEM, FALSE);
|
|
IsmSelectMasterGroup (MASTERGROUP_USER, FALSE);
|
|
IsmSelectMasterGroup (MASTERGROUP_APP, FALSE);
|
|
}
|
|
|
|
SelectComponentsViaInf (infHandle);
|
|
|
|
//
|
|
// Enumerate the system, gather data and analyze
|
|
//
|
|
|
|
if (IsmExecute (args.FullTransport?EXECUTETYPE_EXECUTESOURCE:EXECUTETYPE_VIRTUALCOMPUTER)) {
|
|
//
|
|
// Display report
|
|
//
|
|
|
|
//
|
|
// Save the state
|
|
//
|
|
|
|
// write the app status
|
|
WriteAppStatus (g_JournalPath, SCANSTATE_SAVE);
|
|
|
|
// before we save, let's see if we wanted to change the user name and/or domain
|
|
if (args.NewDomainName) {
|
|
IsmSetEnvironmentString (PLATFORM_SOURCE, S_SYSENVVAR_GROUP, TEXT("ALTUSERDOMAIN"), args.NewDomainName);
|
|
}
|
|
if (args.NewUserName) {
|
|
IsmSetEnvironmentString (PLATFORM_SOURCE, S_SYSENVVAR_GROUP, TEXT("ALTUSERNAME"), args.NewUserName);
|
|
}
|
|
|
|
if (!IsmSave ()) {
|
|
if (!IsmCheckCancel()) {
|
|
LOG ((LOG_FATAL_ERROR, (PCSTR) MSG_CANT_SAVE));
|
|
}
|
|
}
|
|
|
|
// write the app status
|
|
WriteAppStatus (g_JournalPath, SCANSTATE_COMPLETED);
|
|
|
|
} else {
|
|
if (!IsmCheckCancel()) {
|
|
LOG ((LOG_FATAL_ERROR, (PCSTR) MSG_CANT_EXECUTE_SOURCE));
|
|
}
|
|
}
|
|
|
|
} else {
|
|
if (!IsmCheckCancel()) {
|
|
LOG ((LOG_FATAL_ERROR, (PCSTR) MSG_CANT_EXECUTE_SOURCE));
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// We're done!
|
|
//
|
|
|
|
SetupCloseInfFile (infHandle);
|
|
|
|
#ifdef DEBUG
|
|
{
|
|
if (DoesFileExist (TEXT("C:\\SCANSTATE.END"))) {
|
|
pStopAndDisplayInfs (&args.InputInf, FALSE);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
END:
|
|
if (terminateIsm) {
|
|
if (!g_Break) {
|
|
pCleanUpApp();
|
|
}
|
|
}
|
|
|
|
GbFree (&args.BadInfs);
|
|
GbFree (&args.MultiInfs);
|
|
GbFree (&args.InputInf);
|
|
|
|
if (!g_Break) {
|
|
if (g_ReturnCode == RETURN_SUCCESS) {
|
|
PrintMsgOnConsole (MSG_SUCCESS);
|
|
} else if (g_ReturnCode == RETURN_IGNORED_ERROR) {
|
|
if (logEnabled) {
|
|
PrintMsgOnConsole (MSG_IGNORE_FAILED_WITH_LOG);
|
|
} else {
|
|
PrintMsgOnConsole (MSG_IGNORE_FAILED_NO_LOG);
|
|
}
|
|
g_ReturnCode = RETURN_SUCCESS;
|
|
} else {
|
|
if (logEnabled) {
|
|
PrintMsgOnConsole (MSG_FAILED_WITH_LOG);
|
|
} else {
|
|
PrintMsgOnConsole (MSG_FAILED_NO_LOG);
|
|
}
|
|
}
|
|
}
|
|
|
|
TerminateAppCommon();
|
|
UtTerminate ();
|
|
|
|
while (g_Break) {
|
|
// infinite loop, because we'll get terminated in the ctrl+c handler
|
|
Sleep (50);
|
|
}
|
|
|
|
exit (g_ReturnCode);
|
|
}
|
|
|
|
|