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.

1399 lines
50 KiB

  1. // This is a part of the Active Template Library.
  2. // Copyright (C) 1996-1998 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. #ifndef __STATREG_H
  11. #define __STATREG_H
  12. #define E_ATL_REGISTRAR_DESC 0x0201
  13. #define E_ATL_NOT_IN_MAP 0x0202
  14. #define E_ATL_UNEXPECTED_EOS 0x0203
  15. #define E_ATL_VALUE_SET_FAILED 0x0204
  16. #define E_ATL_RECURSE_DELETE_FAILED 0x0205
  17. #define E_ATL_EXPECTING_EQUAL 0x0206
  18. #define E_ATL_CREATE_KEY_FAILED 0x0207
  19. #define E_ATL_DELETE_KEY_FAILED 0x0208
  20. #define E_ATL_OPEN_KEY_FAILED 0x0209
  21. #define E_ATL_CLOSE_KEY_FAILED 0x020A
  22. #define E_ATL_UNABLE_TO_COERCE 0x020B
  23. #define E_ATL_BAD_HKEY 0x020C
  24. #define E_ATL_MISSING_OPENKEY_TOKEN 0x020D
  25. #define E_ATL_CONVERT_FAILED 0x020E
  26. #define E_ATL_TYPE_NOT_SUPPORTED 0x020F
  27. #define E_ATL_COULD_NOT_CONCAT 0x0210
  28. #define E_ATL_COMPOUND_KEY 0x0211
  29. #define E_ATL_INVALID_MAPKEY 0x0212
  30. #define E_ATL_UNSUPPORTED_VT 0x0213
  31. #define E_ATL_VALUE_GET_FAILED 0x0214
  32. #define E_ATL_VALUE_TOO_LARGE 0x0215
  33. #define E_ATL_MISSING_VALUE_DELIMETER 0x0216
  34. #define E_ATL_DATA_NOT_BYTE_ALIGNED 0x0217
  35. namespace ATL
  36. {
  37. const TCHAR chDirSep = _T('\\');
  38. const TCHAR chRightBracket = _T('}');
  39. const TCHAR chLeftBracket = _T('{');
  40. const TCHAR chQuote = _T('\'');
  41. const TCHAR chEquals = _T('=');
  42. const LPCTSTR szStringVal = _T("S");
  43. const LPCTSTR szDwordVal = _T("D");
  44. const LPCTSTR szBinaryVal = _T("B");
  45. const LPCTSTR szValToken = _T("Val");
  46. const LPCTSTR szForceRemove = _T("ForceRemove");
  47. const LPCTSTR szNoRemove = _T("NoRemove");
  48. const LPCTSTR szDelete = _T("Delete");
  49. class CExpansionVector
  50. {
  51. public:
  52. //Declare EXPANDER struct. Only used locally.
  53. struct EXPANDER
  54. {
  55. LPOLESTR szKey;
  56. LPOLESTR szValue;
  57. };
  58. CExpansionVector()
  59. {
  60. m_cEls = 0;
  61. m_nSize=10;
  62. m_p = (EXPANDER**)malloc(m_nSize*sizeof(EXPANDER*));
  63. }
  64. ~CExpansionVector()
  65. {
  66. free(m_p);
  67. }
  68. HRESULT Add(LPCOLESTR lpszKey, LPCOLESTR lpszValue)
  69. {
  70. HRESULT hr = S_OK;
  71. EXPANDER* pExpand = NULL;
  72. ATLTRY(pExpand = new EXPANDER);
  73. if (pExpand == NULL)
  74. return E_OUTOFMEMORY;
  75. DWORD cbKey = (ocslen(lpszKey)+1)*sizeof(OLECHAR);
  76. DWORD cbValue = (ocslen(lpszValue)+1)*sizeof(OLECHAR);
  77. pExpand->szKey = (LPOLESTR)CoTaskMemAlloc(cbKey);
  78. pExpand->szValue = (LPOLESTR)CoTaskMemAlloc(cbValue);
  79. if (pExpand->szKey == NULL || pExpand->szValue == NULL)
  80. {
  81. CoTaskMemFree(pExpand->szKey);
  82. CoTaskMemFree(pExpand->szValue);
  83. delete pExpand;
  84. return E_OUTOFMEMORY;
  85. }
  86. memcpy(pExpand->szKey, lpszKey, cbKey);
  87. memcpy(pExpand->szValue, lpszValue, cbValue);
  88. if (m_cEls == m_nSize)
  89. {
  90. m_nSize*=2;
  91. EXPANDER** p;
  92. p = (EXPANDER**)realloc(m_p, m_nSize*sizeof(EXPANDER*));
  93. if (p == NULL)
  94. {
  95. CoTaskMemFree(pExpand->szKey);
  96. CoTaskMemFree(pExpand->szValue);
  97. delete pExpand;
  98. m_nSize /=2;
  99. hr = E_OUTOFMEMORY;
  100. }
  101. else
  102. m_p = p;
  103. }
  104. if (SUCCEEDED(hr))
  105. {
  106. ATLASSERT(m_p != NULL);
  107. m_p[m_cEls] = pExpand;
  108. m_cEls++;
  109. }
  110. return hr;
  111. }
  112. LPCOLESTR Find(LPTSTR lpszKey)
  113. {
  114. USES_CONVERSION_EX;
  115. for (int iExpand = 0; iExpand < m_cEls; iExpand++)
  116. {
  117. LPTSTR lpOleStr = OLE2T_EX(m_p[iExpand]->szKey, _ATL_SAFE_ALLOCA_DEF_THRESHOLD);
  118. #ifndef _UNICODE
  119. if (lpOleStr == NULL)
  120. {
  121. return NULL;
  122. }
  123. #endif // _UNICODE
  124. if (!lstrcmpi(lpOleStr, lpszKey)) //are equal
  125. return m_p[iExpand]->szValue;
  126. }
  127. return NULL;
  128. }
  129. HRESULT ClearReplacements()
  130. {
  131. for (int iExpand = 0; iExpand < m_cEls; iExpand++)
  132. {
  133. EXPANDER* pExp = m_p[iExpand];
  134. CoTaskMemFree(pExp->szValue);
  135. CoTaskMemFree(pExp->szKey);
  136. delete pExp;
  137. }
  138. m_cEls = 0;
  139. return S_OK;
  140. }
  141. private:
  142. EXPANDER** m_p;
  143. int m_cEls;
  144. int m_nSize;
  145. };
  146. class CRegObject;
  147. class CRegParser
  148. {
  149. public:
  150. CRegParser(CRegObject* pRegObj);
  151. HRESULT PreProcessBuffer(LPTSTR lpszReg, LPTSTR* ppszReg);
  152. HRESULT RegisterBuffer(LPTSTR szReg, BOOL bRegister);
  153. protected:
  154. void SkipWhiteSpace();
  155. HRESULT NextToken(LPTSTR szToken);
  156. HRESULT AddValue(CRegKey& rkParent,LPCTSTR szValueName, LPTSTR szToken, bool bQuoteModule = false);
  157. BOOL CanForceRemoveKey(LPCTSTR szKey);
  158. BOOL HasSubKeys(HKEY hkey);
  159. BOOL HasValues(HKEY hkey);
  160. HRESULT RegisterSubkeys(LPTSTR szToken, HKEY hkParent, BOOL bRegister, BOOL bInRecovery = FALSE);
  161. BOOL IsSpace(TCHAR ch);
  162. LPTSTR m_pchCur;
  163. CRegObject* m_pRegObj;
  164. HRESULT GenerateError(UINT) {return DISP_E_EXCEPTION;}
  165. HRESULT HandleReplacements(LPTSTR& szToken);
  166. HRESULT SkipAssignment(LPTSTR szToken);
  167. BOOL EndOfVar() { return chQuote == *m_pchCur && chQuote != *CharNext(m_pchCur); }
  168. static LPTSTR StrChr(LPTSTR lpsz, TCHAR ch);
  169. static LPCTSTR StrStr(LPCTSTR str1, LPCTSTR str2);
  170. static HKEY HKeyFromString(LPTSTR szToken);
  171. static BYTE ChToByte(const TCHAR ch);
  172. static BOOL VTFromRegType(LPCTSTR szValueType, VARTYPE& vt);
  173. static LPCTSTR rgszNeverDelete[];
  174. static const int cbNeverDelete;
  175. static const int MAX_VALUE;
  176. static const int MAX_TYPE;
  177. class CParseBuffer
  178. {
  179. public:
  180. int nPos;
  181. int nSize;
  182. LPTSTR p;
  183. CParseBuffer(int nInitial)
  184. {
  185. nPos = 0;
  186. nSize = nInitial;
  187. p = (LPTSTR) CoTaskMemAlloc(nSize*sizeof(TCHAR));
  188. if (!p) {
  189. nSize = 0;
  190. }
  191. }
  192. ~CParseBuffer()
  193. {
  194. CoTaskMemFree(p);
  195. }
  196. BOOL AddChar(const TCHAR* pch)
  197. {
  198. if (nPos == nSize) // realloc
  199. {
  200. LPTSTR pNew;
  201. pNew = (LPTSTR) CoTaskMemRealloc(p, nSize*2*sizeof(TCHAR));
  202. if (pNew == NULL)
  203. return FALSE;
  204. nSize *= 2;
  205. p = pNew;
  206. }
  207. p[nPos++] = *pch;
  208. #ifndef _UNICODE
  209. if (IsDBCSLeadByte(*pch))
  210. p[nPos++] = *(pch + 1);
  211. #endif
  212. return TRUE;
  213. }
  214. BOOL AddString(LPCOLESTR lpsz)
  215. {
  216. USES_CONVERSION_EX;
  217. LPCTSTR lpszT = OLE2CT_EX(lpsz, _ATL_SAFE_ALLOCA_DEF_THRESHOLD);
  218. if (lpszT == NULL)
  219. {
  220. return FALSE;
  221. }
  222. while (*lpszT)
  223. {
  224. if (!AddChar(lpszT)) {
  225. return FALSE;
  226. }
  227. lpszT++;
  228. }
  229. return TRUE;
  230. }
  231. LPTSTR Detach()
  232. {
  233. LPTSTR lp = p;
  234. p = NULL;
  235. return lp;
  236. }
  237. };
  238. };
  239. #if defined(_ATL_DLL) | defined(_ATL_DLL_IMPL)
  240. class ATL_NO_VTABLE CRegObject
  241. : public IRegistrar
  242. #else
  243. class CRegObject
  244. #endif
  245. {
  246. public:
  247. ~CRegObject(){ClearReplacements();}
  248. HRESULT FinalConstruct() {return S_OK;}
  249. void FinalRelease() {}
  250. // Map based methods
  251. HRESULT STDMETHODCALLTYPE AddReplacement(LPCOLESTR lpszKey, LPCOLESTR lpszItem);
  252. HRESULT STDMETHODCALLTYPE ClearReplacements();
  253. LPCOLESTR StrFromMap(LPTSTR lpszKey);
  254. // Register via a given mechanism
  255. HRESULT STDMETHODCALLTYPE ResourceRegister(LPCOLESTR pszFileName, UINT nID, LPCOLESTR pszType);
  256. HRESULT STDMETHODCALLTYPE ResourceRegisterSz(LPCOLESTR pszFileName, LPCOLESTR pszID, LPCOLESTR pszType);
  257. HRESULT STDMETHODCALLTYPE ResourceUnregister(LPCOLESTR pszFileName, UINT nID, LPCOLESTR pszType);
  258. HRESULT STDMETHODCALLTYPE ResourceUnregisterSz(LPCOLESTR pszFileName, LPCOLESTR pszID, LPCOLESTR pszType);
  259. HRESULT STDMETHODCALLTYPE FileRegister(LPCOLESTR bstrFileName)
  260. {
  261. return CommonFileRegister(bstrFileName, TRUE);
  262. }
  263. HRESULT STDMETHODCALLTYPE FileUnregister(LPCOLESTR bstrFileName)
  264. {
  265. return CommonFileRegister(bstrFileName, FALSE);
  266. }
  267. HRESULT STDMETHODCALLTYPE StringRegister(LPCOLESTR bstrData)
  268. {
  269. return RegisterWithString(bstrData, TRUE);
  270. }
  271. HRESULT STDMETHODCALLTYPE StringUnregister(LPCOLESTR bstrData)
  272. {
  273. return RegisterWithString(bstrData, FALSE);
  274. }
  275. protected:
  276. HRESULT CommonFileRegister(LPCOLESTR pszFileName, BOOL bRegister);
  277. HRESULT RegisterFromResource(LPCOLESTR pszFileName, LPCTSTR pszID, LPCTSTR pszType, BOOL bRegister);
  278. HRESULT RegisterWithString(LPCOLESTR pszData, BOOL bRegister);
  279. static HRESULT GenerateError(UINT) {return DISP_E_EXCEPTION;}
  280. CExpansionVector m_RepMap;
  281. CComObjectThreadModel::AutoCriticalSection m_csMap;
  282. };
  283. inline HRESULT STDMETHODCALLTYPE CRegObject::AddReplacement(LPCOLESTR lpszKey, LPCOLESTR lpszItem)
  284. {
  285. m_csMap.Lock();
  286. HRESULT hr = m_RepMap.Add(lpszKey, lpszItem);
  287. m_csMap.Unlock();
  288. return hr;
  289. }
  290. inline HRESULT CRegObject::RegisterFromResource(LPCOLESTR bstrFileName, LPCTSTR szID,
  291. LPCTSTR szType, BOOL bRegister)
  292. {
  293. USES_CONVERSION_EX;
  294. HRESULT hr;
  295. CRegParser parser(this);
  296. HINSTANCE hInstResDll;
  297. HRSRC hrscReg;
  298. HGLOBAL hReg;
  299. DWORD dwSize;
  300. LPSTR szRegA;
  301. LPTSTR szReg;
  302. LPCTSTR lpszBSTRFileName = OLE2CT_EX(bstrFileName, _ATL_SAFE_ALLOCA_DEF_THRESHOLD);
  303. #ifndef _UNICODE
  304. if (lpszBSTRFileName == NULL)
  305. {
  306. return E_OUTOFMEMORY;
  307. }
  308. #endif // _UNICODE
  309. hInstResDll = LoadLibraryEx(lpszBSTRFileName, NULL, LOAD_LIBRARY_AS_DATAFILE);
  310. if (NULL == hInstResDll)
  311. {
  312. ATLTRACE2(atlTraceRegistrar, 0, _T("Failed to LoadLibrary on %s\n"), lpszBSTRFileName);
  313. hr = HRESULT_FROM_WIN32(GetLastError());
  314. goto ReturnHR;
  315. }
  316. hrscReg = FindResource((HMODULE)hInstResDll, szID, szType);
  317. if (NULL == hrscReg)
  318. {
  319. if (DWORD_PTR(szID) <= 0xffff)
  320. ATLTRACE2(atlTraceRegistrar, 0, _T("Failed to FindResource on ID:%d TYPE:%s\n"),
  321. (DWORD)(DWORD_PTR)szID, szType);
  322. else
  323. ATLTRACE2(atlTraceRegistrar, 0, _T("Failed to FindResource on ID:%s TYPE:%s\n"),
  324. szID, szType);
  325. hr = HRESULT_FROM_WIN32(GetLastError());
  326. goto ReturnHR;
  327. }
  328. hReg = LoadResource((HMODULE)hInstResDll, hrscReg);
  329. if (NULL == hReg)
  330. {
  331. ATLTRACE2(atlTraceRegistrar, 0, _T("Failed to LoadResource \n"));
  332. hr = HRESULT_FROM_WIN32(GetLastError());
  333. goto ReturnHR;
  334. }
  335. dwSize = SizeofResource((HMODULE)hInstResDll, hrscReg);
  336. szRegA = (LPSTR)hReg;
  337. if (szRegA[dwSize] != NULL)
  338. {
  339. szRegA = (LPSTR)_ATL_SAFE_ALLOCA(dwSize+1, _ATL_SAFE_ALLOCA_DEF_THRESHOLD);
  340. if (szRegA == NULL)
  341. {
  342. hr = E_OUTOFMEMORY;
  343. goto ReturnHR;
  344. }
  345. memcpy(szRegA, (void*)hReg, dwSize+1);
  346. szRegA[dwSize] = NULL;
  347. }
  348. szReg = A2T_EX(szRegA, _ATL_SAFE_ALLOCA_DEF_THRESHOLD);
  349. #ifndef _UNICODE
  350. if(szReg == NULL)
  351. {
  352. hr = E_OUTOFMEMORY;
  353. goto ReturnHR;
  354. }
  355. #endif // _UNICODE
  356. hr = parser.RegisterBuffer(szReg, bRegister);
  357. ReturnHR:
  358. if (NULL != hInstResDll)
  359. FreeLibrary((HMODULE)hInstResDll);
  360. return hr;
  361. }
  362. inline HRESULT STDMETHODCALLTYPE CRegObject::ResourceRegister(LPCOLESTR szFileName, UINT nID, LPCOLESTR szType)
  363. {
  364. USES_CONVERSION_EX;
  365. LPCTSTR lpszT = OLE2CT_EX(szType, _ATL_SAFE_ALLOCA_DEF_THRESHOLD);
  366. #ifndef _UNICODE
  367. if (lpszT == NULL)
  368. {
  369. return E_OUTOFMEMORY;
  370. }
  371. #endif // _UNICODE
  372. return RegisterFromResource(szFileName, MAKEINTRESOURCE(nID), lpszT, TRUE);
  373. }
  374. inline HRESULT STDMETHODCALLTYPE CRegObject::ResourceRegisterSz(LPCOLESTR szFileName, LPCOLESTR szID, LPCOLESTR szType)
  375. {
  376. USES_CONVERSION_EX;
  377. if (szID == NULL || szType == NULL)
  378. return E_INVALIDARG;
  379. LPCTSTR lpszID = OLE2CT_EX(szID, _ATL_SAFE_ALLOCA_DEF_THRESHOLD);
  380. LPCTSTR lpszType = OLE2CT_EX(szType, _ATL_SAFE_ALLOCA_DEF_THRESHOLD);
  381. #ifndef _UNICODE
  382. if (lpszID == NULL || lpszType == NULL)
  383. {
  384. return E_OUTOFMEMORY;
  385. }
  386. #endif // _UNICODE
  387. return RegisterFromResource(szFileName, lpszID, lpszType, TRUE);
  388. }
  389. inline HRESULT STDMETHODCALLTYPE CRegObject::ResourceUnregister(LPCOLESTR szFileName, UINT nID, LPCOLESTR szType)
  390. {
  391. USES_CONVERSION_EX;
  392. LPCTSTR lpszT = OLE2CT_EX(szType, _ATL_SAFE_ALLOCA_DEF_THRESHOLD);
  393. #ifndef _UNICODE
  394. if (lpszT == NULL)
  395. {
  396. return E_OUTOFMEMORY;
  397. }
  398. #endif // _UNICODE
  399. return RegisterFromResource(szFileName, MAKEINTRESOURCE(nID), lpszT, FALSE);
  400. }
  401. inline HRESULT STDMETHODCALLTYPE CRegObject::ResourceUnregisterSz(LPCOLESTR szFileName, LPCOLESTR szID, LPCOLESTR szType)
  402. {
  403. USES_CONVERSION_EX;
  404. if (szID == NULL || szType == NULL)
  405. return E_INVALIDARG;
  406. LPCTSTR lpszID = OLE2CT_EX(szID, _ATL_SAFE_ALLOCA_DEF_THRESHOLD);
  407. LPCTSTR lpszType = OLE2CT_EX(szType, _ATL_SAFE_ALLOCA_DEF_THRESHOLD);
  408. #ifndef _UNICODE
  409. if (lpszID == NULL || lpszType == NULL)
  410. {
  411. return E_OUTOFMEMORY;
  412. }
  413. #endif // _UNICODE
  414. return RegisterFromResource(szFileName, lpszID, lpszType, FALSE);
  415. }
  416. inline HRESULT CRegObject::RegisterWithString(LPCOLESTR bstrData, BOOL bRegister)
  417. {
  418. USES_CONVERSION_EX;
  419. CRegParser parser(this);
  420. LPCTSTR szReg = OLE2CT_EX(bstrData, _ATL_SAFE_ALLOCA_DEF_THRESHOLD);
  421. #ifndef _UNICODE
  422. if (szReg == NULL)
  423. {
  424. return E_OUTOFMEMORY;
  425. }
  426. #endif // _UNICODE
  427. HRESULT hr = parser.RegisterBuffer((LPTSTR)szReg, bRegister);
  428. return hr;
  429. }
  430. inline HRESULT CRegObject::ClearReplacements()
  431. {
  432. m_csMap.Lock();
  433. HRESULT hr = m_RepMap.ClearReplacements();
  434. m_csMap.Unlock();
  435. return hr;
  436. }
  437. inline LPCOLESTR CRegObject::StrFromMap(LPTSTR lpszKey)
  438. {
  439. m_csMap.Lock();
  440. LPCOLESTR lpsz = m_RepMap.Find(lpszKey);
  441. if (lpsz == NULL) // not found!!
  442. ATLTRACE2(atlTraceRegistrar, 0, _T("Map Entry not found\n"));
  443. m_csMap.Unlock();
  444. return lpsz;
  445. }
  446. inline HRESULT CRegObject::CommonFileRegister(LPCOLESTR bstrFileName, BOOL bRegister)
  447. {
  448. USES_CONVERSION_EX;
  449. CRegParser parser(this);
  450. LPCTSTR lpszBSTRFileName = OLE2CT_EX(bstrFileName, _ATL_SAFE_ALLOCA_DEF_THRESHOLD);
  451. #ifndef _UNICODE
  452. if (lpszBSTRFileName == NULL)
  453. {
  454. return E_OUTOFMEMORY;
  455. }
  456. #endif // _UNICODE
  457. HANDLE hFile = CreateFile(lpszBSTRFileName, GENERIC_READ, 0, NULL,
  458. OPEN_EXISTING,
  459. FILE_ATTRIBUTE_READONLY,
  460. NULL);
  461. if (INVALID_HANDLE_VALUE == hFile)
  462. {
  463. ATLTRACE2(atlTraceRegistrar, 0, _T("Failed to CreateFile on %s\n"), lpszBSTRFileName);
  464. return HRESULT_FROM_WIN32(GetLastError());
  465. }
  466. HRESULT hRes = S_OK;
  467. DWORD cbRead;
  468. DWORD cbFile = GetFileSize(hFile, NULL); // No HiOrder DWORD required
  469. char* szReg = (char*)_ATL_SAFE_ALLOCA(cbFile + 1, _ATL_SAFE_ALLOCA_DEF_THRESHOLD);
  470. if (szReg == NULL)
  471. {
  472. hRes = E_OUTOFMEMORY;
  473. goto ReturnHR;
  474. }
  475. if (ReadFile(hFile, szReg, cbFile, &cbRead, NULL) == 0)
  476. {
  477. ATLTRACE2(atlTraceRegistrar, 0, "Read Failed on file%s\n", lpszBSTRFileName);
  478. hRes = HRESULT_FROM_WIN32(GetLastError());
  479. }
  480. if (SUCCEEDED(hRes))
  481. {
  482. szReg[cbRead] = NULL;
  483. LPTSTR szConverted = A2T_EX(szReg, _ATL_SAFE_ALLOCA_DEF_THRESHOLD);
  484. #ifndef _UNICODE
  485. if (szConverted == NULL)
  486. {
  487. hRes = E_OUTOFMEMORY;
  488. goto ReturnHR;
  489. }
  490. #endif // _UNICODE
  491. hRes = parser.RegisterBuffer(szConverted, bRegister);
  492. }
  493. ReturnHR:
  494. CloseHandle(hFile);
  495. return hRes;
  496. }
  497. __declspec(selectany) LPCTSTR CRegParser::rgszNeverDelete[] = //Component Catagories
  498. {
  499. _T("CLSID"), _T("TYPELIB")
  500. };
  501. __declspec(selectany) const int CRegParser::cbNeverDelete = sizeof(rgszNeverDelete) / sizeof(LPCTSTR*);
  502. __declspec(selectany) const int CRegParser::MAX_VALUE=4096;
  503. __declspec(selectany) const int CRegParser::MAX_TYPE=MAX_VALUE;
  504. inline BOOL CRegParser::VTFromRegType(LPCTSTR szValueType, VARTYPE& vt)
  505. {
  506. struct typemap
  507. {
  508. LPCTSTR lpsz;
  509. VARTYPE vt;
  510. };
  511. static const typemap map[] = {
  512. {szStringVal, VT_BSTR},
  513. {szDwordVal, VT_UI4},
  514. {szBinaryVal, VT_UI1}
  515. };
  516. for (int i=0;i<sizeof(map)/sizeof(typemap);i++)
  517. {
  518. if (!lstrcmpi(szValueType, map[i].lpsz))
  519. {
  520. vt = map[i].vt;
  521. return TRUE;
  522. }
  523. }
  524. return FALSE;
  525. }
  526. inline BYTE CRegParser::ChToByte(const TCHAR ch)
  527. {
  528. switch (ch)
  529. {
  530. case '0':
  531. case '1':
  532. case '2':
  533. case '3':
  534. case '4':
  535. case '5':
  536. case '6':
  537. case '7':
  538. case '8':
  539. case '9':
  540. return (BYTE) (ch - '0');
  541. case 'A':
  542. case 'B':
  543. case 'C':
  544. case 'D':
  545. case 'E':
  546. case 'F':
  547. return (BYTE) (10 + (ch - 'A'));
  548. case 'a':
  549. case 'b':
  550. case 'c':
  551. case 'd':
  552. case 'e':
  553. case 'f':
  554. return (BYTE) (10 + (ch - 'a'));
  555. default:
  556. ATLASSERT(FALSE);
  557. ATLTRACE2(atlTraceRegistrar, 0, _T("Bogus value %c passed as binary Hex value\n"), ch);
  558. return 0;
  559. }
  560. }
  561. inline HKEY CRegParser::HKeyFromString(LPTSTR szToken)
  562. {
  563. struct keymap
  564. {
  565. LPCTSTR lpsz;
  566. HKEY hkey;
  567. };
  568. static const keymap map[] = {
  569. {_T("HKCR"), HKEY_CLASSES_ROOT},
  570. {_T("HKCU"), HKEY_CURRENT_USER},
  571. {_T("HKLM"), HKEY_LOCAL_MACHINE},
  572. {_T("HKU"), HKEY_USERS},
  573. {_T("HKPD"), HKEY_PERFORMANCE_DATA},
  574. {_T("HKDD"), HKEY_DYN_DATA},
  575. {_T("HKCC"), HKEY_CURRENT_CONFIG},
  576. {_T("HKEY_CLASSES_ROOT"), HKEY_CLASSES_ROOT},
  577. {_T("HKEY_CURRENT_USER"), HKEY_CURRENT_USER},
  578. {_T("HKEY_LOCAL_MACHINE"), HKEY_LOCAL_MACHINE},
  579. {_T("HKEY_USERS"), HKEY_USERS},
  580. {_T("HKEY_PERFORMANCE_DATA"), HKEY_PERFORMANCE_DATA},
  581. {_T("HKEY_DYN_DATA"), HKEY_DYN_DATA},
  582. {_T("HKEY_CURRENT_CONFIG"), HKEY_CURRENT_CONFIG}
  583. };
  584. for (int i=0;i<sizeof(map)/sizeof(keymap);i++)
  585. {
  586. if (!lstrcmpi(szToken, map[i].lpsz))
  587. return map[i].hkey;
  588. }
  589. return NULL;
  590. }
  591. inline LPTSTR CRegParser::StrChr(LPTSTR lpsz, TCHAR ch)
  592. {
  593. LPTSTR p = NULL;
  594. if (lpsz == NULL)
  595. return NULL;
  596. while (*lpsz)
  597. {
  598. if (*lpsz == ch)
  599. {
  600. p = lpsz;
  601. break;
  602. }
  603. lpsz = CharNext(lpsz);
  604. }
  605. return p;
  606. }
  607. inline LPCTSTR CRegParser::StrStr(LPCTSTR str1, LPCTSTR str2)
  608. {
  609. TCHAR *cp = (TCHAR *) str1;
  610. TCHAR *s1, *s2;
  611. if ( !*str2 )
  612. return((TCHAR *)str1);
  613. while (*cp)
  614. {
  615. s1 = cp;
  616. s2 = (TCHAR *) str2;
  617. while ( *s1 && *s2 && !(*s1-*s2) )
  618. {
  619. TCHAR* s1Temp = CharNext(s1);
  620. TCHAR* s2Temp = CharNext(s2);
  621. if (s1Temp - s1 != s2Temp - s2)
  622. break;
  623. while (s1 < s1Temp)
  624. {
  625. if (!(*(++s1) - *(++s2)))
  626. break;
  627. }
  628. }
  629. if (!*s2)
  630. return(cp);
  631. cp = CharNext(cp);
  632. }
  633. return(NULL);
  634. }
  635. inline CRegParser::CRegParser(CRegObject* pRegObj)
  636. {
  637. m_pRegObj = pRegObj;
  638. m_pchCur = NULL;
  639. }
  640. inline BOOL CRegParser::IsSpace(TCHAR ch)
  641. {
  642. switch (ch)
  643. {
  644. case _T(' '):
  645. case _T('\t'):
  646. case _T('\r'):
  647. case _T('\n'):
  648. return TRUE;
  649. }
  650. return FALSE;
  651. }
  652. inline void CRegParser::SkipWhiteSpace()
  653. {
  654. while(IsSpace(*m_pchCur))
  655. m_pchCur = CharNext(m_pchCur);
  656. }
  657. inline HRESULT CRegParser::NextToken(LPTSTR szToken)
  658. {
  659. SkipWhiteSpace();
  660. // NextToken cannot be called at EOS
  661. if (NULL == *m_pchCur)
  662. return GenerateError(E_ATL_UNEXPECTED_EOS);
  663. LPCTSTR szOrig = szToken;
  664. // handle quoted value / key
  665. if (chQuote == *m_pchCur)
  666. {
  667. m_pchCur = CharNext(m_pchCur);
  668. while (NULL != *m_pchCur && !EndOfVar())
  669. {
  670. if (chQuote == *m_pchCur) // If it is a quote that means we must skip it
  671. m_pchCur = CharNext(m_pchCur);
  672. LPTSTR pchPrev = m_pchCur;
  673. m_pchCur = CharNext(m_pchCur);
  674. if (szToken + sizeof(WORD) >= MAX_VALUE + szOrig)
  675. return GenerateError(E_ATL_VALUE_TOO_LARGE);
  676. for (int i = 0; pchPrev+i < m_pchCur; i++, szToken++)
  677. *szToken = *(pchPrev+i);
  678. }
  679. if (NULL == *m_pchCur)
  680. {
  681. ATLTRACE2(atlTraceRegistrar, 0, _T("NextToken : Unexpected End of File\n"));
  682. return GenerateError(E_ATL_UNEXPECTED_EOS);
  683. }
  684. *szToken = NULL;
  685. m_pchCur = CharNext(m_pchCur);
  686. }
  687. else
  688. {
  689. // Handle non-quoted ie parse up till first "White Space"
  690. while (NULL != *m_pchCur && !IsSpace(*m_pchCur))
  691. {
  692. LPTSTR pchPrev = m_pchCur;
  693. m_pchCur = CharNext(m_pchCur);
  694. if (szToken + sizeof(WORD) >= MAX_VALUE + szOrig)
  695. return GenerateError(E_ATL_VALUE_TOO_LARGE);
  696. for (int i = 0; pchPrev+i < m_pchCur; i++, szToken++)
  697. *szToken = *(pchPrev+i);
  698. }
  699. *szToken = NULL;
  700. }
  701. return S_OK;
  702. }
  703. inline HRESULT CRegParser::AddValue(CRegKey& rkParent,LPCTSTR szValueName, LPTSTR szToken, bool bQuoteModule)
  704. {
  705. USES_CONVERSION_EX;
  706. HRESULT hr;
  707. TCHAR *szTypeToken;
  708. VARTYPE vt;
  709. LONG lRes = ERROR_SUCCESS;
  710. UINT nIDRes = 0;
  711. szTypeToken = (TCHAR *)malloc(sizeof(TCHAR)*MAX_TYPE);
  712. if (!szTypeToken) {
  713. return E_OUTOFMEMORY;
  714. }
  715. if (FAILED(hr = NextToken(szTypeToken))) {
  716. free(szTypeToken);
  717. return hr;
  718. }
  719. if (!VTFromRegType(szTypeToken, vt))
  720. {
  721. ATLTRACE2(atlTraceRegistrar, 0, _T("%s Type not supported\n"), szTypeToken);
  722. free(szTypeToken);
  723. return GenerateError(E_ATL_TYPE_NOT_SUPPORTED);
  724. }
  725. TCHAR *szValue;
  726. szValue = (TCHAR *)malloc(sizeof(TCHAR) * MAX_VALUE);
  727. if (!szValue) {
  728. free(szTypeToken);
  729. return E_OUTOFMEMORY;
  730. }
  731. SkipWhiteSpace();
  732. if (FAILED(hr = NextToken(szValue))) {
  733. free(szValue);
  734. free(szTypeToken);
  735. return hr;
  736. }
  737. ULONG ulVal;
  738. switch (vt)
  739. {
  740. case VT_BSTR:
  741. {
  742. LPTSTR pszValue = szValue;
  743. if (bQuoteModule)
  744. {
  745. if (lstrlen(szValue) > MAX_VALUE - 2)
  746. return E_FAIL;
  747. TCHAR szModuleTemp[MAX_VALUE];
  748. USES_CONVERSION_EX;
  749. LPCOLESTR lpszVar = m_pRegObj->StrFromMap(_T("Module"));
  750. if (lpszVar != NULL)
  751. {
  752. LPCTSTR szModule = OLE2CT_EX(lpszVar, _ATL_SAFE_ALLOCA_DEF_THRESHOLD);
  753. if (szModule != NULL)
  754. {
  755. LPCTSTR p = StrStr(szValue, szModule);
  756. if (p != NULL)
  757. {
  758. if (p == szToken || *CharPrev(szValue, p) != '"')
  759. {
  760. szModuleTemp[0] = 0;
  761. lstrcpyn(szModuleTemp, szValue, (int)(p - szValue));
  762. lstrcat(szModuleTemp, _T("\""));
  763. lstrcat(szModuleTemp, szModule);
  764. lstrcat(szModuleTemp, _T("\""));
  765. lstrcat(szModuleTemp, p + lstrlen(szModule));
  766. pszValue = szModuleTemp;
  767. }
  768. }
  769. }
  770. else
  771. {
  772. return E_OUTOFMEMORY;
  773. }
  774. }
  775. }
  776. lRes = rkParent.SetValue(pszValue, szValueName);
  777. ATLTRACE2(atlTraceRegistrar, 2, _T("Setting Value %s at %s\n"), pszValue, !szValueName ? _T("default") : szValueName);
  778. break;
  779. }
  780. case VT_UI4:
  781. {
  782. LPOLESTR lpszV = T2OLE_EX(szValue, _ATL_SAFE_ALLOCA_DEF_THRESHOLD);
  783. #ifndef _UNICODE
  784. if(lpszV == NULL)
  785. {
  786. free(szValue);
  787. free(szTypeToken);
  788. return E_OUTOFMEMORY;
  789. }
  790. #endif
  791. VarUI4FromStr(lpszV, 0, 0, &ulVal);
  792. lRes = rkParent.SetValue(ulVal, szValueName);
  793. ATLTRACE2(atlTraceRegistrar, 2, _T("Setting Value %d at %s\n"), ulVal, !szValueName ? _T("default") : szValueName);
  794. break;
  795. }
  796. case VT_UI1:
  797. {
  798. int cbValue = lstrlen(szValue);
  799. if (cbValue & 0x00000001)
  800. {
  801. ATLTRACE2(atlTraceRegistrar, 0, _T("Binary Data does not fall on BYTE boundries\n"));
  802. free(szValue);
  803. free(szTypeToken);
  804. return E_FAIL;
  805. }
  806. int cbValDiv2 = cbValue/2;
  807. BYTE* rgBinary = (BYTE*)_ATL_SAFE_ALLOCA(cbValDiv2*sizeof(BYTE), _ATL_SAFE_ALLOCA_DEF_THRESHOLD);
  808. if (rgBinary == NULL)
  809. {
  810. free(szValue);
  811. free(szTypeToken);
  812. return E_FAIL;
  813. }
  814. memset(rgBinary, 0, cbValDiv2);
  815. for (int irg = 0; irg < cbValue; irg++)
  816. rgBinary[(irg/2)] |= (ChToByte(szValue[irg])) << (4*(1 - (irg & 0x00000001)));
  817. lRes = RegSetValueEx(rkParent, szValueName, 0, REG_BINARY, rgBinary, cbValDiv2);
  818. break;
  819. }
  820. }
  821. if (ERROR_SUCCESS != lRes)
  822. {
  823. nIDRes = E_ATL_VALUE_SET_FAILED;
  824. hr = HRESULT_FROM_WIN32(lRes);
  825. }
  826. if (FAILED(hr = NextToken(szToken)))
  827. {
  828. free(szValue);
  829. free(szTypeToken);
  830. return hr;
  831. }
  832. free(szValue);
  833. free(szTypeToken);
  834. return S_OK;
  835. }
  836. inline BOOL CRegParser::CanForceRemoveKey(LPCTSTR szKey)
  837. {
  838. for (int iNoDel = 0; iNoDel < cbNeverDelete; iNoDel++)
  839. if (!lstrcmpi(szKey, rgszNeverDelete[iNoDel]))
  840. return FALSE; // We cannot delete it
  841. return TRUE;
  842. }
  843. inline BOOL CRegParser::HasSubKeys(HKEY hkey)
  844. {
  845. DWORD cbSubKeys = 0;
  846. if (FAILED(RegQueryInfoKey(hkey, NULL, NULL, NULL,
  847. &cbSubKeys, NULL, NULL,
  848. NULL, NULL, NULL, NULL, NULL)))
  849. {
  850. ATLTRACE2(atlTraceRegistrar, 0, _T("Should not be here!!\n"));
  851. ATLASSERT(FALSE);
  852. return FALSE;
  853. }
  854. return cbSubKeys > 0;
  855. }
  856. inline BOOL CRegParser::HasValues(HKEY hkey)
  857. {
  858. DWORD cbValues = 0;
  859. LONG lResult = RegQueryInfoKey(hkey, NULL, NULL, NULL,
  860. NULL, NULL, NULL,
  861. &cbValues, NULL, NULL, NULL, NULL);
  862. if (ERROR_SUCCESS != lResult)
  863. {
  864. ATLTRACE2(atlTraceRegistrar, 0, _T("RegQueryInfoKey Failed "));
  865. ATLASSERT(FALSE);
  866. return FALSE;
  867. }
  868. if (1 == cbValues)
  869. {
  870. DWORD cbMaxName= MAX_VALUE;
  871. TCHAR szValueName[MAX_VALUE];
  872. // Check to see if the Value is default or named
  873. lResult = RegEnumValue(hkey, 0, szValueName, &cbMaxName, NULL, NULL, NULL, NULL);
  874. if (ERROR_SUCCESS == lResult && (szValueName[0] != NULL))
  875. return TRUE; // Named Value means we have a value
  876. return FALSE;
  877. }
  878. return cbValues > 0; // More than 1 means we have a non-default value
  879. }
  880. inline HRESULT CRegParser::SkipAssignment(LPTSTR szToken)
  881. {
  882. HRESULT hr;
  883. TCHAR szValue[MAX_VALUE];
  884. if (*szToken == chEquals)
  885. {
  886. if (FAILED(hr = NextToken(szToken)))
  887. return hr;
  888. // Skip assignment
  889. SkipWhiteSpace();
  890. if (FAILED(hr = NextToken(szValue)))
  891. return hr;
  892. if (FAILED(hr = NextToken(szToken)))
  893. return hr;
  894. }
  895. return S_OK;
  896. }
  897. inline HRESULT CRegParser::PreProcessBuffer(LPTSTR lpszReg, LPTSTR* ppszReg)
  898. {
  899. USES_CONVERSION_EX;
  900. ATLASSERT(lpszReg != NULL);
  901. ATLASSERT(ppszReg != NULL);
  902. if (lpszReg == NULL || ppszReg == NULL)
  903. return E_POINTER;
  904. *ppszReg = NULL;
  905. int nSize = lstrlen(lpszReg)*2;
  906. CParseBuffer pb(nSize);
  907. if (pb.p == NULL)
  908. return E_OUTOFMEMORY;
  909. m_pchCur = lpszReg;
  910. HRESULT hr = S_OK;
  911. while (*m_pchCur != NULL) // look for end
  912. {
  913. if (*m_pchCur == _T('%'))
  914. {
  915. m_pchCur = CharNext(m_pchCur);
  916. if (*m_pchCur == _T('%'))
  917. pb.AddChar(m_pchCur);
  918. else
  919. {
  920. LPTSTR lpszNext = StrChr(m_pchCur, _T('%'));
  921. if (lpszNext == NULL)
  922. {
  923. ATLTRACE2(atlTraceRegistrar, 0, _T("Error no closing %% found\n"));
  924. hr = GenerateError(E_ATL_UNEXPECTED_EOS);
  925. break;
  926. }
  927. int nLength = int(lpszNext - m_pchCur);
  928. if (nLength > 31)
  929. {
  930. hr = E_FAIL;
  931. break;
  932. }
  933. TCHAR buf[32];
  934. lstrcpyn(buf, m_pchCur, nLength+1);
  935. LPCOLESTR lpszVar = m_pRegObj->StrFromMap(buf);
  936. if (lpszVar == NULL)
  937. {
  938. hr = GenerateError(E_ATL_NOT_IN_MAP);
  939. break;
  940. }
  941. pb.AddString(lpszVar);
  942. while (m_pchCur != lpszNext)
  943. m_pchCur = CharNext(m_pchCur);
  944. }
  945. }
  946. else
  947. pb.AddChar(m_pchCur);
  948. m_pchCur = CharNext(m_pchCur);
  949. }
  950. pb.AddChar(m_pchCur);
  951. if (SUCCEEDED(hr))
  952. *ppszReg = pb.Detach();
  953. return hr;
  954. }
  955. inline HRESULT CRegParser::RegisterBuffer(LPTSTR szBuffer, BOOL bRegister)
  956. {
  957. TCHAR szToken[MAX_VALUE];
  958. HRESULT hr = S_OK;
  959. LPTSTR szReg = NULL;
  960. hr = PreProcessBuffer(szBuffer, &szReg);
  961. if (FAILED(hr))
  962. return hr;
  963. #if defined(_DEBUG) && defined(DEBUG_REGISTRATION)
  964. OutputDebugString(szReg); //would call ATLTRACE but szReg is > 512 bytes
  965. OutputDebugString(_T("\n"));
  966. #endif //_DEBUG
  967. m_pchCur = szReg;
  968. // Preprocess szReg
  969. while (NULL != *m_pchCur)
  970. {
  971. if (FAILED(hr = NextToken(szToken)))
  972. break;
  973. HKEY hkBase;
  974. if ((hkBase = HKeyFromString(szToken)) == NULL)
  975. {
  976. ATLTRACE2(atlTraceRegistrar, 0, _T("HKeyFromString failed on %s\n"), szToken);
  977. hr = GenerateError(E_ATL_BAD_HKEY);
  978. break;
  979. }
  980. if (FAILED(hr = NextToken(szToken)))
  981. break;
  982. if (chLeftBracket != *szToken)
  983. {
  984. ATLTRACE2(atlTraceRegistrar, 0, _T("Syntax error, expecting a {, found a %s\n"), szToken);
  985. hr = GenerateError(E_ATL_MISSING_OPENKEY_TOKEN);
  986. break;
  987. }
  988. if (bRegister)
  989. {
  990. LPTSTR szRegAtRegister = m_pchCur;
  991. hr = RegisterSubkeys(szToken, hkBase, bRegister);
  992. if (FAILED(hr))
  993. {
  994. ATLTRACE2(atlTraceRegistrar, 0, _T("Failed to register, cleaning up!\n"));
  995. m_pchCur = szRegAtRegister;
  996. RegisterSubkeys(szToken, hkBase, FALSE);
  997. break;
  998. }
  999. }
  1000. else
  1001. {
  1002. if (FAILED(hr = RegisterSubkeys(szToken, hkBase, bRegister)))
  1003. break;
  1004. }
  1005. SkipWhiteSpace();
  1006. }
  1007. CoTaskMemFree(szReg);
  1008. return hr;
  1009. }
  1010. inline HRESULT CRegParser::RegisterSubkeys(LPTSTR szToken, HKEY hkParent, BOOL bRegister, BOOL bRecover)
  1011. {
  1012. USES_ATL_SAFE_ALLOCA;
  1013. CRegKey keyCur;
  1014. LONG lRes;
  1015. LPTSTR szKey = NULL;
  1016. BOOL bDelete = TRUE;
  1017. BOOL bInRecovery = bRecover;
  1018. HRESULT hr = S_OK;
  1019. ATLTRACE2(atlTraceRegistrar, 2, _T("Num Els = %d\n"), cbNeverDelete);
  1020. if (FAILED(hr = NextToken(szToken)))
  1021. return hr;
  1022. while (*szToken != chRightBracket) // Continue till we see a }
  1023. {
  1024. BOOL bTokenDelete = !lstrcmpi(szToken, szDelete);
  1025. if (!lstrcmpi(szToken, szForceRemove) || bTokenDelete)
  1026. {
  1027. if (FAILED(hr = NextToken(szToken)))
  1028. break;
  1029. if (bRegister)
  1030. {
  1031. CRegKey rkForceRemove;
  1032. if (StrChr(szToken, chDirSep) != NULL)
  1033. return GenerateError(E_ATL_COMPOUND_KEY);
  1034. if (CanForceRemoveKey(szToken))
  1035. {
  1036. rkForceRemove.Attach(hkParent);
  1037. rkForceRemove.RecurseDeleteKey(szToken);
  1038. rkForceRemove.Detach();
  1039. }
  1040. if (bTokenDelete)
  1041. {
  1042. if (FAILED(hr = NextToken(szToken)))
  1043. break;
  1044. if (FAILED(hr = SkipAssignment(szToken)))
  1045. break;
  1046. goto EndCheck;
  1047. }
  1048. }
  1049. }
  1050. if (!lstrcmpi(szToken, szNoRemove))
  1051. {
  1052. bDelete = FALSE; // set even for register
  1053. if (FAILED(hr = NextToken(szToken)))
  1054. break;
  1055. }
  1056. if (!lstrcmpi(szToken, szValToken)) // need to add a value to hkParent
  1057. {
  1058. TCHAR szValueName[_MAX_PATH];
  1059. if (FAILED(hr = NextToken(szValueName)))
  1060. break;
  1061. if (FAILED(hr = NextToken(szToken)))
  1062. break;
  1063. if (*szToken != chEquals)
  1064. return GenerateError(E_ATL_EXPECTING_EQUAL);
  1065. if (bRegister)
  1066. {
  1067. CRegKey rk;
  1068. rk.Attach(hkParent);
  1069. hr = AddValue(rk, szValueName, szToken);
  1070. rk.Detach();
  1071. if (FAILED(hr))
  1072. return hr;
  1073. goto EndCheck;
  1074. }
  1075. else
  1076. {
  1077. if (!bRecover)
  1078. {
  1079. ATLTRACE2(atlTraceRegistrar, 1, _T("Deleting %s\n"), szValueName);
  1080. CRegKey rkParent;
  1081. lRes = rkParent.Open(hkParent, NULL, KEY_WRITE);
  1082. if (lRes == ERROR_SUCCESS)
  1083. {
  1084. lRes = rkParent.DeleteValue(szValueName);
  1085. if ((lRes != ERROR_SUCCESS) && (lRes != ERROR_FILE_NOT_FOUND))
  1086. {
  1087. // Key not present is not an error
  1088. hr = HRESULT_FROM_WIN32(lRes);
  1089. break;
  1090. }
  1091. }
  1092. else
  1093. {
  1094. hr = HRESULT_FROM_WIN32(lRes);
  1095. break;
  1096. }
  1097. }
  1098. if (FAILED(hr = SkipAssignment(szToken)))
  1099. break;
  1100. continue; // can never have a subkey
  1101. }
  1102. }
  1103. if (StrChr(szToken, chDirSep) != NULL)
  1104. return GenerateError(E_ATL_COMPOUND_KEY);
  1105. if (bRegister)
  1106. {
  1107. lRes = keyCur.Open(hkParent, szToken, KEY_ALL_ACCESS);
  1108. if (ERROR_SUCCESS != lRes)
  1109. {
  1110. // Failed all access try read only
  1111. lRes = keyCur.Open(hkParent, szToken, KEY_READ);
  1112. if (ERROR_SUCCESS != lRes)
  1113. {
  1114. // Finally try creating it
  1115. ATLTRACE2(atlTraceRegistrar, 2, _T("Creating key %s\n"), szToken);
  1116. lRes = keyCur.Create(hkParent, szToken, REG_NONE, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE);
  1117. if (ERROR_SUCCESS != lRes)
  1118. return GenerateError(E_ATL_CREATE_KEY_FAILED);
  1119. }
  1120. }
  1121. bool bQuoteModule = false;
  1122. if ((*szToken == 'L' || *szToken == 'l') && lstrcmpi(szToken, _T("LocalServer32")) == 0)
  1123. bQuoteModule = true;
  1124. if (FAILED(hr = NextToken(szToken)))
  1125. break;
  1126. if (*szToken == chEquals)
  1127. {
  1128. if (FAILED(hr = AddValue(keyCur, NULL, szToken, bQuoteModule))) // NULL == default
  1129. break;
  1130. }
  1131. }
  1132. else
  1133. {
  1134. if (!bRecover && keyCur.Open(hkParent, szToken, KEY_READ) != ERROR_SUCCESS)
  1135. bRecover = TRUE;
  1136. // TRACE out Key open status and if in recovery mode
  1137. #ifdef _DEBUG
  1138. if (!bRecover)
  1139. ATLTRACE2(atlTraceRegistrar, 1, _T("Opened Key %s\n"), szToken);
  1140. else
  1141. ATLTRACE2(atlTraceRegistrar, 0, _T("Ignoring Open key on %s : In Recovery mode\n"), szToken);
  1142. #endif //_DEBUG
  1143. // Remember Subkey
  1144. if (szKey == NULL)
  1145. {
  1146. szKey = (LPTSTR)_ATL_SAFE_ALLOCA(sizeof(TCHAR)*_MAX_PATH, _ATL_SAFE_ALLOCA_DEF_THRESHOLD);
  1147. if (szKey == NULL)
  1148. return E_OUTOFMEMORY;
  1149. }
  1150. lstrcpyn(szKey, szToken, _MAX_PATH);
  1151. // If in recovery mode
  1152. if (bRecover || HasSubKeys(keyCur) || HasValues(keyCur))
  1153. {
  1154. if (FAILED(hr = NextToken(szToken)))
  1155. break;
  1156. if (FAILED(hr = SkipAssignment(szToken)))
  1157. break;
  1158. if (*szToken == chLeftBracket)
  1159. {
  1160. if (FAILED(hr = RegisterSubkeys(szToken, keyCur.m_hKey, bRegister, bRecover)))
  1161. break;
  1162. if (bRecover) // Turn off recovery if we are done
  1163. {
  1164. bRecover = bInRecovery;
  1165. ATLTRACE2(atlTraceRegistrar, 0, _T("Ending Recovery Mode\n"));
  1166. if (FAILED(hr = NextToken(szToken)))
  1167. break;
  1168. if (FAILED(hr = SkipAssignment(szToken)))
  1169. break;
  1170. continue;
  1171. }
  1172. }
  1173. if (!bRecover && HasSubKeys(keyCur))
  1174. {
  1175. // See if the KEY is in the NeverDelete list and if so, don't
  1176. if (CanForceRemoveKey(szKey))
  1177. {
  1178. ATLTRACE2(atlTraceRegistrar, 0, _T("Deleting non-empty subkey %s by force\n"), szKey);
  1179. keyCur.RecurseDeleteKey(szKey);
  1180. }
  1181. if (FAILED(hr = NextToken(szToken)))
  1182. break;
  1183. continue;
  1184. }
  1185. if (bRecover)
  1186. continue;
  1187. }
  1188. if (!bRecover && keyCur.Close() != ERROR_SUCCESS)
  1189. return GenerateError(E_ATL_CLOSE_KEY_FAILED);
  1190. if (!bRecover && bDelete)
  1191. {
  1192. ATLTRACE2(atlTraceRegistrar, 0, _T("Deleting Key %s\n"), szKey);
  1193. CRegKey rkParent;
  1194. rkParent.Attach(hkParent);
  1195. rkParent.DeleteSubKey(szKey);
  1196. rkParent.Detach();
  1197. }
  1198. if (FAILED(hr = NextToken(szToken)))
  1199. break;
  1200. if (FAILED(hr = SkipAssignment(szToken)))
  1201. break;
  1202. }
  1203. EndCheck:
  1204. if (bRegister)
  1205. {
  1206. if (*szToken == chLeftBracket && lstrlen(szToken) == 1)
  1207. {
  1208. if (FAILED(hr = RegisterSubkeys(szToken, keyCur.m_hKey, bRegister, FALSE)))
  1209. break;
  1210. if (FAILED(hr = NextToken(szToken)))
  1211. break;
  1212. }
  1213. }
  1214. }
  1215. return hr;
  1216. }
  1217. }; //namespace ATL
  1218. #endif //__STATREG_H