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.

371 lines
10 KiB

  1. #include "precomp.h"
  2. #include "regins.h"
  3. /////////////////////////////////////////////////////////////////////////////
  4. // CRegInsMap operations
  5. HRESULT CRegInsMap::PerformAction(HKEY *phk /*= NULL*/)
  6. {
  7. (void)phk;
  8. return E_NOTIMPL;
  9. }
  10. HRESULT CRegInsMap::RegToIns(HKEY *phk /*= NULL*/, BOOL fClear /*= FALSE*/)
  11. {
  12. TCHAR szBuffer[MAX_PATH];
  13. VARIANT var;
  14. HKEY hk;
  15. HRESULT hr;
  16. DWORD cBuffer, dwType;
  17. LONG lResult;
  18. if ((phk != NULL && *phk == NULL) && m_pszRegKey == NULL)
  19. return E_INVALIDARG;
  20. //----- Special cases processing -----
  21. //_____ Close cached reg key _____
  22. if ((phk != NULL && *phk != NULL) && (m_pszRegKey == NULL && m_pszRegValue == NULL)) {
  23. ASSERT(!fClear);
  24. ASSERT(m_pszInsSection == NULL && m_pszInsKey == NULL);
  25. SHCloseKey(*phk);
  26. *phk = NULL;
  27. return S_FALSE;
  28. }
  29. //_____ Clear ins file entry (not even necessary to open reg key) _____
  30. ASSERT(m_pszInsSection != NULL && m_pszInsKey != NULL);
  31. if (fClear) {
  32. ASSERT(phk == NULL);
  33. // REVIEW: (andrewgu) if i'm clearing and when last entry is gone see if section is gone
  34. // as well and if it is not, do getprivateprofilesection to see if section is empty and
  35. // delete it if it is.
  36. WritePrivateProfileString(m_pszInsSection, m_pszInsKey, NULL, s_pszIns);
  37. return S_FALSE;
  38. }
  39. //----- Main processing -----
  40. hk = (phk != NULL) ? *phk : NULL;
  41. openRegKey(&hk);
  42. if (hk == NULL)
  43. return E_FAIL;
  44. //_____ Special case of caching reg key _____
  45. if (m_pszInsSection == NULL) {
  46. ASSERT(m_pszInsKey == NULL);
  47. if (phk == NULL)
  48. return E_INVALIDARG;
  49. *phk = hk;
  50. return S_FALSE;
  51. }
  52. szBuffer[0] = TEXT('\0');
  53. cBuffer = sizeof(szBuffer);
  54. lResult = SHQueryValueEx(hk, m_pszRegValue, NULL, &dwType, szBuffer, &cBuffer);
  55. if (phk != NULL && *phk != hk)
  56. SHCloseKey(hk);
  57. if (lResult != ERROR_SUCCESS)
  58. return E_UNEXPECTED;
  59. //----- Convert szBuffer into var with proper type -----
  60. hr = S_OK;
  61. VariantClear(&var);
  62. switch (dwType) {
  63. case REG_BINARY:
  64. if (cBuffer > sizeof(int)) {
  65. hr = E_UNEXPECTED;
  66. break;
  67. }
  68. // fall through
  69. // case REG_DWORD_LITTLE_ENDIAN:
  70. case REG_DWORD:
  71. var.vt = VT_I4;
  72. var.lVal = *(PINT)szBuffer;
  73. break;
  74. case REG_SZ:
  75. case REG_EXPAND_SZ:
  76. var.vt = VT_BSTR;
  77. var.bstrVal = T2BSTR(szBuffer);
  78. break;
  79. // case REG_DWORD_BIG_ENDIAN:
  80. // case REG_LINK:
  81. // case REG_MULTI_SZ:
  82. // case REG_NONE:
  83. // case REG_RESOURCE_LIST:
  84. default:
  85. hr = E_FAIL;
  86. }
  87. if (FAILED(hr))
  88. return hr;
  89. //----- Convert var into szBuffer appropriate for WritePrivateProfileString -----
  90. switch (var.vt) {
  91. case VT_I4:
  92. wnsprintf(szBuffer, countof(szBuffer), TEXT("%l"), var.lVal);
  93. break;
  94. case VT_I2:
  95. wnsprintf(szBuffer, countof(szBuffer), TEXT("%i"), var.iVal);
  96. break;
  97. case VT_UI1:
  98. wnsprintf(szBuffer, countof(szBuffer), TEXT("%u"), (UINT)var.bVal);
  99. break;
  100. case VT_BOOL:
  101. wnsprintf(szBuffer, countof(szBuffer), TEXT("%u"), (UINT)var.boolVal);
  102. break;
  103. case VT_BSTR:
  104. W2Tbuf(var.bstrVal, szBuffer, countof(szBuffer));
  105. break;
  106. // too many cases to enumerate that are invalid
  107. default:
  108. hr = E_FAIL;
  109. }
  110. if (FAILED(hr))
  111. return hr;
  112. WritePrivateProfileString(m_pszInsSection, m_pszInsKey, szBuffer, s_pszIns);
  113. return S_OK;
  114. }
  115. HRESULT CRegInsMap::InsToReg(HKEY *phk /*= NULL*/, BOOL fClear /*= FALSE*/)
  116. {
  117. (void)phk; (void)fClear;
  118. return E_NOTIMPL;
  119. }
  120. HRESULT CRegInsMap::RegToInsArray(CRegInsMap *prg, UINT cEntries, BOOL fClear /*= FALSE*/)
  121. {
  122. HKEY hk,
  123. *rghkStack;
  124. HRESULT hr;
  125. UINT i, cStackDepth;
  126. BOOL fContinueOnFailure,
  127. fTotalSuccess, fBufferOverrun;
  128. if (prg == NULL)
  129. return E_INVALIDARG;
  130. if (cEntries == 0)
  131. return S_OK;
  132. hr = S_OK;
  133. fContinueOnFailure = TRUE;
  134. fTotalSuccess = TRUE;
  135. fBufferOverrun = FALSE;
  136. if (fClear) {
  137. for (i = 0; i < cEntries; i++) {
  138. hr = prg->RegToIns(NULL, fClear);
  139. if (FAILED(hr)) {
  140. fTotalSuccess = FALSE;
  141. if (!fContinueOnFailure)
  142. break;
  143. }
  144. }
  145. if (FAILED(hr))
  146. return hr;
  147. return fTotalSuccess ? S_OK : S_FALSE;
  148. }
  149. rghkStack = new HKEY[cEntries/2 + 1];
  150. if (rghkStack == NULL)
  151. return E_OUTOFMEMORY;
  152. cStackDepth = 0;
  153. for (i = 0; i < cEntries; i++) {
  154. if (cStackDepth == 0)
  155. hk = NULL;
  156. else {
  157. hk = rghkStack[cStackDepth-1];
  158. ASSERT(hk != NULL);
  159. }
  160. hr = prg->RegToIns(&hk);
  161. if (FAILED(hr)) {
  162. fTotalSuccess = FALSE;
  163. if (fContinueOnFailure)
  164. continue;
  165. else
  166. break;
  167. }
  168. if (hk != NULL) {
  169. if (hk != rghkStack[cStackDepth-1]) {
  170. if (cStackDepth >= cEntries/2 + 1) {
  171. SHCloseKey(hk);
  172. hr = E_UNEXPECTED;
  173. fTotalSuccess = FALSE;
  174. fBufferOverrun = TRUE;
  175. break;
  176. }
  177. rghkStack[cStackDepth++] = hk;
  178. }
  179. }
  180. else
  181. if (cStackDepth > 0)
  182. rghkStack[--cStackDepth] = NULL;
  183. }
  184. if (FAILED(hr)) {
  185. ASSERT(!fTotalSuccess);
  186. for (i = 0; i < cEntries/2 + 1; i++)
  187. if (rghkStack[i] != NULL) {
  188. SHCloseKey(rghkStack[i]);
  189. rghkStack[i] = NULL;
  190. }
  191. cStackDepth = 0;
  192. }
  193. ASSERT(cStackDepth == 0);
  194. delete[] rghkStack;
  195. if (!fBufferOverrun)
  196. if (fContinueOnFailure && !fTotalSuccess)
  197. hr = S_FALSE;
  198. return hr;
  199. }
  200. HRESULT CRegInsMap::InsToRegArray(CRegInsMap *prg, UINT cEntries, BOOL fClear /*= FALSE*/)
  201. {
  202. (void)prg; (void)cEntries; (void)fClear;
  203. return E_NOTIMPL;
  204. }
  205. /////////////////////////////////////////////////////////////////////////////
  206. // CRegInsMap implementation helper routines
  207. void CRegInsMap::openRegKey(HKEY *phk)
  208. {
  209. LPCTSTR pszRegKey;
  210. HRESULT hr;
  211. LONG lResult;
  212. ASSERT(phk != NULL);
  213. if (*phk != NULL && m_pszRegKey == NULL)
  214. return;
  215. ASSERT(m_pszRegKey != NULL);
  216. if (*phk == NULL) {
  217. hr = getHive(phk, &pszRegKey);
  218. if (FAILED(hr)) {
  219. ASSERT(*phk == NULL && pszRegKey == NULL);
  220. return;
  221. }
  222. ASSERT(*phk != NULL && pszRegKey != NULL);
  223. }
  224. else {
  225. ASSERT(getHive(NULL, NULL, GH_LOOKUPONLY) != S_OK);
  226. pszRegKey = m_pszRegKey;
  227. }
  228. lResult = SHOpenKey(*phk, pszRegKey, KEY_QUERY_VALUE, phk);
  229. if (lResult != ERROR_SUCCESS) {
  230. ASSERT(*phk == NULL);
  231. }
  232. }
  233. HRESULT CRegInsMap::getHive(HKEY *phk, LPCTSTR *ppszRegKey, WORD wFlags /*= GH_DEFAULT*/)
  234. {
  235. LPCTSTR pszSlash;
  236. if (!(wFlags & GH_LOOKUPONLY)) {
  237. if (phk == NULL || ppszRegKey == NULL)
  238. return E_INVALIDARG;
  239. *phk = NULL;
  240. *ppszRegKey = NULL;
  241. }
  242. pszSlash = StrChr(m_pszRegKey, TEXT('\\'));
  243. if (pszSlash == NULL)
  244. return E_FAIL;
  245. ASSERT(*(pszSlash+1) != TEXT('\0'));
  246. struct {
  247. HKEY hk;
  248. LPCTSTR pszHive;
  249. } map[] = {
  250. { HKEY_CLASSES_ROOT, RH_HKCR },
  251. { HKEY_CURRENT_USER, RH_HKCU },
  252. { HKEY_LOCAL_MACHINE, RH_HKLM },
  253. { HKEY_USERS, RH_HKU }
  254. };
  255. for (UINT i = 0; i < countof(map); i++)
  256. if (StrCmpNI(m_pszRegKey, map[i].pszHive, INT(m_pszRegKey-pszSlash) + 1) == 0)
  257. break;
  258. if (i >= countof(map)) {
  259. if (!(wFlags & GH_LOOKUPONLY))
  260. *ppszRegKey = m_pszRegKey;
  261. return S_FALSE;
  262. }
  263. if (!(wFlags & GH_LOOKUPONLY)) {
  264. *phk = map[i].hk;
  265. *ppszRegKey = pszSlash + 1;
  266. }
  267. return S_OK;
  268. }
  269. // HINTS: (andrewgu) on optimization
  270. // 1. to start a regkey optimization section (i.e. to cache a reg key) have InsSection set to
  271. // NULL, at the same time InsKey is ASSERTed NULL, meaning it better be NULL too;
  272. // 2. to close last cached key, have RegKey and RegValue equal NULL. also InsSection and InsKey
  273. // are ASSERTed NULL, so they also should be NULL;
  274. // 3. if in optimization section and reg key is not empty current cached hk will be combined with
  275. // regkey, it'll ASSERT if finds hive in RegKey;
  276. // 4. if hive is not found in RegKey and the object is not in the optimization section it's an error
  277. // 5. nested optimization sections are allowed
  278. /*
  279. LPCTSTR CRegInsMap::s_pszIns = TEXT("c:\foo.ini");
  280. CRegInsMap rgTest1 = { TEXT("HKLM\\RegKey0"), TEXT("RegValue0"), 0L, NULL, NULL };
  281. CRegInsMap rgTest[] = {
  282. { RH_HKLM TEXT("RegKey0"), NULL, 0L, NULL, NULL },
  283. { TEXT("RegKey1"), TEXT("RegValue1"), 0L, TEXT("InsSection1"), TEXT("InsKey1") },
  284. { NULL , TEXT("RegValue2"), 0L, TEXT("InsSection1"), TEXT("InsKey2") },
  285. { NULL, NULL, 0L, NULL, NULL },
  286. { RH_HKCR RK_IEAK, RV_TOOLBARBMP, 0L, IS_BRANDING, IK_TOOLBARBMP },
  287. { TEXT("RegKey4"), TEXT("RegValue4"), 0L, TEXT("InsSection4"), TEXT("InsKey4") },
  288. { TEXT("RegKey5"), TEXT("RegValue5"), 0L, TEXT("InsSection5"), TEXT("InsKey5") },
  289. { TEXT("RegKey6"), TEXT("RegValue6"), 0L, TEXT("InsSection6"), TEXT("InsKey6") },
  290. { TEXT("RegKey7"), TEXT("RegValue7"), 0L, TEXT("InsSection7"), TEXT("InsKey7") },
  291. { TEXT("RegKey8"), TEXT("RegValue8"), 0L, TEXT("InsSection8"), TEXT("InsKey8") },
  292. { TEXT("RegKey9"), TEXT("RegValue9"), 0L, TEXT("InsSection9"), TEXT("InsKey9") }
  293. };
  294. // Example usage
  295. rgTest[0].RegToInsArray(rgTest, countof(rgTest));
  296. */