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.

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