1442 lines
39 KiB
C
1442 lines
39 KiB
C
#include "precomp.h"
|
|
#pragma hdrstop
|
|
/**************************************************************************/
|
|
/***** Shell Component - Init routines ************************************/
|
|
/**************************************************************************/
|
|
|
|
|
|
//#ifdef SYMTAB_STATS
|
|
//extern void SymTabStatDump(void);
|
|
//#endif
|
|
|
|
extern SZ SzGetNextCmdLineString(PSZ);
|
|
extern BOOL fFullScreen;
|
|
extern PSTR LOCAL_SOURCE_DIRECTORY;
|
|
|
|
extern VOID Usage(HANDLE);
|
|
|
|
//
|
|
// Helper macro to make object attribute initialization a little cleaner.
|
|
//
|
|
#define INIT_OBJA(Obja,UnicodeString,UnicodeText) \
|
|
\
|
|
RtlInitUnicodeString((UnicodeString),(UnicodeText)); \
|
|
\
|
|
InitializeObjectAttributes( \
|
|
(Obja), \
|
|
(UnicodeString), \
|
|
OBJ_CASE_INSENSITIVE, \
|
|
NULL, \
|
|
NULL \
|
|
)
|
|
|
|
SZ szShlScriptSection = NULL;
|
|
|
|
CHP szArcPrefix[] = "\\ArcName\\";
|
|
#define ArcPrefixLen ((sizeof(szArcPrefix) / sizeof(CHP)) - 1)
|
|
|
|
CHP szNtPrefix[] = "\\Device\\";
|
|
#define NtPrefixLen ((sizeof(szNtPrefix) / sizeof(CHP)) - 1)
|
|
|
|
//
|
|
// Define a work area for path manipulation (note that we make
|
|
// it large enough for Unicode as well, so it can do dual duty.)
|
|
//
|
|
CHP TemporaryPathBuffer[cchlFullPathMax * sizeof(WCHAR)];
|
|
|
|
//
|
|
// Buffer used in querying object directories
|
|
//
|
|
UCHAR ObjBuffer[1024];
|
|
|
|
SZ szDosType = "DOS";
|
|
SZ szUncType = "UNC";
|
|
|
|
typedef struct _INITSYMHANDLE *PINITSYMHANDLE;
|
|
typedef struct _INITSYMHANDLE {
|
|
SZ szName;
|
|
HANDLE Handle;
|
|
} INITSYMHANDLE;
|
|
|
|
typedef struct _INITSYMNUMBER *PINITSYMNUMBER;
|
|
typedef struct _INITSYMNUMBER {
|
|
SZ szName;
|
|
DWORD dwNumber;
|
|
} INITSYMNUMBER;
|
|
|
|
|
|
INITSYMHANDLE InitSymHandle[] = {
|
|
//
|
|
// Predefined registry handles
|
|
//
|
|
{ "REG_H_LOCAL", HKEY_LOCAL_MACHINE },
|
|
{ "REG_H_CLASSES", HKEY_CLASSES_ROOT },
|
|
{ "REG_H_USERS", HKEY_USERS },
|
|
{ "REG_H_CUSER", HKEY_CURRENT_USER },
|
|
//
|
|
{ NULL, 0 }
|
|
};
|
|
|
|
|
|
INITSYMNUMBER InitSymNumber[] = {
|
|
//
|
|
// Registry key creation options
|
|
//
|
|
{ "REG_OPT_VOLATILE", REG_OPTION_VOLATILE },
|
|
{ "REG_OPT_NONVOL", REG_OPTION_NON_VOLATILE },
|
|
//
|
|
// Registry value types
|
|
//
|
|
{ "REG_VT_NONE", REG_NONE },
|
|
{ "REG_VT_BIN", REG_BINARY },
|
|
{ "REG_VT_SZ", REG_SZ },
|
|
{ "REG_VT_EXPAND_SZ", REG_EXPAND_SZ },
|
|
{ "REG_VT_MULTI_SZ", REG_MULTI_SZ },
|
|
{ "REG_VT_DWORD", REG_DWORD },
|
|
{ "REG_VT_RESOURCE_LIST", REG_RESOURCE_LIST },
|
|
{ "REG_VT_FULL_RESOURCE_DESCRIPTOR", REG_FULL_RESOURCE_DESCRIPTOR },
|
|
{ "REG_VT_RESOURCE_REQUIREMENTS_LIST", REG_RESOURCE_REQUIREMENTS_LIST },
|
|
//
|
|
// Registry access mask bits
|
|
//
|
|
{ "REG_KEY_QUERY_VALUE", KEY_QUERY_VALUE },
|
|
{ "REG_KEY_SET_VALUE", KEY_SET_VALUE },
|
|
{ "REG_KEY_CREATE_SUB_KEY", KEY_CREATE_SUB_KEY },
|
|
{ "REG_KEY_ENUMERATE_SUB_KEYS", KEY_ENUMERATE_SUB_KEYS },
|
|
{ "REG_KEY_NOTIFY", KEY_NOTIFY },
|
|
{ "REG_KEY_READ", KEY_READ },
|
|
{ "REG_KEY_WRITE", KEY_WRITE },
|
|
{ "REG_KEY_READWRITE", KEY_READ | KEY_WRITE },
|
|
{ "REG_KEY_EXECUTE", KEY_EXECUTE },
|
|
{ "REG_KEY_ALL_ACCESS", KEY_ALL_ACCESS },
|
|
//
|
|
// Registry errors BugBug** should replace with values from winerror.h
|
|
//
|
|
{ "REG_ERROR_SUCCESS", 0L },
|
|
//
|
|
// Service Types (Bit Mask)
|
|
//
|
|
{ "SERVICE_KERNEL_DRIVER", SERVICE_KERNEL_DRIVER },
|
|
{ "SERVICE_FILE_SYSTEM_DRIVER", SERVICE_FILE_SYSTEM_DRIVER },
|
|
{ "SERVICE_ADAPTER", SERVICE_ADAPTER },
|
|
{ "SERVICE_WIN32_OWN_PROCESS", SERVICE_WIN32_OWN_PROCESS },
|
|
{ "SERVICE_WIN32_SHARE_PROCESS", SERVICE_WIN32_SHARE_PROCESS },
|
|
//
|
|
// Start Type
|
|
//
|
|
{ "SERVICE_BOOT_START", SERVICE_BOOT_START },
|
|
{ "SERVICE_SYSTEM_START", SERVICE_SYSTEM_START },
|
|
{ "SERVICE_AUTO_START", SERVICE_AUTO_START },
|
|
{ "SERVICE_DEMAND_START", SERVICE_DEMAND_START },
|
|
{ "SERVICE_DISABLED", SERVICE_DISABLED },
|
|
//
|
|
// Error control type
|
|
//
|
|
{ "SERVICE_ERROR_IGNORE", SERVICE_ERROR_IGNORE },
|
|
{ "SERVICE_ERROR_NORMAL", SERVICE_ERROR_NORMAL },
|
|
{ "SERVICE_ERROR_SEVERE", SERVICE_ERROR_SEVERE },
|
|
{ "SERVICE_ERROR_CRITICAL", SERVICE_ERROR_CRITICAL },
|
|
//
|
|
// ShellCode values
|
|
//
|
|
{ "SHELL_CODE_OK", SHELL_CODE_OK },
|
|
{ "SHELL_CODE_NO_SUCH_INF", SHELL_CODE_NO_SUCH_INF },
|
|
{ "SHELL_CODE_NO_SUCH_SECTION", SHELL_CODE_NO_SUCH_SECTION },
|
|
{ "SHELL_CODE_ERROR", SHELL_CODE_ERROR },
|
|
//
|
|
// Exit_Code values
|
|
//
|
|
{ "SETUP_ERROR_SUCCESS", SETUP_ERROR_SUCCESS },
|
|
{ "SETUP_ERROR_USERCANCEL", SETUP_ERROR_USERCANCEL },
|
|
{ "SETUP_ERROR_GENERAL", SETUP_ERROR_GENERAL },
|
|
//
|
|
{ NULL, 0 }
|
|
};
|
|
|
|
|
|
BOOL fCheckInfValidity = fFalse;
|
|
BOOL FMakeWindows(HANDLE hInstance);
|
|
BOOL FProcessForDriveType(SZ, SZ, SZ, SZ);
|
|
BOOL FProcessInfSrcPath( SZ szInf, SZ szCWD, SZ szProcessedDir );
|
|
HWND FindProperParent ( void ) ;
|
|
|
|
|
|
HANDLE hVerDLL = NULL;
|
|
|
|
#define FExistFile(sz) ((BOOL)(PfhOpenFile(sz, ofmExistRead) != (PFH)NULL))
|
|
|
|
|
|
//
|
|
// Symbols that are defined in the command line are kept in a list of
|
|
// VALUE_BLOCKs until the symbol table is created, point at which they
|
|
// are added to the symbol table and the VALUE_BLOCK list is destroyed.
|
|
//
|
|
typedef struct _VALUE_BLOCK *PVALUE_BLOCK;
|
|
typedef struct _VALUE_BLOCK {
|
|
PVALUE_BLOCK pNext; // Next in chain
|
|
SZ szSymbol; // Symbol
|
|
SZ szValue; // Value
|
|
} VALUE_BLOCK;
|
|
|
|
|
|
PVALUE_BLOCK pCmdLineSymbols = NULL;
|
|
|
|
|
|
/*
|
|
** Purpose:
|
|
** Generates a Usage message.
|
|
** Arguments:
|
|
** hInst: For retrieving string resources.
|
|
** Returns:
|
|
** none
|
|
***************************************************************************/
|
|
VOID Usage(hInst)
|
|
HANDLE hInst;
|
|
{
|
|
CHP rgch[1024];
|
|
CCHP cchpBuf = 1024;
|
|
|
|
CCHP cchp, cchpCurrent = 0;
|
|
|
|
UINT wID[] = { IDS_USAGE_MSG1, IDS_USAGE_MSG2, IDS_USAGE_USAGE,
|
|
IDS_USAGE_F, IDS_USAGE_I, IDS_USAGE_C,
|
|
IDS_USAGE_S, IDS_USAGE_T, IDS_USAGE_V
|
|
} ;
|
|
INT i, j;
|
|
|
|
|
|
EvalAssert(LoadString(hInst, IDS_USAGE_TITLE, rgchBufTmpShort,
|
|
cchpBufTmpShortMax));
|
|
|
|
for( i = 0, j = sizeof( wID ) / sizeof( UINT ); i < j; i++ ) {
|
|
Assert(cchpBuf > 0);
|
|
EvalAssert((cchp = LoadString(hInst, wID[i], rgch + cchpCurrent,
|
|
cchpBuf)) != 0);
|
|
cchpCurrent = cchpCurrent + cchp;
|
|
cchpBuf = cchpBuf - cchp;
|
|
}
|
|
|
|
|
|
while (!MessageBox(hWndShell, rgch, rgchBufTmpShort, MB_OK)) {
|
|
if (!FHandleOOM(hWndShell)) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
** Purpose:
|
|
** Generates a message indicating that maintenance-mode setup
|
|
** functionality is now accessible via Control Panel applets.
|
|
** Arguments:
|
|
** hInst: For retrieving string resources.
|
|
** Returns:
|
|
** none
|
|
***************************************************************************/
|
|
VOID MaintSetupObsoleteMsg(hInst)
|
|
HANDLE hInst;
|
|
{
|
|
CHP rgch[1024];
|
|
CCHP cchpBuf = 1024;
|
|
|
|
CCHP cchp, cchpCurrent = 0;
|
|
|
|
UINT wID[] = { IDS_MAINTOBS_MSG1 };
|
|
INT i, j;
|
|
|
|
|
|
EvalAssert(LoadString(hInst, IDS_WINDOWS_NT_SETUP, rgchBufTmpShort,
|
|
cchpBufTmpShortMax));
|
|
|
|
for( i = 0, j = sizeof( wID ) / sizeof( UINT ); i < j; i++ ) {
|
|
Assert(cchpBuf > 0);
|
|
EvalAssert((cchp = LoadString(hInst, wID[i], rgch + cchpCurrent,
|
|
cchpBuf)) != 0);
|
|
cchpCurrent = cchpCurrent + cchp;
|
|
cchpBuf = cchpBuf - cchp;
|
|
}
|
|
|
|
|
|
while (!MessageBox(hWndShell, rgch, rgchBufTmpShort, MB_ICONINFORMATION | MB_OK)) {
|
|
if (!FHandleOOM(hWndShell)) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
** Purpose:
|
|
** Gets the next string on the Command Line.
|
|
** Arguments:
|
|
** pszCmdLine: Command Line argument as received in WinMain().
|
|
** Returns:
|
|
** SZ
|
|
***************************************************************************/
|
|
SZ SzGetNextCmdLineString(pszCmdLine)
|
|
PSZ pszCmdLine;
|
|
{
|
|
SZ szCur = *pszCmdLine;
|
|
SZ szAnswer;
|
|
|
|
while (FWhiteSpaceChp(*szCur))
|
|
szCur = SzNextChar(szCur);
|
|
|
|
if (*szCur == '"')
|
|
{
|
|
SZ szWriteCur;
|
|
CB cbWrite = (CB)0;
|
|
|
|
while ((szWriteCur = szAnswer = (SZ)SAlloc((CB)4096)) == (SZ)NULL)
|
|
if (!FHandleOOM(hWndShell))
|
|
return((SZ)NULL);
|
|
|
|
szCur = SzNextChar(szCur);
|
|
while (fTrue)
|
|
{
|
|
SZ szNext;
|
|
|
|
if (*szCur == '"' &&
|
|
*(szCur = SzNextChar(szCur)) != '"')
|
|
break;
|
|
|
|
if (*szCur == '\0')
|
|
{
|
|
SFree(szAnswer);
|
|
return((SZ)NULL);
|
|
}
|
|
|
|
szNext = SzNextChar(szCur);
|
|
while (szCur < szNext)
|
|
{
|
|
if (++cbWrite >= 4096)
|
|
{
|
|
SFree(szAnswer);
|
|
return((SZ)NULL);
|
|
}
|
|
*szWriteCur++ = *szCur++;
|
|
}
|
|
}
|
|
*szWriteCur = '\0';
|
|
|
|
Assert(strlen(szAnswer) == cbWrite);
|
|
Assert(cbWrite + 1 <= (CB)4096);
|
|
if (cbWrite + 1 < (CB)4096)
|
|
szAnswer = SRealloc((PB)szAnswer, cbWrite + 1);
|
|
Assert(szAnswer != (SZ)NULL);
|
|
}
|
|
else if (*(*pszCmdLine = szCur) == '\0')
|
|
return((SZ)NULL);
|
|
else
|
|
{
|
|
CHP chpSav;
|
|
|
|
while (*szCur != '\0' &&
|
|
!FWhiteSpaceChp(*szCur))
|
|
szCur = SzNextChar(szCur);
|
|
|
|
chpSav = *szCur;
|
|
*szCur = '\0';
|
|
while ((szAnswer = SzDupl(*pszCmdLine)) == (SZ)NULL)
|
|
if (!FHandleOOM(hWndShell))
|
|
break;
|
|
*szCur = chpSav;
|
|
}
|
|
|
|
while (*szCur != '\0' &&
|
|
FWhiteSpaceChp(*szCur))
|
|
szCur = SzNextChar(szCur);
|
|
|
|
*pszCmdLine = szCur;
|
|
|
|
return(szAnswer);
|
|
}
|
|
|
|
|
|
/*
|
|
** Purpose:
|
|
** Parses the Command Line received in WinMain().
|
|
** Arguments:
|
|
** ??
|
|
** Returns:
|
|
** BOOL
|
|
***************************************************************************/
|
|
INT
|
|
ParseCmdLine(
|
|
HANDLE hInst,
|
|
SZ szCmdLine,
|
|
PSZ pszInfSrcPath,
|
|
PSZ pszDestDir,
|
|
PSZ pszSrcDir,
|
|
PSZ pszCWD,
|
|
INT * pwModeSetup
|
|
)
|
|
|
|
{
|
|
BOOL fSetupInfSpecified = fFalse;
|
|
BOOL fScriptSectionSpecified = fFalse;
|
|
BOOL fSourcePathSpecified = fFalse;
|
|
|
|
SZ szBase;
|
|
INT cchp;
|
|
SZ szCur;
|
|
SZ szLastBackSlash = NULL;
|
|
CHAR szInfPath[MAX_PATH];
|
|
BOOL bStatus;
|
|
|
|
|
|
*pwModeSetup = wModeSetupNormal;
|
|
|
|
while(FWhiteSpaceChp(*szCmdLine)) {
|
|
szCmdLine = SzNextChar(szCmdLine);
|
|
}
|
|
|
|
while(*szCmdLine) {
|
|
if (*szCmdLine == '-' || *szCmdLine == '/') {
|
|
|
|
szCmdLine++;
|
|
|
|
switch (*szCmdLine++){
|
|
|
|
case 'c':
|
|
case 'C':
|
|
|
|
if(fScriptSectionSpecified
|
|
|| (szShlScriptSection = SzGetNextCmdLineString(&szCmdLine)) == NULL) {
|
|
|
|
Usage(hInst);
|
|
return(CMDLINE_ERROR);
|
|
}
|
|
|
|
if(*(szShlScriptSection) == '\0'
|
|
|| *(szShlScriptSection) == ']'
|
|
|| *(szShlScriptSection) == '[') {
|
|
|
|
LoadString(
|
|
hInst,
|
|
IDS_ERROR,
|
|
rgchBufTmpShort,
|
|
cchpBufTmpShortMax
|
|
);
|
|
|
|
LoadString(
|
|
hInst,
|
|
IDS_BAD_SHL_SCRIPT_SECT,
|
|
rgchBufTmpLong,
|
|
cchpBufTmpLongMax
|
|
);
|
|
|
|
MessageBox(
|
|
hWndShell,
|
|
rgchBufTmpLong,
|
|
rgchBufTmpShort,
|
|
MB_OK | MB_ICONHAND
|
|
);
|
|
|
|
Usage(hInst);
|
|
return(CMDLINE_ERROR);
|
|
}
|
|
|
|
fScriptSectionSpecified = fTrue;
|
|
break;
|
|
|
|
//
|
|
// Allow /k but ignore it. It's processed in setup.c.
|
|
//
|
|
case 'f':
|
|
case 'F':
|
|
case 'k':
|
|
case 'K':
|
|
break;
|
|
|
|
case 'w':
|
|
case 'W':
|
|
//
|
|
// Since the /w parameter has already been handled
|
|
// (see SETUP.C), eat the argument.
|
|
//
|
|
if(szBase = SzGetNextCmdLineString(&szCmdLine)) {
|
|
SFree(szBase);
|
|
}
|
|
break;
|
|
|
|
case 'i':
|
|
case 'I':
|
|
if (fSetupInfSpecified ||
|
|
(*pszInfSrcPath = SzGetNextCmdLineString(&szCmdLine)) == (SZ)NULL)
|
|
{
|
|
Usage(hInst);
|
|
return(CMDLINE_ERROR);
|
|
}
|
|
|
|
if (**pszInfSrcPath == '\0') {
|
|
LoadString(hInst, IDS_ERROR, rgchBufTmpShort,
|
|
cchpBufTmpShortMax);
|
|
LoadString(hInst, IDS_BAD_INF_SRC, rgchBufTmpLong,
|
|
cchpBufTmpLongMax);
|
|
MessageBox(hWndShell, rgchBufTmpLong, rgchBufTmpShort,
|
|
MB_OK | MB_ICONHAND);
|
|
Usage(hInst);
|
|
return(CMDLINE_ERROR);
|
|
}
|
|
|
|
fSetupInfSpecified = fTrue;
|
|
break;
|
|
|
|
case 'g':
|
|
case 'G':
|
|
if (*pwModeSetup != wModeSetupNormal)
|
|
{
|
|
Usage(hInst);
|
|
return(CMDLINE_ERROR);
|
|
}
|
|
*pwModeSetup = wModeGuiInitialSetup;
|
|
break;
|
|
|
|
case 's':
|
|
case 'S':
|
|
|
|
*pszSrcDir = SzGetNextCmdLineString(&szCmdLine);
|
|
if(*pszSrcDir == NULL) {
|
|
Usage(hInst);
|
|
return(CMDLINE_ERROR);
|
|
}
|
|
|
|
if(**pszSrcDir == '\0') {
|
|
|
|
LoadString(
|
|
hInst,
|
|
IDS_ERROR,
|
|
rgchBufTmpShort,
|
|
cchpBufTmpShortMax
|
|
);
|
|
|
|
LoadString(
|
|
hInst,
|
|
IDS_BAD_SRC_PATH,
|
|
rgchBufTmpLong,
|
|
cchpBufTmpLongMax
|
|
);
|
|
|
|
MessageBox(
|
|
hWndShell,
|
|
rgchBufTmpLong,
|
|
rgchBufTmpShort,
|
|
MB_OK | MB_ICONHAND
|
|
);
|
|
|
|
Usage(hInst);
|
|
return(CMDLINE_ERROR);
|
|
}
|
|
|
|
fSourcePathSpecified = fTrue;
|
|
break;
|
|
|
|
case 't':
|
|
case 'T':
|
|
{
|
|
SZ szSymbol;
|
|
SZ szEqual;
|
|
SZ szValue;
|
|
PVALUE_BLOCK pVb;
|
|
|
|
|
|
if ( ( szSymbol = SzGetNextCmdLineString( &szCmdLine ) ) == NULL ) {
|
|
Usage(hInst);
|
|
return CMDLINE_ERROR;
|
|
}
|
|
|
|
if ( ( szEqual = SzGetNextCmdLineString( &szCmdLine ) ) == NULL ) {
|
|
Usage(hInst);
|
|
return CMDLINE_ERROR;
|
|
}
|
|
|
|
if ( ( szValue = SzGetNextCmdLineString( &szCmdLine ) ) == NULL ) {
|
|
Usage(hInst);
|
|
return CMDLINE_ERROR;
|
|
}
|
|
|
|
if ( (*szEqual != '=') || (*(szEqual+1) != '\0' ) ) {
|
|
Usage(hInst);
|
|
return CMDLINE_ERROR;
|
|
}
|
|
|
|
while ( (pVb = (PVALUE_BLOCK)SAlloc( sizeof( VALUE_BLOCK ) )) == NULL ) {
|
|
if ( !FHandleOOM(hWndShell)) {
|
|
return CMDLINE_ERROR;
|
|
}
|
|
}
|
|
|
|
pVb->szSymbol = szSymbol;
|
|
pVb->szValue = szValue;
|
|
|
|
|
|
if ( pCmdLineSymbols ) {
|
|
pVb->pNext = pCmdLineSymbols;
|
|
} else {
|
|
pVb->pNext = NULL;
|
|
}
|
|
pCmdLineSymbols = pVb;
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
case 'v':
|
|
case 'V':
|
|
|
|
fCheckInfValidity = fTrue;
|
|
break;
|
|
|
|
case '?':
|
|
default:
|
|
|
|
Usage(hInst);
|
|
return(CMDLINE_SETUPDONE);
|
|
|
|
} // switch
|
|
|
|
} else {
|
|
|
|
Usage(hInst);
|
|
return(CMDLINE_ERROR);
|
|
|
|
} // if we have - or /
|
|
|
|
while (FWhiteSpaceChp(*szCmdLine)) {
|
|
szCmdLine = SzNextChar(szCmdLine);
|
|
}
|
|
|
|
} // while unseen chars on cmd line
|
|
|
|
while((szCur = *pszCWD = (SZ)SAlloc((CB)4096)) == NULL) {
|
|
if(!FHandleOOM(hWndShell)) {
|
|
return(CMDLINE_ERROR);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Want name of exe, not name of this dll.
|
|
//
|
|
if ((cchp = GetModuleFileName(hInst, (LPSTR)szCur, 4095)) >= 4095) {
|
|
|
|
LoadString(hInst, IDS_ERROR, rgchBufTmpShort, cchpBufTmpShortMax);
|
|
LoadString(hInst, IDS_EXE_PATH_LONG, rgchBufTmpLong,cchpBufTmpLongMax);
|
|
|
|
MessageBox(hWndShell, rgchBufTmpLong, rgchBufTmpShort,MB_OK | MB_ICONHAND);
|
|
SFree(szCur);
|
|
return(CMDLINE_ERROR);
|
|
}
|
|
|
|
if (PfhOpenFile(szCur, ofmExistRead) == NULL) {
|
|
|
|
LoadString(hInst, IDS_INTERNAL_ERROR, rgchBufTmpShort,
|
|
cchpBufTmpShortMax);
|
|
LoadString(hInst, IDS_GET_MOD_FAIL, rgchBufTmpLong,
|
|
cchpBufTmpLongMax);
|
|
MessageBox(hWndShell, rgchBufTmpLong, rgchBufTmpShort,
|
|
MB_OK | MB_ICONHAND);
|
|
SFree(*pszCWD);
|
|
return(CMDLINE_ERROR);
|
|
}
|
|
|
|
while(*szCur) {
|
|
if(*szCur++ == '\\') {
|
|
szLastBackSlash = szCur;
|
|
}
|
|
}
|
|
|
|
if (szLastBackSlash == (SZ)NULL) {
|
|
LoadString(hInst, IDS_INTERNAL_ERROR, rgchBufTmpShort,
|
|
cchpBufTmpShortMax);
|
|
LoadString(hInst, IDS_GET_MOD_FAIL, rgchBufTmpLong,
|
|
cchpBufTmpLongMax);
|
|
MessageBox(hWndShell, rgchBufTmpLong, rgchBufTmpShort,
|
|
MB_OK | MB_ICONHAND);
|
|
SFree(*pszCWD);
|
|
return(CMDLINE_ERROR);
|
|
}
|
|
|
|
if(!fSetupInfSpecified) {
|
|
|
|
szCur = szLastBackSlash;
|
|
while (*szCur != '\0') {
|
|
|
|
if (*szCur == '.') {
|
|
*szCur = '\0';
|
|
break;
|
|
}
|
|
|
|
szCur++;
|
|
}
|
|
|
|
while((szBase = SzDupl(szLastBackSlash)) == (SZ)NULL) {
|
|
if(!FHandleOOM(hWndShell)) {
|
|
return(CMDLINE_ERROR);
|
|
}
|
|
}
|
|
}
|
|
|
|
*szLastBackSlash = '\0';
|
|
|
|
if(strlen(*pszCWD) + 1 < 4096) {
|
|
|
|
*pszCWD = SRealloc(*pszCWD,strlen(*pszCWD)+1);
|
|
}
|
|
|
|
if(!fSourcePathSpecified) {
|
|
while((*pszSrcDir = SzDupl(*pszCWD)) == (SZ)NULL) {
|
|
if (!FHandleOOM(hWndShell)) {
|
|
return(CMDLINE_ERROR);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// if setup inf is not specified, then user is attempting to enter
|
|
// maintenance-mode setup, which is obsolete. Give the user a friendly
|
|
// message informing them of this, and directing them to the new functionality
|
|
// in the Control Panel.
|
|
//
|
|
if(!fSetupInfSpecified) {
|
|
|
|
Assert(szBase);
|
|
SFree(szBase);
|
|
|
|
MaintSetupObsoleteMsg(hInst);
|
|
|
|
return CMDLINE_ERROR;
|
|
|
|
/*
|
|
LoadString(hInst,IDS_SETUP_INF,rgchBufTmpLong,cchpBufTmpLongMax);
|
|
|
|
while((*pszInfSrcPath = SAlloc(strlen(szBase)+strlen(rgchBufTmpLong)+2)) == NULL) {
|
|
if (!FHandleOOM(hWndShell)) {
|
|
return( CMDLINE_ERROR );
|
|
}
|
|
}
|
|
|
|
strcpy(*pszInfSrcPath,szBase);
|
|
lstrcat(*pszInfSrcPath,".");
|
|
lstrcat(*pszInfSrcPath,rgchBufTmpLong);
|
|
*/
|
|
}
|
|
|
|
//
|
|
// Process the setup inf found ( check to see if it exists ) in the
|
|
// cwd or in windows system .. and get a full path back to the processed
|
|
// setup inf location
|
|
//
|
|
bStatus = FProcessInfSrcPath(*pszInfSrcPath,*pszCWD,szInfPath);
|
|
|
|
if(!bStatus) {
|
|
|
|
LoadString( hInst, IDS_ERROR, rgchBufTmpShort, cchpBufTmpShortMax );
|
|
LoadString( hInst, IDS_BAD_INF_SRC, rgchBufTmpLong, cchpBufTmpLongMax);
|
|
MessageBox(hWndShell, rgchBufTmpLong, rgchBufTmpShort,MB_OK | MB_ICONHAND);
|
|
|
|
Usage(hInst);
|
|
return(CMDLINE_ERROR);
|
|
}
|
|
|
|
SFree(*pszInfSrcPath);
|
|
*pszInfSrcPath = SAlloc(strlen( szInfPath ) + 1 );
|
|
strcpy(*pszInfSrcPath, szInfPath);
|
|
|
|
*pszDestDir = NULL;
|
|
|
|
if(!fScriptSectionSpecified) {
|
|
|
|
LoadString(hInst,IDS_SHELL_CMDS_SECT,rgchBufTmpShort,cchpBufTmpShortMax);
|
|
|
|
while((szShlScriptSection = SzDupl(rgchBufTmpShort)) == (SZ)NULL) {
|
|
|
|
if(!FHandleOOM(hWndShell)) {
|
|
return(CMDLINE_ERROR);
|
|
}
|
|
}
|
|
}
|
|
|
|
return(CMDLINE_SUCCESS);
|
|
}
|
|
|
|
|
|
BOOL
|
|
CreateShellWindow(
|
|
IN HANDLE hInstance,
|
|
IN INT nCmdShow,
|
|
IN BOOL CleanUp
|
|
)
|
|
{
|
|
HDC hdc;
|
|
TEXTMETRIC tm;
|
|
WNDCLASS wc;
|
|
BOOL RegisterStatus;
|
|
|
|
if(!CleanUp) {
|
|
|
|
nCmdShow = SW_SHOWMAXIMIZED;
|
|
hInst = hInstance;
|
|
|
|
wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
|
|
wc.lpfnWndProc = ShellWndProc;
|
|
wc.cbClsExtra = 0;
|
|
wc.cbWndExtra = 0;
|
|
wc.hInstance = hInstance;
|
|
wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_STF_ICON));
|
|
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
|
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
|
|
wc.lpszMenuName = NULL;
|
|
}
|
|
|
|
wc.lpszClassName = "Stuff-Shell";
|
|
|
|
if(CleanUp) {
|
|
ProInit(FALSE);
|
|
ControlInit(FALSE);
|
|
DlgDefClassInit(hInstance,FALSE);
|
|
ButtonControlTerm();
|
|
UnregisterClass(wc.lpszClassName,hInst);
|
|
return(TRUE);
|
|
} else {
|
|
RegisterStatus = RegisterClass(&wc);
|
|
RegisterStatus &= ButtonControlInit(hInstance);
|
|
RegisterStatus &= DlgDefClassInit(hInstance,TRUE);
|
|
RegisterStatus &= ControlInit(TRUE);
|
|
RegisterStatus &= ProInit(TRUE);
|
|
}
|
|
|
|
if(!RegisterStatus) {
|
|
|
|
LoadString(hInstance,IDS_ERROR,rgchBufTmpShort,cchpBufTmpShortMax);
|
|
LoadString(hInstance,IDS_REGISTER_CLASS,rgchBufTmpLong,cchpBufTmpLongMax);
|
|
|
|
MessageBox(
|
|
NULL,
|
|
rgchBufTmpLong,
|
|
rgchBufTmpShort,
|
|
MB_OK | MB_ICONHAND | MB_SYSTEMMODAL
|
|
);
|
|
|
|
return(fFalse);
|
|
}
|
|
|
|
hdc = GetDC(NULL);
|
|
if (hdc) {
|
|
|
|
GetTextMetrics(hdc, &tm);
|
|
dxChar = tm.tmAveCharWidth;
|
|
dyChar = tm.tmHeight;
|
|
ReleaseDC(NULL, hdc);
|
|
|
|
}
|
|
|
|
if(!FMakeWindows(hInstance)) {
|
|
|
|
LoadString(hInstance,IDS_ERROR,rgchBufTmpShort,cchpBufTmpShortMax);
|
|
LoadString(hInstance,IDS_CREATE_WINDOW,rgchBufTmpLong,cchpBufTmpLongMax);
|
|
|
|
MessageBox(
|
|
NULL,
|
|
rgchBufTmpLong,
|
|
rgchBufTmpShort,
|
|
MB_OK | MB_ICONHAND | MB_SYSTEMMODAL
|
|
);
|
|
|
|
return(fFalse);
|
|
}
|
|
|
|
if ( ! fFullScreen ) {
|
|
RECT rWind ;
|
|
|
|
GetWindowRect( hWndShell, & rWind ) ;
|
|
|
|
MoveWindow( hWndShell,
|
|
20000,
|
|
20000,
|
|
rWind.right - rWind.left,
|
|
rWind.bottom - rWind.top,
|
|
FALSE ) ;
|
|
|
|
nCmdShow = SW_SHOWNOACTIVATE ;
|
|
}
|
|
|
|
ShowWindow(hWndShell,nCmdShow);
|
|
UpdateWindow(hWndShell);
|
|
|
|
if (!FInitHook()) {
|
|
//
|
|
// BUGBUG.. Do we need to process this error, or do we just lose
|
|
// the capability to process keyboard hooks
|
|
//
|
|
}
|
|
|
|
return(fTrue);
|
|
}
|
|
|
|
|
|
/*
|
|
** Purpose:
|
|
** Initializes structures.
|
|
** Arguments:
|
|
** ??
|
|
** Returns:
|
|
** BOOL
|
|
***************************************************************************/
|
|
BOOL
|
|
FInitApp(
|
|
HANDLE hInstance,
|
|
SZ szInfSrcPath,
|
|
SZ szDestDir,
|
|
SZ szSrcDir,
|
|
SZ szCWD,
|
|
INT wModeSetup
|
|
)
|
|
|
|
{
|
|
GRC grc = grcOkay;
|
|
INT Line;
|
|
CHAR szName[cchlFullPathMax];
|
|
CHAR szDriveType[10];
|
|
CHAR szProcessedDir[cchlFullPathMax];
|
|
PINFCONTEXT pContext;
|
|
PINFTEMPINFO pTempInfo;
|
|
SZ szInstallType;
|
|
|
|
ChkArg(hInstance != (HANDLE)NULL, 1, fFalse);
|
|
ChkArg(szInfSrcPath != (SZ)NULL && *szInfSrcPath != '\0', 2, fFalse);
|
|
ChkArg(szSrcDir != (SZ)NULL && *szSrcDir != '\0', 4, fFalse);
|
|
ChkArg(szCWD != (SZ)NULL && *szCWD != '\0', 5, fFalse);
|
|
|
|
Assert(szShlScriptSection != (SZ)NULL && *(szShlScriptSection) != '\0');
|
|
|
|
//
|
|
// Create INF permanent and temporary info.
|
|
//
|
|
|
|
PathToInfName( szInfSrcPath, szName );
|
|
while ( !(pTempInfo = (PINFTEMPINFO)CreateInfTempInfo( AddInfPermInfo( szName ) )) ) {
|
|
if (!FHandleOOM(hWndShell))
|
|
return(fFalse);
|
|
}
|
|
|
|
//
|
|
// Create global context.
|
|
//
|
|
while ( !(pContext = (PINFCONTEXT)SAlloc( (CB)sizeof(CONTEXT) )) ) {
|
|
if (!FHandleOOM(hWndShell))
|
|
return(fFalse);
|
|
}
|
|
|
|
pContext->pInfTempInfo = pTempInfo;
|
|
pContext->pNext = NULL;
|
|
|
|
PushContext( pContext );
|
|
|
|
pLocalContext()->szShlScriptSection = szShlScriptSection;
|
|
|
|
//
|
|
// Add all the symbols specified in the command line
|
|
//
|
|
while ( pCmdLineSymbols ) {
|
|
|
|
PVALUE_BLOCK p = pCmdLineSymbols;
|
|
|
|
pCmdLineSymbols = pCmdLineSymbols->pNext;
|
|
|
|
while (!FAddSymbolValueToSymTab(p->szSymbol, p->szValue)) {
|
|
if (!FHandleOOM(hWndShell)) {
|
|
return(fFalse);
|
|
}
|
|
}
|
|
|
|
SFree( p->szSymbol );
|
|
SFree( p->szValue );
|
|
SFree( p );
|
|
}
|
|
|
|
FInitParsingTables();
|
|
|
|
GetWindowsDirectory(szProcessedDir,sizeof(szProcessedDir));
|
|
while(!FAddSymbolValueToSymTab("STF_WINDOWS_DIR",szProcessedDir)) {
|
|
if(!FHandleOOM(hWndShell)) {
|
|
return(fFalse);
|
|
}
|
|
}
|
|
GetSystemDirectory(szProcessedDir,sizeof(szProcessedDir));
|
|
while(!FAddSymbolValueToSymTab("STF_SYSTEM_DIR",szProcessedDir)) {
|
|
if(!FHandleOOM(hWndShell)) {
|
|
return(fFalse);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Process SRC DIR
|
|
//
|
|
|
|
if (!FProcessForDriveType(szSrcDir, szDriveType, szCWD, szProcessedDir)) {
|
|
return(fFalse);
|
|
}
|
|
|
|
while (!FAddSymbolValueToSymTab("STF_SRCTYPE", szDriveType)) {
|
|
if (!FHandleOOM(hWndShell)) {
|
|
return(fFalse);
|
|
}
|
|
}
|
|
|
|
while (!FAddSymbolValueToSymTab("STF_SRCDIR", szProcessedDir)) {
|
|
if (!FHandleOOM(hWndShell)) {
|
|
return(fFalse);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Process DEST DIR
|
|
//
|
|
|
|
if (szDestDir != NULL) {
|
|
if (!FProcessForDriveType(szDestDir, szDriveType, szCWD, szProcessedDir)) {
|
|
return(fFalse);
|
|
}
|
|
|
|
while (!FAddSymbolValueToSymTab("STF_DSTTYPE", szDriveType)) {
|
|
if (!FHandleOOM(hWndShell)) {
|
|
return(fFalse);
|
|
}
|
|
}
|
|
|
|
while (!FAddSymbolValueToSymTab("STF_DSTDIR", szProcessedDir)) {
|
|
if (!FHandleOOM(hWndShell)) {
|
|
return(fFalse);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
while (!FAddSymbolValueToSymTab("STF_DSTTYPE", "NONE")) {
|
|
if (!FHandleOOM(hWndShell)) {
|
|
return(fFalse);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Process INF SRC PATH
|
|
//
|
|
|
|
while (!FAddSymbolValueToSymTab("STF_SRCINFPATH", szInfSrcPath))
|
|
if (!FHandleOOM(hWndShell))
|
|
return(fFalse);
|
|
|
|
while (!FAddSymbolValueToSymTab("STF_CONTEXTINFNAME", szInfSrcPath))
|
|
if (!FHandleOOM(hWndShell))
|
|
return(fFalse);
|
|
|
|
//
|
|
// Get the SETUP working directory
|
|
//
|
|
|
|
while (!FAddSymbolValueToSymTab("STF_CWDDIR", szCWD))
|
|
if (!FHandleOOM(hWndShell))
|
|
return(fFalse);
|
|
|
|
while (!FAddSymbolValueToSymTab("STF_SYS_INIT", "NO"))
|
|
if (!FHandleOOM(hWndShell))
|
|
return(fFalse);
|
|
|
|
{
|
|
char NumTmp[9];
|
|
HWND hw ;
|
|
|
|
hw = hwParam
|
|
? FindProperParent()
|
|
: hWndShell ;
|
|
|
|
wsprintf(NumTmp,"%lx",hw);
|
|
|
|
while (!FAddSymbolValueToSymTab("STF_HWND", NumTmp))
|
|
{
|
|
if (!FHandleOOM(hWndShell)) {
|
|
return(fFalse);
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
//
|
|
// Registry constants
|
|
//
|
|
char NumTmp[20];
|
|
PINITSYMHANDLE pSymHandle;
|
|
PINITSYMNUMBER pSymNumber;
|
|
|
|
|
|
//
|
|
// Handles
|
|
//
|
|
pSymHandle = InitSymHandle;
|
|
while ( pSymHandle->szName ) {
|
|
|
|
wsprintf(NumTmp,"|%ld", pSymHandle->Handle );
|
|
while (!FAddSymbolValueToSymTab(pSymHandle->szName, NumTmp)) {
|
|
if (!FHandleOOM(hWndShell)) {
|
|
return(fFalse);
|
|
}
|
|
}
|
|
|
|
pSymHandle++;
|
|
}
|
|
|
|
//
|
|
// Numeric values
|
|
//
|
|
pSymNumber = InitSymNumber;
|
|
while ( pSymNumber->szName ) {
|
|
|
|
wsprintf(NumTmp,"%ld", pSymNumber->dwNumber );
|
|
while (!FAddSymbolValueToSymTab(pSymNumber->szName, NumTmp)) {
|
|
if (!FHandleOOM(hWndShell)) {
|
|
return(fFalse);
|
|
}
|
|
}
|
|
|
|
pSymNumber++;
|
|
}
|
|
}
|
|
|
|
if (wModeSetup == wModeSetupNormal) {
|
|
szInstallType = "NORMAL";
|
|
}
|
|
#if 0
|
|
else if (wModeSetup == wModeSetupToShare) {
|
|
szInstallType = "SETUPTOSHARE";
|
|
}
|
|
#endif
|
|
else if (wModeSetup == wModeGuiInitialSetup) {
|
|
szInstallType = "SETUPBOOTED";
|
|
}
|
|
else {
|
|
AssertRet(fFalse, fFalse);
|
|
}
|
|
|
|
while (!FAddSymbolValueToSymTab("STF_INSTALL_TYPE", szInstallType)) {
|
|
if (!FHandleOOM(hWndShell)) {
|
|
return(fFalse);
|
|
}
|
|
}
|
|
|
|
|
|
#if DBG
|
|
fCheckInfValidity = fTrue;
|
|
#endif /* DBG */
|
|
while ((grc = GrcOpenInf(szInfSrcPath, pGlobalContext()->pInfTempInfo)) != grcOkay)
|
|
if (EercErrorHandler(hWndShell, grc, fTrue, szInfSrcPath, 0, 0)
|
|
!= eercRetry)
|
|
return(fFalse);
|
|
|
|
while ((grc = GrcFillSrcDescrListFromInf()) != grcOkay)
|
|
if (EercErrorHandler(hWndShell, grc, fTrue, szInfSrcPath, 0, 0)
|
|
!= eercRetry)
|
|
return(fFalse);
|
|
|
|
if ((Line = FindFirstLineFromInfSection(pLocalContext()->szShlScriptSection)) == -1)
|
|
{
|
|
LoadString(hInstance, IDS_ERROR, rgchBufTmpShort, cchpBufTmpShortMax);
|
|
LoadString(hInstance, IDS_CANT_FIND_SHL_SECT, rgchBufTmpLong,
|
|
cchpBufTmpLongMax);
|
|
MessageBox(hWndShell, rgchBufTmpLong, rgchBufTmpShort,
|
|
MB_OK | MB_ICONHAND);
|
|
return(fFalse);
|
|
}
|
|
|
|
if ((psptShellScript = PsptInitParsingTable(rgscp)) == (PSPT)NULL ||
|
|
!FInitFlowPspt())
|
|
{
|
|
Assert(fFalse);
|
|
return(fFalse);
|
|
}
|
|
|
|
PostMessage(hWndShell, STF_SHL_INTERP, Line+1, 0L);
|
|
|
|
return(fTrue);
|
|
}
|
|
|
|
|
|
/*
|
|
* FMakeWindows -- create Windows used by Setup
|
|
*/
|
|
BOOL
|
|
FMakeWindows(
|
|
IN HANDLE hInstance
|
|
)
|
|
|
|
{
|
|
int xSize = GetSystemMetrics(SM_CXSCREEN),
|
|
ySize = GetSystemMetrics(SM_CYSCREEN) ;
|
|
|
|
DWORD dwStyle = WS_POPUP | WS_CLIPCHILDREN ;
|
|
|
|
if ( ! fFullScreen )
|
|
{
|
|
xSize = 2 ;
|
|
ySize = 2 ;
|
|
dwStyle = WS_POPUP ;
|
|
}
|
|
|
|
if ( hwParam )
|
|
{
|
|
DWORD dwThreadId = GetCurrentThreadId() ;
|
|
DWORD dwParentThreadId = GetWindowThreadProcessId( hwParam,
|
|
NULL ) ;
|
|
|
|
AttachThreadInput( dwThreadId,
|
|
dwParentThreadId,
|
|
TRUE ) ;
|
|
}
|
|
|
|
//
|
|
// Create the main setup window
|
|
//
|
|
|
|
hWndShell = CreateWindowEx(
|
|
fFullScreen ? 0 : WS_EX_TRANSPARENT,
|
|
"Stuff-Shell",
|
|
"Setup",
|
|
dwStyle,
|
|
0,
|
|
0,
|
|
xSize,
|
|
ySize,
|
|
hwParam,
|
|
NULL,
|
|
hInstance,
|
|
NULL
|
|
);
|
|
|
|
//
|
|
// return status of operation
|
|
//
|
|
|
|
if ( hWndShell == (HWND)NULL ) {
|
|
|
|
return( fFalse );
|
|
|
|
}
|
|
|
|
return( fTrue );
|
|
}
|
|
|
|
BOOL
|
|
FProcessForDriveType(
|
|
SZ szDir,
|
|
SZ szDriveType,
|
|
SZ szCWD,
|
|
SZ szProcessedDir
|
|
)
|
|
{
|
|
ChkArg(szDir != (SZ)NULL, 1, fFalse);
|
|
ChkArg(szDriveType != (SZ)NULL, 2, fFalse);
|
|
ChkArg(szProcessedDir != (SZ)NULL, 3, fFalse);
|
|
|
|
//
|
|
// Only drive types are DOS and UNC.
|
|
//
|
|
if(ISUNC(szDir)) {
|
|
|
|
lstrcpy(szDriveType,szUncType);
|
|
lstrcpy(szProcessedDir,szDir);
|
|
|
|
} else {
|
|
|
|
lstrcpy(szDriveType,szDosType);
|
|
|
|
//
|
|
// Handle drive-relative paths.
|
|
//
|
|
if(*szDir == '\\') {
|
|
|
|
//
|
|
// root relative szDir, get current drive and slap it in
|
|
//
|
|
*szProcessedDir = (UCHAR)_getdrive() + (UCHAR)'A' - (UCHAR)1;
|
|
*(szProcessedDir + 1) = ':';
|
|
*(szProcessedDir + 2) = '\0';
|
|
|
|
} else {
|
|
if(*(szDir + 1) == ':') {
|
|
|
|
//
|
|
// Drive relative path (we don't need to do anything)
|
|
//
|
|
*szProcessedDir = '\0';
|
|
|
|
} else {
|
|
|
|
//
|
|
// No root specified, so we assume the directory is relative to
|
|
// szCWD
|
|
//
|
|
lstrcpy(szProcessedDir,szCWD);
|
|
}
|
|
}
|
|
|
|
lstrcat(szProcessedDir,szDir);
|
|
}
|
|
|
|
//
|
|
// The szProcessedDir should be terminated by a '\\'
|
|
//
|
|
if (*(szProcessedDir + lstrlen(szProcessedDir) - 1) != '\\') {
|
|
lstrcat(szProcessedDir,"\\");
|
|
}
|
|
|
|
return(fTrue);
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
FProcessInfSrcPath(
|
|
SZ szInf,
|
|
SZ szCWD,
|
|
SZ szProcessedDir
|
|
)
|
|
{
|
|
#define INF_ABSOLUTE 0
|
|
#define INF_RELATIVE 1
|
|
|
|
INT PathType = INF_RELATIVE;
|
|
PFH pfh = (PFH)NULL;
|
|
|
|
//
|
|
// Check to see if the inf path specified is a relative path or
|
|
// an absolute path
|
|
//
|
|
|
|
if ( lstrlen( szInf ) >= 2 ) {
|
|
|
|
//
|
|
// See if the INF has a drive relative src path spec
|
|
//
|
|
|
|
if (ISUNC( szInf ) ) {
|
|
lstrcpy(szProcessedDir, szInf);
|
|
PathType = INF_ABSOLUTE;
|
|
}
|
|
else if (*szInf == '\\') {
|
|
|
|
//
|
|
// root relative szInf
|
|
//
|
|
|
|
*szProcessedDir = (UCHAR)_getdrive() + (UCHAR)'A' - (UCHAR)1;
|
|
*(szProcessedDir + 1) = ':';
|
|
*(szProcessedDir + 2) = '\0';
|
|
lstrcat(szProcessedDir, szInf);
|
|
PathType = INF_ABSOLUTE;
|
|
|
|
}
|
|
else if (*(szInf + 1) == ':') {
|
|
|
|
//
|
|
// drive relative path (we don't need to do anything)
|
|
//
|
|
|
|
lstrcpy(szProcessedDir, szInf);
|
|
PathType = INF_ABSOLUTE;
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// If it is an absolute path try opening the INF as is
|
|
//
|
|
|
|
if ( PathType == INF_ABSOLUTE ) {
|
|
if (( pfh = PfhOpenFile(szProcessedDir, ofmRead)) != (PFH)NULL ) {
|
|
EvalAssert(FCloseFile(pfh));
|
|
return( TRUE );
|
|
}
|
|
else {
|
|
return( FALSE );
|
|
}
|
|
}
|
|
|
|
//
|
|
// Path is a relative path, try first combining the szCWD and the inf.
|
|
//
|
|
|
|
lstrcpy( szProcessedDir, szCWD );
|
|
lstrcat( szProcessedDir, szInf );
|
|
if (( pfh = PfhOpenFile(szProcessedDir, ofmRead)) != (PFH)NULL ) {
|
|
EvalAssert(FCloseFile(pfh));
|
|
return( TRUE );
|
|
}
|
|
|
|
//
|
|
// Then try combining the windows system directory and the INF
|
|
//
|
|
|
|
EvalAssert( GetSystemDirectory( szProcessedDir, MAX_PATH ) <= MAX_PATH );
|
|
lstrcat( szProcessedDir, "\\" );
|
|
lstrcat( szProcessedDir, szInf );
|
|
if (( pfh = PfhOpenFile(szProcessedDir, ofmRead)) != (PFH)NULL ) {
|
|
EvalAssert(FCloseFile(pfh));
|
|
return( TRUE );
|
|
}
|
|
|
|
//
|
|
// Inf not found
|
|
//
|
|
|
|
return( FALSE );
|
|
|
|
}
|
|
|
|
|
|
HWND FindProperParent ( void )
|
|
{
|
|
RECT rect ;
|
|
HWND hwMaster, hwParent ;
|
|
POINT ptMax ;
|
|
|
|
hwParent = hwMaster = GetDesktopWindow() ;
|
|
|
|
// If we have a main window that is not the blue screen,
|
|
// make sure that we have a valid parent that is visible.
|
|
|
|
if ( hwParam )
|
|
{
|
|
BOOL bOk = FALSE ;
|
|
|
|
ptMax.x = GetSystemMetrics( SM_CXFULLSCREEN ) ;
|
|
ptMax.y = GetSystemMetrics( SM_CYFULLSCREEN ) ;
|
|
|
|
hwMaster = hwParam ;
|
|
|
|
do
|
|
{
|
|
if ( IsWindow( hwMaster )
|
|
&& GetWindowRect( hwMaster, & rect ) )
|
|
{
|
|
bOk = rect.left >= 0
|
|
&& rect.left < ptMax.x
|
|
&& rect.top >= 0
|
|
&& rect.top < ptMax.y ;
|
|
}
|
|
|
|
if ( ! bOk )
|
|
{
|
|
hwMaster = GetParent( hwMaster ) ;
|
|
}
|
|
} while ( ! bOk && hwMaster != NULL ) ;
|
|
|
|
if ( bOk )
|
|
hwParent = hwMaster ;
|
|
}
|
|
|
|
return hwPseudoParent = hwParent ;
|
|
}
|