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.

426 lines
12 KiB

  1. //
  2. // Registry.cpp
  3. //
  4. // Wrapper class to make the registry less painful.
  5. //
  6. // 3/04/1998 KenSh Created
  7. // 3/28/1999 KenSh Added DeleteAllValues, CloneSubKey
  8. //
  9. #include "stdafx.h"
  10. #include "Registry.h"
  11. #ifdef _DEBUG
  12. #ifdef DEBUG_NEW
  13. #define new DEBUG_NEW
  14. #endif
  15. #undef THIS_FILE
  16. static char THIS_FILE[] = __FILE__;
  17. #endif
  18. #ifndef ASSERT
  19. #define ASSERT(x)
  20. #endif
  21. #ifndef _countof
  22. #define _countof(ar) (sizeof(ar) / sizeof((ar)[0]))
  23. #endif
  24. CRegistry::CRegistry(HKEY hkeyParent, LPCTSTR pszKey, REGSAM dwAccessFlags /*=KEY_ALL_ACCESS*/, BOOL bCreateIfMissing /*=TRUE*/)
  25. {
  26. m_hKey = NULL;
  27. ASSERT(hkeyParent != NULL);
  28. ASSERT(pszKey != NULL);
  29. if (bCreateIfMissing)
  30. CreateKey(hkeyParent, pszKey, dwAccessFlags);
  31. else
  32. OpenKey(hkeyParent, pszKey, dwAccessFlags);
  33. }
  34. CRegistry::~CRegistry()
  35. {
  36. CloseKey();
  37. }
  38. void CRegistry::CloseKey()
  39. {
  40. if (m_hKey != NULL)
  41. {
  42. RegCloseKey(m_hKey);
  43. m_hKey = NULL;
  44. }
  45. }
  46. BOOL CRegistry::OpenKey(HKEY hkeyParent, LPCTSTR pszKey, REGSAM dwAccessFlags /*=KEY_ALL_ACCESS*/)
  47. {
  48. CloseKey();
  49. return (ERROR_SUCCESS == RegOpenKeyEx(hkeyParent, pszKey, 0, dwAccessFlags, &m_hKey));
  50. }
  51. BOOL CRegistry::CreateKey(HKEY hkeyParent, LPCTSTR pszKey, REGSAM dwAccessFlags /*=KEY_ALL_ACCESS*/)
  52. {
  53. DWORD dwDisposition;
  54. CloseKey();
  55. return (ERROR_SUCCESS == RegCreateKeyEx(hkeyParent, pszKey, 0, NULL, REG_OPTION_NON_VOLATILE,
  56. dwAccessFlags, NULL, &m_hKey, &dwDisposition));
  57. }
  58. BOOL CRegistry::OpenSubKey(LPCTSTR pszKey, REGSAM dwAccessFlags /*=KEY_ALL_ACCESS*/)
  59. {
  60. BOOL bResult = FALSE;
  61. if (m_hKey)
  62. {
  63. HKEY hkey = m_hKey;
  64. m_hKey = NULL;
  65. bResult = OpenKey(hkey, pszKey, dwAccessFlags);
  66. RegCloseKey(hkey);
  67. }
  68. return bResult;
  69. }
  70. BOOL CRegistry::CreateSubKey(LPCTSTR pszKey, REGSAM dwAccessFlags /*=KEY_ALL_ACCESS*/)
  71. {
  72. BOOL bResult = FALSE;
  73. if (m_hKey)
  74. {
  75. HKEY hkey = m_hKey;
  76. m_hKey = NULL;
  77. bResult = CreateKey(hkey, pszKey, dwAccessFlags);
  78. RegCloseKey(hkey);
  79. }
  80. return bResult;
  81. }
  82. DWORD RegDeleteSubKey(HKEY hkey, LPCTSTR pszSubKey)
  83. {
  84. {
  85. HKEY hSubKey;
  86. LONG err = RegOpenKeyEx(hkey, pszSubKey, 0, KEY_ALL_ACCESS, &hSubKey);
  87. if (ERROR_SUCCESS == err)
  88. {
  89. DWORD dwNumSubKeys;
  90. RegQueryInfoKey(hSubKey, NULL, NULL, NULL, &dwNumSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
  91. for (DWORD iSubKey = dwNumSubKeys; iSubKey > 0; iSubKey--)
  92. {
  93. TCHAR szSubKey[260];
  94. DWORD cchSubKey = _countof(szSubKey);
  95. if (ERROR_SUCCESS == RegEnumKeyEx(hSubKey, iSubKey-1, szSubKey, &cchSubKey, NULL, NULL, NULL, NULL))
  96. {
  97. RegDeleteSubKey(hSubKey, szSubKey);
  98. }
  99. }
  100. RegCloseKey(hSubKey);
  101. }
  102. }
  103. return RegDeleteKey(hkey, pszSubKey);
  104. }
  105. BOOL CRegistry::DeleteSubKey(LPCTSTR pszKey)
  106. {
  107. if (m_hKey && RegDeleteSubKey(m_hKey, pszKey) == ERROR_SUCCESS)
  108. {
  109. return TRUE;
  110. }
  111. else
  112. {
  113. return FALSE;
  114. }
  115. }
  116. // Zero is returned if and only if the value does not exist.
  117. DWORD CRegistry::GetValueSize(LPCTSTR pszValueName)
  118. {
  119. DWORD dwSize = 0;
  120. if (m_hKey)
  121. RegQueryValueEx(m_hKey, pszValueName, NULL, NULL, NULL, &dwSize);
  122. return dwSize;
  123. }
  124. #ifdef _AFX
  125. BOOL CRegistry::QueryStringValue(LPCTSTR pszValueName, CString& strResult)
  126. {
  127. BOOL bSuccess = FALSE;
  128. if (m_hKey)
  129. {
  130. TCHAR szBuf[50]; // default buffer for short strings
  131. DWORD dwSize = sizeof(szBuf);
  132. LONG lResult;
  133. #if _REG_STRONGTYPES
  134. DWORD dwType;
  135. lResult = RegQueryValueEx(m_hKey, pszValueName, NULL, &dwType, (LPBYTE)szBuf, &dwSize);
  136. if ((lResult == ERROR_SUCCESS || lResult == ERROR_MORE_DATA) && dwType == REG_SZ)
  137. #else
  138. lResult = RegQueryValueEx(m_hKey, pszValueName, NULL, NULL, (LPBYTE)szBuf, &dwSize);
  139. if (lResult == ERROR_SUCCESS || lResult == ERROR_MORE_DATA)
  140. #endif
  141. {
  142. if (lResult == ERROR_SUCCESS)
  143. {
  144. strResult = szBuf;
  145. bSuccess = TRUE;
  146. }
  147. else
  148. {
  149. int cch = (dwSize / sizeof(TCHAR)) - 1;
  150. LPTSTR psz = strResult.GetBufferSetLength(cch);
  151. bSuccess = (ERROR_SUCCESS == RegQueryValueEx(m_hKey, pszValueName, NULL, NULL, (LPBYTE)psz, &dwSize));
  152. strResult.ReleaseBuffer(cch);
  153. }
  154. }
  155. }
  156. if (!bSuccess)
  157. {
  158. strResult.Empty();
  159. }
  160. return bSuccess;
  161. }
  162. #endif // _AFX
  163. #ifdef _AFX
  164. CString CRegistry::QueryStringValue(LPCTSTR pszValueName)
  165. {
  166. CString str;
  167. QueryStringValue(pszValueName, str);
  168. return str;
  169. }
  170. #endif // _AFX
  171. #ifdef _AFX
  172. BOOL CRegistry::SetStringValue(LPCTSTR pszValueName, const CString& strData)
  173. {
  174. return m_hKey && (ERROR_SUCCESS == RegSetValueEx(m_hKey, pszValueName, 0, REG_SZ, (LPBYTE)(LPCTSTR)strData, (DWORD)strData.GetLength() + 1));
  175. }
  176. #endif // _AFX
  177. BOOL CRegistry::QueryStringValue(LPCTSTR pszValueName, LPTSTR pszBuf, int cchBuf, int* pNumCharsWritten)
  178. {
  179. BOOL bSuccess = FALSE;
  180. if (m_hKey)
  181. {
  182. #if _REG_STRONGTYPES
  183. DWORD dwType;
  184. bSuccess = (ERROR_SUCCESS == RegQueryValueEx(m_hKey, pszValueName, NULL, &dwType, (LPBYTE)pszBuf, (DWORD*)&cchBuf)
  185. && dwType == REG_SZ);
  186. #else
  187. bSuccess = (ERROR_SUCCESS == RegQueryValueEx(m_hKey, pszValueName, NULL, NULL, (LPBYTE)pszBuf, (DWORD*)&cchBuf));
  188. #endif
  189. if (pNumCharsWritten != NULL)
  190. {
  191. if (!bSuccess)
  192. *pNumCharsWritten = 0;
  193. else
  194. *pNumCharsWritten = (int)((DWORD)cchBuf / sizeof(TCHAR)) - 1;
  195. }
  196. }
  197. return bSuccess;
  198. }
  199. // string is allocated with new TCHAR[], use delete[] to delete it.
  200. #if _REG_ALLOCMEM
  201. LPTSTR CRegistry::QueryStringValue(LPCTSTR pszValueName, int* pNumCharsWritten /*=NULL*/)
  202. {
  203. LPTSTR pszResult = NULL;
  204. int cch = 0;
  205. if (m_hKey)
  206. {
  207. TCHAR szBuf[50]; // default buffer for short strings
  208. DWORD dwSize = sizeof(szBuf);
  209. LONG lResult;
  210. #if _REG_STRONGTYPES
  211. DWORD dwType;
  212. lResult = RegQueryValueEx(m_hKey, pszValueName, NULL, &dwType, (LPBYTE)szBuf, &dwSize);
  213. if ((lResult == ERROR_SUCCESS || lResult == ERROR_MORE_DATA) && dwType == REG_SZ)
  214. #else
  215. lResult = RegQueryValueEx(m_hKey, pszValueName, NULL, NULL, (LPBYTE)szBuf, &dwSize);
  216. if (lResult == ERROR_SUCCESS || lResult == ERROR_MORE_DATA)
  217. #endif
  218. {
  219. cch = (dwSize / sizeof(TCHAR)) - 1;
  220. pszResult = new TCHAR[cch+1];
  221. if (pszResult != NULL)
  222. {
  223. if (lResult == ERROR_SUCCESS)
  224. {
  225. memcpy(pszResult, szBuf, dwSize);
  226. }
  227. else
  228. {
  229. if (ERROR_SUCCESS != RegQueryValueEx(m_hKey, pszValueName, NULL, NULL, (LPBYTE)pszResult, &dwSize))
  230. {
  231. delete [] pszResult;
  232. pszResult = NULL;
  233. cch = 0;
  234. }
  235. }
  236. }
  237. }
  238. }
  239. if (pNumCharsWritten != NULL)
  240. *pNumCharsWritten = cch;
  241. return pszResult;
  242. }
  243. #endif // _REG_ALLOCMEM
  244. BOOL CRegistry::SetStringValue(LPCTSTR pszValueName, LPCTSTR pszData)
  245. {
  246. return m_hKey && (ERROR_SUCCESS == RegSetValueEx(m_hKey, pszValueName, 0, REG_SZ, (LPBYTE)pszData, (DWORD)(lstrlen(pszData)+1) * sizeof(TCHAR)));
  247. }
  248. BOOL CRegistry::QueryDwordValue(LPCTSTR pszValueName, DWORD* pVal)
  249. {
  250. BOOL bSuccess = FALSE;
  251. if (m_hKey)
  252. {
  253. DWORD dwSize = sizeof(DWORD);
  254. #if _REG_STRONGTYPES
  255. DWORD dwType;
  256. if (ERROR_SUCCESS == RegQueryValueEx(m_hKey, pszValueName, NULL, &dwType, (LPBYTE)pVal, &dwSize))
  257. {
  258. if (dwType == REG_DWORD || (dwType == REG_BINARY && dwSize == sizeof(DWORD)))
  259. bSuccess = TRUE;
  260. }
  261. #else
  262. bSuccess = (ERROR_SUCCESS == RegQueryValueEx(m_hKey, pszValueName, NULL, NULL, (LPBYTE)pVal, &dwSize));
  263. #endif
  264. }
  265. return bSuccess;
  266. }
  267. BOOL CRegistry::SetDwordValue(LPCTSTR pszValueName, DWORD dwVal)
  268. {
  269. return m_hKey && (ERROR_SUCCESS == RegSetValueEx(m_hKey, pszValueName, 0, REG_DWORD, (LPBYTE)&dwVal, sizeof(DWORD)));
  270. }
  271. BOOL CRegistry::SetBinaryValue(LPCTSTR pszValueName, LPCVOID pvData, DWORD cbData)
  272. {
  273. return m_hKey && (ERROR_SUCCESS == RegSetValueEx(m_hKey, pszValueName, 0, REG_BINARY, (LPBYTE)pvData, cbData));
  274. }
  275. BOOL CRegistry::DeleteAllValues()
  276. {
  277. if (m_hKey)
  278. {
  279. TCHAR szValueName[MAX_PATH];
  280. for (;;)
  281. {
  282. DWORD cbValueName = _countof(szValueName);
  283. if (ERROR_SUCCESS != RegEnumValue(m_hKey, 0, szValueName, &cbValueName, NULL, NULL, NULL, NULL))
  284. return TRUE;
  285. if (!DeleteValue(szValueName))
  286. return FALSE;
  287. }
  288. }
  289. return TRUE;
  290. }
  291. // Copies the named subkey from this registry key to the named subkey in the target registry key.
  292. BOOL CRegistry::CloneSubKey(LPCTSTR pszExistingSubKey, CRegistry& regDest, BOOL bRecursive)
  293. {
  294. ASSERT(pszExistingSubKey != NULL);
  295. if (!m_hKey || !regDest.m_hKey)
  296. return FALSE;
  297. CRegistry regSrc;
  298. if (!regSrc.OpenKey(m_hKey, pszExistingSubKey, KEY_READ))
  299. {
  300. ASSERT(FALSE);
  301. return FALSE;
  302. }
  303. DWORD cbAlloc = 256;
  304. HANDLE hHeap = GetProcessHeap();
  305. BYTE* pbData = (BYTE*)HeapAlloc(hHeap, 0, cbAlloc);
  306. if (pbData)
  307. {
  308. // Copy values first
  309. for (DWORD iValue = 0; ; iValue++)
  310. {
  311. TCHAR szValueName[MAX_PATH];
  312. DWORD cbValueName = _countof(szValueName);
  313. DWORD dwType;
  314. DWORD cbData;
  315. if (ERROR_SUCCESS != RegEnumValue(regSrc.m_hKey, iValue, szValueName, &cbValueName, NULL, &dwType, NULL, &cbData))
  316. break;
  317. if (cbData > cbAlloc)
  318. {
  319. BYTE* pbDataNew = (BYTE*)HeapReAlloc(hHeap, 0, pbData, cbData + 256);
  320. if (pbDataNew == NULL)
  321. {
  322. HeapFree(hHeap, 0, pbData);
  323. return FALSE;
  324. }
  325. pbData = pbDataNew;
  326. cbAlloc = cbData + 256;
  327. }
  328. if (ERROR_SUCCESS != RegQueryValueEx(regSrc.m_hKey, szValueName, NULL, NULL, pbData, &cbData))
  329. break; // REVIEW: return FALSE?
  330. if (ERROR_SUCCESS != RegSetValueEx(regDest.m_hKey, szValueName, 0, dwType, pbData, cbData))
  331. break; // REVIEW: return FALSE? (need to free memory)
  332. }
  333. HeapFree(hHeap, 0, pbData);
  334. }
  335. // Copy subkeys
  336. if (bRecursive)
  337. {
  338. for (DWORD iSubKey = 0; ; iSubKey++)
  339. {
  340. TCHAR szKeyName[MAX_PATH];
  341. DWORD cbKeyName = _countof(szKeyName);
  342. if (ERROR_SUCCESS != RegEnumKeyEx(regSrc.m_hKey, iSubKey, szKeyName, &cbKeyName, NULL, NULL, NULL, NULL))
  343. break;
  344. CRegistry regDest2;
  345. if (!regDest2.CreateKey(regDest.m_hKey, szKeyName, KEY_ALL_ACCESS))
  346. return FALSE;
  347. if (!regSrc.CloneSubKey(szKeyName, regDest2, TRUE))
  348. return FALSE;
  349. }
  350. }
  351. return TRUE;
  352. }
  353. // Copies the named subkey to a new subkey of this registry class, with a new name.
  354. BOOL CRegistry::CloneSubKey(LPCTSTR pszExistingSubKey, LPCTSTR pszNewSubKey, BOOL bRecursive)
  355. {
  356. ASSERT(pszExistingSubKey != NULL);
  357. ASSERT(pszNewSubKey != NULL);
  358. ASSERT(0 != lstrcmpi(pszExistingSubKey, pszNewSubKey)); // names can't be the same
  359. CRegistry regDest;
  360. if (!m_hKey || !regDest.CreateKey(m_hKey, pszNewSubKey, KEY_ALL_ACCESS))
  361. {
  362. return FALSE;
  363. }
  364. return CloneSubKey(pszExistingSubKey, regDest, bRecursive);
  365. }