Leaked source code of windows server 2003
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.

1059 lines
24 KiB

  1. // This is a part of the Active Template Library.
  2. // Copyright (C) Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Active Template Library Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Active Template Library product.
  10. ///////////////////////////////////////
  11. #define RET_ON_ERROR(x) \
  12. if (FAILED(hr = x))\
  13. return hr;
  14. ///////////////////////////////////////
  15. #define BREAK_ON_ERROR(x) \
  16. if (FAILED(hr = x))\
  17. break;
  18. ///////////////////////////////////////
  19. #ifdef _DEBUG
  20. #define REPORT_ERROR(name, func) \
  21. if (func != ERROR_SUCCESS)\
  22. ATLTRACE(_T("NON CRITICAL ERROR : %s failed\n"), name);
  23. #define REG_TRACE_RECOVER() \
  24. if (!bRecover) \
  25. ATLTRACE(_T("Opened Key %s\n"), szToken); \
  26. else \
  27. ATLTRACE(_T("Ignoring Open key on %s : In Recovery mode\n"), szToken);
  28. #else //!_DEBUG
  29. #define REG_TRACE_RECOVER()
  30. #define REPORT_ERROR(name, func) \
  31. func;
  32. #endif //_DEBUG
  33. ///////////////////////////////////////
  34. //
  35. // this value has been changed to 256 bytes for sdoias
  36. // because on handling sdopipeline.rgs stack overflow takes
  37. // places due to much stack allocation on recursion
  38. // MKarki - 4/25/98
  39. //
  40. #define MAX_TYPE MAX_VALUE
  41. //#define MAX_VALUE 4096
  42. #define MAX_VALUE 256
  43. #ifndef ATL_NO_NAMESPACE
  44. namespace ATL
  45. {
  46. #endif
  47. class CParseBuffer
  48. {
  49. public:
  50. int nPos;
  51. int nSize;
  52. LPTSTR p;
  53. CParseBuffer(int nInitial);
  54. ~CParseBuffer() {CoTaskMemFree(p);}
  55. BOOL AddChar(TCHAR ch);
  56. BOOL AddString(LPCOLESTR lpsz);
  57. LPTSTR Detach();
  58. };
  59. LPCTSTR rgszNeverDelete[] = //Component Catagories
  60. {
  61. _T("CLSID"), _T("TYPELIB")
  62. };
  63. const int cbNeverDelete = sizeof(rgszNeverDelete) / sizeof(LPCTSTR*);
  64. static LPTSTR StrChr(LPTSTR lpsz, TCHAR ch)
  65. {
  66. LPTSTR p = NULL;
  67. while (*lpsz)
  68. {
  69. if (*lpsz == ch)
  70. {
  71. p = lpsz;
  72. break;
  73. }
  74. lpsz = CharNext(lpsz);
  75. }
  76. return p;
  77. }
  78. static HKEY WINAPI HKeyFromString(LPTSTR szToken)
  79. {
  80. struct keymap
  81. {
  82. LPCTSTR lpsz;
  83. HKEY hkey;
  84. };
  85. static const keymap map[] = {
  86. {_T("HKCR"), HKEY_CLASSES_ROOT},
  87. {_T("HKCU"), HKEY_CURRENT_USER},
  88. {_T("HKLM"), HKEY_LOCAL_MACHINE},
  89. {_T("HKU"), HKEY_USERS},
  90. {_T("HKPD"), HKEY_PERFORMANCE_DATA},
  91. {_T("HKDD"), HKEY_DYN_DATA},
  92. {_T("HKCC"), HKEY_CURRENT_CONFIG},
  93. {_T("HKEY_CLASSES_ROOT"), HKEY_CLASSES_ROOT},
  94. {_T("HKEY_CURRENT_USER"), HKEY_CURRENT_USER},
  95. {_T("HKEY_LOCAL_MACHINE"), HKEY_LOCAL_MACHINE},
  96. {_T("HKEY_USERS"), HKEY_USERS},
  97. {_T("HKEY_PERFORMANCE_DATA"), HKEY_PERFORMANCE_DATA},
  98. {_T("HKEY_DYN_DATA"), HKEY_DYN_DATA},
  99. {_T("HKEY_CURRENT_CONFIG"), HKEY_CURRENT_CONFIG}
  100. };
  101. for (int i=0;i<sizeof(map)/sizeof(keymap);i++)
  102. {
  103. if (!lstrcmpi(szToken, map[i].lpsz))
  104. return map[i].hkey;
  105. }
  106. return NULL;
  107. }
  108. static HKEY HKeyFromCompoundString(LPTSTR szToken, LPTSTR& szTail)
  109. {
  110. if (NULL == szToken)
  111. return NULL;
  112. LPTSTR lpsz = StrChr(szToken, chDirSep);
  113. if (NULL == lpsz)
  114. return NULL;
  115. szTail = CharNext(lpsz);
  116. *lpsz = chEOS;
  117. HKEY hKey = HKeyFromString(szToken);
  118. *lpsz = chDirSep;
  119. return hKey;
  120. }
  121. static LPVOID QueryValue(HKEY hKey, LPCTSTR szValName, DWORD& dwType)
  122. {
  123. DWORD dwCount = 0;
  124. if (RegQueryValueEx(hKey, szValName, NULL, &dwType, NULL, &dwCount) != ERROR_SUCCESS)
  125. {
  126. ATLTRACE(_T("RegQueryValueEx failed for Value %s\n"), szValName);
  127. return NULL;
  128. }
  129. if (!dwCount)
  130. {
  131. ATLTRACE(_T("RegQueryValueEx returned 0 bytes\n"));
  132. return NULL;
  133. }
  134. // Not going to Check for fail on CoTaskMemAlloc & RegQueryValueEx as NULL
  135. // will be returned regardless if anything failed
  136. LPVOID pData = CoTaskMemAlloc(dwCount);
  137. RegQueryValueEx(hKey, szValName, NULL, &dwType, (LPBYTE) pData, &dwCount);
  138. return pData;
  139. }
  140. /////////////////////////////////////////////////////////////////////////////
  141. //
  142. HRESULT CRegParser::GenerateError(UINT nID)
  143. {
  144. // m_re.m_nID = nID;
  145. // m_re.m_cLines = m_cLines;
  146. return DISP_E_EXCEPTION;
  147. }
  148. CRegParser::CRegParser(CRegObject* pRegObj)
  149. {
  150. m_pRegObj = pRegObj;
  151. m_pchCur = NULL;
  152. m_cLines = 1;
  153. }
  154. BOOL CRegParser::IsSpace(TCHAR ch)
  155. {
  156. switch (ch)
  157. {
  158. case chSpace:
  159. case chTab:
  160. case chCR:
  161. case chLF:
  162. return TRUE;
  163. }
  164. return FALSE;
  165. }
  166. void CRegParser::IncrementLinePos()
  167. {
  168. m_pchCur = CharNext(m_pchCur);
  169. if (chLF == *m_pchCur)
  170. IncrementLineCount();
  171. }
  172. void CRegParser::SkipWhiteSpace()
  173. {
  174. while(IsSpace(*m_pchCur))
  175. IncrementLinePos();
  176. }
  177. HRESULT CRegParser::NextToken(LPTSTR szToken)
  178. {
  179. USES_CONVERSION;
  180. UINT ichToken = 0;
  181. SkipWhiteSpace();
  182. // NextToken cannot be called at EOS
  183. if (chEOS == *m_pchCur)
  184. return GenerateError(E_ATL_UNEXPECTED_EOS);
  185. // handle quoted value / key
  186. if (chQuote == *m_pchCur)
  187. {
  188. LPCTSTR szOrig = szToken;
  189. IncrementLinePos(); // Skip Quote
  190. while (chEOS != *m_pchCur && !EndOfVar())
  191. {
  192. if (chQuote == *m_pchCur) // If it is a quote that means we must skip it
  193. IncrementLinePos(); // as it has been escaped
  194. LPTSTR pchPrev = m_pchCur;
  195. IncrementLinePos();
  196. if (szToken + sizeof(WORD) >= MAX_VALUE + szOrig)
  197. return GenerateError(E_ATL_VALUE_TOO_LARGE);
  198. for (int i = 0; pchPrev+i < m_pchCur; i++, szToken++)
  199. *szToken = *(pchPrev+i);
  200. }
  201. if (chEOS == *m_pchCur)
  202. {
  203. ATLTRACE(_T("NextToken : Unexpected End of File\n"));
  204. return GenerateError(E_ATL_UNEXPECTED_EOS);
  205. }
  206. *szToken = chEOS;
  207. IncrementLinePos(); // Skip end quote
  208. }
  209. else
  210. { // Handle non-quoted ie parse up till first "White Space"
  211. while (chEOS != *m_pchCur && !IsSpace(*m_pchCur))
  212. {
  213. LPTSTR pchPrev = m_pchCur;
  214. IncrementLinePos();
  215. for (int i = 0; pchPrev+i < m_pchCur; i++, szToken++)
  216. *szToken = *(pchPrev+i);
  217. }
  218. *szToken = chEOS;
  219. }
  220. return S_OK;
  221. }
  222. static BOOL VTFromRegType(LPCTSTR szValueType, VARTYPE& vt)
  223. {
  224. struct typemap
  225. {
  226. LPCTSTR lpsz;
  227. VARTYPE vt;
  228. };
  229. static const typemap map[] = {
  230. {szStringVal, VT_BSTR},
  231. {szDwordVal, VT_I4}
  232. };
  233. for (int i=0;i<sizeof(map)/sizeof(typemap);i++)
  234. {
  235. if (!lstrcmpi(szValueType, map[i].lpsz))
  236. {
  237. vt = map[i].vt;
  238. return TRUE;
  239. }
  240. }
  241. return FALSE;
  242. }
  243. HRESULT CRegParser::AddValue(CRegKey& rkParent,LPCTSTR szValueName, LPTSTR szToken)
  244. {
  245. USES_CONVERSION;
  246. HRESULT hr;
  247. TCHAR szTypeToken[MAX_TYPE];
  248. VARTYPE vt;
  249. LONG lRes = ERROR_SUCCESS;
  250. UINT nIDRes = 0;
  251. RET_ON_ERROR(NextToken(szTypeToken))
  252. if (!VTFromRegType(szTypeToken, vt))
  253. {
  254. ATLTRACE(_T("%s Type not supported\n"), szTypeToken);
  255. return GenerateError(E_ATL_TYPE_NOT_SUPPORTED);
  256. }
  257. TCHAR szValue[MAX_VALUE];
  258. SkipWhiteSpace();
  259. RET_ON_ERROR(NextToken(szValue));
  260. long lVal;
  261. switch (vt)
  262. {
  263. case VT_BSTR:
  264. lRes = rkParent.SetValue(szValue, szValueName);
  265. ATLTRACE(_T("Setting Value %s at %s\n"), szValue, !szValueName ? _T("default") : szValueName);
  266. break;
  267. case VT_I4:
  268. VarI4FromStr(T2OLE(szValue), 0, 0, &lVal);
  269. lRes = rkParent.SetValue(lVal, szValueName);
  270. ATLTRACE(_T("Setting Value %d at %s\n"), lVal, !szValueName ? _T("default") : szValueName);
  271. break;
  272. }
  273. if (ERROR_SUCCESS != lRes)
  274. {
  275. nIDRes = E_ATL_VALUE_SET_FAILED;
  276. hr = HRESULT_FROM_WIN32(lRes);
  277. }
  278. RET_ON_ERROR(NextToken(szToken))
  279. return S_OK;
  280. }
  281. BOOL CRegParser::CanForceRemoveKey(LPCTSTR szKey)
  282. {
  283. for (int iNoDel = 0; iNoDel < cbNeverDelete; iNoDel++)
  284. if (!lstrcmpi(szKey, rgszNeverDelete[iNoDel]))
  285. return FALSE; // We cannot delete it
  286. return TRUE;
  287. }
  288. BOOL CRegParser::HasSubKeys(HKEY hkey)
  289. {
  290. DWORD cbSubKeys = 0;
  291. if (FAILED(RegQueryInfoKey(hkey, NULL, NULL, NULL,
  292. &cbSubKeys, NULL, NULL,
  293. NULL, NULL, NULL, NULL, NULL)))
  294. {
  295. ATLTRACE(_T("Should not be here!!\n"));
  296. _ASSERTE(FALSE);
  297. return FALSE;
  298. }
  299. return cbSubKeys > 0;
  300. }
  301. BOOL CRegParser::HasValues(HKEY hkey)
  302. {
  303. DWORD cbValues = 0;
  304. LONG lResult = RegQueryInfoKey(hkey, NULL, NULL, NULL,
  305. NULL, NULL, NULL,
  306. &cbValues, NULL, NULL, NULL, NULL);
  307. if (ERROR_SUCCESS != lResult)
  308. {
  309. ATLTRACE(_T("RegQueryInfoKey Failed "));
  310. _ASSERTE(FALSE);
  311. return FALSE;
  312. }
  313. if (1 == cbValues)
  314. {
  315. DWORD cbData = 0;
  316. lResult = RegQueryValueEx(hkey, NULL, NULL, NULL, NULL, &cbData);
  317. if (ERROR_SUCCESS == lResult)
  318. return !cbData;
  319. else
  320. return TRUE;
  321. }
  322. return cbValues > 0;
  323. }
  324. HRESULT CRegParser::SkipAssignment(LPTSTR szToken)
  325. {
  326. HRESULT hr;
  327. TCHAR szValue[MAX_VALUE];
  328. if (*szToken == chEquals)
  329. {
  330. RET_ON_ERROR(NextToken(szToken))
  331. // Skip assignment
  332. SkipWhiteSpace();
  333. RET_ON_ERROR(NextToken(szValue));
  334. RET_ON_ERROR(NextToken(szToken))
  335. }
  336. return S_OK;
  337. }
  338. HRESULT CRegParser::RegisterSubkeys(HKEY hkParent, BOOL bRegister, BOOL bRecover)
  339. {
  340. CRegKey keyCur;
  341. TCHAR szToken[MAX_VALUE];
  342. LONG lRes;
  343. TCHAR szKey[MAX_VALUE];
  344. BOOL bDelete = TRUE;
  345. BOOL bInRecovery = bRecover;
  346. HRESULT hr = S_OK;
  347. ATLTRACE(_T("Num Els = %d\n"), cbNeverDelete);
  348. RET_ON_ERROR(NextToken(szToken)) // Should be key name
  349. while (*szToken != chRightBracket) // Continue till we see a }
  350. {
  351. BOOL bTokenDelete = !lstrcmpi(szToken, szDelete);
  352. if (!lstrcmpi(szToken, szForceRemove) || bTokenDelete)
  353. {
  354. BREAK_ON_ERROR(NextToken(szToken))
  355. if (bRegister)
  356. {
  357. CRegKey rkForceRemove;
  358. if (StrChr(szToken, chDirSep) != NULL)
  359. return GenerateError(E_ATL_COMPOUND_KEY);
  360. if (CanForceRemoveKey(szToken))
  361. {
  362. rkForceRemove.Attach(hkParent);
  363. rkForceRemove.RecurseDeleteKey(szToken);
  364. rkForceRemove.Detach();
  365. }
  366. if (bTokenDelete)
  367. {
  368. BREAK_ON_ERROR(NextToken(szToken))
  369. BREAK_ON_ERROR(SkipAssignment(szToken))
  370. goto EndCheck;
  371. }
  372. }
  373. }
  374. if (!lstrcmpi(szToken, szNoRemove))
  375. {
  376. bDelete = FALSE; // set even for register
  377. BREAK_ON_ERROR(NextToken(szToken))
  378. }
  379. if (!lstrcmpi(szToken, szValToken)) // need to add a value to hkParent
  380. {
  381. TCHAR szValueName[_MAX_PATH];
  382. BREAK_ON_ERROR(NextToken(szValueName))
  383. BREAK_ON_ERROR(NextToken(szToken))
  384. if (*szToken != chEquals)
  385. return GenerateError(E_ATL_EXPECTING_EQUAL);
  386. if (bRegister)
  387. {
  388. CRegKey rk;
  389. rk.Attach(hkParent);
  390. hr = AddValue(rk, szValueName, szToken);
  391. rk.Detach();
  392. if (FAILED(hr))
  393. return hr;
  394. goto EndCheck;
  395. }
  396. else
  397. {
  398. if (!bRecover)
  399. {
  400. ATLTRACE(_T("Deleting %s\n"), szValueName);
  401. REPORT_ERROR(_T("RegDeleteValue"), RegDeleteValue(hkParent, szValueName))
  402. }
  403. BREAK_ON_ERROR(SkipAssignment(szToken)) // Strip off type
  404. continue; // can never have a subkey
  405. }
  406. }
  407. if (StrChr(szToken, chDirSep) != NULL)
  408. return GenerateError(E_ATL_COMPOUND_KEY);
  409. if (bRegister)
  410. {
  411. lRes = keyCur.Open(hkParent, szToken, KEY_ALL_ACCESS);
  412. if (ERROR_SUCCESS != lRes)
  413. {
  414. // Failed all access try read only
  415. lRes = keyCur.Open(hkParent, szToken, KEY_READ);
  416. if (ERROR_SUCCESS != lRes)
  417. {
  418. // Finally try creating it
  419. ATLTRACE(_T("Creating key %s\n"), szToken);
  420. lRes = keyCur.Create(hkParent, szToken);
  421. if (ERROR_SUCCESS != lRes)
  422. return GenerateError(E_ATL_CREATE_KEY_FAILED);
  423. }
  424. }
  425. BREAK_ON_ERROR(NextToken(szToken))
  426. if (*szToken == chEquals)
  427. BREAK_ON_ERROR(AddValue(keyCur, NULL, szToken)) // NULL == default
  428. }
  429. else
  430. {
  431. if (!bRecover && keyCur.Open(hkParent, szToken) != ERROR_SUCCESS)
  432. bRecover = TRUE;
  433. // TRACE out Key open status and if in recovery mode
  434. REG_TRACE_RECOVER()
  435. // Remember Subkey
  436. lstrcpyn(szKey, szToken, MAX_VALUE);
  437. // If in recovery mode
  438. if (bRecover || HasSubKeys(keyCur) || HasValues(keyCur))
  439. {
  440. BREAK_ON_ERROR(NextToken(szToken))
  441. BREAK_ON_ERROR(SkipAssignment(szToken))
  442. if (*szToken == chLeftBracket)
  443. {
  444. BREAK_ON_ERROR(RegisterSubkeys(keyCur.m_hKey, bRegister, bRecover))
  445. if (bRecover) // Turn off recovery if we are done
  446. {
  447. bRecover = bInRecovery;
  448. ATLTRACE(_T("Ending Recovery Mode\n"));
  449. BREAK_ON_ERROR(NextToken(szToken))
  450. BREAK_ON_ERROR(SkipAssignment(szToken))
  451. continue;
  452. }
  453. }
  454. if (!bRecover && HasSubKeys(keyCur))
  455. {
  456. // See if the KEY is in the NeverDelete list and if so, don't
  457. if (CanForceRemoveKey(szKey))
  458. {
  459. ATLTRACE(_T("Deleting non-empty subkey %s by force\n"), szKey);
  460. REPORT_ERROR(_T("RecurseDeleteKey"), keyCur.RecurseDeleteKey(szKey))
  461. }
  462. BREAK_ON_ERROR(NextToken(szToken))
  463. continue;
  464. }
  465. if (bRecover)
  466. continue;
  467. }
  468. if (!bRecover && keyCur.Close() != ERROR_SUCCESS)
  469. return GenerateError(E_ATL_CLOSE_KEY_FAILED);
  470. if (!bRecover && bDelete)
  471. {
  472. ATLTRACE(_T("Deleting Key %s\n"), szKey);
  473. REPORT_ERROR(_T("RegDeleteKey"), RegDeleteKey(hkParent, szKey))
  474. }
  475. BREAK_ON_ERROR(NextToken(szToken))
  476. BREAK_ON_ERROR(SkipAssignment(szToken))
  477. }
  478. EndCheck:
  479. if (bRegister)
  480. {
  481. if (*szToken == chLeftBracket)
  482. {
  483. BREAK_ON_ERROR(RegisterSubkeys(keyCur.m_hKey, bRegister, FALSE))
  484. BREAK_ON_ERROR(NextToken(szToken))
  485. }
  486. }
  487. }
  488. return hr;
  489. }
  490. LPTSTR CParseBuffer::Detach()
  491. {
  492. LPTSTR lp = p;
  493. p = NULL;
  494. return lp;
  495. }
  496. CParseBuffer::CParseBuffer(int nInitial)
  497. {
  498. nPos = 0;
  499. nSize = nInitial;
  500. p = (LPTSTR) CoTaskMemAlloc(nSize*sizeof(TCHAR));
  501. }
  502. BOOL CParseBuffer::AddString(LPCOLESTR lpsz)
  503. {
  504. USES_CONVERSION;
  505. LPCTSTR lpszT = OLE2CT(lpsz);
  506. while (*lpszT)
  507. {
  508. AddChar(*lpszT);
  509. lpszT++;
  510. }
  511. return TRUE;
  512. }
  513. BOOL CParseBuffer::AddChar(TCHAR ch)
  514. {
  515. if (nPos == nSize) // realloc
  516. {
  517. int newSize = nSize * 2;
  518. void* newPointer = (LPTSTR) CoTaskMemRealloc(p, newSize*sizeof(TCHAR));
  519. if (newPointer == 0)
  520. {
  521. return FALSE;
  522. }
  523. else
  524. {
  525. nSize = newSize;
  526. p = static_cast<LPTSTR>(newPointer);
  527. }
  528. }
  529. p[nPos++] = ch;
  530. return TRUE;
  531. }
  532. HRESULT CRegParser::PreProcessBuffer(LPTSTR lpszReg, LPTSTR* ppszReg)
  533. {
  534. USES_CONVERSION;
  535. _ASSERTE(lpszReg != NULL);
  536. _ASSERTE(ppszReg != NULL);
  537. *ppszReg = NULL;
  538. int nSize = lstrlen(lpszReg)*2;
  539. CParseBuffer pb(nSize);
  540. if (pb.p == NULL)
  541. return E_OUTOFMEMORY;
  542. m_pchCur = lpszReg;
  543. HRESULT hr = S_OK;
  544. while (*m_pchCur != NULL) // look for end
  545. {
  546. if (*m_pchCur == _T('%'))
  547. {
  548. IncrementLinePos();
  549. if (*m_pchCur == _T('%'))
  550. pb.AddChar(*m_pchCur);
  551. else
  552. {
  553. LPTSTR lpszNext = StrChr(m_pchCur, _T('%'));
  554. if (lpszNext == NULL)
  555. {
  556. ATLTRACE(_T("Error no closing % found\n"));
  557. hr = GenerateError(E_ATL_UNEXPECTED_EOS);
  558. break;
  559. }
  560. int nLength = (int)(lpszNext - m_pchCur);
  561. if (nLength > 31)
  562. {
  563. hr = E_FAIL;
  564. break;
  565. }
  566. TCHAR buf[32];
  567. lstrcpyn(buf, m_pchCur, nLength+1);
  568. LPCOLESTR lpszVar = m_pRegObj->StrFromMap(buf);
  569. if (lpszVar == NULL)
  570. {
  571. hr = GenerateError(E_ATL_NOT_IN_MAP);
  572. break;
  573. }
  574. pb.AddString(lpszVar);
  575. while (m_pchCur != lpszNext)
  576. IncrementLinePos();
  577. }
  578. }
  579. else
  580. pb.AddChar(*m_pchCur);
  581. IncrementLinePos();
  582. }
  583. pb.AddChar(NULL);
  584. if (SUCCEEDED(hr))
  585. *ppszReg = pb.Detach();
  586. return hr;
  587. }
  588. HRESULT CRegParser::RegisterBuffer(LPTSTR szBuffer, BOOL bRegister)
  589. {
  590. TCHAR szToken[_MAX_PATH];
  591. HRESULT hr = S_OK;
  592. LPTSTR szReg;
  593. hr = PreProcessBuffer(szBuffer, &szReg);
  594. if (FAILED(hr))
  595. return hr;
  596. m_pchCur = szReg;
  597. // Preprocess szReg
  598. while (chEOS != *m_pchCur)
  599. {
  600. BREAK_ON_ERROR(NextToken(szToken))
  601. HKEY hkBase;
  602. if ((hkBase = HKeyFromString(szToken)) == NULL)
  603. {
  604. ATLTRACE(_T("HKeyFromString failed on %s\n"), szToken);
  605. hr = GenerateError(E_ATL_BAD_HKEY);
  606. break;
  607. }
  608. BREAK_ON_ERROR(NextToken(szToken))
  609. if (chLeftBracket != *szToken)
  610. {
  611. ATLTRACE(_T("Syntax error, expecting a {, found a %s\n"), szToken);
  612. hr = GenerateError(E_ATL_MISSING_OPENKEY_TOKEN);
  613. break;
  614. }
  615. if (bRegister)
  616. {
  617. LPTSTR szRegAtRegister = m_pchCur;
  618. hr = RegisterSubkeys(hkBase, bRegister);
  619. if (FAILED(hr))
  620. {
  621. ATLTRACE(_T("Failed to register, cleaning up!\n"));
  622. m_pchCur = szRegAtRegister;
  623. RegisterSubkeys(hkBase, FALSE);
  624. break;
  625. }
  626. }
  627. else
  628. {
  629. BREAK_ON_ERROR(RegisterSubkeys(hkBase, bRegister))
  630. }
  631. SkipWhiteSpace();
  632. }
  633. CoTaskMemFree(szReg);
  634. return hr;
  635. }
  636. HRESULT CExpansionVector::Add(LPCOLESTR lpszKey, LPCOLESTR lpszValue)
  637. {
  638. USES_CONVERSION;
  639. HRESULT hr = S_OK;
  640. EXPANDER* pExpand = NULL;
  641. ATLTRY(pExpand = new EXPANDER);
  642. if (pExpand == NULL)
  643. return E_OUTOFMEMORY;
  644. DWORD cbKey = (ocslen(lpszKey)+1)*sizeof(OLECHAR);
  645. DWORD cbValue = (ocslen(lpszValue)+1)*sizeof(OLECHAR);
  646. pExpand->szKey = (LPOLESTR)CoTaskMemAlloc(cbKey);
  647. pExpand->szValue = (LPOLESTR)CoTaskMemAlloc(cbValue);
  648. if (pExpand->szKey == NULL || pExpand->szValue == NULL)
  649. {
  650. CoTaskMemFree(pExpand->szKey);
  651. CoTaskMemFree(pExpand->szValue);
  652. delete pExpand;
  653. return E_OUTOFMEMORY;
  654. }
  655. memcpy(pExpand->szKey, lpszKey, cbKey);
  656. memcpy(pExpand->szValue, lpszValue, cbValue);
  657. if (m_cEls == m_nSize)
  658. {
  659. int newSize = m_nSize * 2;
  660. void* newPointer = (EXPANDER**)realloc(m_p, newSize*sizeof(EXPANDER*));
  661. if (newPointer == NULL)
  662. {
  663. return E_OUTOFMEMORY;
  664. }
  665. else
  666. {
  667. m_p = static_cast<EXPANDER **>(newPointer);
  668. m_nSize = newSize;
  669. }
  670. }
  671. if (NULL != m_p)
  672. {
  673. m_p[m_cEls] = pExpand;
  674. m_cEls++;
  675. }
  676. else
  677. hr = E_OUTOFMEMORY;
  678. return hr;
  679. }
  680. LPCOLESTR CExpansionVector::Find(LPTSTR lpszKey)
  681. {
  682. USES_CONVERSION;
  683. for (int iExpand = 0; iExpand < m_cEls; iExpand++)
  684. {
  685. if (!lstrcmpi(OLE2T(m_p[iExpand]->szKey), lpszKey)) //are equal
  686. return m_p[iExpand]->szValue;
  687. }
  688. return NULL;
  689. }
  690. HRESULT CExpansionVector::ClearReplacements()
  691. {
  692. for (int iExpand = 0; iExpand < m_cEls; iExpand++)
  693. {
  694. EXPANDER* pExp = m_p[iExpand];
  695. CoTaskMemFree(pExp->szValue);
  696. CoTaskMemFree(pExp->szKey);
  697. delete pExp;
  698. }
  699. m_cEls = 0;
  700. return S_OK;
  701. }
  702. HRESULT CRegObject::GenerateError(UINT nID)
  703. {
  704. // re.m_nID = nID;
  705. // re.m_cLines = -1;
  706. return DISP_E_EXCEPTION;
  707. }
  708. HRESULT STDMETHODCALLTYPE CRegObject::AddReplacement(LPCOLESTR lpszKey, LPCOLESTR lpszItem)
  709. {
  710. m_csMap.Lock();
  711. HRESULT hr = m_RepMap.Add(lpszKey, lpszItem);
  712. m_csMap.Unlock();
  713. return hr;
  714. }
  715. HRESULT CRegObject::RegisterFromResource(LPCOLESTR bstrFileName, LPCTSTR szID,
  716. LPCTSTR szType, BOOL bRegister)
  717. {
  718. USES_CONVERSION;
  719. HRESULT hr;
  720. CRegParser parser(this);
  721. HINSTANCE hInstResDll;
  722. HRSRC hrscReg;
  723. HGLOBAL hReg;
  724. DWORD dwSize;
  725. LPSTR szRegA;
  726. LPTSTR szReg;
  727. hInstResDll = LoadLibraryEx(OLE2CT(bstrFileName), NULL, LOAD_LIBRARY_AS_DATAFILE);
  728. if (NULL == hInstResDll)
  729. {
  730. ATLTRACE(_T("Failed to LoadLibrary on %s\n"), OLE2CT(bstrFileName));
  731. hr = HRESULT_FROM_WIN32(GetLastError());
  732. goto ReturnHR;
  733. }
  734. hrscReg = FindResource((HMODULE)hInstResDll, szID, szType);
  735. if (NULL == hrscReg)
  736. {
  737. ATLTRACE(_T("Failed to FindResource on ID:%s TYPE:%s\n"), szID, szType);
  738. hr = HRESULT_FROM_WIN32(GetLastError());
  739. goto ReturnHR;
  740. }
  741. hReg = LoadResource((HMODULE)hInstResDll, hrscReg);
  742. if (NULL == hReg)
  743. {
  744. ATLTRACE(_T("Failed to LoadResource \n"));
  745. hr = HRESULT_FROM_WIN32(GetLastError());
  746. goto ReturnHR;
  747. }
  748. dwSize = SizeofResource((HMODULE)hInstResDll, hrscReg);
  749. szRegA = (LPSTR)hReg;
  750. if (szRegA[dwSize] != NULL)
  751. {
  752. szRegA = (LPSTR)_alloca(dwSize+1);
  753. memcpy(szRegA, (void*)hReg, dwSize+1);
  754. szRegA[dwSize] = NULL;
  755. }
  756. szReg = A2T(szRegA);
  757. #ifdef _DEBUG
  758. OutputDebugString(szReg); //would call ATLTRACE but szReg is > 512 bytes
  759. OutputDebugString(_T("\n"));
  760. #endif //_DEBUG
  761. hr = parser.RegisterBuffer(szReg, bRegister);
  762. ReturnHR:
  763. if (NULL != hInstResDll)
  764. FreeLibrary((HMODULE)hInstResDll);
  765. return hr;
  766. }
  767. HRESULT STDMETHODCALLTYPE CRegObject::ResourceRegister(LPCOLESTR szFileName, UINT nID, LPCOLESTR szType)
  768. {
  769. USES_CONVERSION;
  770. return RegisterFromResource(szFileName, MAKEINTRESOURCE(nID), OLE2CT(szType), TRUE);
  771. }
  772. HRESULT STDMETHODCALLTYPE CRegObject::ResourceRegisterSz(LPCOLESTR szFileName, LPCOLESTR szID, LPCOLESTR szType)
  773. {
  774. USES_CONVERSION;
  775. if (szID == NULL || szType == NULL)
  776. return E_INVALIDARG;
  777. return RegisterFromResource(szFileName, OLE2CT(szID), OLE2CT(szType), TRUE);
  778. }
  779. HRESULT STDMETHODCALLTYPE CRegObject::ResourceUnregister(LPCOLESTR szFileName, UINT nID, LPCOLESTR szType)
  780. {
  781. USES_CONVERSION;
  782. return RegisterFromResource(szFileName, MAKEINTRESOURCE(nID), OLE2CT(szType), FALSE);
  783. }
  784. HRESULT STDMETHODCALLTYPE CRegObject::ResourceUnregisterSz(LPCOLESTR szFileName, LPCOLESTR szID, LPCOLESTR szType)
  785. {
  786. USES_CONVERSION;
  787. if (szID == NULL || szType == NULL)
  788. return E_INVALIDARG;
  789. return RegisterFromResource(szFileName, OLE2CT(szID), OLE2CT(szType), FALSE);
  790. }
  791. HRESULT CRegObject::RegisterWithString(LPCOLESTR bstrData, BOOL bRegister)
  792. {
  793. USES_CONVERSION;
  794. CRegParser parser(this);
  795. LPCTSTR szReg = OLE2CT(bstrData);
  796. #ifdef _DEBUG
  797. OutputDebugString(szReg); //would call ATLTRACE but szReg is > 512 bytes
  798. OutputDebugString(_T("\n"));
  799. #endif //_DEBUG
  800. HRESULT hr = parser.RegisterBuffer((LPTSTR)szReg, bRegister);
  801. return hr;
  802. }
  803. HRESULT CRegObject::ClearReplacements()
  804. {
  805. m_csMap.Lock();
  806. HRESULT hr = m_RepMap.ClearReplacements();
  807. m_csMap.Unlock();
  808. return hr;
  809. }
  810. LPCOLESTR CRegObject::StrFromMap(LPTSTR lpszKey)
  811. {
  812. m_csMap.Lock();
  813. LPCOLESTR lpsz = m_RepMap.Find(lpszKey);
  814. if (lpsz == NULL) // not found!!
  815. ATLTRACE(_T("Map Entry not found\n"));
  816. m_csMap.Unlock();
  817. return lpsz;
  818. }
  819. HRESULT CRegObject::MemMapAndRegister(LPCOLESTR bstrFileName, BOOL bRegister)
  820. {
  821. USES_CONVERSION;
  822. CRegParser parser(this);
  823. HANDLE hFile = CreateFile(OLE2CT(bstrFileName), GENERIC_READ, 0, NULL,
  824. OPEN_EXISTING,
  825. FILE_ATTRIBUTE_READONLY,
  826. NULL);
  827. if (INVALID_HANDLE_VALUE == hFile)
  828. {
  829. ATLTRACE(_T("Failed to CreateFile on %s\n"), OLE2CT(bstrFileName));
  830. return HRESULT_FROM_WIN32(GetLastError());
  831. }
  832. DWORD cbFile = GetFileSize(hFile, NULL); // No HiOrder DWORD required
  833. HANDLE hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
  834. if (NULL == hMapping)
  835. {
  836. ATLTRACE(_T("Failed to CreateFileMapping\n"));
  837. return HRESULT_FROM_WIN32(GetLastError());
  838. }
  839. LPVOID pMap = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
  840. if (NULL == pMap)
  841. {
  842. ATLTRACE(_T("Failed to MapViewOfFile\n"));
  843. return HRESULT_FROM_WIN32(GetLastError());
  844. }
  845. LPTSTR szReg = A2T((char*)pMap);
  846. if (chEOS != szReg[cbFile]) //ensure buffer is NULL terminated
  847. {
  848. ATLTRACE(_T("ERROR : Bad or missing End of File\n"));
  849. return E_FAIL; // make a real error
  850. }
  851. #ifdef _DEBUG
  852. OutputDebugString(szReg); //would call ATLTRACE but szReg is > 512 bytes
  853. OutputDebugString(_T("\n"));
  854. #endif //_DEBUG
  855. HRESULT hRes = parser.RegisterBuffer(szReg, bRegister);
  856. // if (FAILED(hRes))
  857. // re = parser.GetRegException();
  858. UnmapViewOfFile(pMap);
  859. CloseHandle(hMapping);
  860. CloseHandle(hFile);
  861. return hRes;
  862. }
  863. HRESULT STDMETHODCALLTYPE CRegObject::FileRegister(LPCOLESTR bstrFileName)
  864. {
  865. return MemMapAndRegister(bstrFileName, TRUE);
  866. }
  867. HRESULT STDMETHODCALLTYPE CRegObject::FileUnregister(LPCOLESTR bstrFileName)
  868. {
  869. return MemMapAndRegister(bstrFileName, FALSE);
  870. }
  871. HRESULT STDMETHODCALLTYPE CRegObject::StringRegister(LPCOLESTR bstrData)
  872. {
  873. return RegisterWithString(bstrData, TRUE);
  874. }
  875. HRESULT STDMETHODCALLTYPE CRegObject::StringUnregister(LPCOLESTR bstrData)
  876. {
  877. return RegisterWithString(bstrData, FALSE);
  878. }
  879. #ifndef ATL_NO_NAMESPACE
  880. }; //namespace ATL
  881. #endif