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.

958 lines
25 KiB

  1. //****************************************************************************
  2. //
  3. // Copyright (c) 1993, Microsoft Corp.
  4. //
  5. // File: DOMDLGS.H
  6. //
  7. // Implementation file for registry management classes
  8. //
  9. // History:
  10. // Scott V. Walker 10/5/94
  11. //
  12. //****************************************************************************
  13. #include "stdafx.h"
  14. #include "portable.h"
  15. #include "regkey.h"
  16. BOOL g_bLostConnection = FALSE;
  17. //****************************************************************************
  18. //
  19. // CRegistryValue Implementation
  20. //
  21. //****************************************************************************
  22. IMPLEMENT_DYNAMIC(CRegistryValue, CObject)
  23. //****************************************************************************
  24. //
  25. // CRegistryValue::CRegistryValue
  26. //
  27. //****************************************************************************
  28. CRegistryValue::CRegistryValue()
  29. {
  30. m_dwType = REG_NONE;
  31. m_dwDataLength = 0;
  32. m_pData = NULL;
  33. }
  34. //****************************************************************************
  35. //
  36. // CRegistryValue::CRegistryValue
  37. //
  38. //****************************************************************************
  39. CRegistryValue::CRegistryValue(LPCTSTR pszName, DWORD dwType,
  40. DWORD dwDataLength, LPBYTE pData)
  41. {
  42. Set(pszName, dwType, dwDataLength, pData);
  43. }
  44. //****************************************************************************
  45. //
  46. // CRegistryValue::~CRegistryValue
  47. //
  48. //****************************************************************************
  49. CRegistryValue::~CRegistryValue()
  50. {
  51. Empty();
  52. }
  53. //****************************************************************************
  54. //
  55. // CRegistryValue::Set
  56. //
  57. // Sets the value data fields. The data pointed to by pData is COPIED!
  58. //
  59. //****************************************************************************
  60. void CRegistryValue::Set(LPCTSTR pszName, DWORD dwType,
  61. DWORD dwDataLength, LPBYTE pData)
  62. {
  63. Empty();
  64. m_sName = pszName;
  65. m_dwType = dwType;
  66. m_dwDataLength = dwDataLength;
  67. if (dwDataLength == 0 || pData == NULL)
  68. m_pData = NULL;
  69. else
  70. {
  71. m_pData = new BYTE[dwDataLength];
  72. memcpy(m_pData, pData, dwDataLength);
  73. }
  74. }
  75. //****************************************************************************
  76. //
  77. // CRegistryValue::Get
  78. //
  79. // Gets the value data fields. The data pointed to by m_pData is COPIED
  80. // into the buffer pointed to by pData... this buffer better be big enough!
  81. // If pData is NULL, no copy is performed.
  82. //
  83. //****************************************************************************
  84. void CRegistryValue::Get(CString &sName, DWORD &dwType,
  85. DWORD &dwDataLength, LPBYTE pData)
  86. {
  87. sName = m_sName;
  88. dwType = m_dwType;
  89. dwDataLength = m_dwDataLength;
  90. if (dwDataLength != 0 && pData != NULL)
  91. memcpy(pData, m_pData, m_dwDataLength);
  92. }
  93. //****************************************************************************
  94. //
  95. // CRegistryValue::Empty
  96. //
  97. // Clear the value data and deletes its data buffer.
  98. //
  99. //****************************************************************************
  100. void CRegistryValue::Empty()
  101. {
  102. m_sName.Empty();
  103. m_dwType = REG_NONE;
  104. m_dwDataLength = 0;
  105. if (m_pData != NULL)
  106. delete m_pData;
  107. m_pData = NULL;
  108. }
  109. //****************************************************************************
  110. //
  111. // CRegistryValue::operator=
  112. //
  113. // Assignment operator. Copies CRegistryValue object.
  114. //
  115. //****************************************************************************
  116. const CRegistryValue& CRegistryValue::operator=(CRegistryValue &other)
  117. {
  118. Set(other.m_sName, other.m_dwType, other.m_dwDataLength, other.m_pData);
  119. return *this;
  120. }
  121. //****************************************************************************
  122. //
  123. // CRegistryKey Implementation
  124. //
  125. //****************************************************************************
  126. IMPLEMENT_DYNAMIC(CRegistryKey, CObject)
  127. //****************************************************************************
  128. //
  129. // CRegistryKey::CRegistryKey
  130. //
  131. //****************************************************************************
  132. CRegistryKey::CRegistryKey()
  133. {
  134. // The lost connection status is initialized only once so that if a connection
  135. // is ever lost we won't waste any time trying to close keys.
  136. Initialize();
  137. }
  138. //****************************************************************************
  139. //
  140. // CRegistryKey::Initialize
  141. //
  142. //****************************************************************************
  143. void CRegistryKey::Initialize()
  144. {
  145. m_bConnected = FALSE;
  146. m_bOpen = FALSE;
  147. m_bLocal = TRUE;
  148. m_bDirty = FALSE;
  149. m_hkeyConnect = NULL;
  150. m_hkeyRemote = NULL;
  151. m_hkeyOpen = NULL;
  152. m_Sam = 0;
  153. m_dwSubKeys = 0;
  154. m_dwMaxSubKey = 0;
  155. m_dwMaxClass = 0;
  156. m_dwValues = 0;
  157. m_dwMaxValueName = 0;
  158. m_dwMaxValueData = 0;
  159. m_dwSecurityDescriptor = 0;
  160. m_ftLastWriteTime.dwLowDateTime = 0;
  161. m_ftLastWriteTime.dwHighDateTime = 0;
  162. m_lResult = ERROR_SUCCESS;
  163. }
  164. //****************************************************************************
  165. //
  166. // CRegistryKey::~CRegistryKey
  167. //
  168. // Destructor.
  169. //
  170. //****************************************************************************
  171. CRegistryKey::~CRegistryKey()
  172. {
  173. if (g_bLostConnection) {
  174. // If we lost the registry connection, it will be useless to do anything.
  175. return;
  176. }
  177. // If we're currently open, then close.
  178. if (m_bOpen)
  179. Close(TRUE);
  180. // If we're currently connected, then disconnect.
  181. if (m_bConnected)
  182. Disconnect(TRUE);
  183. }
  184. //****************************************************************************
  185. //
  186. // CRegistryKey::Connect
  187. //
  188. //****************************************************************************
  189. LONG CRegistryKey::Connect(LPCTSTR pszComputer, HKEY hkey)
  190. {
  191. if (g_bLostConnection) {
  192. return RPC_S_SERVER_UNAVAILABLE;
  193. }
  194. TCHAR szName[MAX_COMPUTERNAME_LENGTH + 1];
  195. CString sComputer;
  196. HKEY hkeyRemote;
  197. DWORD dwNumChars;
  198. m_lResult = ERROR_SUCCESS;
  199. if (m_bConnected)
  200. {
  201. m_lResult = Disconnect(TRUE);
  202. if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
  203. g_bLostConnection = TRUE;
  204. }
  205. if (m_lResult != ERROR_SUCCESS)
  206. return m_lResult;
  207. }
  208. // Is this the local machine?
  209. dwNumChars = MAX_COMPUTERNAME_LENGTH + 1;
  210. sComputer = pszComputer;
  211. GetComputerName(szName, &dwNumChars);
  212. if (sComputer.IsEmpty() || !lstrcmpi(pszComputer, szName))
  213. {
  214. // Local
  215. m_bLocal = TRUE;
  216. hkeyRemote = NULL;
  217. }
  218. else
  219. {
  220. // Remote
  221. m_bLocal = FALSE;
  222. m_lResult = RegConnectRegistry(pszComputer, hkey, &hkeyRemote);
  223. if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
  224. g_bLostConnection = TRUE;
  225. }
  226. if (m_lResult != ERROR_SUCCESS)
  227. return m_lResult;
  228. lstrcpy(szName, pszComputer);
  229. }
  230. m_bConnected = TRUE;
  231. m_hkeyConnect = hkey;
  232. m_hkeyRemote = hkeyRemote;
  233. m_sComputer = szName;
  234. return ERROR_SUCCESS;
  235. }
  236. //****************************************************************************
  237. //
  238. // CRegistryKey::Disconnect
  239. //
  240. //****************************************************************************
  241. LONG CRegistryKey::Disconnect(BOOL bForce)
  242. {
  243. m_lResult = ERROR_SUCCESS;
  244. if (m_bConnected)
  245. {
  246. // Close the open key
  247. if (m_bOpen)
  248. {
  249. m_lResult = Close(bForce);
  250. if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
  251. g_bLostConnection = TRUE;
  252. }
  253. if (!bForce && m_lResult != ERROR_SUCCESS)
  254. return m_lResult;
  255. }
  256. // Close the remote connection
  257. if (!g_bLostConnection) {
  258. if (!m_bLocal)
  259. {
  260. m_lResult = RegCloseKey(m_hkeyRemote);
  261. if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
  262. g_bLostConnection = TRUE;
  263. }
  264. if (!bForce && m_lResult != ERROR_SUCCESS)
  265. return m_lResult;
  266. }
  267. }
  268. }
  269. Initialize();
  270. return ERROR_SUCCESS;
  271. }
  272. //****************************************************************************
  273. //
  274. // CRegistryKey::Create
  275. //
  276. //****************************************************************************
  277. LONG CRegistryKey::Create(LPCTSTR pszKeyName, DWORD &dwDisposition,
  278. LPCTSTR pszClass, REGSAM samDesired, LPSECURITY_ATTRIBUTES lpSecAttr)
  279. {
  280. if (g_bLostConnection) {
  281. return RPC_S_SERVER_UNAVAILABLE;
  282. }
  283. HKEY hkeyOpen, hkey;
  284. m_lResult = ERROR_SUCCESS;
  285. dwDisposition = 0;
  286. if (m_bOpen)
  287. {
  288. m_lResult = Close(TRUE);
  289. if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
  290. g_bLostConnection = TRUE;
  291. }
  292. if (m_lResult != ERROR_SUCCESS)
  293. return m_lResult;
  294. }
  295. // If not connected, default to \\Local_Machine\HKEY_LOCAL_MACHINE
  296. if (!m_bConnected)
  297. {
  298. m_lResult = Connect();
  299. if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
  300. g_bLostConnection = TRUE;
  301. }
  302. if (m_lResult != ERROR_SUCCESS)
  303. return m_lResult;
  304. }
  305. // Attempt to create the specified subkey
  306. if (m_bLocal)
  307. hkey = m_hkeyConnect;
  308. else
  309. hkey = m_hkeyRemote;
  310. m_lResult = RegCreateKeyEx(hkey, pszKeyName, 0, (LPTSTR)pszClass,
  311. REG_OPTION_NON_VOLATILE, samDesired, lpSecAttr, &hkeyOpen,
  312. &dwDisposition);
  313. if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
  314. g_bLostConnection = TRUE;
  315. }
  316. if (m_lResult != ERROR_SUCCESS)
  317. return m_lResult;
  318. m_lResult = RegCloseKey(hkeyOpen);
  319. if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
  320. g_bLostConnection = TRUE;
  321. return m_lResult;
  322. }
  323. return Open(pszKeyName, samDesired);
  324. }
  325. //****************************************************************************
  326. //
  327. // CRegistryKey::Open
  328. //
  329. //****************************************************************************
  330. LONG CRegistryKey::Open(LPCTSTR pszKeyName, REGSAM samDesired)
  331. {
  332. if (g_bLostConnection) {
  333. return RPC_S_SERVER_UNAVAILABLE;
  334. }
  335. HKEY hkeyOpen, hkey;
  336. CString sWork;
  337. int nPos;
  338. m_lResult = ERROR_SUCCESS;
  339. if (m_bOpen)
  340. {
  341. m_lResult = Close(TRUE);
  342. if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
  343. g_bLostConnection = TRUE;
  344. }
  345. if (m_lResult != ERROR_SUCCESS)
  346. return m_lResult;
  347. }
  348. // If not connected, default to \\Local_Machine\HKEY_LOCAL_MACHINE
  349. if (!m_bConnected)
  350. {
  351. m_lResult = Connect();
  352. if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
  353. g_bLostConnection = TRUE;
  354. }
  355. if (m_lResult != ERROR_SUCCESS)
  356. return m_lResult;
  357. }
  358. // Attempt to open the specified subkey
  359. if (m_bLocal)
  360. hkey = m_hkeyConnect;
  361. else
  362. hkey = m_hkeyRemote;
  363. m_lResult = RegOpenKeyEx(hkey, pszKeyName, 0, samDesired, &hkeyOpen);
  364. if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
  365. g_bLostConnection = TRUE;
  366. }
  367. if (m_lResult != ERROR_SUCCESS)
  368. return m_lResult;
  369. // Attempt to get info about this key.
  370. TCHAR szBuffer[1024 + 1];
  371. DWORD dwClass, dwSubKeys, dwMaxSubKey, dwMaxClass, dwValues;
  372. DWORD dwMaxValueName, dwMaxValueData, dwSecurityDescriptor;
  373. FILETIME ftLastWriteTime;
  374. dwClass = 1024 + 1;
  375. m_lResult = RegQueryInfoKey(hkeyOpen, szBuffer, &dwClass, 0, &dwSubKeys,
  376. &dwMaxSubKey, &dwMaxClass, &dwValues, &dwMaxValueName,
  377. &dwMaxValueData, &dwSecurityDescriptor, &ftLastWriteTime);
  378. if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
  379. g_bLostConnection = TRUE;
  380. return m_lResult;
  381. }
  382. if (m_lResult != ERROR_SUCCESS)
  383. {
  384. RegCloseKey(hkeyOpen);
  385. return m_lResult;
  386. }
  387. // Success! save all the data.
  388. m_sFullName = pszKeyName;
  389. nPos = m_sFullName.ReverseFind('\\');
  390. if (nPos >= 0)
  391. m_sKeyName = m_sFullName.Mid(nPos + 1);
  392. else
  393. m_sKeyName = m_sFullName;
  394. m_hkeyOpen = hkeyOpen;
  395. m_bOpen = TRUE;
  396. m_Sam = samDesired;
  397. m_sClass = szBuffer;
  398. m_dwSubKeys = dwSubKeys;
  399. m_dwMaxSubKey = dwMaxSubKey;
  400. m_dwMaxClass = dwMaxClass;
  401. m_dwValues = dwValues;
  402. m_dwMaxValueName = dwMaxValueName;
  403. m_dwMaxValueData = dwMaxValueData;
  404. m_dwSecurityDescriptor = dwSecurityDescriptor;
  405. m_ftLastWriteTime = ftLastWriteTime;
  406. return ERROR_SUCCESS;
  407. }
  408. //****************************************************************************
  409. //
  410. // CRegistryKey::Close
  411. //
  412. //****************************************************************************
  413. LONG CRegistryKey::Close(BOOL bForce)
  414. {
  415. if (!g_bLostConnection) {
  416. m_lResult = ERROR_SUCCESS;
  417. if (!m_bOpen)
  418. return ERROR_SUCCESS;
  419. if (m_bDirty)
  420. {
  421. m_lResult = RegFlushKey(m_hkeyOpen);
  422. if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
  423. g_bLostConnection = TRUE;
  424. }
  425. if (!bForce && m_lResult != ERROR_SUCCESS)
  426. return m_lResult;
  427. }
  428. if (!g_bLostConnection) {
  429. m_lResult = RegCloseKey(m_hkeyOpen);
  430. if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
  431. g_bLostConnection = TRUE;
  432. }
  433. if (!bForce && m_lResult != ERROR_SUCCESS)
  434. return m_lResult;
  435. }
  436. }
  437. m_bDirty = FALSE;
  438. m_hkeyOpen = NULL;
  439. m_bOpen = FALSE;
  440. m_sFullName.Empty();
  441. m_sClass.Empty();
  442. m_Sam = 0;
  443. m_dwSubKeys = 0;
  444. m_dwMaxSubKey = 0;
  445. m_dwMaxClass = 0;
  446. m_dwValues = 0;
  447. m_dwMaxValueName = 0;
  448. m_dwMaxValueData = 0;
  449. m_dwSecurityDescriptor = 0;
  450. m_ftLastWriteTime.dwLowDateTime = 0;
  451. m_ftLastWriteTime.dwHighDateTime = 0;
  452. if (g_bLostConnection) {
  453. m_lResult = RPC_S_SERVER_UNAVAILABLE;
  454. return RPC_S_SERVER_UNAVAILABLE;
  455. }
  456. else {
  457. m_lResult = ERROR_SUCCESS;
  458. return ERROR_SUCCESS;
  459. }
  460. }
  461. //****************************************************************************
  462. //
  463. // CRegistryKey::EnumValues
  464. //
  465. // Returns NULL if unsuccessful, returns empty array if successful but open
  466. // key has no values.
  467. // NOTE: Caller is responsible for deleting returned string array.
  468. //
  469. //****************************************************************************
  470. CStringArray* CRegistryKey::EnumValues()
  471. {
  472. if (g_bLostConnection) {
  473. m_lResult = RPC_S_SERVER_UNAVAILABLE;
  474. return NULL;
  475. }
  476. TCHAR szBuffer[1024 + 1];
  477. DWORD dwLength;
  478. CStringArray *pArr;
  479. int i;
  480. m_lResult = ERROR_SUCCESS;
  481. if (!m_bOpen || g_bLostConnection)
  482. return NULL;
  483. // Enumerate all the values into a string array
  484. pArr = new CStringArray;
  485. i = 0;
  486. m_lResult = ERROR_SUCCESS;
  487. while (TRUE)
  488. {
  489. dwLength = 1024 + 1;
  490. m_lResult = RegEnumValue(m_hkeyOpen, i, szBuffer, &dwLength, NULL,
  491. NULL, NULL, NULL);
  492. if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
  493. g_bLostConnection = TRUE;
  494. }
  495. if (m_lResult != ERROR_SUCCESS)
  496. break;
  497. if (dwLength > 0)
  498. pArr->Add(szBuffer);
  499. i++;
  500. }
  501. // Did we find a normal end condition?
  502. if (m_lResult == ERROR_NO_MORE_ITEMS)
  503. return pArr;
  504. delete pArr;
  505. return NULL;
  506. }
  507. //****************************************************************************
  508. //
  509. // CRegistryKey::EnumSubKeys
  510. //
  511. // Returns NULL if unsuccessful, returns empty array if successful but open
  512. // key has no values.
  513. // NOTE: Caller is responsible for deleting returned string array.
  514. //
  515. //****************************************************************************
  516. CStringArray* CRegistryKey::EnumSubKeys()
  517. {
  518. if (g_bLostConnection) {
  519. m_lResult = RPC_S_SERVER_UNAVAILABLE;
  520. return NULL;
  521. }
  522. TCHAR szBuffer[1024 + 1];
  523. DWORD dwLength;
  524. CStringArray *pArr;
  525. int i;
  526. m_lResult = ERROR_SUCCESS;
  527. if (!m_bOpen)
  528. return NULL;
  529. // Enumerate all the subkeys into a string array
  530. pArr = new CStringArray;
  531. i = 0;
  532. while (TRUE)
  533. {
  534. dwLength = 1024 + 1;
  535. m_lResult = RegEnumKeyEx(m_hkeyOpen, i, szBuffer, &dwLength, NULL,
  536. NULL, NULL, NULL);
  537. if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
  538. g_bLostConnection = TRUE;
  539. }
  540. if (m_lResult != ERROR_SUCCESS)
  541. break;
  542. if (dwLength > 0)
  543. pArr->Add(szBuffer);
  544. i++;
  545. }
  546. // Did we find a normal end condition?
  547. if (m_lResult == ERROR_NO_MORE_ITEMS)
  548. return pArr;
  549. delete pArr;
  550. return NULL;
  551. }
  552. //****************************************************************************
  553. //
  554. // CRegistryKey::GetValue
  555. //
  556. // Note: regval is always emptied regardless of success/failure
  557. //
  558. //****************************************************************************
  559. BOOL CRegistryKey::GetValue(LPCTSTR pszValue, CRegistryValue &regval)
  560. {
  561. DWORD dwLength, dwType;
  562. BYTE *pBuffer;
  563. regval.Empty();
  564. if (g_bLostConnection) {
  565. m_lResult = RPC_S_SERVER_UNAVAILABLE;
  566. return FALSE;
  567. }
  568. if (!m_bOpen)
  569. {
  570. m_lResult = ERROR_INVALID_FUNCTION;
  571. return FALSE;
  572. }
  573. // Find out how big the data is
  574. m_lResult = RegQueryValueEx(m_hkeyOpen, (LPTSTR)pszValue, NULL, NULL,
  575. NULL, &dwLength);
  576. if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
  577. g_bLostConnection = TRUE;
  578. }
  579. if (m_lResult != ERROR_SUCCESS)
  580. return FALSE;
  581. if (dwLength == 0)
  582. return TRUE;
  583. // Now make a buffer big enough for it.
  584. pBuffer = new BYTE[dwLength];
  585. if (pBuffer == NULL)
  586. return FALSE;
  587. m_lResult = RegQueryValueEx(m_hkeyOpen, (LPTSTR)pszValue, NULL, &dwType,
  588. pBuffer, &dwLength);
  589. if (m_lResult == ERROR_SUCCESS)
  590. regval.Set(pszValue, dwType, dwLength, pBuffer);
  591. delete pBuffer;
  592. if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
  593. g_bLostConnection = TRUE;
  594. }
  595. if (m_lResult != ERROR_SUCCESS)
  596. return FALSE;
  597. return TRUE;
  598. }
  599. //****************************************************************************
  600. //
  601. // CRegistryKey::SetValue
  602. //
  603. //****************************************************************************
  604. BOOL CRegistryKey::SetValue(CRegistryValue &regval)
  605. {
  606. if (g_bLostConnection) {
  607. m_lResult = RPC_S_SERVER_UNAVAILABLE;
  608. return FALSE;
  609. }
  610. if (!m_bOpen)
  611. {
  612. m_lResult = ERROR_INVALID_FUNCTION;
  613. return FALSE;
  614. }
  615. if (regval.m_sName.IsEmpty())
  616. {
  617. m_lResult = ERROR_INVALID_DATA;
  618. return FALSE;
  619. }
  620. m_lResult = RegSetValueEx(m_hkeyOpen, regval.m_sName, 0, regval.m_dwType,
  621. regval.m_pData, regval.m_dwDataLength);
  622. if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
  623. g_bLostConnection = TRUE;
  624. }
  625. if (m_lResult != ERROR_SUCCESS)
  626. return FALSE;
  627. m_bDirty = TRUE;
  628. return TRUE;
  629. }
  630. //****************************************************************************
  631. //
  632. // CRegistryKey::GetSubKey
  633. //
  634. // Note: If successful, regkey is returned connected and open on the
  635. // specified key. If failure, regkey is returned disconnected.
  636. //
  637. //****************************************************************************
  638. BOOL CRegistryKey::GetSubKey(LPCTSTR pszSubKey, CRegistryKey &regkey)
  639. {
  640. if (g_bLostConnection) {
  641. m_lResult = RPC_S_SERVER_UNAVAILABLE;
  642. return FALSE;
  643. }
  644. CString sSubKey;
  645. m_lResult = ERROR_SUCCESS;
  646. if (!m_bOpen)
  647. return FALSE;
  648. m_lResult = regkey.Disconnect(TRUE);
  649. if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
  650. g_bLostConnection = TRUE;
  651. }
  652. if (m_lResult != ERROR_SUCCESS)
  653. return FALSE;
  654. // Try to connect and open same key
  655. m_lResult = regkey.Connect(m_sComputer, m_hkeyConnect);
  656. if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
  657. g_bLostConnection = TRUE;
  658. }
  659. if (m_lResult != ERROR_SUCCESS)
  660. return FALSE;
  661. sSubKey = pszSubKey;
  662. m_lResult = regkey.Open(m_sFullName + "\\" + sSubKey, m_Sam);
  663. if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
  664. g_bLostConnection = TRUE;
  665. }
  666. if (m_lResult != ERROR_SUCCESS)
  667. {
  668. regkey.Disconnect(TRUE);
  669. return FALSE;
  670. }
  671. return TRUE;
  672. }
  673. //****************************************************************************
  674. //
  675. // CRegistryKey::CreateSubKey
  676. //
  677. // Note: If successful, regkey is returned connected and open on the
  678. // new key; if the key already existed, it is simply opened. If failure,
  679. // regkey is returned disconnected.
  680. //
  681. //****************************************************************************
  682. BOOL CRegistryKey::CreateSubKey(
  683. LPCTSTR pszSubKey,
  684. CRegistryKey &regkey,
  685. LPCTSTR pszClass,
  686. LPSECURITY_ATTRIBUTES lpSecAttr,
  687. BOOL bIsVolatile)
  688. {
  689. if (g_bLostConnection) {
  690. m_lResult = RPC_S_SERVER_UNAVAILABLE;
  691. return FALSE;
  692. }
  693. CString sSubKey, sClass;
  694. HKEY hkeyOpen;
  695. DWORD dwDisposition;
  696. m_lResult = ERROR_SUCCESS;
  697. if (!m_bOpen)
  698. return FALSE;
  699. m_lResult = regkey.Disconnect(TRUE);
  700. if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
  701. g_bLostConnection = TRUE;
  702. }
  703. if (m_lResult != ERROR_SUCCESS)
  704. return FALSE;
  705. // Try to connect and open same key
  706. m_lResult = regkey.Connect(m_sComputer, m_hkeyConnect);
  707. if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
  708. g_bLostConnection = TRUE;
  709. }
  710. if (m_lResult != ERROR_SUCCESS)
  711. return FALSE;
  712. sSubKey = pszSubKey;
  713. sClass = pszClass;
  714. DWORD dwRegOptions = bIsVolatile ? REG_OPTION_VOLATILE : REG_OPTION_NON_VOLATILE;
  715. m_lResult = RegCreateKeyEx(m_hkeyOpen, sSubKey, 0, (LPTSTR)(LPCTSTR)sClass,
  716. dwRegOptions, m_Sam, lpSecAttr, &hkeyOpen, &dwDisposition);
  717. if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
  718. g_bLostConnection = TRUE;
  719. }
  720. if (m_lResult != ERROR_SUCCESS)
  721. {
  722. regkey.Disconnect(TRUE);
  723. return FALSE;
  724. }
  725. m_lResult = RegCloseKey(hkeyOpen);
  726. if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
  727. g_bLostConnection = TRUE;
  728. }
  729. if (m_lResult != ERROR_SUCCESS)
  730. return FALSE;
  731. m_lResult = regkey.Open(m_sFullName + "\\" + sSubKey, m_Sam);
  732. if (m_lResult != ERROR_SUCCESS)
  733. {
  734. if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
  735. g_bLostConnection = TRUE;
  736. }
  737. regkey.Disconnect(TRUE);
  738. return FALSE;
  739. }
  740. m_bDirty = TRUE;
  741. if (dwDisposition == REG_CREATED_NEW_KEY)
  742. regkey.m_bDirty = TRUE;
  743. return TRUE;
  744. }
  745. //****************************************************************************
  746. //
  747. // CRegistryKey::DeleteSubKey
  748. //
  749. //****************************************************************************
  750. BOOL CRegistryKey::DeleteSubKey(LPCTSTR pszSubKey)
  751. {
  752. if (g_bLostConnection) {
  753. return FALSE;
  754. }
  755. CString sSubKey;
  756. CRegistryKey subkey;
  757. int i;
  758. m_lResult = ERROR_SUCCESS;
  759. sSubKey = pszSubKey;
  760. if (!m_bOpen)
  761. return FALSE;
  762. if (!GetSubKey(sSubKey, subkey))
  763. return FALSE;
  764. // Delete all subkeys of the specified subkey (RegDeleteKey limitation)
  765. CStringArray *parr = subkey.EnumSubKeys();
  766. for (i=0; i<parr->GetSize(); i++)
  767. {
  768. if (!subkey.DeleteSubKey(parr->GetAt(i)))
  769. return FALSE;
  770. }
  771. delete parr;
  772. subkey.Close(TRUE);
  773. m_lResult = RegDeleteKey(m_hkeyOpen, sSubKey);
  774. if (m_lResult != ERROR_SUCCESS) {
  775. if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
  776. g_bLostConnection = TRUE;
  777. }
  778. return FALSE;
  779. }
  780. return TRUE;
  781. }