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.

688 lines
21 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. regprop.cpp
  5. Abstract:
  6. This module contains the implementation for the Server
  7. Extension Object Registry Property Bag.
  8. Author:
  9. Don Dumitru (dondu@microsoft.com)
  10. Revision History:
  11. dondu 11/26/96 created
  12. andyj 01/14/97 made usable for reading
  13. andyj 02/12/97 Converted PropertyBag's to Dictonary's
  14. --*/
  15. // REGPROP.cpp : Implementation of CSEORegDictionary
  16. #include "stdafx.h"
  17. #include "seodefs.h"
  18. //#include "String"
  19. #include "REGPROP.h"
  20. // Registry Path Separator
  21. #define PATH_SEP "\\"
  22. void Data2Variant(DWORD dwType, LPCSTR pData, CComVariant &varResult) {
  23. varResult.Clear();
  24. switch (dwType) { // Depending on the Registry type
  25. case REG_DWORD:
  26. varResult = *((long *) pData);
  27. break;
  28. case REG_DWORD_BIG_ENDIAN:
  29. varResult = MAKELONG(HIWORD(*((ULONG *) pData)),
  30. LOWORD(*((ULONG *) pData)));
  31. break;
  32. case REG_EXPAND_SZ:
  33. {
  34. int iSize = ExpandEnvironmentStringsA(pData, NULL, 0);
  35. LPSTR szTemp = (LPSTR) _alloca(iSize);
  36. if(ExpandEnvironmentStringsA(pData, szTemp, iSize)) {
  37. varResult = szTemp;
  38. }
  39. }
  40. break;
  41. case REG_LINK:
  42. case REG_RESOURCE_LIST:
  43. case REG_MULTI_SZ:
  44. case REG_SZ:
  45. case REG_BINARY:
  46. case REG_NONE:
  47. default:
  48. varResult = pData;
  49. break;
  50. }
  51. }
  52. /////////////////////////////////////////////////////////////////////////////
  53. // CSEORegDictionaryEnum
  54. class CSEORegDictionaryEnum :
  55. public CComObjectRootEx<CComMultiThreadModelNoCS>,
  56. // public CComCoClass<CSEORegDictionaryEnum, &CLSID_CSEORegDictionary>,
  57. public IDispatchImpl<IEnumVARIANT, &IID_IEnumVARIANT, &LIBID_SEOLib>
  58. {
  59. public:
  60. HRESULT FinalConstruct();
  61. void FinalRelease();
  62. HRESULT STDMETHODCALLTYPE Next(DWORD, LPVARIANT, LPDWORD);
  63. HRESULT STDMETHODCALLTYPE Skip(DWORD);
  64. HRESULT STDMETHODCALLTYPE Reset(void);
  65. HRESULT STDMETHODCALLTYPE Clone(IEnumVARIANT **);
  66. // Not Exported
  67. HRESULT STDMETHODCALLTYPE Init(CSEORegDictionary *);
  68. BEGIN_COM_MAP(CSEORegDictionaryEnum)
  69. COM_INTERFACE_ENTRY(IEnumVARIANT)
  70. END_COM_MAP()
  71. private: // Data members
  72. DWORD m_index;
  73. CSEORegDictionary *m_dictionary;
  74. };
  75. HRESULT CSEORegDictionaryEnum::FinalConstruct() {
  76. m_index = 0;
  77. m_dictionary = NULL;
  78. return S_OK;
  79. }
  80. void CSEORegDictionaryEnum::FinalRelease() {
  81. if(m_dictionary) m_dictionary->Release();
  82. m_dictionary = NULL;
  83. }
  84. STDMETHODIMP CSEORegDictionaryEnum::Init(CSEORegDictionary *pDict) {
  85. if(m_dictionary) m_dictionary->Release();
  86. m_dictionary = pDict;
  87. if(m_dictionary) m_dictionary->AddRef();
  88. return S_OK;
  89. }
  90. STDMETHODIMP CSEORegDictionaryEnum::Next(DWORD dwCount, LPVARIANT varDest,
  91. LPDWORD pdwResult) {
  92. if(!m_dictionary) return E_FAIL; // Hasn't been properly initialized
  93. *pdwResult = 0; // Nothing done so far
  94. int iSize = max(m_dictionary->m_dwcMaxNameLen + 1,
  95. m_dictionary->m_dwcMaxValueData);
  96. LPSTR pData = (LPSTR) _alloca(iSize); // Temp Buffer
  97. while(*pdwResult < dwCount) {
  98. DWORD retCode = ERROR_SUCCESS; // Initialize
  99. CComVariant varResult;
  100. if(m_index < m_dictionary->m_dwValueCount) { // Still doing Values
  101. DWORD dwcNameSize = m_dictionary->m_dwcMaxNameLen + 1;
  102. DWORD dwcValueSize = m_dictionary->m_dwcMaxValueData;
  103. DWORD dwType = 0;
  104. LPSTR psName = (LPSTR) _alloca(dwcNameSize); // Temporary buffer for the name
  105. retCode = RegEnumValueA (m_dictionary->m_hkThisKey, m_index, psName, &dwcNameSize, NULL,
  106. &dwType, (LPBYTE) pData, &dwcValueSize);
  107. if (retCode != ERROR_SUCCESS) return E_FAIL;
  108. // tbd: perhaps race condition that longer entry was added after RegQueryInfoKey call
  109. Data2Variant(dwType, pData, varResult);
  110. } else if(m_index < (m_dictionary->m_dwValueCount + m_dictionary->m_dwKeyCount)) { // Now do Keys
  111. CComPtr<CComObject<CSEORegDictionary> > pKey;
  112. retCode = RegEnumKeyA(m_dictionary->m_hkThisKey,
  113. m_index - m_dictionary->m_dwValueCount, pData, iSize);
  114. if (retCode != ERROR_SUCCESS) return E_FAIL;
  115. CAndyString strTemp = m_dictionary->m_strSubKey;
  116. if(strTemp.length() > 0) strTemp += PATH_SEP; // Add separator if needed
  117. strTemp += pData;
  118. HRESULT hrRes = CComObject<CSEORegDictionary>::CreateInstance(&pKey);
  119. if(FAILED(hrRes)) return hrRes;
  120. if(!pKey) return E_FAIL;
  121. pKey.p->AddRef(); // Do this for CComPtr counting
  122. hrRes = pKey->Load(m_dictionary->m_strMachine.data(), (SEO_HKEY) (DWORD_PTR) m_dictionary->m_hkBaseKey, strTemp.data());
  123. if (FAILED(hrRes)) return hrRes;
  124. LPUNKNOWN punkResult = NULL;
  125. hrRes = pKey->QueryInterface(IID_ISEODictionary, (LPVOID *) &punkResult);
  126. if (FAILED(hrRes)) return hrRes;
  127. varResult = punkResult;
  128. } else {
  129. return S_OK; // No more data
  130. }
  131. varResult.Detach(&varDest[*pdwResult]);
  132. ++m_index; // Point to the next one
  133. ++(*pdwResult); // Increment successful count for caller
  134. }
  135. return S_OK;
  136. }
  137. STDMETHODIMP CSEORegDictionaryEnum::Skip(DWORD dwCount) {
  138. m_index += dwCount;
  139. return S_OK;
  140. }
  141. STDMETHODIMP CSEORegDictionaryEnum::Reset(void) {
  142. m_index = 0;
  143. return S_OK;
  144. }
  145. STDMETHODIMP CSEORegDictionaryEnum::Clone(IEnumVARIANT **ppunkResult) {
  146. // Based on Samples\ATL\circcoll\objects.cpp (see also ATL\beeper\beeper.*
  147. if (ppunkResult == NULL) return E_POINTER;
  148. *ppunkResult = NULL;
  149. CComPtr<CComObject<CSEORegDictionaryEnum> > p;
  150. HRESULT hrRes = CComObject<CSEORegDictionaryEnum>::CreateInstance(&p);
  151. if (!SUCCEEDED(hrRes)) return (hrRes);
  152. p.p->AddRef(); // Do this for CComPtr counting
  153. hrRes = p->Init(m_dictionary);
  154. if (SUCCEEDED(hrRes)) hrRes = p->QueryInterface(IID_IEnumVARIANT, (void**)ppunkResult);
  155. return hrRes;
  156. }
  157. /////////////////////////////////////////////////////////////////////////////
  158. // CSEORegDictionary
  159. HRESULT STDMETHODCALLTYPE CSEORegDictionary::get_Item(
  160. /* [in] */ VARIANT __RPC_FAR *pvarName,
  161. /* [retval][out] */ VARIANT __RPC_FAR *pvarResult)
  162. {
  163. USES_CONVERSION; // Needed for W2A(), etc.
  164. return (pvarName->vt != VT_BSTR) ? E_INVALIDARG :
  165. GetVariantA(W2A(pvarName->bstrVal), pvarResult);
  166. }
  167. HRESULT STDMETHODCALLTYPE CSEORegDictionary::put_Item(
  168. /* [in] */ VARIANT __RPC_FAR *pvarName,
  169. /* [in] */ VARIANT __RPC_FAR *pvarValue)
  170. {
  171. ATLTRACENOTIMPL(_T("CSEORegDictionary::put_Item"));
  172. }
  173. HRESULT STDMETHODCALLTYPE CSEORegDictionary::get__NewEnum(
  174. /* [retval][out] */ IUnknown __RPC_FAR *__RPC_FAR *ppunkResult)
  175. {
  176. // Based on Samples\ATL\circcoll\objects.cpp (see also ATL\beeper\beeper.*
  177. if (ppunkResult == NULL) return E_POINTER;
  178. *ppunkResult = NULL;
  179. CComObject<CSEORegDictionaryEnum> *p;
  180. HRESULT hrRes = CComObject<CSEORegDictionaryEnum>::CreateInstance(&p);
  181. if (!SUCCEEDED(hrRes)) return (hrRes);
  182. hrRes = p->Init(this);
  183. if (SUCCEEDED(hrRes)) hrRes = p->QueryInterface(IID_IEnumVARIANT, (void**)ppunkResult);
  184. if (FAILED(hrRes)) delete p;
  185. return hrRes;
  186. }
  187. HRESULT STDMETHODCALLTYPE CSEORegDictionary::GetVariantA(
  188. /* [in] */ LPCSTR pszName,
  189. /* [retval][out] */ VARIANT __RPC_FAR *pvarResult)
  190. {
  191. CComVariant varResult;
  192. DWORD dwType = 0;
  193. LPSTR pData = (LPSTR) _alloca(m_dwcMaxValueData);
  194. HRESULT hr = LoadItemA(pszName, dwType, (LPBYTE) pData);
  195. if(FAILED(hr)) { // Not a value, perhaps a key
  196. CComPtr<IUnknown> pRef;
  197. hr = GetInterfaceA(pszName, IID_ISEORegDictionary, &pRef);
  198. varResult = pRef;
  199. if(SUCCEEDED(hr)) hr = varResult.Detach(pvarResult);
  200. return hr;
  201. }
  202. Data2Variant(dwType, pData, varResult);
  203. if(SUCCEEDED(hr)) hr = varResult.Detach(pvarResult);
  204. return hr;
  205. }
  206. HRESULT STDMETHODCALLTYPE CSEORegDictionary::GetVariantW(
  207. /* [in] */ LPCWSTR pszName,
  208. /* [retval][out] */ VARIANT __RPC_FAR *pvarResult)
  209. {
  210. USES_CONVERSION; // Needed for W2A(), etc.
  211. return GetVariantA(W2A(pszName), pvarResult);
  212. }
  213. HRESULT STDMETHODCALLTYPE CSEORegDictionary::SetVariantA(
  214. /* [in] */ LPCSTR pszName,
  215. /* [in] */ VARIANT __RPC_FAR *pvarValue)
  216. {
  217. ATLTRACENOTIMPL(_T("CSEORegDictionary::SetVariantA"));
  218. }
  219. HRESULT STDMETHODCALLTYPE CSEORegDictionary::SetVariantW(
  220. /* [in] */ LPCWSTR pszName,
  221. /* [in] */ VARIANT __RPC_FAR *pvarValue)
  222. {
  223. ATLTRACENOTIMPL(_T("CSEORegDictionary::SetVariantW"));
  224. }
  225. HRESULT STDMETHODCALLTYPE CSEORegDictionary::GetStringA(
  226. /* [in] */ LPCSTR pszName,
  227. /* [out][in] */ DWORD __RPC_FAR *pchCount,
  228. /* [retval][size_is][out] */ LPSTR pszResult)
  229. {
  230. DWORD dwType = 0;
  231. LPSTR pData = (LPSTR) _alloca(*pchCount);
  232. HRESULT hr = LoadItemA(pszName, dwType, (LPBYTE) pData, pchCount);
  233. if(FAILED(hr)) return hr;
  234. if(dwType == REG_EXPAND_SZ) { // It needs environment string substitutions
  235. DWORD dwSize = ExpandEnvironmentStringsA(pData, pszResult, *pchCount);
  236. if(!dwSize && *pData) hr = E_FAIL;
  237. } else {
  238. memcpy(pszResult, pData, *pchCount);
  239. }
  240. return hr;
  241. }
  242. HRESULT STDMETHODCALLTYPE CSEORegDictionary::GetStringW(
  243. /* [in] */ LPCWSTR pszName,
  244. /* [out][in] */ DWORD __RPC_FAR *pchCount,
  245. /* [retval][size_is][out] */ LPWSTR pszResult)
  246. {
  247. USES_CONVERSION; // Needed for A2W(), etc.
  248. DWORD dwType = 0;
  249. DWORD dwBytes = *pchCount * sizeof(WCHAR);
  250. LPWSTR pData = (LPWSTR) _alloca(dwBytes);
  251. HRESULT hr = LoadItemW(pszName, dwType, (LPBYTE) pData, &dwBytes);
  252. if(FAILED(hr)) return hr;
  253. if(dwType == REG_EXPAND_SZ) { // It needs environment string substitutions
  254. *pchCount = ExpandEnvironmentStringsW(pData, pszResult, *pchCount);
  255. } else {
  256. memcpy(pszResult, pData, dwBytes);
  257. *pchCount = dwBytes / sizeof(WCHAR);
  258. }
  259. return hr;
  260. }
  261. HRESULT STDMETHODCALLTYPE CSEORegDictionary::SetStringA(
  262. /* [in] */ LPCSTR pszName,
  263. /* [in] */ DWORD chCount,
  264. /* [size_is][in] */ LPCSTR pszValue)
  265. {
  266. ATLTRACENOTIMPL(_T("CSEORegDictionary::SetStringA"));
  267. }
  268. HRESULT STDMETHODCALLTYPE CSEORegDictionary::SetStringW(
  269. /* [in] */ LPCWSTR pszName,
  270. /* [in] */ DWORD chCount,
  271. /* [size_is][in] */ LPCWSTR pszValue)
  272. {
  273. ATLTRACENOTIMPL(_T("CSEORegDictionary::SetStringW"));
  274. }
  275. HRESULT STDMETHODCALLTYPE CSEORegDictionary::GetDWordA(
  276. /* [in] */ LPCSTR pszName,
  277. /* [retval][out] */ DWORD __RPC_FAR *pdwResult)
  278. {
  279. DWORD dwType = 0;
  280. LPBYTE pData = (LPBYTE) _alloca(m_dwcMaxValueData);
  281. HRESULT hr = LoadItemA(pszName, dwType, pData);
  282. if(FAILED(hr)) return hr;
  283. *pdwResult = *((DWORD *) pData);
  284. return hr;
  285. }
  286. HRESULT STDMETHODCALLTYPE CSEORegDictionary::GetDWordW(
  287. /* [in] */ LPCWSTR pszName,
  288. /* [retval][out] */ DWORD __RPC_FAR *pdwResult)
  289. {
  290. USES_CONVERSION; // Needed for W2A(), etc.
  291. return GetDWordA(W2A(pszName), pdwResult);
  292. }
  293. HRESULT STDMETHODCALLTYPE CSEORegDictionary::SetDWordA(
  294. /* [in] */ LPCSTR pszName,
  295. /* [in] */ DWORD dwValue)
  296. {
  297. ATLTRACENOTIMPL(_T("CSEORegDictionary::SetDWordA"));
  298. }
  299. HRESULT STDMETHODCALLTYPE CSEORegDictionary::SetDWordW(
  300. /* [in] */ LPCWSTR pszName,
  301. /* [in] */ DWORD dwValue)
  302. {
  303. ATLTRACENOTIMPL(_T("CSEORegDictionary::SetDWordW"));
  304. }
  305. HRESULT STDMETHODCALLTYPE CSEORegDictionary::GetInterfaceA(
  306. /* [in] */ LPCSTR pszName,
  307. /* [in] */ REFIID iidDesired,
  308. /* [retval][iid_is][out] */ IUnknown __RPC_FAR *__RPC_FAR *ppunkResult)
  309. {
  310. CComObject<CSEORegDictionary> *pKey;
  311. HRESULT hrRes = CComObject<CSEORegDictionary>::CreateInstance(&pKey);
  312. if (!SUCCEEDED(hrRes)) return (hrRes);
  313. CAndyString strTemp = m_strSubKey;
  314. if(strTemp.length() > 0) strTemp += PATH_SEP; // Add separator if needed
  315. strTemp += pszName;
  316. hrRes = pKey->Load(m_strMachine.data(), (SEO_HKEY) (DWORD_PTR) m_hkBaseKey, strTemp.data());
  317. if (SUCCEEDED(hrRes)) {
  318. hrRes = pKey->QueryInterface(iidDesired, (LPVOID *) ppunkResult);
  319. }
  320. if (FAILED(hrRes)) delete pKey;
  321. return (hrRes);
  322. }
  323. HRESULT STDMETHODCALLTYPE CSEORegDictionary::GetInterfaceW(
  324. /* [in] */ LPCWSTR pszName,
  325. /* [in] */ REFIID iidDesired,
  326. /* [retval][iid_is][out] */ IUnknown __RPC_FAR *__RPC_FAR *ppunkResult)
  327. {
  328. USES_CONVERSION; // Needed for W2A(), etc.
  329. return GetInterfaceA(W2A(pszName), iidDesired, ppunkResult);
  330. }
  331. HRESULT STDMETHODCALLTYPE CSEORegDictionary::SetInterfaceA(
  332. /* [in] */ LPCSTR pszName,
  333. /* [in] */ IUnknown __RPC_FAR *punkValue)
  334. {
  335. ATLTRACENOTIMPL(_T("CSEORegDictionary::SetInterfaceA"));
  336. }
  337. HRESULT STDMETHODCALLTYPE CSEORegDictionary::SetInterfaceW(
  338. /* [in] */ LPCWSTR pszName,
  339. /* [in] */ IUnknown __RPC_FAR *punkValue)
  340. {
  341. ATLTRACENOTIMPL(_T("CSEORegDictionary::SetInterfaceW"));
  342. }
  343. /*
  344. STDMETHODIMP CSEORegPropertyBagEx::Write(LPCOLESTR pszPropName, VARIANT *pVar) {
  345. DWORD dwIdx;
  346. if (!pszPropName) {
  347. return (E_POINTER);
  348. }
  349. if (pVar && ((pVar->vt & VT_TYPEMASK) == VT_UNKNOWN)) {
  350. IUnknown *pTmp;
  351. ISEORegPropertyBagEx *pKey;
  352. HRESULT hrRes;
  353. BSTR strTmp;
  354. pTmp = (pVar->vt & VT_BYREF) ? (pVar->ppunkVal ? *pVar->ppunkVal : NULL) : pVar->punkVal;
  355. if (!pTmp) {
  356. return (E_INVALIDARG);
  357. }
  358. hrRes = pTmp->QueryInterface(IID_ISEORegPropertyBagEx,(LPVOID *) &pKey);
  359. if (!SUCCEEDED(hrRes)) {
  360. return (hrRes);
  361. }
  362. strTmp = SysAllocStringLen(m_strSubKey,wcslen(m_strSubKey)+wcslen(pszPropName)+1);
  363. wcscat(strTmp, PATH_SEP);
  364. wcscat(strTmp,pszPropName);
  365. hrRes = pKey->Load(m_strMachine.data(),(SEO_HKEY) (DWORD) m_hkBaseKey,strTmp,NULL);
  366. SysFreeString(strTmp);
  367. pKey->Release();
  368. // tbd
  369. return (hrRes);
  370. } else {
  371. for (dwIdx=0;dwIdx<m_dwValueCnt;dwIdx++) {
  372. if (_wcsicmp(pszPropName,m_paValue[dwIdx].strName) == 0) {
  373. break;
  374. }
  375. }
  376. if ((dwIdx==m_dwValueCnt) && (!pVar || (pVar->vt==VT_EMPTY))) {
  377. return (S_OK);
  378. }
  379. if (dwIdx < m_dwValueCnt) {
  380. MySysFreeStringInPlace(&m_paValue[dwIdx].strData);
  381. } else if (!MyReallocInPlace(&m_paValue,sizeof(m_paValue[0])*(m_dwValueCnt+1))) {
  382. return (E_OUTOFMEMORY);
  383. } else {
  384. m_dwValueCnt++;
  385. }
  386. // tbd
  387. }
  388. return (S_OK);
  389. }
  390. STDMETHODIMP CSEORegPropertyBagEx::CreateSubKey(LPCOLESTR pszPropName, ISEOPropertyBagEx **ppSubKey) {
  391. CComObject<CSEORegPropertyBagEx> *pKey;
  392. VARIANT varTmp;
  393. HRESULT hrRes;
  394. hrRes = CComObject<CSEORegPropertyBagEx>::CreateInstance(&pKey);
  395. if (!SUCCEEDED(hrRes)) {
  396. return (hrRes);
  397. }
  398. VariantInit(&varTmp);
  399. varTmp.vt = VT_UNKNOWN | VT_BYREF;
  400. hrRes = pKey->QueryInterface(IID_IUnknown,(LPVOID *) varTmp.ppunkVal);
  401. if (!SUCCEEDED(hrRes)) {
  402. pKey->Release();
  403. return (hrRes);
  404. }
  405. hrRes = pKey->QueryInterface(IID_ISEOPropertyBagEx,(LPVOID *) ppSubKey);
  406. if (!SUCCEEDED(hrRes)) {
  407. pKey->Release();
  408. return (hrRes);
  409. }
  410. hrRes = Write(pszPropName,&varTmp);
  411. if (!SUCCEEDED(hrRes)) {
  412. pKey->Release();
  413. return (hrRes);
  414. }
  415. return (hrRes);
  416. }
  417. // The following is based on the MONKEY sample app in MSDN
  418. STDMETHODIMP CSEORegDictionary::ReLoad() {
  419. USES_CONVERSION; // Needed for A2W(), etc.
  420. HKEY hKey;
  421. DWORD retCode = ERROR_SUCCESS; // Initialize
  422. DWORD dwcMaxValueName = 0; // Longest Value name.
  423. DWORD dwcMaxValueData = 0; // Longest Value data size.
  424. retCode = RegQueryInfoKey(hKey, NULL, NULL, NULL, &m_dwKeyCnt, NULL, NULL,
  425. &m_dwValueCnt, &dwcMaxValueName, &dwcMaxValueData, 0, 0);
  426. if (retCode != ERROR_SUCCESS) return E_FAIL; // Unable to get data for key
  427. // Allocate memory
  428. if(m_dwKeyCnt) {
  429. m_paKey = (KeyEntry *) MyMalloc(sizeof(KeyEntry) * m_dwKeyCnt);
  430. if (!m_paKey) return E_FAIL; // Unable to allocate memory
  431. }
  432. if(m_dwValueCnt) {
  433. m_paValue = (ValueEntry *) MyMalloc(sizeof(ValueEntry) * m_dwValueCnt);
  434. if (!m_paValue) return E_FAIL; // Unable to allocate memory
  435. }
  436. retCode = ERROR_SUCCESS; // Initialize for the loop
  437. for (DWORD i = 0; (i < m_dwKeyCnt) && (retCode == ERROR_SUCCESS); i++) {
  438. m_paKey[i].pKey = NULL; // No object for it, yet
  439. m_paKey[i].strName = SysAllocStringLen(NULL, MAX_PATH + 1);
  440. if (!m_paKey[i].strName) return E_FAIL;
  441. retCode = RegEnumKeyW(hKey, i, m_paKey[i].strName, MAX_PATH + 1);
  442. if (retCode != ERROR_SUCCESS) return E_FAIL;
  443. }
  444. retCode = ERROR_SUCCESS; // Initialize for the loop
  445. for (i = 0; (i < m_dwValueCnt) && (retCode == ERROR_SUCCESS); i++) {
  446. m_paValue[i].bDirty = FALSE; // Not dirty
  447. m_paValue[i].strName = SysAllocStringLen(NULL, dwcMaxValueName);
  448. m_paValue[i].strData = SysAllocStringLen(NULL, dwcMaxValueData);
  449. if (!m_paValue[i].strName || !m_paValue[i].strData) return E_FAIL;
  450. DWORD dwcNameLen = dwcMaxValueName + 1;
  451. DWORD dwcValueSize = dwcMaxValueData;
  452. retCode = RegEnumValueW (hKey, i, m_paValue[i].strName, &dwcNameLen,
  453. NULL, &m_paValue[i].dwType, (LPBYTE) m_paValue[i].strData,
  454. &dwcValueSize);
  455. if (retCode != ERROR_SUCCESS) return E_FAIL;
  456. // tbd: perhaps race condition that longer entry was added after RegQueryInfoKey call
  457. }
  458. RegCloseKey (hKey); // Close the key handle.
  459. return S_OK;
  460. }
  461. STDMETHODIMP CSEORegDictionary::FreeBase() {
  462. m_hkBaseKey = NULL;
  463. return (S_OK);
  464. }
  465. STDMETHODIMP CSEORegDictionary::FreeData() {
  466. DWORD dwIdx;
  467. for (dwIdx=0;dwIdx<m_dwValueCnt;dwIdx++) {
  468. MySysFreeStringInPlace(&m_paValue[dwIdx].strName);
  469. MySysFreeStringInPlace(&m_paValue[dwIdx].strData);
  470. }
  471. m_dwValueCnt = 0;
  472. MyFreeInPlace(&m_paValue);
  473. for (dwIdx=0;dwIdx<m_dwKeyCnt;dwIdx++) {
  474. MySysFreeStringInPlace(&m_paKey[dwIdx].strName);
  475. if (m_paKey[dwIdx].pKey) {
  476. RELEASE_AND_SHREAD_POINTER(m_paKey[dwIdx].pKey);
  477. }
  478. }
  479. MyFreeInPlace(&m_paKey);
  480. return (S_OK);
  481. }
  482. DATA (Member variables):
  483. DWORD m_dwValueCnt;
  484. struct ValueEntry {
  485. BSTR strName;
  486. DWORD dwType;
  487. BSTR strData;
  488. BOOL bDirty;
  489. } *m_paValue;
  490. DWORD m_dwKeyCnt;
  491. struct KeyEntry {
  492. BSTR strName;
  493. CComObject<CSEORegDictionary> *pKey;
  494. } *m_paKey;
  495. */
  496. STDMETHODIMP CSEORegDictionary::Load(LPCOLESTR pszMachine,
  497. SEO_HKEY skBaseKey,
  498. LPCOLESTR pszSubKey,
  499. IErrorLog *) {
  500. USES_CONVERSION; // Needed for OLE2A(), etc.
  501. if (!pszMachine || !pszSubKey)
  502. return (E_INVALIDARG);
  503. else
  504. return Load(OLE2A(pszMachine), skBaseKey, OLE2A(pszSubKey));
  505. }
  506. STDMETHODIMP CSEORegDictionary::Load(LPCSTR pszMachine,
  507. SEO_HKEY skBaseKey,
  508. LPCSTR pszSubKey) {
  509. HRESULT hrRes;
  510. if (!skBaseKey) return (E_INVALIDARG);
  511. if (!m_strMachine.empty() || m_hkBaseKey || !m_strSubKey.empty()) {
  512. CloseKey();
  513. }
  514. m_strMachine = pszMachine;
  515. m_strSubKey = pszSubKey;
  516. DWORD dwLastPos = m_strSubKey.length() - 1;
  517. if(m_strSubKey[dwLastPos] == *PATH_SEP) m_strSubKey.erase(dwLastPos, 1);
  518. m_hkBaseKey = (HKEY) skBaseKey;
  519. if (!m_strMachine.data() || !m_strSubKey.data()) return (E_OUTOFMEMORY);
  520. hrRes = OpenKey();
  521. return (hrRes);
  522. }
  523. HRESULT CSEORegDictionary::FinalConstruct() {
  524. HRESULT hrRes;
  525. m_hkBaseKey = NULL;
  526. m_hkThisKey = NULL;
  527. m_dwValueCount = 0;
  528. m_dwKeyCount = 0;
  529. m_dwcMaxValueData = 0; // Longest Value data size
  530. m_dwcMaxNameLen = 0; // Longest Key name size
  531. hrRes = CoCreateFreeThreadedMarshaler(GetControllingUnknown(),&m_pUnkMarshaler.p);
  532. _ASSERTE(!SUCCEEDED(hrRes)||m_pUnkMarshaler);
  533. return (SUCCEEDED(hrRes)?S_OK:hrRes);
  534. }
  535. void CSEORegDictionary::FinalRelease() {
  536. CloseKey();
  537. m_pUnkMarshaler.Release();
  538. }
  539. STDMETHODIMP CSEORegDictionary::OpenKey() {
  540. // tbd: Verify that the A version of RegOpenKeyEx is compatible with the
  541. // W version of RegQueryValueEx, etc.
  542. DWORD retCode = RegOpenKeyExA (m_hkBaseKey, m_strSubKey.data(),
  543. 0, KEY_READ, &m_hkThisKey);
  544. if (retCode != ERROR_SUCCESS) {
  545. m_hkThisKey = NULL; // Ensure this wasn't set
  546. return E_FAIL; // Unable to open key
  547. }
  548. DWORD dwKeyNameLen = 0;
  549. DWORD dwValueNameLen = 0;
  550. retCode = RegQueryInfoKey(m_hkThisKey, NULL, NULL, NULL, &m_dwKeyCount,
  551. &dwKeyNameLen, NULL, &m_dwValueCount,
  552. &dwValueNameLen, &m_dwcMaxValueData, NULL, NULL);
  553. if (retCode != ERROR_SUCCESS) return E_FAIL; // Unable to get data for key
  554. m_dwcMaxNameLen = max(dwKeyNameLen, dwValueNameLen);
  555. return S_OK;
  556. }
  557. STDMETHODIMP CSEORegDictionary::CloseKey() {
  558. if(m_hkThisKey) RegCloseKey (m_hkThisKey); // Close the key handle.
  559. return S_OK;
  560. }
  561. STDMETHODIMP CSEORegDictionary::LoadItemA(LPCSTR lpValueName,
  562. DWORD &dType,
  563. LPBYTE lpData,
  564. LPDWORD lpcbDataParam) {
  565. if (!m_hkThisKey) return E_FAIL; // Wasn't opened
  566. DWORD dwDummy = m_dwcMaxValueData;
  567. if(!lpcbDataParam) lpcbDataParam = &dwDummy;
  568. DWORD retCode = RegQueryValueExA(m_hkThisKey, lpValueName, NULL, &dType,
  569. lpData, lpcbDataParam);
  570. if (retCode != ERROR_SUCCESS) return E_FAIL; // Error reading data
  571. return S_OK;
  572. }
  573. STDMETHODIMP CSEORegDictionary::LoadItemW(LPCWSTR lpValueName,
  574. DWORD &dType,
  575. LPBYTE lpData,
  576. LPDWORD lpcbDataParam) {
  577. if (!m_hkThisKey) return E_FAIL; // Wasn't opened
  578. DWORD dwDummy = m_dwcMaxValueData;
  579. if(!lpcbDataParam) lpcbDataParam = &dwDummy;
  580. DWORD retCode = RegQueryValueExW(m_hkThisKey, lpValueName, NULL, &dType,
  581. lpData, lpcbDataParam);
  582. if (retCode != ERROR_SUCCESS) return E_FAIL; // Error reading data
  583. return S_OK;
  584. }