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
8.5 KiB

  1. #include "pch.h"
  2. #pragma hdrstop
  3. #include "registry.h"
  4. RegKey::RegKey(
  5. void
  6. ) : m_hkeyRoot(NULL),
  7. m_hkey(NULL)
  8. {
  9. DBGTRACE((DM_REG, DL_MID, TEXT("RegKey::RegKey [default]")));
  10. }
  11. RegKey::RegKey(
  12. HKEY hkeyRoot,
  13. LPCTSTR pszSubKey
  14. ) : m_hkeyRoot(hkeyRoot),
  15. m_hkey(NULL),
  16. m_strSubKey(pszSubKey)
  17. {
  18. DBGTRACE((DM_REG, DL_MID, TEXT("RegKey::RegKey")));
  19. //
  20. // Nothing to do.
  21. //
  22. }
  23. RegKey::~RegKey(
  24. void
  25. )
  26. {
  27. DBGTRACE((DM_REG, DL_MID, TEXT("RegKey::~RegKey")));
  28. Close();
  29. }
  30. HRESULT
  31. RegKey::Open(
  32. REGSAM samDesired, // Access mask (i.e. KEY_READ, KEY_WRITE etc.)
  33. bool bCreate // Create key if it doesn't exist?
  34. ) const
  35. {
  36. DBGTRACE((DM_REG, DL_HIGH, TEXT("RegKey::Open")));
  37. DBGPRINT((DM_REG, DL_HIGH, TEXT("\thkeyRoot = 0x%08X, SubKey = \"%s\""),
  38. m_hkeyRoot, m_strSubKey.Cstr()));
  39. DWORD dwResult = ERROR_SUCCESS;
  40. Close();
  41. if (bCreate)
  42. {
  43. DWORD dwDisposition;
  44. dwResult = RegCreateKeyEx(m_hkeyRoot,
  45. (LPCTSTR)m_strSubKey,
  46. 0,
  47. NULL,
  48. 0,
  49. samDesired,
  50. NULL,
  51. &m_hkey,
  52. &dwDisposition);
  53. }
  54. else
  55. {
  56. dwResult = RegOpenKeyEx(m_hkeyRoot,
  57. (LPCTSTR)m_strSubKey,
  58. 0,
  59. samDesired,
  60. &m_hkey);
  61. }
  62. return HRESULT_FROM_WIN32(dwResult);
  63. }
  64. void
  65. RegKey::Attach(
  66. HKEY hkey
  67. )
  68. {
  69. Close();
  70. m_strSubKey.Empty();
  71. m_hkeyRoot = NULL;
  72. m_hkey = hkey;
  73. }
  74. void
  75. RegKey::Detach(
  76. void
  77. )
  78. {
  79. m_hkey = NULL;
  80. }
  81. void
  82. RegKey::Close(
  83. void
  84. ) const
  85. {
  86. DBGTRACE((DM_REG, DL_HIGH, TEXT("RegKey::Close")));
  87. DBGPRINT((DM_REG, DL_HIGH, TEXT("\thkeyRoot = 0x%08X, SubKey = \"%s\""),
  88. m_hkeyRoot, m_strSubKey.Cstr()));
  89. if (NULL != m_hkey)
  90. {
  91. //
  92. // Do this little swap so that the m_hkey member is NULL
  93. // when the actual key is being closed. This lets the async
  94. // change proc determine if it was signaled because of a true
  95. // change or because the key was being closed.
  96. //
  97. HKEY hkeyTemp = m_hkey;
  98. m_hkey = NULL;
  99. RegCloseKey(hkeyTemp);
  100. }
  101. }
  102. //
  103. // This is the basic form of GetValue. All other forms of
  104. // GetValue() call into this one.
  105. //
  106. HRESULT
  107. RegKey::GetValue(
  108. LPCTSTR pszValueName,
  109. DWORD dwTypeExpected,
  110. LPBYTE pbData,
  111. int cbData
  112. ) const
  113. {
  114. DWORD dwType;
  115. DWORD dwResult = RegQueryValueEx(m_hkey,
  116. pszValueName,
  117. 0,
  118. &dwType,
  119. pbData,
  120. (LPDWORD)&cbData);
  121. if (ERROR_SUCCESS == dwResult && dwType != dwTypeExpected)
  122. dwResult = ERROR_INVALID_DATATYPE;
  123. return HRESULT_FROM_WIN32(dwResult);
  124. }
  125. //
  126. // Get a DWORD value (REG_DWORD).
  127. //
  128. HRESULT
  129. RegKey::GetValue(
  130. LPCTSTR pszValueName,
  131. DWORD *pdwDataOut
  132. ) const
  133. {
  134. return GetValue(pszValueName, REG_DWORD, (LPBYTE)pdwDataOut, sizeof(DWORD));
  135. }
  136. //
  137. // Get a byte buffer value (REG_BINARY).
  138. //
  139. HRESULT
  140. RegKey::GetValue(
  141. LPCTSTR pszValueName,
  142. LPBYTE pbDataOut,
  143. int cbDataOut
  144. ) const
  145. {
  146. return GetValue(pszValueName, REG_BINARY, pbDataOut, cbDataOut);
  147. }
  148. //
  149. // Get a text string value (REG_SZ) and write it to a CString object.
  150. //
  151. HRESULT
  152. RegKey::GetValue(
  153. LPCTSTR pszValueName,
  154. CString *pstrDataOut
  155. ) const
  156. {
  157. HRESULT hr = E_FAIL;
  158. int cch = GetValueBufferSize(pszValueName) / sizeof(TCHAR);
  159. if (NULL != pstrDataOut && 0 < cch)
  160. {
  161. //
  162. // Get a buffer 1 character larger than needed. Zero-out
  163. // the entire buffer in case the data in the registry is not
  164. // nul-terminated.
  165. //
  166. LPTSTR pszBuffer = pstrDataOut->GetBuffer(cch + 1);
  167. ZeroMemory(pszBuffer, pstrDataOut->SizeBytes());
  168. hr = GetValue(pszValueName,
  169. REG_SZ,
  170. (LPBYTE)pszBuffer,
  171. pstrDataOut->SizeBytes());
  172. pstrDataOut->ReleaseBuffer();
  173. }
  174. return hr;
  175. }
  176. //
  177. // Get a multi-text string value (REG_MULTI_SZ) and write it to a CArray<CString> object.
  178. //
  179. HRESULT
  180. RegKey::GetValue(
  181. LPCTSTR pszValueName,
  182. CArray<CString> *prgstrOut
  183. ) const
  184. {
  185. HRESULT hr = E_FAIL;
  186. int cb = GetValueBufferSize(pszValueName);
  187. if (NULL != prgstrOut && 0 < cb)
  188. {
  189. //
  190. // Allocate a buffer one character larger than what we need
  191. // and then zero-init that buffer. This is in case the data in the
  192. // registry is not nul-terminated.
  193. //
  194. const size_t cch = cb / sizeof(TCHAR);
  195. array_autoptr<TCHAR> ptrTemp(new TCHAR[cch + 1]);
  196. LPTSTR psz = ptrTemp.get();
  197. ZeroMemory(psz, (cch + 1) * sizeof(TCHAR));
  198. hr = GetValue(pszValueName, REG_MULTI_SZ, (LPBYTE)psz, cb);
  199. if (SUCCEEDED(hr))
  200. {
  201. while(psz && TEXT('\0') != *psz)
  202. {
  203. prgstrOut->Append(CString(psz));
  204. psz += lstrlen(psz) + 1;
  205. }
  206. }
  207. }
  208. return hr;
  209. }
  210. //
  211. // Return the required buffer size for a given registry value.
  212. //
  213. int
  214. RegKey::GetValueBufferSize(
  215. LPCTSTR pszValueName
  216. ) const
  217. {
  218. DWORD dwType;
  219. int cbData = 0;
  220. DWORD dwDummy;
  221. DWORD dwResult = RegQueryValueEx(m_hkey,
  222. pszValueName,
  223. 0,
  224. &dwType,
  225. (LPBYTE)&dwDummy,
  226. (LPDWORD)&cbData);
  227. if (ERROR_MORE_DATA != dwResult)
  228. cbData = 0;
  229. return cbData;
  230. }
  231. //
  232. // This is the basic form of SetValue. All other forms of
  233. // SetValue() call into this one.
  234. //
  235. HRESULT
  236. RegKey::SetValue(
  237. LPCTSTR pszValueName,
  238. DWORD dwValueType,
  239. const LPBYTE pbData,
  240. int cbData
  241. )
  242. {
  243. DWORD dwResult = RegSetValueEx(m_hkey,
  244. pszValueName,
  245. 0,
  246. dwValueType,
  247. pbData,
  248. cbData);
  249. return HRESULT_FROM_WIN32(dwResult);
  250. }
  251. //
  252. // Set a DWORD value (REG_DWORD).
  253. //
  254. HRESULT
  255. RegKey::SetValue(
  256. LPCTSTR pszValueName,
  257. DWORD dwData
  258. )
  259. {
  260. return SetValue(pszValueName, REG_DWORD, (const LPBYTE)&dwData, sizeof(dwData));
  261. }
  262. //
  263. // Set a byte buffer value (REG_BINARY).
  264. //
  265. HRESULT
  266. RegKey::SetValue(
  267. LPCTSTR pszValueName,
  268. const LPBYTE pbData,
  269. int cbData
  270. )
  271. {
  272. return SetValue(pszValueName, REG_BINARY, pbData, cbData);
  273. }
  274. //
  275. // Set a text string value (REG_SZ).
  276. //
  277. HRESULT
  278. RegKey::SetValue(
  279. LPCTSTR pszValueName,
  280. LPCTSTR pszData
  281. )
  282. {
  283. return SetValue(pszValueName, REG_SZ, (const LPBYTE)pszData, (lstrlen(pszData) + 1) * sizeof(TCHAR));
  284. }
  285. //
  286. // Set a text string value (REG_MULTI_SZ).
  287. //
  288. HRESULT
  289. RegKey::SetValue(
  290. LPCTSTR pszValueName,
  291. const CArray<CString>& rgstrSrc
  292. )
  293. {
  294. array_autoptr<TCHAR> ptrValues(CreateDoubleNulTermList(rgstrSrc));
  295. int cch = 1;
  296. int n = rgstrSrc.Count();
  297. for (int i = 0; i < n; i++)
  298. cch += rgstrSrc[i].Length() + 1;
  299. return SetValue(pszValueName, REG_MULTI_SZ, (const LPBYTE)ptrValues.get(), cch * sizeof(TCHAR));
  300. }
  301. LPTSTR
  302. RegKey::CreateDoubleNulTermList(
  303. const CArray<CString>& rgstrSrc
  304. ) const
  305. {
  306. int cEntries = rgstrSrc.Count();
  307. size_t cch = 1; // Account for 2nd nul term.
  308. int i;
  309. for (i = 0; i < cEntries; i++)
  310. cch += rgstrSrc[i].Length() + 1;
  311. LPTSTR pszBuf = new TCHAR[cch];
  312. LPTSTR pszWrite = pszBuf;
  313. for (i = 0; i < cEntries; i++)
  314. {
  315. CString& s = rgstrSrc[i];
  316. StringCchCopyEx(pszWrite, cch, s, &pszWrite, &cch, 0);
  317. //
  318. // Advance one beyond terminating nul.
  319. //
  320. pszWrite++;
  321. cch--;
  322. }
  323. DBGASSERT((1 == cch));
  324. *pszWrite = TEXT('\0'); // Double nul term.
  325. return pszBuf;
  326. }