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.

1084 lines
24 KiB

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