/************************************************************************ * @doc SHROOM EXTERNAL API * * TITLE: CIMAIN.CPP * * OWNER: johnrush (John C. Rush) * * DATE CREATED: January 29, 1997 * * DESCRIPTION: * This is the main file for the Command Interpreter. * *********************************************************************/ #include // Global debug variable #ifdef _DEBUG static char s_aszModule[] = __FILE__; #endif // Include Files #include #include #include #include #include "cmdint.h" #include "ciutil.h" #include "cierror.h" CITCmdInt::~CITCmdInt () { Dispose(); } /************************************************************************ * @method HRESULT WINAPI | IITCmdInt | Initiate | * Initializes the command interpreter. Should be called before any other * methods for this class. * * @parm IITSvMgr | *piitsv | Pointer to the instance of the service manager. * * @rvalue E_OUTOFMEMORY | Resources for command interpreter couldn't be allocated. * @rvalue S_OK | Command interpreter was successfull initialized * * @xref ************************************************************************/ HRESULT WINAPI CITCmdInt::Initiate (IITSvMgr *piitsv) { if (m_fInit) return E_ALREADYINIT; HRESULT hr; (m_piitsv = piitsv)->AddRef(); if (SUCCEEDED(hr = piitsv->GetBuildObject (L"", IID_IITDatabase, (void **)&m_piitdb)) && SUCCEEDED(hr = (NULL == (m_pBlockMgr = BlockInitiate ((DWORD)65500, 0, 0, 0)) ? E_OUTOFMEMORY : S_OK)) ) { MEMSET(m_wstrHelper, 0, sizeof(m_wstrHelper)); m_dwMaxInstance = 0; m_fInit = TRUE; } return hr; } /* CITCmdInt::Initiate */ /************************************************************************ * @method HRESULT WINAPI | IITCmdInt | Dispose | * Frees any resources allocated by the command interpreter. Should be * the last method called. * * * @rvalue S_OK | All resources were freed successfully * * @xref ************************************************************************/ HRESULT WINAPI CITCmdInt::Dispose (void) { if (FALSE == m_fInit) return E_NOTINIT; m_piitsv->Release(); m_piitdb->Release(); BlockFree(m_pBlockMgr); m_fInit = FALSE; return S_OK; } /* CITCmdInt::Dispose */ /************************************************************************ * @method HRESULT WINAPI | IITCmdInt | LoadFromStream | * Loads and parses the build configuration information from the given input * stream. * * @rvalue S_OK | The configuration stream was loaded successfully * @rvalue E_OUTOFMEMORY | Not enough memory was available to parse the stream * @rvalue Other | Another I/O condition prevents the processing of the stream * * @xref * * @comm During the parsing of the stream, various warnings may occur as a result * of authoring error, and these are written to the log file. In this case, the * method still returns S_OK if none of the errors was fatal. ************************************************************************/ HRESULT WINAPI CITCmdInt::LoadFromStream (IStream *pStream, //@parm Pointer to the input

IStream *pLogStream) //@parm Pointer to the log stream

{ HRESULT hr; if (FALSE == m_fInit) return E_NOTINIT; m_piistmLog = pLogStream; m_errc.iLine = 0; m_errc.ep = epLine; m_ConfigParser.SetStream(pStream); hr = ParseConfigStream(); m_piistmLog = NULL; return hr; } /* CITCmdInt::LoadFromStream */ HRESULT WINAPI CITCmdInt::ParseBogusSz(LPWSTR) { return S_OK; } HRESULT WINAPI CITCmdInt::ParseIndexSz(LPWSTR wstrLine) { ITASSERT(wstrLine); KEYVAL *pKeyValue; HRESULT hr = ParseKeyAndValue(m_pBlockMgr, wstrLine, &pKeyValue); if (FAILED(hr)) return hr; // Verify the format if (!pKeyValue->vaValue.dwArgc) // TODO: Issue warning message return E_INVALIDARG; CLSID clsid; hr = CLSIDFromProgID((LPCWSTR)pKeyValue->vaValue.Argv[0], &clsid); IITBuildCollect *pInterface = NULL; if (SUCCEEDED(hr) && SUCCEEDED (hr = m_piitsv->CreateBuildObject(pKeyValue->pwstrKey, clsid))) { if(FAILED(hr = m_piitsv->GetBuildObject (pKeyValue->pwstrKey, IID_IITBuildCollect, (void**)&pInterface))) { ITASSERT(0); } } if(SUCCEEDED(hr)) { // Skip the first 2 (required params) DWORD dwArgc = pKeyValue->vaValue.dwArgc; if((int)(dwArgc -= 2) < 0) dwArgc = 0; VARARG vaNew = {0}; vaNew.dwArgc = dwArgc; LPWSTR *ppwstr = (LPWSTR *)pKeyValue->vaValue.Argv + 2; for(DWORD loop = 0; loop < dwArgc; ++loop, ++ppwstr) { *(vaNew.Argv + loop) = *ppwstr; } hr = pInterface->SetConfigInfo(m_piitdb, vaNew); } if(SUCCEEDED(hr) && (LPWSTR)pKeyValue->vaValue.Argv[1] && *(LPWSTR)pKeyValue->vaValue.Argv[1]) { for(DWORD loop = 0; loop <= m_dwMaxInstance; ++loop) { if((m_wstrHelper + loop)->pwstrName && !WSTRCMP ((m_wstrHelper+loop)->pwstrName, (LPWSTR)pKeyValue->vaValue.Argv[1])) { tagHELPERSTUFF *pInfo = (m_wstrHelper + loop); hr = pInterface->InitHelperInstance (loop, m_piitdb, pInfo->dwCodePage, pInfo->lcid, pInfo->kvDword, pInfo->kvString); break; } } } if(pInterface) pInterface->Release(); return hr; } HRESULT WINAPI CITCmdInt::ParseHelperSz(LPWSTR wstrLine) { int iLineCount; KEYVAL *pKeyValue, *pkvDword, *pkvString; CLSID clsid; DWORD dwCodePage; LCID lcid; // The +3 skips to 'HO:' prefix HRESULT hr = ParseKeyAndValue(m_pBlockMgr, wstrLine, &pKeyValue); if (FAILED(hr)) return hr; if (!WSTRICMP(L"VIProgId", pKeyValue->pwstrKey)) { if(pKeyValue->vaValue.dwArgc != 1) return SetErrReturn(E_INVALIDARG); hr = CLSIDFromProgID((LPCWSTR)pKeyValue->vaValue.Argv[0], &clsid); } else hr = E_FAIL; if (SUCCEEDED(hr)) { m_ConfigParser.GetLogicalLine(&wstrLine, &iLineCount); m_errc.iLine += iLineCount; hr = ParseKeyAndValue(m_pBlockMgr, wstrLine, &pKeyValue); if (!WSTRICMP(L"CodePage", pKeyValue->pwstrKey)) { if(pKeyValue->vaValue.dwArgc != 1) return E_INVALIDARG; dwCodePage = _wtol((LPWSTR)pKeyValue->vaValue.Argv[0]); } else hr = E_FAIL; } if (SUCCEEDED(hr)) { m_ConfigParser.GetLogicalLine(&wstrLine, &iLineCount); m_errc.iLine += iLineCount; hr = ParseKeyAndValue(m_pBlockMgr, wstrLine, &pKeyValue); if (!WSTRICMP(L"Locale", pKeyValue->pwstrKey)) { if(pKeyValue->vaValue.dwArgc != 1) return E_INVALIDARG; lcid = _wtol((LPWSTR)pKeyValue->vaValue.Argv[0]); } else hr = E_FAIL; } if (SUCCEEDED(hr)) { m_ConfigParser.GetLogicalLine(&wstrLine, &iLineCount); m_errc.iLine += iLineCount; hr = ParseKeyAndValue(m_pBlockMgr, wstrLine, &pKeyValue); if (SUCCEEDED(hr) && !WSTRICMP(L"DWORD", pKeyValue->pwstrKey)) { pkvDword = pKeyValue; LPWSTR *ppwstr = (LPWSTR *)pKeyValue->vaValue.Argv; DWORD *pdwCur = (DWORD *)ppwstr; for (DWORD loop = 0; loop < pKeyValue->vaValue.dwArgc; ++loop) { *pdwCur++ = _wtol(*ppwstr++); } m_ConfigParser.GetLogicalLine(&wstrLine, &iLineCount); m_errc.iLine += iLineCount; (void)ParseKeyAndValue(m_pBlockMgr, wstrLine, &pKeyValue); } if (SUCCEEDED(hr) && !WSTRICMP(L"String", pKeyValue->pwstrKey)) { pkvString = pKeyValue; } } DWORD dwInstance; if (SUCCEEDED(hr) && SUCCEEDED(hr = m_piitdb->CreateObject(clsid, &dwInstance))) { ITASSERT(dwInstance <= MAX_HELPER_INSTANCE); if(dwInstance > m_dwMaxInstance) m_dwMaxInstance = dwInstance; if(NULL == (m_wstrHelper[dwInstance].pwstrName = (LPWSTR)BlockCopy(m_pBlockMgr, (LPB)(m_wstrSection + 3), (DWORD) WSTRCB(m_wstrSection + 3), 0))) { SetErrCode(&hr, E_OUTOFMEMORY); } m_wstrHelper[dwInstance].dwCodePage = dwCodePage; m_wstrHelper[dwInstance].lcid = lcid; m_wstrHelper[dwInstance].kvDword = pkvDword->vaValue; m_wstrHelper[dwInstance].kvString = pkvString->vaValue; } return hr; } /* ParseHelperSz */ HRESULT WINAPI CITCmdInt::ParseConfigStream(void) { LPWSTR pwstrLine; BOOL fParsingHelper = TRUE; PFPARSE2 pfparse; int iLineCount; for(;;) { if (S_OK != m_ConfigParser.GetLogicalLine (&pwstrLine, &iLineCount)) { if (fParsingHelper) { m_ConfigParser.Reset(); m_errc.iLine = 0; fParsingHelper = FALSE; continue; } else break; } m_errc.iLine += iLineCount; if(S_OK == IsSectionHeading(pwstrLine)) { (void)GetFunctionFromSection(pwstrLine + 1, (void **)&pfparse); WSTRCPY(m_wstrSection, pwstrLine + 1); continue; } if (fParsingHelper) { if (ParseHelperSz == pfparse) (void)ParseHelperSz(pwstrLine); } else if(ParseIndexSz == pfparse) (void)ParseIndexSz(pwstrLine); } return S_OK; } /* ParseConfigStream */ struct tagSection { LPCWSTR szName; PFPARSE2 pfparse; }; HRESULT WINAPI CITCmdInt::GetFunctionFromSection (LPWSTR pwstrSection, void **ppvoid) { ITASSERT(pwstrSection && ppvoid); PFPARSE2 *ppfparse = (PFPARSE2 *)ppvoid; const int NUM_RECOGNIZED_SECTIONS = 3; const tagSection rgSection[NUM_RECOGNIZED_SECTIONS] = { { L"OPTIONS", CITCmdInt::ParseBogusSz }, { L"INDEX", CITCmdInt::ParseIndexSz }, { L"HO:", CITCmdInt::ParseHelperSz }, }; *ppfparse = NULL; for (int loop = 0; loop < NUM_RECOGNIZED_SECTIONS; ++loop) { if (!WSTRNICMP (rgSection[loop].szName, pwstrSection, WSTRLEN(rgSection[loop].szName))) { *ppfparse = rgSection[loop].pfparse; break; } } if (NULL == *ppfparse) *ppfparse = ParseBogusSz; return S_OK; } /* GetFunctionFromSection */ HRESULT WINAPI CITCmdInt::IsSectionHeading(LPWSTR pwstrLine) { ITASSERT(pwstrLine); HRESULT hr = S_FALSE; if (*pwstrLine == '[') { LPWSTR pch = pwstrLine + WSTRLEN(pwstrLine) - 1; /***************************************************** * IS SECTION HEADING TERMINATED WITH CLOSING BRACKET? *****************************************************/ if (*pch != ']') // *** NO! *** { m_errc.errCode = CIERR_SectionHeadingSyntax; ReportError (m_piistmLog, m_errc); } else { // *** YES! *** *pch = '\0'; pch = pwstrLine + 1; pch = SkipWhitespace(pch); StripTrailingBlanks(pch); hr = S_OK; } } return hr; } /* IsSectionHeading */