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.

512 lines
14 KiB

  1. /*******************************************************************************
  2. *
  3. * (C) COPYRIGHT MICROSOFT CORPORATION, 1998
  4. *
  5. * TITLE: SIMREG.CPP
  6. *
  7. * VERSION: 1.0
  8. *
  9. * AUTHOR: ShaunIv
  10. *
  11. * DATE: 5/12/1998
  12. *
  13. * DESCRIPTION: Simple registry access class
  14. *
  15. *******************************************************************************/
  16. #include "precomp.h"
  17. #pragma hdrstop
  18. #include <simreg.h>
  19. CSimpleReg::CSimpleReg( HKEY hkRoot, const CSimpleString &strSubKey, bool bCreate, REGSAM samDesired, LPSECURITY_ATTRIBUTES lpsa )
  20. : m_strKeyName(strSubKey),
  21. m_hRootKey(hkRoot),
  22. m_hKey(NULL),
  23. m_bCreate(bCreate),
  24. m_lpsaSecurityAttributes(lpsa),
  25. m_samDesiredAccess(samDesired)
  26. {
  27. Open();
  28. }
  29. CSimpleReg::CSimpleReg(void)
  30. : m_strKeyName(TEXT("")),
  31. m_hRootKey(NULL),
  32. m_hKey(NULL),
  33. m_bCreate(false),
  34. m_lpsaSecurityAttributes(NULL),
  35. m_samDesiredAccess(0)
  36. {
  37. }
  38. CSimpleReg::CSimpleReg(const CSimpleReg &other)
  39. : m_strKeyName(other.GetSubKeyName()),
  40. m_hRootKey(other.GetRootKey()),
  41. m_hKey(NULL),
  42. m_bCreate(other.GetCreate()),
  43. m_lpsaSecurityAttributes(other.GetSecurityAttributes()),
  44. m_samDesiredAccess(other.DesiredAccess())
  45. {
  46. Open();
  47. }
  48. CSimpleReg::~CSimpleReg(void)
  49. {
  50. Close();
  51. m_hRootKey = NULL;
  52. m_lpsaSecurityAttributes = NULL;
  53. }
  54. CSimpleReg &CSimpleReg::operator=(const CSimpleReg &other )
  55. {
  56. if (this != &other)
  57. {
  58. Close();
  59. m_strKeyName = other.GetSubKeyName();
  60. m_hRootKey = other.GetRootKey();
  61. m_bCreate = other.GetCreate();
  62. m_lpsaSecurityAttributes = other.GetSecurityAttributes();
  63. m_samDesiredAccess = other.DesiredAccess();
  64. Open();
  65. }
  66. return *this;
  67. }
  68. bool CSimpleReg::Open(void)
  69. {
  70. HKEY hkKey = NULL;
  71. LONG nRet;
  72. DWORD bCreatedNewKey = 0;
  73. Close();
  74. if (m_bCreate)
  75. {
  76. nRet = RegCreateKeyEx( m_hRootKey, m_strKeyName.String(), 0, TEXT(""), REG_OPTION_NON_VOLATILE, m_samDesiredAccess?m_samDesiredAccess:KEY_ALL_ACCESS, m_lpsaSecurityAttributes, &hkKey, &bCreatedNewKey );
  77. }
  78. else
  79. {
  80. nRet = RegOpenKeyEx( m_hRootKey, m_strKeyName.String(), 0, m_samDesiredAccess ? m_samDesiredAccess : KEY_ALL_ACCESS, &hkKey );
  81. }
  82. if (nRet == ERROR_SUCCESS)
  83. {
  84. m_hKey = hkKey;
  85. }
  86. return m_hKey != NULL;
  87. }
  88. bool CSimpleReg::Close(void)
  89. {
  90. //
  91. // In case the key was closed by someone else
  92. //
  93. __try
  94. {
  95. if (OK())
  96. {
  97. RegCloseKey(m_hKey);
  98. }
  99. }
  100. __except( EXCEPTION_EXECUTE_HANDLER )
  101. {
  102. #ifdef DBG
  103. OutputDebugString(TEXT("CSimpleReg::Close(): An exception occurred while closing the handle. Make sure the handle wasn't already freed."));
  104. DebugBreak();
  105. #endif
  106. }
  107. m_hKey = NULL;
  108. return true;
  109. }
  110. bool CSimpleReg::Flush(void)
  111. {
  112. if (!OK())
  113. {
  114. return false;
  115. }
  116. return (ERROR_SUCCESS == RegFlushKey(m_hKey));
  117. }
  118. bool CSimpleReg::IsStringValue( DWORD nType )
  119. {
  120. if (nType != REG_SZ && nType != REG_EXPAND_SZ && nType != REG_MULTI_SZ && nType != REG_LINK && nType != REG_RESOURCE_LIST)
  121. {
  122. return false;
  123. }
  124. else return true;
  125. }
  126. // Query functions
  127. DWORD CSimpleReg::Size( const CSimpleString &strValueName ) const
  128. {
  129. if (!OK())
  130. {
  131. return 0;
  132. }
  133. DWORD nType;
  134. DWORD nSize=0;
  135. LONG Ret = RegQueryValueEx( m_hKey, strValueName.String(), NULL, &nType, NULL, &nSize);
  136. if (Ret==ERROR_SUCCESS)
  137. {
  138. return nSize;
  139. }
  140. return 0;
  141. }
  142. DWORD CSimpleReg::Type( const CSimpleString &key ) const
  143. {
  144. if (!OK())
  145. {
  146. return 0;
  147. }
  148. DWORD dwType;
  149. DWORD dwSize;
  150. LONG Ret = RegQueryValueEx( m_hKey, key.String(), NULL, &dwType, NULL, &dwSize);
  151. if (Ret==ERROR_SUCCESS)
  152. {
  153. return dwType;
  154. }
  155. return 0;
  156. }
  157. CSimpleString CSimpleReg::Query( const CSimpleString &strValueName, const CSimpleString &strDef ) const
  158. {
  159. // If the key is not open, or if this value is not a string type, return the default
  160. if (!OK() || !IsStringValue(Type(strValueName)))
  161. {
  162. return strDef;
  163. }
  164. DWORD nSize = Size(strValueName) / sizeof(TCHAR);
  165. //
  166. // NOTE: There are some cases when components (e.g. usbscan.sys) write a string value to the registry,
  167. // and dont NULL terminate it correctly. Now nSize contains the number of characters, NOT
  168. // including the NULL terminator. To get around this, we actually allocate one more
  169. // character than needed. Then, after reading in up to a maximum of nSize characters, we
  170. // set the extra character to TEXT('\0), ensuring that our string is always NULL terminated
  171. // correctly, without losing the last character (which would happen if we simply allocated
  172. // nSize and set lpszTmp[nSize-1] to TEXT('\0')).
  173. //
  174. LPTSTR lpszTmp = nSize ? new TCHAR[nSize + 1] : NULL;
  175. CSimpleString strTmp;
  176. if (lpszTmp)
  177. {
  178. Query( strValueName, strDef, lpszTmp, nSize );
  179. //
  180. // Ensure that we are correctly NULL terminated. Note that we null out the extra character
  181. // allocated for us - not any of the actual data.
  182. //
  183. lpszTmp[nSize] = TEXT('\0');
  184. strTmp = lpszTmp;
  185. delete[] lpszTmp;
  186. }
  187. return strTmp;
  188. }
  189. LPTSTR CSimpleReg::Query( const CSimpleString &strValueName, const CSimpleString &strDef, LPTSTR pszBuffer, DWORD nLen ) const
  190. {
  191. //
  192. // If the programmer passes 0 for some reason, return NULL
  193. //
  194. if (!nLen)
  195. {
  196. return NULL;
  197. }
  198. //
  199. // Initialize the result
  200. //
  201. *pszBuffer = 0;
  202. //
  203. // If the key is not open, or if this value is not a string type, return the default
  204. //
  205. if (!OK() || !IsStringValue(Type(strValueName)))
  206. {
  207. //
  208. // Make sure we have a valid default string
  209. //
  210. if (strDef.String())
  211. {
  212. lstrcpyn( pszBuffer, strDef.String(), nLen );
  213. }
  214. //
  215. // Early return
  216. //
  217. return pszBuffer;
  218. }
  219. DWORD nSize = (DWORD)(nLen * sizeof(pszBuffer[0]));
  220. DWORD nType;
  221. LONG nRet = RegQueryValueEx( m_hKey, strValueName.String(), NULL, &nType, (PBYTE)pszBuffer, &nSize );
  222. if (ERROR_SUCCESS != nRet)
  223. {
  224. lstrcpyn( pszBuffer, strDef.String(), nLen );
  225. pszBuffer[nLen-1] = TEXT('\0');
  226. }
  227. return pszBuffer;
  228. }
  229. DWORD CSimpleReg::Query( const CSimpleString &strValueName, DWORD nDef ) const
  230. {
  231. if (!OK() || (REG_DWORD != Type(strValueName)) || (sizeof(DWORD) != Size(strValueName)))
  232. {
  233. return nDef;
  234. }
  235. DWORD nValue;
  236. DWORD nType;
  237. DWORD nSize = sizeof(DWORD);
  238. LONG nRet;
  239. nRet = RegQueryValueEx( m_hKey, strValueName.String(), NULL, &nType, (PBYTE)&nValue, &nSize);
  240. if (ERROR_SUCCESS == nRet)
  241. {
  242. return nValue;
  243. }
  244. else
  245. {
  246. return nDef;
  247. }
  248. }
  249. bool CSimpleReg::Set( const CSimpleString &strValueName, const CSimpleString &strValue, DWORD nType ) const
  250. { // Set a REG_SZ value for the specified key.
  251. if (!OK())
  252. {
  253. return false;
  254. }
  255. LONG nRet;
  256. nRet = RegSetValueEx( m_hKey, strValueName.String(), 0, nType, (PBYTE)strValue.String(), sizeof(strValue[0])*(strValue.Length()+1) );
  257. return (ERROR_SUCCESS==nRet);
  258. }
  259. bool CSimpleReg::Set( const CSimpleString &strValueName, DWORD nValue ) const
  260. { // Set a REG_SZ value for the specified key.
  261. if (!OK())
  262. return false;
  263. LONG nRet;
  264. nRet = RegSetValueEx( m_hKey, strValueName.String(), 0, REG_DWORD, (PBYTE)&nValue, sizeof(DWORD) );
  265. return (ERROR_SUCCESS==nRet);
  266. }
  267. DWORD CSimpleReg::QueryBin( const CSimpleString &strValueName, PBYTE pData, DWORD nMaxLen ) const
  268. {
  269. if (!OK())
  270. {
  271. return 0;
  272. }
  273. if (nMaxLen <= 0)
  274. {
  275. return Size(strValueName.String());
  276. }
  277. DWORD nType;
  278. DWORD nSize = nMaxLen;
  279. LONG nRet = RegQueryValueEx( m_hKey, strValueName.String(), NULL, &nType, pData, &nSize );
  280. if (ERROR_SUCCESS!=nRet)
  281. {
  282. return 0;
  283. }
  284. return nSize;
  285. }
  286. bool CSimpleReg::SetBin( const CSimpleString &strValueName, const PBYTE pValue, DWORD nLen, DWORD dwType ) const
  287. {
  288. if (!OK())
  289. return false;
  290. LONG nRet = RegSetValueEx( m_hKey, strValueName.String(), 0, dwType, (PBYTE)pValue, nLen );
  291. return (ERROR_SUCCESS==nRet);
  292. }
  293. DWORD CSimpleReg::SubKeyCount(void) const
  294. {
  295. TCHAR szClass[256]=TEXT("");
  296. DWORD nClassSize = sizeof(szClass)/sizeof(szClass[0]);
  297. DWORD nSubKeyCount=0;
  298. RegQueryInfoKey(m_hKey,szClass,&nClassSize,NULL,&nSubKeyCount,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
  299. return nSubKeyCount;
  300. }
  301. HKEY CSimpleReg::GetHkeyFromName( const CSimpleString &strName )
  302. {
  303. static const struct
  304. {
  305. LPCTSTR pszName;
  306. HKEY hkKey;
  307. } KeyNames[] =
  308. {
  309. { TEXT("HKEY_CLASSES_ROOT"), HKEY_CLASSES_ROOT},
  310. { TEXT("HKEY_CURRENT_USER"), HKEY_CURRENT_USER},
  311. { TEXT("HKEY_LOCAL_MACHINE"), HKEY_LOCAL_MACHINE},
  312. { TEXT("HKEY_USERS"), HKEY_USERS},
  313. { TEXT("HKEY_CURRENT_CONFIG"), HKEY_CURRENT_CONFIG},
  314. { TEXT("HKEY_DYN_DATA"), HKEY_DYN_DATA},
  315. { TEXT("HKCR"), HKEY_CLASSES_ROOT},
  316. { TEXT("HKCU"), HKEY_CURRENT_USER},
  317. { TEXT("HKLM"), HKEY_LOCAL_MACHINE},
  318. { TEXT("HKU"), HKEY_USERS},
  319. { TEXT("HKCC"), HKEY_CURRENT_CONFIG},
  320. { TEXT("HKDD"), HKEY_DYN_DATA},
  321. { NULL, NULL}
  322. };
  323. for (int i=0;KeyNames[i].pszName;i++)
  324. {
  325. if (!lstrcmpi(strName.String(),KeyNames[i].pszName))
  326. {
  327. return KeyNames[i].hkKey;
  328. }
  329. }
  330. return NULL;
  331. }
  332. bool CSimpleReg::Delete( HKEY hkRoot, const CSimpleString &strKeyName )
  333. {
  334. return (RegDeleteKey(hkRoot, strKeyName.String()) == ERROR_SUCCESS);
  335. }
  336. bool CSimpleReg::Delete( const CSimpleString &strValue )
  337. {
  338. if (!OK())
  339. {
  340. return false;
  341. }
  342. return (RegDeleteValue( m_hKey, strValue.String() ) == ERROR_SUCCESS);
  343. }
  344. bool CSimpleReg::DeleteRecursively( HKEY hkRoot, const CSimpleString &strKeyName )
  345. {
  346. if (CSimpleReg( hkRoot, strKeyName ).RecurseKeys( DeleteEnumKeyProc, NULL, CSimpleReg::PostOrder ))
  347. {
  348. return CSimpleReg::Delete( hkRoot, strKeyName );
  349. }
  350. return false;
  351. }
  352. bool CSimpleReg::EnumValues( SimRegValueEnumProc enumProc, LPARAM lParam )
  353. {
  354. TCHAR szName[256];
  355. DWORD nSize;
  356. DWORD nType;
  357. bool bResult = true;
  358. for (int i=0;;i++)
  359. {
  360. nSize = sizeof(szName) / sizeof(szName[0]);
  361. if (RegEnumValue(m_hKey,i,szName,&nSize,NULL,&nType,NULL,NULL) != ERROR_SUCCESS)
  362. break;
  363. CValueEnumInfo info(*this,szName,nType,nSize,lParam);
  364. if (enumProc)
  365. {
  366. if (!enumProc(info))
  367. {
  368. bResult = false;
  369. break;
  370. }
  371. }
  372. }
  373. return bResult;
  374. }
  375. bool CSimpleReg::RecurseKeys( SimRegKeyEnumProc enumProc, LPARAM lParam, int recurseOrder, bool bFailOnOpenError ) const
  376. {
  377. return DoRecurseKeys(m_hKey, TEXT(""), enumProc, lParam, 0, recurseOrder, bFailOnOpenError );
  378. }
  379. bool CSimpleReg::EnumKeys( SimRegKeyEnumProc enumProc, LPARAM lParam, bool bFailOnOpenError ) const
  380. {
  381. return DoEnumKeys(m_hKey, TEXT(""), enumProc, lParam, bFailOnOpenError );
  382. }
  383. bool CSimpleReg::DoRecurseKeys( HKEY hkKey, const CSimpleString &root, SimRegKeyEnumProc enumProc, LPARAM lParam, int nLevel, int recurseOrder, bool bFailOnOpenError )
  384. {
  385. TCHAR szName[256]=TEXT("");
  386. DWORD nNameSize;
  387. TCHAR szClass[256]=TEXT("");
  388. DWORD nClassSize;
  389. FILETIME ftFileTime;
  390. CSimpleReg reg(hkKey,root);
  391. if (!reg.OK())
  392. {
  393. return (bFailOnOpenError ? false : true);
  394. }
  395. DWORD nSubKeyCount = reg.SubKeyCount();
  396. for (DWORD i=nSubKeyCount;i>0;i--)
  397. {
  398. nNameSize = sizeof(szName)/sizeof(szName[0]);
  399. nClassSize = sizeof(szClass)/sizeof(szClass[0]);
  400. LONG lRes = RegEnumKeyEx(reg.GetKey(),i-1,szName,&nNameSize,NULL,szClass,&nClassSize,&ftFileTime);
  401. if (lRes != ERROR_SUCCESS)
  402. {
  403. break;
  404. }
  405. CKeyEnumInfo EnumInfo;
  406. EnumInfo.strName = szName;
  407. EnumInfo.hkRoot = reg.GetKey();
  408. EnumInfo.nLevel = nLevel;
  409. EnumInfo.lParam = lParam;
  410. if (enumProc && recurseOrder==PreOrder)
  411. {
  412. if (!enumProc(EnumInfo))
  413. {
  414. return false;
  415. }
  416. }
  417. if (!DoRecurseKeys(reg.GetKey(),szName,enumProc,lParam,nLevel+1,recurseOrder, bFailOnOpenError))
  418. {
  419. return false;
  420. }
  421. if (enumProc && recurseOrder==PostOrder)
  422. {
  423. if (!enumProc(EnumInfo))
  424. {
  425. return false;
  426. }
  427. }
  428. }
  429. return true;
  430. }
  431. bool CSimpleReg::DoEnumKeys( HKEY hkKey, const CSimpleString &root, SimRegKeyEnumProc enumProc, LPARAM lParam, bool bFailOnOpenError )
  432. {
  433. TCHAR szName[256]=TEXT("");
  434. DWORD szNameSize;
  435. TCHAR szClass[256]=TEXT("");
  436. DWORD szClassSize;
  437. FILETIME ftFileTime;
  438. CSimpleReg reg(hkKey,root);
  439. LONG lRes;
  440. if (!reg.OK())
  441. {
  442. return (bFailOnOpenError ? false : true);
  443. }
  444. DWORD nSubKeyCount = reg.SubKeyCount();
  445. for (DWORD i=nSubKeyCount;i>0;i--)
  446. {
  447. szNameSize = sizeof(szName)/sizeof(szName[0]);
  448. szClassSize = sizeof(szClass)/sizeof(szClass[0]);
  449. if ((lRes=RegEnumKeyEx(reg.GetKey(),i-1,szName,&szNameSize,NULL,szClass,&szClassSize,&ftFileTime)) != ERROR_SUCCESS)
  450. {
  451. break;
  452. }
  453. CKeyEnumInfo EnumInfo;
  454. EnumInfo.strName = szName;
  455. EnumInfo.hkRoot = reg.GetKey();
  456. EnumInfo.nLevel = 0;
  457. EnumInfo.lParam = lParam;
  458. if (!enumProc(EnumInfo))
  459. {
  460. return false;
  461. }
  462. }
  463. return true;
  464. }
  465. bool CSimpleReg::DeleteEnumKeyProc( CSimpleReg::CKeyEnumInfo &enumInfo )
  466. {
  467. return CSimpleReg::Delete( enumInfo.hkRoot, enumInfo.strName );
  468. }