#include "precomp.h" #pragma hdrstop /**************************************************************************/ /***** Shell Component - Script Interpreting routine **********************/ /**************************************************************************/ #define NEWINF extern BOOL FAddSymSectionToUpdateList(SZ); extern BOOL FUpdateAllReadSymSections(VOID); extern BOOL FFreeSymSectionsUpdateList(VOID); extern BOOL FUIEntryPoint(HANDLE, HWND, RGSZ, USHORT); int SymTabDumpCount = 0; BOOL FShellCommand( RGSZ rgszArg ); BOOL FShellReturn( RGSZ rgszArg ); /* ** Symbol Section Update List Element structure */ typedef struct _ssule { SZ szSection; struct _ssule * pssuleNext; } SSULE; typedef SSULE * PSSULE; /* ** Global Variable for head of list for Symbol Sections to update */ PSSULE pssuleSymSectionUpdateList = (PSSULE)NULL; /* ** Purpose: ** ?? ** Arguments: ** none ** Returns: ** none ** *************************************************************************/ BOOL FAddSymSectionToUpdateList(szSection) SZ szSection; { PSSULE pssule; while ((pssule = (PSSULE)SAlloc((CB)sizeof(SSULE))) == (PSSULE)NULL) if (!FHandleOOM(hWndShell)) return(fFalse); while ((pssule->szSection = SzDupl(szSection)) == (SZ)NULL) if (!FHandleOOM(hWndShell)) return(fFalse); pssule->pssuleNext = pssuleSymSectionUpdateList; pssuleSymSectionUpdateList = pssule; return(fTrue); } /* ** Purpose: ** ?? ** Arguments: ** none ** Returns: ** none ** *************************************************************************/ BOOL FUpdateAllReadSymSections(VOID) { #ifndef NEWINF PSSULE pssule = pssuleSymSectionUpdateList; while (pssule != (PSSULE)NULL) { if (!FUpdateInfSectionUsingSymTab(pssule->szSection)) return(fFalse); pssule = pssule->pssuleNext; } #endif return(fTrue); } /* ** Purpose: ** ?? ** Arguments: ** none ** Returns: ** none ** *************************************************************************/ BOOL FFreeSymSectionsUpdateList(VOID) { PSSULE pssule; while ((pssule = pssuleSymSectionUpdateList) != (PSSULE)NULL) { pssuleSymSectionUpdateList = pssule->pssuleNext; SFree(pssule->szSection); SFree(pssule); } return(fTrue); } /* ** Purpose: ** Reads and Interprets the current line in the INF file. ** Arguments: ** wParam: if not 0, line # of new current line + 1 ** lParam: cc ** Returns: ** fFalse ** fTrue ** **************************************************************************/ BOOL FInterpretNextInfLine(WPARAM wParam,LPARAM lParam) { SPC spc; UINT cFields; UINT iField; RGSZ rgsz = (RGSZ)NULL; PFH pfh; GRC grc; CHAR FileName[MAX_PATH]; Unused(lParam); PreCondition(psptShellScript != (PSPT)NULL, fFalse); PreCondition(pLocalContext()->szShlScriptSection != (SZ)NULL && *(pLocalContext()->szShlScriptSection) != '\0' && *(pLocalContext()->szShlScriptSection) != '[', fFalse); if(wParam) { pLocalContext()->CurrentLine = (INT)(wParam - 1); } #if 0 sprintf(FileName,"C:\\SYMTAB.%03d",SymTabDumpCount); OutputDebugString("SETUPDLL: "); OutputDebugString( FileName ); OutputDebugString( "\n" ); SymTabDumpCount++; DumpSymbolTableToFile(FileName); #endif if (!FHandleFlowStatements(&(pLocalContext()->CurrentLine), hWndShell, pLocalContext()->szShlScriptSection, &cFields , &rgsz)) return(fFalse); Assert(cFields); Assert(rgsz); switch ((spc = SpcParseString(psptShellScript, rgsz[0]))) { case spcUI: SdAtNewLine(pLocalContext()->CurrentLine); if (!FUIEntryPoint(hInst, hWndShell, rgsz + 1, (USHORT)(cFields - 1))) goto LParseExitErr; break; case spcDetect: SdAtNewLine(pLocalContext()->CurrentLine); if (!FDetectEntryPoint(hInst, hWndShell, rgsz + 1, (USHORT)(cFields - 1))) goto LParseExitErr; break; case spcInstall: SdAtNewLine(pLocalContext()->CurrentLine); if (!FInstallEntryPoint(hInst, hWndShell, rgsz + 1, (USHORT)(cFields - 1))) goto LParseExitErr; break; case spcExit: SdAtNewLine(pLocalContext()->CurrentLine); if (cFields != 1) goto LScriptError; EvalAssert(FFreeRgsz(rgsz)); FDestroyShellWindow() ; return(fTrue); case spcReadSyms: SdAtNewLine(pLocalContext()->CurrentLine); if (cFields == 1) goto LScriptError; case spcUpdateInf: if(spc == spcUpdateInf) { SdAtNewLine(pLocalContext()->CurrentLine); } #ifdef NEWINF if(spc == spcUpdateInf) { MessBoxSzSz("","Update-Inf encountered, no action taken"); break; } #endif if (spc == spcUpdateInf && cFields > 1) EvalAssert(FFreeSymSectionsUpdateList()); for (iField = 1; iField < cFields; iField++) { RGSZ rgszCur; PSZ psz; while ((rgszCur = RgszFromSzListValue(rgsz[iField])) == (RGSZ)NULL) if (!FHandleOOM(hWndShell)) goto LParseExitErr; psz = rgszCur; while (*psz != (SZ)NULL) { if (**psz == '\0' || FWhiteSpaceChp(**psz)) { EvalAssert(FFreeRgsz(rgszCur)); goto LScriptError; } if (FindInfSectionLine(*psz) == -1) { LoadString(hInst, IDS_ERROR, rgchBufTmpShort, cchpBufTmpShortMax); LoadString(hInst, IDS_INF_SECT_REF, rgchBufTmpLong, cchpBufTmpLongMax); EvalAssert(SzStrCat(rgchBufTmpLong,*psz) == rgchBufTmpLong); MessageBox(hWndShell, rgchBufTmpLong, rgchBufTmpShort, MB_OK | MB_ICONHAND); EvalAssert(FFreeRgsz(rgszCur)); goto LParseExitErr; } while (spc == spcReadSyms && (grc = GrcAddSymsFromInfSection(*psz)) != grcOkay) { if (EercErrorHandler(hWndShell, grc, fTrue, 0, 0, 0) != eercRetry) { EvalAssert(FFreeRgsz(rgszCur)); goto LParseExitErr; } } if (!FAddSymSectionToUpdateList(*psz)) { EvalAssert(FFreeRgsz(rgszCur)); goto LParseExitErr; } psz++; } EvalAssert(FFreeRgsz(rgszCur)); } if (spc == spcReadSyms) break; #ifndef NEWINF if (!FUpdateAllReadSymSections()) { LoadString(hInst, IDS_ERROR, rgchBufTmpShort, cchpBufTmpShortMax); LoadString(hInst, IDS_UPDATE_INF, rgchBufTmpLong, cchpBufTmpLongMax); MessageBox(hWndShell, rgchBufTmpLong, rgchBufTmpShort, MB_OK | MB_ICONHAND); goto LParseExitErr; } EvalAssert(FFreeSymSectionsUpdateList()); #endif break; case spcWriteInf: SdAtNewLine(pLocalContext()->CurrentLine); if (cFields != 2 || *(rgsz[1]) == '\0') goto LScriptError; #ifndef NEWINF while (!FWriteInfFile(rgsz[1])) if (EercErrorHandler(hWndShell, grcWriteInf, fTrue, rgsz[1], 0, 0) != eercRetry) goto LParseExitErr; #else MessBoxSzSz("","WriteInf encountered, no action taken"); #endif break; case spcWriteSymTab: SdAtNewLine(pLocalContext()->CurrentLine); if((cFields != 2) || (*rgsz[1] == '\0')) { goto LScriptError; } retry_dump: if(!DumpSymbolTableToFile(rgsz[1])) { EERC eerc; if((eerc = EercErrorHandler(hWndShell,grcWriteFileErr,fFalse,rgsz[1],0,0)) == eercAbort) { goto LParseExitErr; } else if (eerc == eercRetry) { goto retry_dump; } } break; case spcSetTitle: SdAtNewLine(pLocalContext()->CurrentLine); if (cFields == 1) SetWindowText(hWndShell, ""); else if (cFields == 2) SetWindowText(hWndShell, (LPSTR)(rgsz[1])); else goto LScriptError; break; case spcEnableExit: SdAtNewLine(pLocalContext()->CurrentLine); // EnableExit(fTrue); break; case spcDisableExit: SdAtNewLine(pLocalContext()->CurrentLine); // EnableExit(fFalse); break; case spcExitAndExec: SdAtNewLine(pLocalContext()->CurrentLine); if (cFields != 2) goto LScriptError; /* BLOCK */ { SZ sz = rgsz[1]; /* Set Working Directory for DLL loads */ if (*sz != '\0' && *(sz + 1) == ':') { AnsiUpperBuff(sz, 1); if (!_chdrive(*sz - 'A' + 1)) { SZ szLastSlash = NULL; sz += 2; while (*sz != '\0' && !FWhiteSpaceChp(*sz)) { if (*sz == '\\') szLastSlash = sz; sz++; } if (szLastSlash != NULL) { *szLastSlash = '\0'; sz = rgsz[1] + 2; if (*sz != '\0') { AnsiUpper(sz); _chdir(sz); } *szLastSlash = '\\'; } } } WinExec(rgsz[1], SW_SHOWNORMAL); /* REVIEW error handling */ } EvalAssert(FFreeRgsz(rgsz)); FDestroyShellWindow() ; return(fTrue); case spcShell: SdAtNewLine(pLocalContext()->CurrentLine); if (cFields < 3) { goto LScriptError; } return FShellCommand( &rgsz[1] ); case spcReturn: SdAtNewLine(pLocalContext()->CurrentLine); return FShellReturn( &rgsz[1] ); default: SdAtNewLine(pLocalContext()->CurrentLine); goto LScriptError; } EvalAssert(FFreeRgsz(rgsz)); if ((pLocalContext()->CurrentLine = FindNextLineFromInf(pLocalContext()->CurrentLine)) == -1) { LoadString(hInst, IDS_ERROR, rgchBufTmpShort, cchpBufTmpShortMax); LoadString(hInst, IDS_NEED_EXIT, rgchBufTmpLong, cchpBufTmpLongMax); MessageBox(hWndShell, rgchBufTmpLong, rgchBufTmpShort, MB_OK | MB_ICONHAND); return(fFalse); } if (spc != spcUI) PostMessage(hWndShell, (WORD)STF_SHL_INTERP, 0, 0L); return(fTrue); LScriptError: LoadString(hInst, IDS_ERROR, rgchBufTmpShort, cchpBufTmpShortMax); /* BLOCK */ { USHORT iszCur = 0; SZ szCur; LoadString(hInst, IDS_SHL_CMD_ERROR, rgchBufTmpLong, cchpBufTmpLongMax); Assert(rgsz != (RGSZ)NULL); EvalAssert((szCur = *rgsz) != (SZ)NULL); while (szCur != (SZ)NULL) { if (iszCur == 0) EvalAssert(SzStrCat(rgchBufTmpLong, "\n'") == rgchBufTmpLong); else EvalAssert(SzStrCat(rgchBufTmpLong, " ") == rgchBufTmpLong); if (strlen(rgchBufTmpLong) + strlen(szCur) > (cchpBufTmpLongMax - 7)) { Assert(strlen(rgchBufTmpLong) <= (cchpBufTmpLongMax - 5)); EvalAssert(SzStrCat(rgchBufTmpLong, "...") == rgchBufTmpLong); break; } else EvalAssert(SzStrCat(rgchBufTmpLong, szCur) == rgchBufTmpLong); szCur = rgsz[++iszCur]; } EvalAssert(SzStrCat(rgchBufTmpLong, "'") == rgchBufTmpLong); } MessageBox(hWndShell, rgchBufTmpLong, rgchBufTmpShort, MB_OK | MB_ICONHAND); LParseExitErr: if (rgsz != (RGSZ)NULL) EvalAssert(FFreeRgsz(rgsz)); return(fFalse); } /* ** Purpose: ** ?? ** Arguments: ** none ** Returns: ** none ** *************************************************************************/ BOOL FUIEntryPoint(HANDLE hInst, HWND hWnd, RGSZ rgsz, USHORT cItems) { BOOL fRetVal; ChkArg(hInst != (HANDLE)NULL, 1, fFalse); ChkArg(hWnd != (HWND)NULL, 2, fFalse); ChkArg(cItems >= 2, 4, fFalse); ChkArg(rgsz != (RGSZ)NULL && *rgsz != (SZ)NULL && *(rgsz + 1) != (SZ)NULL, 3, fFalse); if (CrcStringCompareI(*rgsz, "START") == crcEqual) { HANDLE hInstRes = hInst; // // See whether there is a library handle specified // if(rgsz[2] && rgsz[2][0]) { if(rgsz[2][0] != '|') { goto err; } hInstRes = LongToPtr(atol(rgsz[2] + 1)); } fRetVal = FDoDialog(*(rgsz + 1), hInstRes, hWnd); UpdateWindow(hWnd); return(fRetVal); } else if (CrcStringCompareI(*rgsz, "POP") == crcEqual) { fRetVal = FKillNDialogs((USHORT)atoi(*(rgsz + 1)), fFalse); UpdateWindow(hWnd); if (fRetVal) { PostMessage(hWndShell, (WORD)STF_SHL_INTERP, 0, 0L); } return(fRetVal); } err: LoadString(hInst, IDS_ERROR, rgchBufTmpShort, cchpBufTmpShortMax); LoadString(hInst, IDS_UI_CMD_ERROR, rgchBufTmpLong, cchpBufTmpLongMax); MessageBox(hWndShell, rgchBufTmpLong, rgchBufTmpShort, MB_OK | MB_ICONHAND); UpdateWindow(hWnd); return(fFalse); } /* ** Purpose: ** Pushes a new context onto the context stack and executes the ** specified shell section of an INF file. ** ** Arguments: ** ** Returns: ** ** *************************************************************************/ BOOL FShellCommand( RGSZ rgszArg ) { SZ szInfFileOrg; SZ szInfFile; SZ szSection; PINFCONTEXT pNewContext; PINFTEMPINFO pTempInfo; PINFPERMINFO pPermInfo; GRC grc = grcOkay; CHAR szName[cchlFullPathMax]; CHAR szFullName[cchlFullPathMax]; BOOL fCreated = fFalse; INT Line; INT cArg = 0; BOOL fOkay = fTrue; SZ szNamePart; SZ p; pLocalContext()->CurrentLine++; // // Guarantee that $ShellCode is set correctly to !SHELL_CODE_OK. // while (!FAddSymbolValueToSymTab( "$ShellCode", SzFindSymbolValueInSymTab("!G:SHELL_CODE_OK") )) { if (!FHandleOOM(hWndShell)) { return(fFalse); } } // // Allocate a new context // while ( !(pNewContext = (PINFCONTEXT)SAlloc( (CB)sizeof(INFCONTEXT) )) ) { if (!FHandleOOM(hWndShell)) { return(fFalse); } } if ( **rgszArg == '\0' ) { // // Null INF file, use the one being used by the current context. // pTempInfo = pLocalInfTempInfo(); pPermInfo = pLocalInfPermInfo(); szInfFileOrg = SzFindSymbolValueInSymTab("STF_CONTEXTINFNAME"); szInfFile = szInfFileOrg; } else { // // Determine if the desired INF file is already loaded. // szInfFileOrg = *rgszArg; PathToInfName( szInfFileOrg, szName ); GetFullPathName( szInfFileOrg, cchlFullPathMax, szFullName, &szNamePart ); szInfFile = szFullName; pPermInfo = NameToInfPermInfo( szName , fTrue ); if ( pPermInfo ) { pTempInfo = pInfTempInfo( pGlobalContext() ); while ( pTempInfo ) { if ( pTempInfo->pInfPermInfo == pPermInfo ) { break; } pTempInfo = pTempInfo->pNext; } } else { pTempInfo = NULL; } } rgszArg++; szSection = *rgszArg++; if ( pTempInfo ) { // // Reuse existing INF temp info. We just increment its reference count. // pNewContext->pInfTempInfo = pTempInfo; pTempInfo->cRef++; } else { // // We have to create a new INF temp info block for the INF. // fCreated = fTrue; while ( !(pNewContext->pInfTempInfo = (PINFTEMPINFO)CreateInfTempInfo( pPermInfo )) ) { if (!FHandleOOM(hWndShell)) { SFree(pNewContext); return(fFalse); } } // // Parse the INF file if we don't already have it parsed. // if ( pNewContext->pInfTempInfo->pParsedInf->MasterLineArray == NULL ) { while ((grc = GrcOpenInf(szInfFile, pNewContext->pInfTempInfo)) != grcOkay) { // // Could not open the INF file requested. // // If the INF file name given does not contain a path (i.e. // only the file part was given) then try to open the INF // with the same name in the directory of the global INF // file. If that fails, we try to open the INF in the // system directory. // szNamePart = szInfFileOrg; while ( p = strchr( szNamePart, '\\' ) ) { szNamePart = p+1; } strcpy( szName, szNamePart ); if ( strlen( szInfFileOrg ) == strlen( szName ) ) { szInfFile = SzFindSymbolValueInSymTab("!G:STF_CONTEXTINFNAME"); if ( szInfFile ) { strcpy( szFullName, szInfFile ); szInfFile = szFullName; szNamePart = szInfFile; while ( p = strchr( szNamePart, '\\' ) ) { szNamePart = p+1; } strcpy( szNamePart, szName ); grc = GrcOpenInf(szInfFile, pNewContext->pInfTempInfo); } if ( grc != grcOkay ) { // // Could not open that INF either, look for the INF in // the system directory // if ( GetSystemDirectory( szFullName, cchlFullPathMax ) ) { if ( szFullName[ strlen(szFullName) -1 ] != '\\' ) { strcat( szFullName, "\\" ); } strcat( szFullName, szName ); grc = GrcOpenInf(szFullName, pNewContext->pInfTempInfo); } } } if ( grc != grcOkay ) { FFreeInfTempInfo( pNewContext->pInfTempInfo ); SFree(pNewContext); while (!FAddSymbolValueToSymTab( "$ShellCode", SzFindSymbolValueInSymTab("!G:SHELL_CODE_NO_SUCH_INF") )) { if (!FHandleOOM(hWndShell)) { return(fFalse); } } Line = pLocalContext()->CurrentLine; goto NextLine; } } } } // // We now have the INF Temp section in memory. // Push the new context onto the stack // if ( !PushContext( pNewContext ) ) { FFreeInfTempInfo(pNewContext->pInfTempInfo ); SFree(pNewContext); //if ( pLocalContext() == pGlobalContext() ) { // return fFalse; //} else { while (!FAddSymbolValueToSymTab( "$ShellCode", SzFindSymbolValueInSymTab("!G:SHELL_CODE_ERROR") )) { if (!FHandleOOM(hWndShell)) { return(fFalse); } } Line = pLocalContext()->CurrentLine; goto NextLine; //} } pLocalContext()->szShlScriptSection = SzDupl( szSection ); // // Get the media description list if there is a media description section // if ( fCreated && !pLocalInfPermInfo()->psdleHead && FindFirstLineFromInfSection("Source Media Descriptions") != -1) { while ( fOkay && ((grc = GrcFillSrcDescrListFromInf()) != grcOkay)) { //if ( pLocalContext() == pGlobalContext() ) { // if (EercErrorHandler(hWndShell, grc, fTrue, szInfFile, 0, 0) // != eercRetry) { // PopContext(); // FFreeInfTempInfo(pNewContext->pInfTempInfo ); // FreeContext( pNewContext ); // return fFalse; // } //} PopContext(); FFreeInfTempInfo(pNewContext->pInfTempInfo ); FreeContext( pNewContext ); while (!FAddSymbolValueToSymTab( "$ShellCode", SzFindSymbolValueInSymTab("!G:SHELL_CODE_ERROR") )) { if (!FHandleOOM(hWndShell)) { return(fFalse); } } Line = pLocalContext()->CurrentLine; goto NextLine; } } while (!FAddSymbolValueToSymTab("STF_CONTEXTINFNAME", szInfFile)) if (!FHandleOOM(hWndShell)) { fOkay = fFalse; } // // Parameters are passed in the following symbols: // // $# - Number of parameters // // $0 - First parameter // $1 - Second parameter // // ... etc. // while ( fOkay && (*rgszArg != NULL) ) { sprintf( szName, "$%u", cArg ); while (!FAddSymbolValueToSymTab( szName, *rgszArg)) { if (!FHandleOOM(hWndShell)) { fOkay = fFalse; break; } } cArg++; rgszArg++; } if ( fOkay ) { sprintf( szName, "%u", cArg ); while (!FAddSymbolValueToSymTab( "$#", szName)) { if (!FHandleOOM(hWndShell)) { fOkay = fFalse; break; } } } if ( !fOkay ) { PopContext(); FFreeInfTempInfo(pNewContext->pInfTempInfo ); FreeContext( pNewContext ); return fFalse; } if ((Line = FindFirstLineFromInfSection(szSection)) == -1) { // // Pop new context off the stack // PopContext(); FFreeInfTempInfo( pNewContext->pInfTempInfo ); FreeContext( pNewContext ); //if ( pLocalContext() == pGlobalContext() ) { // return(fFalse); //} else { while (!FAddSymbolValueToSymTab( "$ShellCode", SzFindSymbolValueInSymTab("!G:SHELL_CODE_NO_SUCH_SECTION") )) { if (!FHandleOOM(hWndShell)) { return(fFalse); } } Line = pLocalContext()->CurrentLine; goto NextLine; //} } NextLine: // // Execute the specified Section in the new context // PostMessage(hWndShell, STF_SHL_INTERP, Line+1, 0L); return fTrue; } // // Storage for last return value // PSTR LastShellReturn; DWORD LastShellReturnSize; BOOL FShellReturn( RGSZ rgszArg ) { PINFCONTEXT pOldContext; INT cArg = 0; BOOL fOkay = fTrue; BOOL fGlobalOkay = fTrue; CHAR szName[cchlFullPathMax]; PSTR pwCur = LastShellReturn; UINT BufCnt = 0; UINT Temp; if ( pLocalContext() != pGlobalContext() ) { // // Deallocate the INF Temp Info. // FFreeInfTempInfo( pLocalInfTempInfo() ); // // Pop Context from stack // pOldContext = PopContext(); // // Destroy poped context // FreeContext( pOldContext ); // // Results are stored in the ReturnBuffer using // the format: "<$R0>\0<$R1>\0...<$Rn>\0\0" // if(LastShellReturnSize > 1 && LastShellReturn) { LastShellReturn[0] = '\0'; LastShellReturn[1] = '\0'; BufCnt = 0; } // // Results are returned in the following symbols: // // $R# - Number of returned results // // $R0 - First result // $R1 - Second result // // ... etc. // while( rgszArg[cArg] != NULL) { // // Add element to return Buffer and update pointer to next // region to place an element. Make sure that element doesn't // overflow the buffer // Temp = strlen(rgszArg[cArg]) + 1; if( fGlobalOkay && (BufCnt + Temp) < LastShellReturnSize) { strcat( pwCur, rgszArg[cArg] ); BufCnt += Temp; pwCur += Temp; *pwCur = '\0'; } else { // // If we can not add an element to the buffer then we don't // want to just skip it, so note a reminder to stop adding // items into the global return buffer // fGlobalOkay = FALSE; } sprintf( szName, "$R%u",cArg); while (!FAddSymbolValueToSymTab( szName, rgszArg[cArg])) { if (!FHandleOOM(hWndShell)) { fOkay = fFalse; break; } } if ( !fOkay ) { break; } cArg++; } if ( fOkay ) { sprintf( szName, "%u", cArg ); while (!FAddSymbolValueToSymTab( "$R#", szName)) { if (!FHandleOOM(hWndShell)) { fOkay = fFalse; break; } } } // // Resume execution at the next line of the parent context. // PostMessage(hWndShell, STF_SHL_INTERP, pLocalContext()->CurrentLine+1, 0L); } return fOkay; }