Source code of Windows XP (NT5)
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.

411 lines
11 KiB

  1. /************************************************************************
  2. * @doc SHROOM EXTERNAL API
  3. *
  4. * TITLE: CIMAIN.CPP
  5. *
  6. * OWNER: johnrush (John C. Rush)
  7. *
  8. * DATE CREATED: January 29, 1997
  9. *
  10. * DESCRIPTION:
  11. * This is the main file for the Command Interpreter.
  12. *
  13. *********************************************************************/
  14. #include <mvopsys.h>
  15. // Global debug variable
  16. #ifdef _DEBUG
  17. static char s_aszModule[] = __FILE__;
  18. #endif
  19. // Include Files
  20. #include <windows.h>
  21. #include <orkin.h>
  22. #include <common.h>
  23. #include <itdb.h>
  24. #include "cmdint.h"
  25. #include "ciutil.h"
  26. #include "cierror.h"
  27. CITCmdInt::~CITCmdInt ()
  28. {
  29. Dispose();
  30. }
  31. /************************************************************************
  32. * @method HRESULT WINAPI | IITCmdInt | Initiate |
  33. * Initializes the command interpreter. Should be called before any other
  34. * methods for this class.
  35. *
  36. * @parm IITSvMgr | *piitsv | Pointer to the instance of the service manager.
  37. *
  38. * @rvalue E_OUTOFMEMORY | Resources for command interpreter couldn't be allocated.
  39. * @rvalue S_OK | Command interpreter was successfull initialized
  40. *
  41. * @xref <om.Dispose>
  42. ************************************************************************/
  43. HRESULT WINAPI CITCmdInt::Initiate (IITSvMgr *piitsv)
  44. {
  45. if (m_fInit)
  46. return E_ALREADYINIT;
  47. HRESULT hr;
  48. (m_piitsv = piitsv)->AddRef();
  49. if (SUCCEEDED(hr = piitsv->GetBuildObject
  50. (L"", IID_IITDatabase, (void **)&m_piitdb))
  51. &&
  52. SUCCEEDED(hr = (NULL == (m_pBlockMgr =
  53. BlockInitiate ((DWORD)65500, 0, 0, 0)) ? E_OUTOFMEMORY : S_OK))
  54. )
  55. {
  56. MEMSET(m_wstrHelper, 0, sizeof(m_wstrHelper));
  57. m_dwMaxInstance = 0;
  58. m_fInit = TRUE;
  59. }
  60. return hr;
  61. } /* CITCmdInt::Initiate */
  62. /************************************************************************
  63. * @method HRESULT WINAPI | IITCmdInt | Dispose |
  64. * Frees any resources allocated by the command interpreter. Should be
  65. * the last method called.
  66. *
  67. *
  68. * @rvalue S_OK | All resources were freed successfully
  69. *
  70. * @xref <om.Initiate>
  71. ************************************************************************/
  72. HRESULT WINAPI CITCmdInt::Dispose (void)
  73. {
  74. if (FALSE == m_fInit)
  75. return E_NOTINIT;
  76. m_piitsv->Release();
  77. m_piitdb->Release();
  78. BlockFree(m_pBlockMgr);
  79. m_fInit = FALSE;
  80. return S_OK;
  81. } /* CITCmdInt::Dispose */
  82. /************************************************************************
  83. * @method HRESULT WINAPI | IITCmdInt | LoadFromStream |
  84. * Loads and parses the build configuration information from the given input
  85. * stream.
  86. *
  87. * @rvalue S_OK | The configuration stream was loaded successfully
  88. * @rvalue E_OUTOFMEMORY | Not enough memory was available to parse the stream
  89. * @rvalue Other | Another I/O condition prevents the processing of the stream
  90. *
  91. * @xref <om.Initiate>
  92. *
  93. * @comm During the parsing of the stream, various warnings may occur as a result
  94. * of authoring error, and these are written to the log file. In this case, the
  95. * method still returns S_OK if none of the errors was fatal.
  96. ************************************************************************/
  97. HRESULT WINAPI CITCmdInt::LoadFromStream
  98. (IStream *pStream, //@parm Pointer to the input <p IStream>
  99. IStream *pLogStream) //@parm Pointer to the log stream <p IStream>
  100. {
  101. HRESULT hr;
  102. if (FALSE == m_fInit)
  103. return E_NOTINIT;
  104. m_piistmLog = pLogStream;
  105. m_errc.iLine = 0;
  106. m_errc.ep = epLine;
  107. m_ConfigParser.SetStream(pStream);
  108. hr = ParseConfigStream();
  109. m_piistmLog = NULL;
  110. return hr;
  111. } /* CITCmdInt::LoadFromStream */
  112. HRESULT WINAPI CITCmdInt::ParseBogusSz(LPWSTR)
  113. {
  114. return S_OK;
  115. }
  116. HRESULT WINAPI CITCmdInt::ParseIndexSz(LPWSTR wstrLine)
  117. {
  118. ITASSERT(wstrLine);
  119. KEYVAL *pKeyValue;
  120. HRESULT hr = ParseKeyAndValue(m_pBlockMgr, wstrLine, &pKeyValue);
  121. if (FAILED(hr))
  122. return hr;
  123. // Verify the format
  124. if (!pKeyValue->vaValue.dwArgc)
  125. // TODO: Issue warning message
  126. return E_INVALIDARG;
  127. CLSID clsid;
  128. hr = CLSIDFromProgID((LPCWSTR)pKeyValue->vaValue.Argv[0], &clsid);
  129. IITBuildCollect *pInterface = NULL;
  130. if (SUCCEEDED(hr) && SUCCEEDED
  131. (hr = m_piitsv->CreateBuildObject(pKeyValue->pwstrKey, clsid)))
  132. {
  133. if(FAILED(hr = m_piitsv->GetBuildObject
  134. (pKeyValue->pwstrKey, IID_IITBuildCollect, (void**)&pInterface))) {
  135. ITASSERT(0);
  136. }
  137. }
  138. if(SUCCEEDED(hr))
  139. {
  140. // Skip the first 2 (required params)
  141. DWORD dwArgc = pKeyValue->vaValue.dwArgc;
  142. if((int)(dwArgc -= 2) < 0)
  143. dwArgc = 0;
  144. VARARG vaNew = {0};
  145. vaNew.dwArgc = dwArgc;
  146. LPWSTR *ppwstr = (LPWSTR *)pKeyValue->vaValue.Argv + 2;
  147. for(DWORD loop = 0; loop < dwArgc; ++loop, ++ppwstr)
  148. {
  149. *(vaNew.Argv + loop) = *ppwstr;
  150. }
  151. hr = pInterface->SetConfigInfo(m_piitdb, vaNew);
  152. }
  153. if(SUCCEEDED(hr) && (LPWSTR)pKeyValue->vaValue.Argv[1]
  154. && *(LPWSTR)pKeyValue->vaValue.Argv[1])
  155. {
  156. for(DWORD loop = 0; loop <= m_dwMaxInstance; ++loop)
  157. {
  158. if((m_wstrHelper + loop)->pwstrName &&
  159. !WSTRCMP ((m_wstrHelper+loop)->pwstrName,
  160. (LPWSTR)pKeyValue->vaValue.Argv[1]))
  161. {
  162. tagHELPERSTUFF *pInfo = (m_wstrHelper + loop);
  163. hr = pInterface->InitHelperInstance
  164. (loop, m_piitdb, pInfo->dwCodePage, pInfo->lcid,
  165. pInfo->kvDword, pInfo->kvString);
  166. break;
  167. }
  168. }
  169. }
  170. if(pInterface)
  171. pInterface->Release();
  172. return hr;
  173. }
  174. HRESULT WINAPI CITCmdInt::ParseHelperSz(LPWSTR wstrLine)
  175. {
  176. int iLineCount;
  177. KEYVAL *pKeyValue, *pkvDword, *pkvString;
  178. CLSID clsid;
  179. DWORD dwCodePage;
  180. LCID lcid;
  181. // The +3 skips to 'HO:' prefix
  182. HRESULT hr = ParseKeyAndValue(m_pBlockMgr, wstrLine, &pKeyValue);
  183. if (FAILED(hr))
  184. return hr;
  185. if (!WSTRICMP(L"VIProgId", pKeyValue->pwstrKey))
  186. {
  187. if(pKeyValue->vaValue.dwArgc != 1)
  188. return SetErrReturn(E_INVALIDARG);
  189. hr = CLSIDFromProgID((LPCWSTR)pKeyValue->vaValue.Argv[0], &clsid);
  190. }
  191. else hr = E_FAIL;
  192. if (SUCCEEDED(hr))
  193. {
  194. m_ConfigParser.GetLogicalLine(&wstrLine, &iLineCount);
  195. m_errc.iLine += iLineCount;
  196. hr = ParseKeyAndValue(m_pBlockMgr, wstrLine, &pKeyValue);
  197. if (!WSTRICMP(L"CodePage", pKeyValue->pwstrKey))
  198. {
  199. if(pKeyValue->vaValue.dwArgc != 1)
  200. return E_INVALIDARG;
  201. dwCodePage = _wtol((LPWSTR)pKeyValue->vaValue.Argv[0]);
  202. }
  203. else hr = E_FAIL;
  204. }
  205. if (SUCCEEDED(hr))
  206. {
  207. m_ConfigParser.GetLogicalLine(&wstrLine, &iLineCount);
  208. m_errc.iLine += iLineCount;
  209. hr = ParseKeyAndValue(m_pBlockMgr, wstrLine, &pKeyValue);
  210. if (!WSTRICMP(L"Locale", pKeyValue->pwstrKey))
  211. {
  212. if(pKeyValue->vaValue.dwArgc != 1)
  213. return E_INVALIDARG;
  214. lcid = _wtol((LPWSTR)pKeyValue->vaValue.Argv[0]);
  215. }
  216. else hr = E_FAIL;
  217. }
  218. if (SUCCEEDED(hr))
  219. {
  220. m_ConfigParser.GetLogicalLine(&wstrLine, &iLineCount);
  221. m_errc.iLine += iLineCount;
  222. hr = ParseKeyAndValue(m_pBlockMgr, wstrLine, &pKeyValue);
  223. if (SUCCEEDED(hr) && !WSTRICMP(L"DWORD", pKeyValue->pwstrKey))
  224. {
  225. pkvDword = pKeyValue;
  226. LPWSTR *ppwstr = (LPWSTR *)pKeyValue->vaValue.Argv;
  227. DWORD *pdwCur = (DWORD *)ppwstr;
  228. for (DWORD loop = 0; loop < pKeyValue->vaValue.dwArgc; ++loop)
  229. {
  230. *pdwCur++ = _wtol(*ppwstr++);
  231. }
  232. m_ConfigParser.GetLogicalLine(&wstrLine, &iLineCount);
  233. m_errc.iLine += iLineCount;
  234. (void)ParseKeyAndValue(m_pBlockMgr, wstrLine, &pKeyValue);
  235. }
  236. if (SUCCEEDED(hr) && !WSTRICMP(L"String", pKeyValue->pwstrKey))
  237. {
  238. pkvString = pKeyValue;
  239. }
  240. }
  241. DWORD dwInstance;
  242. if (SUCCEEDED(hr)
  243. && SUCCEEDED(hr = m_piitdb->CreateObject(clsid, &dwInstance)))
  244. {
  245. ITASSERT(dwInstance <= MAX_HELPER_INSTANCE);
  246. if(dwInstance > m_dwMaxInstance)
  247. m_dwMaxInstance = dwInstance;
  248. if(NULL == (m_wstrHelper[dwInstance].pwstrName =
  249. (LPWSTR)BlockCopy(m_pBlockMgr,
  250. (LPB)(m_wstrSection + 3),
  251. (DWORD) WSTRCB(m_wstrSection + 3), 0)))
  252. {
  253. SetErrCode(&hr, E_OUTOFMEMORY);
  254. }
  255. m_wstrHelper[dwInstance].dwCodePage = dwCodePage;
  256. m_wstrHelper[dwInstance].lcid = lcid;
  257. m_wstrHelper[dwInstance].kvDword = pkvDword->vaValue;
  258. m_wstrHelper[dwInstance].kvString = pkvString->vaValue;
  259. }
  260. return hr;
  261. } /* ParseHelperSz */
  262. HRESULT WINAPI CITCmdInt::ParseConfigStream(void)
  263. {
  264. LPWSTR pwstrLine;
  265. BOOL fParsingHelper = TRUE;
  266. PFPARSE2 pfparse;
  267. int iLineCount;
  268. for(;;)
  269. {
  270. if (S_OK != m_ConfigParser.GetLogicalLine
  271. (&pwstrLine, &iLineCount))
  272. {
  273. if (fParsingHelper)
  274. {
  275. m_ConfigParser.Reset();
  276. m_errc.iLine = 0;
  277. fParsingHelper = FALSE;
  278. continue;
  279. }
  280. else
  281. break;
  282. }
  283. m_errc.iLine += iLineCount;
  284. if(S_OK == IsSectionHeading(pwstrLine))
  285. {
  286. (void)GetFunctionFromSection(pwstrLine + 1, (void **)&pfparse);
  287. WSTRCPY(m_wstrSection, pwstrLine + 1);
  288. continue;
  289. }
  290. if (fParsingHelper)
  291. {
  292. if (ParseHelperSz == pfparse)
  293. (void)ParseHelperSz(pwstrLine);
  294. } else if(ParseIndexSz == pfparse)
  295. (void)ParseIndexSz(pwstrLine);
  296. }
  297. return S_OK;
  298. } /* ParseConfigStream */
  299. struct tagSection
  300. {
  301. LPCWSTR szName;
  302. PFPARSE2 pfparse;
  303. };
  304. HRESULT WINAPI CITCmdInt::GetFunctionFromSection
  305. (LPWSTR pwstrSection, void **ppvoid)
  306. {
  307. ITASSERT(pwstrSection && ppvoid);
  308. PFPARSE2 *ppfparse = (PFPARSE2 *)ppvoid;
  309. const int NUM_RECOGNIZED_SECTIONS = 3;
  310. const tagSection rgSection[NUM_RECOGNIZED_SECTIONS] =
  311. {
  312. { L"OPTIONS", CITCmdInt::ParseBogusSz },
  313. { L"INDEX", CITCmdInt::ParseIndexSz },
  314. { L"HO:", CITCmdInt::ParseHelperSz },
  315. };
  316. *ppfparse = NULL;
  317. for (int loop = 0; loop < NUM_RECOGNIZED_SECTIONS; ++loop)
  318. {
  319. if (!WSTRNICMP (rgSection[loop].szName, pwstrSection,
  320. WSTRLEN(rgSection[loop].szName)))
  321. {
  322. *ppfparse = rgSection[loop].pfparse;
  323. break;
  324. }
  325. }
  326. if (NULL == *ppfparse)
  327. *ppfparse = ParseBogusSz;
  328. return S_OK;
  329. } /* GetFunctionFromSection */
  330. HRESULT WINAPI CITCmdInt::IsSectionHeading(LPWSTR pwstrLine)
  331. {
  332. ITASSERT(pwstrLine);
  333. HRESULT hr = S_FALSE;
  334. if (*pwstrLine == '[')
  335. {
  336. LPWSTR pch = pwstrLine + WSTRLEN(pwstrLine) - 1;
  337. /*****************************************************
  338. * IS SECTION HEADING TERMINATED WITH CLOSING BRACKET?
  339. *****************************************************/
  340. if (*pch != ']') // *** NO! ***
  341. {
  342. m_errc.errCode = CIERR_SectionHeadingSyntax;
  343. ReportError (m_piistmLog, m_errc);
  344. }
  345. else
  346. { // *** YES! ***
  347. *pch = '\0';
  348. pch = pwstrLine + 1;
  349. pch = SkipWhitespace(pch);
  350. StripTrailingBlanks(pch);
  351. hr = S_OK;
  352. }
  353. }
  354. return hr;
  355. } /* IsSectionHeading */