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.

411 lines
9.3 KiB

  1. //
  2. // MODULE: "RegUtil.cpp"
  3. //
  4. // PURPOSE: class CRegUtil
  5. // Encapsulates access to system registry.
  6. // This is intended as generic access to the registry, independent of any particular
  7. // application.
  8. //
  9. // PROJECT: first developed as part of Belief Network Editing Tools ("Argon")
  10. // Later modified to provide more extensive features as part of version 3.0 of the
  11. // Online Troubleshooter (APGTS)
  12. //
  13. // AUTHOR: Lonnie Gerrald (LDG), Oleg Kalosha, Joe Mabel
  14. //
  15. // ORIGINAL DATE: 3/25/98
  16. //
  17. // NOTES:
  18. // 1. The Create, Open, and Close functions support a model where m_hKey represents a
  19. // "position" in the registry. Successive calls to Create() or Open() migrate deeper
  20. // into the registry hierarchy. Close closes all keys encountered on the way down to
  21. // the current m_hKey.
  22. //
  23. //
  24. // Version Date By Comments
  25. //--------------------------------------------------------------------
  26. // V0.1(Argon) 3/25/98 LDG
  27. // V3.0 8/??/98 OK
  28. // V3.0 9/9/98 JM
  29. //
  30. #include "stdafx.h"
  31. #include "regutil.h"
  32. #include "event.h"
  33. #include "baseexception.h"
  34. #include "CharConv.h"
  35. //////////////////////////////////////////////////////////////////////
  36. // CRegUtil
  37. //////////////////////////////////////////////////////////////////////
  38. CRegUtil::CRegUtil()
  39. : m_hKey(NULL),
  40. m_WinError(ERROR_SUCCESS)
  41. {
  42. }
  43. CRegUtil::CRegUtil(HKEY key)
  44. : m_hKey(key),
  45. m_WinError(ERROR_SUCCESS)
  46. {
  47. }
  48. CRegUtil::~CRegUtil()
  49. {
  50. Close();
  51. }
  52. // creates the specified key. If the key already exists in the registry, the function opens it.
  53. // returns true on success, false otherwise.
  54. bool CRegUtil::Create(HKEY hKeyParent, const CString& strKeyName, bool* bCreatedNew, REGSAM access /*=KEY_ALL_ACCESS*/)
  55. {
  56. HKEY hRetKey = NULL;
  57. DWORD dwDisposition = 0;
  58. m_WinError = ::RegCreateKeyEx(
  59. hKeyParent,
  60. strKeyName,
  61. 0,
  62. NULL,
  63. REG_OPTION_NON_VOLATILE,
  64. access,
  65. NULL,
  66. &hRetKey,
  67. &dwDisposition
  68. );
  69. if(m_WinError == ERROR_SUCCESS)
  70. {
  71. m_hKey = hRetKey;
  72. *bCreatedNew = dwDisposition == REG_CREATED_NEW_KEY ? true : false;
  73. try
  74. {
  75. m_arrKeysToClose.push_back(hRetKey);
  76. }
  77. catch (exception& x)
  78. {
  79. CString str;
  80. // Note STL exception in event log.
  81. CBuildSrcFileLinenoStr SrcLoc( __FILE__, __LINE__ );
  82. CEvent::ReportWFEvent( SrcLoc.GetSrcFileLineStr(),
  83. SrcLoc.GetSrcFileLineStr(),
  84. CCharConversion::ConvertACharToString(x.what(), str),
  85. _T(""),
  86. EV_GTS_STL_EXCEPTION );
  87. }
  88. return true;
  89. }
  90. return false;
  91. }
  92. // Unlike CRegUtil::Create, CRegUtil::Open does not create the specified key if the key does not
  93. // exist in the registry. Thus it can be used to test whether the key exists.
  94. // returns true on success, false otherwise.
  95. bool CRegUtil::Open(HKEY hKeyParent, const CString& strKeyName, REGSAM access /*=KEY_ALL_ACCESS*/)
  96. {
  97. HKEY hRetKey = NULL;
  98. m_WinError = ::RegOpenKeyEx(
  99. hKeyParent,
  100. strKeyName,
  101. 0,
  102. access,
  103. &hRetKey
  104. );
  105. if(m_WinError == ERROR_SUCCESS)
  106. {
  107. m_hKey = hRetKey;
  108. try
  109. {
  110. m_arrKeysToClose.push_back(hRetKey);
  111. }
  112. catch (exception& x)
  113. {
  114. CString str;
  115. // Note STL exception in event log.
  116. CBuildSrcFileLinenoStr SrcLoc( __FILE__, __LINE__ );
  117. CEvent::ReportWFEvent( SrcLoc.GetSrcFileLineStr(),
  118. SrcLoc.GetSrcFileLineStr(),
  119. CCharConversion::ConvertACharToString(x.what(), str),
  120. _T(""),
  121. EV_GTS_STL_EXCEPTION );
  122. }
  123. return true;
  124. }
  125. return false;
  126. }
  127. // creates the specified subkey of m_hKey. If the key already exists in the registry, the function opens it.
  128. // returns true on success, false otherwise.
  129. bool CRegUtil::Create(const CString& strKeyName, bool* bCreatedNew, REGSAM access /*=KEY_ALL_ACCESS*/)
  130. {
  131. return Create(m_hKey, strKeyName, bCreatedNew, access);
  132. }
  133. // opens the specified subkey of m_hKey.
  134. // Unlike CRegUtil::Create, CRegUtil::Open does not create the specified key if the key does not
  135. // exist in the registry. Thus it can be used to test whether the key exists.
  136. // returns true on success, false otherwise.
  137. bool CRegUtil::Open(const CString& strKeyName, REGSAM access /*=KEY_ALL_ACCESS*/)
  138. {
  139. return Open(m_hKey, strKeyName, access);
  140. }
  141. // Close all keys encountered on the way down to the current m_hKey.
  142. void CRegUtil::Close()
  143. {
  144. for (vector<HKEY>::reverse_iterator i = m_arrKeysToClose.rbegin(); i != m_arrKeysToClose.rend(); i++)
  145. ::RegCloseKey( *i );
  146. m_arrKeysToClose.clear();
  147. }
  148. bool CRegUtil::DeleteSubKey(const CString& strSubKey)
  149. {
  150. // What does m_hKey point to after a successful deletion? RAB-981116.
  151. m_WinError = ::RegDeleteKey(m_hKey, strSubKey);
  152. if (m_WinError == ERROR_SUCCESS)
  153. return true;
  154. return false;
  155. }
  156. bool CRegUtil::DeleteValue(const CString& strValue)
  157. {
  158. m_WinError = ::RegDeleteValue(m_hKey, strValue);
  159. if (m_WinError == ERROR_SUCCESS)
  160. return true;
  161. return false;
  162. }
  163. bool CRegUtil::SetNumericValue(const CString& strValueName, DWORD dwValue)
  164. {
  165. BYTE* pData = (BYTE*)&dwValue;
  166. m_WinError = ::RegSetValueEx(
  167. m_hKey,
  168. strValueName,
  169. 0,
  170. REG_DWORD,
  171. pData,
  172. sizeof(DWORD)
  173. );
  174. if (m_WinError == ERROR_SUCCESS)
  175. return true;
  176. return false;
  177. }
  178. bool CRegUtil::SetStringValue(const CString& strValueName, const CString& strValue)
  179. {
  180. BYTE* pData = (BYTE*)(LPCTSTR)strValue;
  181. m_WinError = ::RegSetValueEx(
  182. m_hKey,
  183. strValueName,
  184. 0,
  185. REG_SZ,
  186. pData,
  187. strValue.GetLength()+sizeof(TCHAR)
  188. );
  189. if (m_WinError == ERROR_SUCCESS)
  190. return true;
  191. return false;
  192. }
  193. bool CRegUtil::SetBinaryValue(const CString& strValueName, char* buf, long buf_len)
  194. {
  195. BYTE* pData = (BYTE*)buf;
  196. m_WinError = ::RegSetValueEx(
  197. m_hKey,
  198. strValueName,
  199. 0,
  200. REG_BINARY,
  201. pData,
  202. buf_len
  203. );
  204. if (m_WinError == ERROR_SUCCESS)
  205. return true;
  206. return false;
  207. }
  208. bool CRegUtil::GetNumericValue(const CString& strValueName, DWORD& dwValue)
  209. {
  210. DWORD tmp = 0;
  211. BYTE* pData = (BYTE*)&tmp;
  212. DWORD type = 0;
  213. DWORD size = sizeof(DWORD);
  214. m_WinError = ::RegQueryValueEx(
  215. m_hKey,
  216. strValueName,
  217. NULL,
  218. &type,
  219. pData,
  220. &size
  221. );
  222. if (type != REG_DWORD)
  223. return false;
  224. if (m_WinError == ERROR_SUCCESS)
  225. {
  226. dwValue = tmp;
  227. return true;
  228. }
  229. return false;
  230. }
  231. bool CRegUtil::GetStringValue(const CString& strValueName, CString& strValue)
  232. {
  233. BYTE* pData = NULL;
  234. DWORD type = 0;
  235. DWORD size = 0;
  236. // determine data size
  237. m_WinError = ::RegQueryValueEx(
  238. m_hKey,
  239. strValueName,
  240. NULL,
  241. &type,
  242. NULL,
  243. &size
  244. );
  245. if (m_WinError != ERROR_SUCCESS)
  246. return false;
  247. if (type != REG_SZ && type != REG_EXPAND_SZ)
  248. return false;
  249. bool bRet = false; // should be only one return from here down: we're about to
  250. // alloc pData and must make sure it's correctly cleaned up.
  251. try
  252. {
  253. pData = new BYTE[size];
  254. }
  255. catch (bad_alloc&)
  256. {
  257. return false;
  258. }
  259. memset(pData, 0, size);
  260. m_WinError = ::RegQueryValueEx(
  261. m_hKey,
  262. strValueName,
  263. NULL,
  264. &type,
  265. pData,
  266. &size
  267. );
  268. if (m_WinError == ERROR_SUCCESS)
  269. {
  270. if (type == REG_EXPAND_SZ )
  271. {
  272. BYTE* pDataExpanded = NULL;
  273. DWORD dwExpandedSize;
  274. // first we call ExpandEnvironmentStrings just to get the length
  275. // casting away unsignedness
  276. dwExpandedSize = ::ExpandEnvironmentStrings(
  277. reinterpret_cast<const TCHAR *>(pData),
  278. reinterpret_cast<TCHAR *>(pDataExpanded),
  279. 0);
  280. if (dwExpandedSize > 0)
  281. {
  282. try
  283. {
  284. pDataExpanded = new BYTE[dwExpandedSize];
  285. // then we call ExpandEnvironmentStrings again to get the expanded value
  286. // casting away unsignedness
  287. if (::ExpandEnvironmentStrings(
  288. reinterpret_cast<const TCHAR *>(pData),
  289. reinterpret_cast<TCHAR *>(pDataExpanded),
  290. dwExpandedSize))
  291. {
  292. strValue = (LPTSTR)pDataExpanded;
  293. delete [] pDataExpanded;
  294. bRet = true;
  295. }
  296. }
  297. catch (bad_alloc&)
  298. {
  299. // Note memory failure in event log.
  300. CBuildSrcFileLinenoStr SrcLoc( __FILE__, __LINE__ );
  301. CEvent::ReportWFEvent( SrcLoc.GetSrcFileLineStr(),
  302. SrcLoc.GetSrcFileLineStr(),
  303. _T(""), _T(""), EV_GTS_CANT_ALLOC );
  304. }
  305. }
  306. }
  307. else
  308. {
  309. strValue = (LPTSTR)pData;
  310. bRet = true;
  311. }
  312. }
  313. delete [] pData;
  314. return bRet;
  315. }
  316. // The second parameter should be passed in as the address of a char *.
  317. // Note that if this returns true, *ppBuf will point to a new buffer on the heap.
  318. // The caller of this function is responsible for deleting that.
  319. bool CRegUtil::GetBinaryValue(const CString& strValueName, char** ppBuf, long* pBufLen)
  320. {
  321. BYTE* pData = NULL;
  322. DWORD type = 0;
  323. DWORD size = 0;
  324. // determine data size
  325. m_WinError = ::RegQueryValueEx(
  326. m_hKey,
  327. strValueName,
  328. NULL,
  329. &type,
  330. NULL,
  331. &size
  332. );
  333. if (m_WinError != ERROR_SUCCESS || type != REG_BINARY)
  334. return false;
  335. try
  336. {
  337. // Increase the buffer size by one over what we need. Small price to
  338. // pay for processing convenience elsewhere.
  339. pData = new BYTE[size+1];
  340. }
  341. catch (bad_alloc&)
  342. {
  343. return false;
  344. }
  345. memset(pData, 0, size);
  346. m_WinError = ::RegQueryValueEx(
  347. m_hKey,
  348. strValueName,
  349. NULL,
  350. &type,
  351. pData,
  352. &size
  353. );
  354. if (m_WinError == ERROR_SUCCESS)
  355. {
  356. // Null terminate the binary string for processing convenience elsewhere.
  357. pData[size]= 0;
  358. *ppBuf = (char*)pData;
  359. *pBufLen = size;
  360. return true;
  361. }
  362. delete [] pData;
  363. return false;
  364. }