windows-nt/Source/XPSP1/NT/base/ntsetup/legacy/dll/init.c
2020-09-26 16:20:57 +08:00

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 ;
}