Source code of Windows XP (NT5)
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.

1554 lines
31 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. regutils.c
  5. Abstract:
  6. Implements wrappers similar to migutil's reg.c, but for Win95 registry.
  7. Author:
  8. Jim Schmidt (jimschm) 30-Jan-1998
  9. Revisions:
  10. --*/
  11. #include "pch.h"
  12. #ifdef DEBUG
  13. #undef Win95RegCloseKey
  14. #endif
  15. #define DBG_REGUTILS "RegUtils"
  16. //
  17. // Private prototypes
  18. //
  19. BOOL
  20. pPopRegKeyInfo95A (
  21. IN PREGTREE_ENUMA EnumPtr
  22. );
  23. BOOL
  24. pPopRegKeyInfo95W (
  25. IN PREGTREE_ENUMW EnumPtr
  26. );
  27. //
  28. // Implementation
  29. //
  30. /*++
  31. Routine Description:
  32. EnumFirstRegKey95A and EnumFirstRegKey95W begin an enumeration of registry
  33. subkeys. They initialize the registy enumeration structure and
  34. call the registry APIs to enumerate subkeys of the specified key handle.
  35. Arguments:
  36. EnumPtr - Receives the updated state of enumeration. The structure
  37. can be accessed directly.
  38. Key - Specifies the handle of the registry key to enumerate.
  39. Return Value:
  40. TRUE if successful, or FALSE if an error or if no more subkeys are available.
  41. Call GetLastError for the failure code.
  42. --*/
  43. BOOL
  44. EnumFirstRegKey95A (
  45. OUT PREGKEY_ENUMA EnumPtr,
  46. IN HKEY hKey
  47. )
  48. {
  49. ZeroMemory (EnumPtr, sizeof (REGKEY_ENUMA));
  50. EnumPtr->KeyHandle = hKey;
  51. return EnumNextRegKey95A (EnumPtr);
  52. }
  53. BOOL
  54. EnumFirstRegKey95W (
  55. OUT PREGKEY_ENUMW EnumPtr,
  56. IN HKEY hKey
  57. )
  58. {
  59. ZeroMemory (EnumPtr, sizeof (REGKEY_ENUMW));
  60. EnumPtr->KeyHandle = hKey;
  61. return EnumNextRegKey95W (EnumPtr);
  62. }
  63. /*++
  64. Routine Description:
  65. OpenRegKeyStr95A and OpenRegKeyStr95W parse a text string that specifies a
  66. registry key into the hive and subkey, and then they open the subkey
  67. and return the handle.
  68. Arguments:
  69. RegKey - Specifies the complete path to the registry subkey, including
  70. the hive.
  71. Return Value:
  72. A non-NULL registry handle if successful, or NULL if either the subkey
  73. could not be opened or the string is malformed.
  74. --*/
  75. HKEY
  76. RealOpenRegKeyStr95A (
  77. IN PCSTR RegKey
  78. DEBUG_TRACKING_PARAMS
  79. )
  80. {
  81. DWORD End;
  82. HKEY RootKey;
  83. HKEY Key;
  84. RootKey = ConvertRootStringToKeyA (RegKey, &End);
  85. if (!RootKey) {
  86. return NULL;
  87. }
  88. if (!RegKey[End]) {
  89. OurRegOpenRootKey95A (RootKey, RegKey /* , */ DEBUG_TRACKING_ARGS);
  90. return RootKey;
  91. }
  92. Key = RealOpenRegKey95A (RootKey, &RegKey[End] /* , */ DEBUG_TRACKING_ARGS);
  93. return Key;
  94. }
  95. HKEY
  96. RealOpenRegKeyStr95W (
  97. IN PCWSTR RegKey
  98. DEBUG_TRACKING_PARAMS
  99. )
  100. {
  101. PCSTR AnsiRegKey;
  102. HKEY Key;
  103. AnsiRegKey = ConvertWtoA (RegKey);
  104. if (!AnsiRegKey) {
  105. return NULL;
  106. }
  107. Key = RealOpenRegKeyStr95A (AnsiRegKey /* , */ DEBUG_TRACKING_ARGS);
  108. FreeConvertedStr (AnsiRegKey);
  109. return Key;
  110. }
  111. /*++
  112. Routine Description:
  113. EnumFirstRegKeyStr95A and EnumFirstRegKeyStr95W start an enumeration of
  114. subkeys within the given key. In these functions, the key is specified
  115. via a string instead of an HKEY value.
  116. Arguments:
  117. EnumPtr - Receives the updated state of enumeration. The structure
  118. can be accessed directly.
  119. RegKey - Specifies the full path of the registry key to enumerate.
  120. Return Value:
  121. TRUE if successful, or FALSE if an error or if no more subkeys are available.
  122. Call GetLastError for the failure code.
  123. --*/
  124. BOOL
  125. RealEnumFirstRegKeyStr95A (
  126. OUT PREGKEY_ENUMA EnumPtr,
  127. IN PCSTR RegKey
  128. DEBUG_TRACKING_PARAMS
  129. )
  130. {
  131. HKEY Key;
  132. BOOL b;
  133. Key = RealOpenRegKeyStr95A (RegKey /* , */ DEBUG_TRACKING_ARGS);
  134. if (!Key) {
  135. return FALSE;
  136. }
  137. b = EnumFirstRegKey95A (EnumPtr, Key);
  138. if (!b) {
  139. CloseRegKey95 (Key);
  140. } else {
  141. EnumPtr->OpenedByEnum = TRUE;
  142. }
  143. return b;
  144. }
  145. BOOL
  146. RealEnumFirstRegKeyStr95W (
  147. IN PREGKEY_ENUMW EnumPtr,
  148. IN PCWSTR RegKey
  149. DEBUG_TRACKING_PARAMS
  150. )
  151. {
  152. HKEY Key;
  153. BOOL b;
  154. Key = RealOpenRegKeyStr95W (RegKey /* , */ DEBUG_TRACKING_ARGS);
  155. if (!Key) {
  156. return FALSE;
  157. }
  158. b = EnumFirstRegKey95W (EnumPtr, Key);
  159. if (!b) {
  160. CloseRegKey95 (Key);
  161. } else {
  162. EnumPtr->OpenedByEnum = TRUE;
  163. }
  164. return b;
  165. }
  166. /*++
  167. Routine Description:
  168. AbortRegKeyEnum95A and AbortRegKeyEnum95W release all resources associated
  169. with a registry subkey enumeration. Call this function to stop the
  170. enumeration before it completes by itself.
  171. Arguments:
  172. EnumPtr - Specifies the enumeration to stop. Receives the updated
  173. state of enumeration.
  174. Return Value:
  175. none
  176. --*/
  177. VOID
  178. AbortRegKeyEnum95A (
  179. IN OUT PREGKEY_ENUMA EnumPtr
  180. )
  181. {
  182. if (EnumPtr->OpenedByEnum && EnumPtr->KeyHandle) {
  183. CloseRegKey95 (EnumPtr->KeyHandle);
  184. EnumPtr->KeyHandle = NULL;
  185. }
  186. }
  187. VOID
  188. AbortRegKeyEnum95W (
  189. IN OUT PREGKEY_ENUMW EnumPtr
  190. )
  191. {
  192. if (EnumPtr->OpenedByEnum && EnumPtr->KeyHandle) {
  193. CloseRegKey95 (EnumPtr->KeyHandle);
  194. EnumPtr->KeyHandle = NULL;
  195. }
  196. }
  197. /*++
  198. Routine Description:
  199. EnumNextRegKey95A and EnumNextRegKey95W continue an enumeration started by
  200. one of the subkey enumeration routines above. If all items have been
  201. enumerated, this function cleans up all resources and returns FALSE.
  202. Arguments:
  203. EnumPtr - Specifies the enumeration to continue. Receives the updated
  204. state of enumeration. The structure can be accessed directly.
  205. Return Value:
  206. TRUE if successful, or FALSE if an error or if no more subkeys are available.
  207. Call GetLastError for the failure code.
  208. --*/
  209. BOOL
  210. EnumNextRegKey95A (
  211. IN OUT PREGKEY_ENUMA EnumPtr
  212. )
  213. {
  214. LONG rc;
  215. rc = Win95RegEnumKeyA (
  216. EnumPtr->KeyHandle,
  217. EnumPtr->Index,
  218. EnumPtr->SubKeyName,
  219. MAX_REGISTRY_KEYA
  220. );
  221. if (rc != ERROR_SUCCESS) {
  222. if (EnumPtr->OpenedByEnum) {
  223. CloseRegKey95 (EnumPtr->KeyHandle);
  224. EnumPtr->KeyHandle = NULL;
  225. }
  226. if (rc == ERROR_NO_MORE_ITEMS) {
  227. SetLastError (ERROR_SUCCESS);
  228. } else {
  229. SetLastError (rc);
  230. }
  231. return FALSE;
  232. }
  233. EnumPtr->Index += 1;
  234. return TRUE;
  235. }
  236. BOOL
  237. EnumNextRegKey95W (
  238. IN OUT PREGKEY_ENUMW EnumPtr
  239. )
  240. {
  241. LONG rc;
  242. rc = Win95RegEnumKeyW (
  243. EnumPtr->KeyHandle,
  244. EnumPtr->Index,
  245. EnumPtr->SubKeyName,
  246. MAX_REGISTRY_KEYW
  247. );
  248. if (rc != ERROR_SUCCESS) {
  249. if (EnumPtr->OpenedByEnum) {
  250. CloseRegKey95 (EnumPtr->KeyHandle);
  251. EnumPtr->KeyHandle = NULL;
  252. }
  253. if (rc == ERROR_NO_MORE_ITEMS) {
  254. SetLastError (ERROR_SUCCESS);
  255. } else {
  256. SetLastError (rc);
  257. }
  258. return FALSE;
  259. }
  260. EnumPtr->Index += 1;
  261. return TRUE;
  262. }
  263. BOOL
  264. pPushRegKeyInfo95A (
  265. IN PREGTREE_ENUMA EnumPtr,
  266. IN PCSTR KeyName
  267. )
  268. {
  269. PREGKEYINFOA RetVal;
  270. PSTR p;
  271. RetVal = (PREGKEYINFOA) PoolMemGetAlignedMemory (
  272. EnumPtr->EnumPool,
  273. sizeof (REGKEYINFOA)
  274. );
  275. if (!RetVal) {
  276. return FALSE;
  277. }
  278. //
  279. // Initialize struct to zero
  280. //
  281. ZeroMemory (RetVal, sizeof (REGKEYINFOA));
  282. //
  283. // Link parent and child pointers
  284. //
  285. RetVal->Parent = EnumPtr->CurrentKey;
  286. if (EnumPtr->CurrentKey) {
  287. EnumPtr->CurrentKey->Child = RetVal;
  288. }
  289. EnumPtr->CurrentKey = RetVal;
  290. //
  291. // Prepare full key path by appending the key name to the existing
  292. // base
  293. //
  294. RetVal->BaseKeyBytes = EnumPtr->FullKeyNameBytes;
  295. p = (PSTR) ((PBYTE) EnumPtr->FullKeyName + RetVal->BaseKeyBytes);
  296. if (EnumPtr->FullKeyNameBytes) {
  297. StringCopyA (p, "\\");
  298. EnumPtr->FullKeyNameBytes += ByteCountA (p);
  299. p = _mbsinc (p);
  300. }
  301. _mbssafecpy (p, KeyName, MAX_REGISTRY_KEYA - EnumPtr->FullKeyNameBytes);
  302. EnumPtr->FullKeyNameBytes += ByteCountA (KeyName);
  303. //
  304. // Save the key name independent of the full registry path.
  305. // Also open the key.
  306. //
  307. _mbssafecpy (RetVal->KeyName, KeyName, MAX_REGISTRY_KEYA);
  308. RetVal->KeyHandle = OpenRegKeyStr95A (EnumPtr->FullKeyName);
  309. if (!RetVal->KeyHandle) {
  310. pPopRegKeyInfo95A (EnumPtr);
  311. return FALSE;
  312. }
  313. return TRUE;
  314. }
  315. BOOL
  316. pPushRegKeyInfo95W (
  317. IN PREGTREE_ENUMW EnumPtr,
  318. IN PCWSTR KeyName
  319. )
  320. {
  321. PREGKEYINFOW RetVal;
  322. PWSTR p;
  323. RetVal = (PREGKEYINFOW) PoolMemGetAlignedMemory (
  324. EnumPtr->EnumPool,
  325. sizeof (REGKEYINFOW)
  326. );
  327. if (!RetVal) {
  328. return FALSE;
  329. }
  330. //
  331. // Initialize struct to zero
  332. //
  333. ZeroMemory (RetVal, sizeof (REGKEYINFOW));
  334. //
  335. // Link parent and child pointers
  336. //
  337. RetVal->Parent = EnumPtr->CurrentKey;
  338. if (EnumPtr->CurrentKey) {
  339. EnumPtr->CurrentKey->Child = RetVal;
  340. }
  341. EnumPtr->CurrentKey = RetVal;
  342. //
  343. // Prepare full key path by appending the key name to the existing
  344. // base
  345. //
  346. RetVal->BaseKeyBytes = EnumPtr->FullKeyNameBytes;
  347. p = (PWSTR) ((PBYTE) EnumPtr->FullKeyName + RetVal->BaseKeyBytes);
  348. if (EnumPtr->FullKeyNameBytes) {
  349. StringCopyW (p, L"\\");
  350. EnumPtr->FullKeyNameBytes += ByteCountW (p);
  351. p++;
  352. }
  353. _wcssafecpy (p, KeyName, MAX_REGISTRY_KEYW - (EnumPtr->FullKeyNameBytes / sizeof (WCHAR)));
  354. EnumPtr->FullKeyNameBytes += ByteCountW (KeyName);
  355. //
  356. // Save the key name independent of the full registry path.
  357. // Also open the key.
  358. //
  359. _wcssafecpy (RetVal->KeyName, KeyName, MAX_REGISTRY_KEYW);
  360. RetVal->KeyHandle = OpenRegKeyStr95W (EnumPtr->FullKeyName);
  361. if (!RetVal->KeyHandle) {
  362. pPopRegKeyInfo95W (EnumPtr);
  363. return FALSE;
  364. }
  365. return TRUE;
  366. }
  367. BOOL
  368. pPopRegKeyInfo95A (
  369. IN PREGTREE_ENUMA EnumPtr
  370. )
  371. {
  372. PREGKEYINFOA FreeMe;
  373. PSTR p;
  374. FreeMe = EnumPtr->CurrentKey;
  375. //
  376. // Skip if nothing was ever pushed
  377. //
  378. if (!FreeMe) {
  379. return FALSE;
  380. }
  381. //
  382. // Trim the full key string
  383. //
  384. EnumPtr->CurrentKey = FreeMe->Parent;
  385. EnumPtr->FullKeyNameBytes = FreeMe->BaseKeyBytes;
  386. p = (PSTR) ((PBYTE) EnumPtr->FullKeyName + FreeMe->BaseKeyBytes);
  387. *p = 0;
  388. //
  389. // Adjust the linkage
  390. //
  391. if (EnumPtr->CurrentKey) {
  392. EnumPtr->CurrentKey->Child = NULL;
  393. }
  394. //
  395. // Clean up resources
  396. //
  397. if (FreeMe->KeyHandle) {
  398. CloseRegKey95 (FreeMe->KeyHandle);
  399. }
  400. AbortRegKeyEnum95A (&FreeMe->KeyEnum);
  401. PoolMemReleaseMemory (EnumPtr->EnumPool, (PVOID) FreeMe);
  402. //
  403. // Return FALSE if last item was poped
  404. //
  405. return EnumPtr->CurrentKey != NULL;
  406. }
  407. BOOL
  408. pPopRegKeyInfo95W (
  409. IN PREGTREE_ENUMW EnumPtr
  410. )
  411. {
  412. PREGKEYINFOW FreeMe;
  413. PWSTR p;
  414. FreeMe = EnumPtr->CurrentKey;
  415. //
  416. // Skip if nothing was ever pushed
  417. //
  418. if (!FreeMe) {
  419. return FALSE;
  420. }
  421. //
  422. // Trim the full key string
  423. //
  424. EnumPtr->CurrentKey = FreeMe->Parent;
  425. EnumPtr->FullKeyNameBytes = FreeMe->BaseKeyBytes;
  426. p = (PWSTR) ((PBYTE) EnumPtr->FullKeyName + FreeMe->BaseKeyBytes);
  427. *p = 0;
  428. //
  429. // Adjust the linkage
  430. //
  431. if (EnumPtr->CurrentKey) {
  432. EnumPtr->CurrentKey->Child = NULL;
  433. }
  434. //
  435. // Clean up resources
  436. //
  437. if (FreeMe->KeyHandle) {
  438. CloseRegKey95 (FreeMe->KeyHandle);
  439. }
  440. AbortRegKeyEnum95W (&FreeMe->KeyEnum);
  441. PoolMemReleaseMemory (EnumPtr->EnumPool, (PVOID) FreeMe);
  442. //
  443. // Return FALSE if last item was poped
  444. //
  445. return EnumPtr->CurrentKey != NULL;
  446. }
  447. BOOL
  448. RealEnumFirstRegKeyInTree95A (
  449. OUT PREGTREE_ENUMA EnumPtr,
  450. IN PCSTR BaseKeyStr
  451. )
  452. {
  453. ZeroMemory (EnumPtr, sizeof (REGTREE_ENUMA));
  454. //
  455. // Allocate pool for enum structs
  456. //
  457. EnumPtr->EnumPool = PoolMemInitNamedPool ("RegKeyInTree95A");
  458. if (!EnumPtr->EnumPool) {
  459. return FALSE;
  460. }
  461. PoolMemSetMinimumGrowthSize (EnumPtr->EnumPool, 32768);
  462. PoolMemDisableTracking (EnumPtr->EnumPool);
  463. //
  464. // Push base key on the enum stack
  465. //
  466. if (!pPushRegKeyInfo95A (EnumPtr, BaseKeyStr)) {
  467. DEBUGMSG ((DBG_REGUTILS, "EnumFirstRegKeyInTree95A failed to push base key"));
  468. AbortRegKeyTreeEnum95A (EnumPtr);
  469. return FALSE;
  470. }
  471. EnumPtr->EnumBaseBytes = ByteCountA (BaseKeyStr);
  472. //
  473. // Set state so EnumNextRegKeyInTree95 knows what to do
  474. //
  475. EnumPtr->State = ENUMERATE_SUBKEY_BEGIN;
  476. return TRUE;
  477. }
  478. BOOL
  479. RealEnumFirstRegKeyInTree95W (
  480. OUT PREGTREE_ENUMW EnumPtr,
  481. IN PCWSTR BaseKeyStr
  482. )
  483. {
  484. ZeroMemory (EnumPtr, sizeof (REGTREE_ENUMW));
  485. //
  486. // Allocate pool for enum structs
  487. //
  488. EnumPtr->EnumPool = PoolMemInitNamedPool ("RegKeyInTree95W");
  489. if (!EnumPtr->EnumPool) {
  490. return FALSE;
  491. }
  492. PoolMemSetMinimumGrowthSize (EnumPtr->EnumPool, 32768);
  493. PoolMemDisableTracking (EnumPtr->EnumPool);
  494. //
  495. // Push base key on the enum stack
  496. //
  497. if (!pPushRegKeyInfo95W (EnumPtr, BaseKeyStr)) {
  498. DEBUGMSG ((DBG_REGUTILS, "EnumFirstRegKeyInTree95W failed to push base key"));
  499. AbortRegKeyTreeEnum95W (EnumPtr);
  500. return FALSE;
  501. }
  502. EnumPtr->EnumBaseBytes = ByteCountW (BaseKeyStr);
  503. //
  504. // Set state so EnumNextRegKeyInTree95 knows what to do
  505. //
  506. EnumPtr->State = ENUMERATE_SUBKEY_BEGIN;
  507. return TRUE;
  508. }
  509. BOOL
  510. RealEnumNextRegKeyInTree95A (
  511. IN OUT PREGTREE_ENUMA EnumPtr
  512. )
  513. {
  514. if (EnumPtr->State == NO_MORE_ITEMS) {
  515. return FALSE;
  516. }
  517. while (TRUE) {
  518. switch (EnumPtr->State) {
  519. case ENUMERATE_SUBKEY_BEGIN:
  520. //
  521. // Start enumeration
  522. //
  523. if (EnumFirstRegKey95A (
  524. &EnumPtr->CurrentKey->KeyEnum,
  525. EnumPtr->CurrentKey->KeyHandle
  526. )) {
  527. EnumPtr->State = ENUMERATE_SUBKEY_RETURN;
  528. } else {
  529. EnumPtr->State = ENUMERATE_SUBKEY_DONE;
  530. }
  531. break;
  532. case ENUMERATE_SUBKEY_NEXT:
  533. //
  534. // Continue enumerations
  535. //
  536. if (EnumNextRegKey95A (&EnumPtr->CurrentKey->KeyEnum)) {
  537. EnumPtr->State = ENUMERATE_SUBKEY_RETURN;
  538. } else {
  539. EnumPtr->State = ENUMERATE_SUBKEY_DONE;
  540. }
  541. break;
  542. case ENUMERATE_SUBKEY_DONE:
  543. //
  544. // Enumeration of this key is done; pop and continue.
  545. //
  546. if (!pPopRegKeyInfo95A (EnumPtr)) {
  547. EnumPtr->State = NO_MORE_ITEMS;
  548. AbortRegKeyTreeEnum95A (EnumPtr);
  549. } else {
  550. EnumPtr->State = ENUMERATE_SUBKEY_NEXT;
  551. }
  552. break;
  553. case ENUMERATE_SUBKEY_RETURN:
  554. //
  555. // Return enumerated item to caller
  556. //
  557. if (!pPushRegKeyInfo95A (EnumPtr, EnumPtr->CurrentKey->KeyEnum.SubKeyName)) {
  558. DEBUGMSGA ((
  559. DBG_REGUTILS,
  560. "EnumFirstRegKeyInTree95A failed to push sub key %s",
  561. EnumPtr->CurrentKey->KeyEnum.SubKeyName
  562. ));
  563. EnumPtr->State = ENUMERATE_SUBKEY_NEXT;
  564. break;
  565. }
  566. if (!EnumPtr->FirstEnumerated) {
  567. EnumPtr->FirstEnumerated = TRUE;
  568. EnumPtr->EnumBaseBytes += sizeof (CHAR);
  569. }
  570. EnumPtr->State = ENUMERATE_SUBKEY_BEGIN;
  571. return TRUE;
  572. default:
  573. MYASSERT (EnumPtr->State == NO_MORE_ITEMS);
  574. return FALSE;
  575. }
  576. }
  577. }
  578. BOOL
  579. RealEnumNextRegKeyInTree95W (
  580. IN OUT PREGTREE_ENUMW EnumPtr
  581. )
  582. {
  583. if (EnumPtr->State == NO_MORE_ITEMS) {
  584. return FALSE;
  585. }
  586. while (TRUE) {
  587. switch (EnumPtr->State) {
  588. case ENUMERATE_SUBKEY_BEGIN:
  589. //
  590. // Start enumeration
  591. //
  592. if (EnumFirstRegKey95W (
  593. &EnumPtr->CurrentKey->KeyEnum,
  594. EnumPtr->CurrentKey->KeyHandle
  595. )) {
  596. EnumPtr->State = ENUMERATE_SUBKEY_RETURN;
  597. } else {
  598. EnumPtr->State = ENUMERATE_SUBKEY_DONE;
  599. }
  600. break;
  601. case ENUMERATE_SUBKEY_NEXT:
  602. //
  603. // Continue enumerations
  604. //
  605. if (EnumNextRegKey95W (&EnumPtr->CurrentKey->KeyEnum)) {
  606. EnumPtr->State = ENUMERATE_SUBKEY_RETURN;
  607. } else {
  608. EnumPtr->State = ENUMERATE_SUBKEY_DONE;
  609. }
  610. break;
  611. case ENUMERATE_SUBKEY_DONE:
  612. //
  613. // Enumeration of this key is done; pop and continue.
  614. //
  615. if (!pPopRegKeyInfo95W (EnumPtr)) {
  616. EnumPtr->State = NO_MORE_ITEMS;
  617. AbortRegKeyTreeEnum95W (EnumPtr);
  618. } else {
  619. EnumPtr->State = ENUMERATE_SUBKEY_NEXT;
  620. }
  621. break;
  622. case ENUMERATE_SUBKEY_RETURN:
  623. //
  624. // Return enumerated item to caller
  625. //
  626. if (!pPushRegKeyInfo95W (EnumPtr, EnumPtr->CurrentKey->KeyEnum.SubKeyName)) {
  627. DEBUGMSGW ((
  628. DBG_REGUTILS,
  629. "EnumFirstRegKeyInTree95A failed to push sub key %s",
  630. EnumPtr->CurrentKey->KeyEnum.SubKeyName
  631. ));
  632. EnumPtr->State = ENUMERATE_SUBKEY_NEXT;
  633. break;
  634. }
  635. if (!EnumPtr->FirstEnumerated) {
  636. EnumPtr->FirstEnumerated = TRUE;
  637. EnumPtr->EnumBaseBytes += sizeof (WCHAR);
  638. }
  639. EnumPtr->State = ENUMERATE_SUBKEY_BEGIN;
  640. return TRUE;
  641. default:
  642. MYASSERT (EnumPtr->State == NO_MORE_ITEMS);
  643. return FALSE;
  644. }
  645. }
  646. }
  647. VOID
  648. AbortRegKeyTreeEnum95A (
  649. IN OUT PREGTREE_ENUMA EnumPtr
  650. )
  651. {
  652. //
  653. // Free all resources
  654. //
  655. while (pPopRegKeyInfo95A (EnumPtr)) {
  656. }
  657. PoolMemDestroyPool (EnumPtr->EnumPool);
  658. }
  659. VOID
  660. AbortRegKeyTreeEnum95W (
  661. IN OUT PREGTREE_ENUMW EnumPtr
  662. )
  663. {
  664. //
  665. // Free all resources
  666. //
  667. while (pPopRegKeyInfo95W (EnumPtr)) {
  668. }
  669. PoolMemDestroyPool (EnumPtr->EnumPool);
  670. }
  671. /*++
  672. Routine Description:
  673. EnumFirstRegValue95A and EnumerateFirstRegvalueW enumerate the first registry
  674. value name in the specified subkey.
  675. Arguments:
  676. EnumPtr - Receives the updated state of enumeration. The structure
  677. can be accessed directly.
  678. hKey - Specifies handle of registry subkey to enumerate.
  679. Return Value:
  680. TRUE if successful, or FALSE if an error or if no more values are available.
  681. Call GetLastError for the failure code.
  682. --*/
  683. BOOL
  684. EnumFirstRegValue95A (
  685. IN PREGVALUE_ENUMA EnumPtr,
  686. IN HKEY hKey
  687. )
  688. {
  689. ZeroMemory (EnumPtr, sizeof (REGVALUE_ENUMA));
  690. EnumPtr->KeyHandle = hKey;
  691. return EnumNextRegValue95A (EnumPtr);
  692. }
  693. BOOL
  694. EnumFirstRegValue95W (
  695. IN PREGVALUE_ENUMW EnumPtr,
  696. IN HKEY hKey
  697. )
  698. {
  699. ZeroMemory (EnumPtr, sizeof (REGVALUE_ENUMW));
  700. EnumPtr->KeyHandle = hKey;
  701. return EnumNextRegValue95W (EnumPtr);
  702. }
  703. /*++
  704. Routine Description:
  705. EnumNextRegValue95A and EnumNextRegValue95W continue the enumeration started
  706. by EnumFirstRegValue95A/W. The enumeration structure is updated to
  707. reflect the next value name in the subkey being enumerated.
  708. Arguments:
  709. EnumPtr - Specifies the registry subkey and enumeration position.
  710. Receives the updated state of enumeration. The structure
  711. can be accessed directly.
  712. Return Value:
  713. TRUE if successful, or FALSE if an error or if no more values are available.
  714. Call GetLastError for the failure code.
  715. --*/
  716. BOOL
  717. EnumNextRegValue95A (
  718. IN OUT PREGVALUE_ENUMA EnumPtr
  719. )
  720. {
  721. LONG rc;
  722. DWORD ValueNameSize;
  723. ValueNameSize = MAX_REGISTRY_VALUE_NAMEA;
  724. rc = Win95RegEnumValueA (
  725. EnumPtr->KeyHandle,
  726. EnumPtr->Index,
  727. EnumPtr->ValueName,
  728. &ValueNameSize,
  729. NULL,
  730. &EnumPtr->Type,
  731. NULL,
  732. &EnumPtr->DataSize
  733. );
  734. if (rc == ERROR_NO_MORE_ITEMS) {
  735. SetLastError (ERROR_SUCCESS);
  736. return FALSE;
  737. } else if (rc != ERROR_SUCCESS) {
  738. SetLastError (rc);
  739. return FALSE;
  740. }
  741. EnumPtr->Index += 1;
  742. return TRUE;
  743. }
  744. BOOL
  745. EnumNextRegValue95W (
  746. IN OUT PREGVALUE_ENUMW EnumPtr
  747. )
  748. {
  749. LONG rc;
  750. DWORD ValueNameSize;
  751. ValueNameSize = MAX_REGISTRY_VALUE_NAMEW;
  752. rc = Win95RegEnumValueW (
  753. EnumPtr->KeyHandle,
  754. EnumPtr->Index,
  755. EnumPtr->ValueName,
  756. &ValueNameSize,
  757. NULL,
  758. &EnumPtr->Type,
  759. NULL,
  760. &EnumPtr->DataSize
  761. );
  762. if (rc == ERROR_NO_MORE_ITEMS) {
  763. SetLastError (ERROR_SUCCESS);
  764. return FALSE;
  765. } else if (rc != ERROR_SUCCESS) {
  766. SetLastError (rc);
  767. return FALSE;
  768. }
  769. EnumPtr->Index += 1;
  770. return TRUE;
  771. }
  772. PVOID
  773. pMemAllocWrapper95 (
  774. IN DWORD Size
  775. )
  776. /*++
  777. Routine Description:
  778. pMemAllocWrapper95 implements a default allocation routine. The APIs
  779. that have a "2" at the end allow the caller to supply an alternative
  780. allocator or deallocator. The routines without the "2" use this
  781. default allocator.
  782. Arguments:
  783. Size - Specifies the amount of memory (in bytes) to allocate
  784. Return Value:
  785. A pointer to a block of memory that can hold Size bytes, or NULL
  786. if allocation fails.
  787. --*/
  788. {
  789. return MemAlloc (g_hHeap, 0, Size);
  790. }
  791. VOID
  792. pMemFreeWrapper95 (
  793. IN PVOID Mem
  794. )
  795. /*++
  796. Routine Description:
  797. pMemFreeWrapper95 implements a default deallocation routine.
  798. See pMemAllocWrapper95 above.
  799. Arguments:
  800. Mem - Specifies the block of memory to free, and was allocated by the
  801. pMemAllocWrapper95 function.
  802. Return Value:
  803. none
  804. --*/
  805. {
  806. MemFree (g_hHeap, 0, Mem);
  807. }
  808. /*++
  809. Routine Description:
  810. GetRegValueDataEx95A and GetRegValueDataEx95W query a registry value and
  811. return the data as a pointer. They use the specified Alloc and Free
  812. routines to allocate and free the memory as needed.
  813. A GetRegValueData macro is defined, and it uses the default allocators,
  814. simplifying the function parameters and allowing the caller to free
  815. the return value via MemFree.
  816. Arguments:
  817. hKey - Specifies the registry key that holds the specified value.
  818. Value - Specifies the value name to query.
  819. Alloc - Specifies the allocation routine, called to allocate a block of
  820. memory for the return data.
  821. Free - Specifies the deallocation routine, called if an error is encountered
  822. during processing.
  823. Return Value:
  824. A pointer to the data retrieved, or NULL if the value does not exist or an
  825. error occurred. Call GetLastError to obtian the failure code.
  826. --*/
  827. PBYTE
  828. GetRegValueDataEx95A (
  829. IN HKEY hKey,
  830. IN PCSTR Value,
  831. IN ALLOCATOR Alloc,
  832. IN DEALLOCATOR Free
  833. )
  834. {
  835. LONG rc;
  836. DWORD BufSize;
  837. PBYTE DataBuf;
  838. rc = Win95RegQueryValueExA (hKey, Value, NULL, NULL, NULL, &BufSize);
  839. if (rc != ERROR_SUCCESS) {
  840. SetLastError (rc);
  841. return NULL;
  842. }
  843. DataBuf = (PBYTE) Alloc (BufSize + sizeof (CHAR));
  844. rc = Win95RegQueryValueExA (hKey, Value, NULL, NULL, DataBuf, &BufSize);
  845. if (rc == ERROR_SUCCESS) {
  846. *((PSTR) DataBuf + BufSize) = 0;
  847. return DataBuf;
  848. }
  849. Free (DataBuf);
  850. SetLastError (rc);
  851. return NULL;
  852. }
  853. PBYTE
  854. GetRegValueDataEx95W (
  855. IN HKEY hKey,
  856. IN PCWSTR Value,
  857. IN ALLOCATOR Alloc,
  858. IN DEALLOCATOR Free
  859. )
  860. {
  861. LONG rc;
  862. DWORD BufSize;
  863. PBYTE DataBuf;
  864. rc = Win95RegQueryValueExW (hKey, Value, NULL, NULL, NULL, &BufSize);
  865. if (rc != ERROR_SUCCESS) {
  866. SetLastError (rc);
  867. return NULL;
  868. }
  869. DataBuf = (PBYTE) Alloc (BufSize + sizeof(WCHAR));
  870. rc = Win95RegQueryValueExW (hKey, Value, NULL, NULL, DataBuf, &BufSize);
  871. if (rc == ERROR_SUCCESS) {
  872. *((PWSTR) (DataBuf + BufSize)) = 0;
  873. return DataBuf;
  874. }
  875. Free (DataBuf);
  876. SetLastError (rc);
  877. return NULL;
  878. }
  879. /*++
  880. Routine Description:
  881. GetRegValueDataOfTypeEx95A and GetRegValueDataOfTypeEx95W are extensions of
  882. GetRegValueData. They only return a data pointer when the data stored
  883. in the registry value is the correct type.
  884. Arguments:
  885. hKey - Specifies the registry key to query
  886. Value - Specifies the value name to query
  887. MustBeType - Specifies the type of data (a REG_* constant). If the specified
  888. value has data but is a different type, NULL will be returned.
  889. Alloc - Specifies the allocation routine, called to allocate the return data.
  890. Free - Specifies the deallocation routine, called when an error is encountered.
  891. Return Value:
  892. If successful, returns a pointer to data that matches the specified type.
  893. If the data is a different type, the value name does not exist, or an
  894. error occurs during the query, NULL is returned, and the failure code
  895. can be obtained from GetLastError.
  896. --*/
  897. PBYTE
  898. GetRegValueDataOfTypeEx95A (
  899. IN HKEY hKey,
  900. IN PCSTR Value,
  901. IN DWORD MustBeType,
  902. IN ALLOCATOR Alloc,
  903. IN DEALLOCATOR Free
  904. )
  905. {
  906. LONG rc;
  907. DWORD BufSize;
  908. PBYTE DataBuf;
  909. DWORD Type;
  910. rc = Win95RegQueryValueExA (hKey, Value, NULL, &Type, NULL, &BufSize);
  911. if (rc != ERROR_SUCCESS || Type != MustBeType) {
  912. SetLastError (rc);
  913. return NULL;
  914. }
  915. DataBuf = (PBYTE) Alloc (BufSize + sizeof (CHAR));
  916. rc = Win95RegQueryValueExA (hKey, Value, NULL, NULL, DataBuf, &BufSize);
  917. if (rc == ERROR_SUCCESS) {
  918. *((PSTR) DataBuf + BufSize) = 0;
  919. return DataBuf;
  920. }
  921. Free (DataBuf);
  922. SetLastError (rc);
  923. return NULL;
  924. }
  925. PBYTE
  926. GetRegValueDataOfTypeEx95W (
  927. IN HKEY hKey,
  928. IN PCWSTR Value,
  929. IN DWORD MustBeType,
  930. IN ALLOCATOR Alloc,
  931. IN DEALLOCATOR Free
  932. )
  933. {
  934. LONG rc;
  935. DWORD BufSize;
  936. PBYTE DataBuf;
  937. DWORD Type;
  938. rc = Win95RegQueryValueExW (hKey, Value, NULL, &Type, NULL, &BufSize);
  939. if (rc != ERROR_SUCCESS || Type != MustBeType) {
  940. SetLastError (rc);
  941. return NULL;
  942. }
  943. DataBuf = (PBYTE) Alloc (BufSize + sizeof(WCHAR));
  944. rc = Win95RegQueryValueExW (hKey, Value, NULL, NULL, DataBuf, &BufSize);
  945. if (rc == ERROR_SUCCESS) {
  946. *((PWSTR) (DataBuf + BufSize)) = 0;
  947. return DataBuf;
  948. }
  949. Free (DataBuf);
  950. SetLastError (rc);
  951. return NULL;
  952. }
  953. /*++
  954. Routine Description:
  955. GetRegKeyDataEx95A and GetRegKeyDataEx95W return default data associated
  956. with a registry key. They open the specified subkey, query the value,
  957. close the subkey and return the data.
  958. Arguments:
  959. Parent - Specifies the key that contains SubKey.
  960. SubKey - Specifies the name of the subkey to obtain the default value for.
  961. Alloc - Specifies the allocation routine, called to allocate a block of
  962. memory for the registry data.
  963. Free - Specifies the deallocation routine, called to free the block of
  964. data if an error occurs.
  965. Return Value:
  966. A pointer to the block of data obtained from the subkey's default value,
  967. or NULL if the subkey does not exist or an error was encountered. Call
  968. GetLastError for a failure code.
  969. --*/
  970. PBYTE
  971. GetRegKeyDataEx95A (
  972. IN HKEY Parent,
  973. IN PCSTR SubKey,
  974. IN ALLOCATOR Alloc,
  975. IN DEALLOCATOR Free
  976. )
  977. {
  978. HKEY SubKeyHandle;
  979. PBYTE Data;
  980. SubKeyHandle = OpenRegKey95A (Parent, SubKey);
  981. if (!SubKeyHandle) {
  982. return NULL;
  983. }
  984. Data = GetRegValueDataEx95A (SubKeyHandle, "", Alloc, Free);
  985. CloseRegKey95 (SubKeyHandle);
  986. return Data;
  987. }
  988. PBYTE
  989. GetRegKeyDataEx95W (
  990. IN HKEY Parent,
  991. IN PCWSTR SubKey,
  992. IN ALLOCATOR Alloc,
  993. IN DEALLOCATOR Free
  994. )
  995. {
  996. HKEY SubKeyHandle;
  997. PBYTE Data;
  998. SubKeyHandle = OpenRegKey95W (Parent, SubKey);
  999. if (!SubKeyHandle) {
  1000. return NULL;
  1001. }
  1002. Data = GetRegValueDataEx95W (SubKeyHandle, L"", Alloc, Free);
  1003. CloseRegKey95 (SubKeyHandle);
  1004. return Data;
  1005. }
  1006. /*++
  1007. Routine Description:
  1008. GetRegDataEx95A and GetRegDataEx95W open a registry key, query a value,
  1009. close the registry key and return the value.
  1010. Arguments:
  1011. KeyString - Specifies the registry key to open
  1012. ValueName - Specifies the value to query
  1013. Alloc - Specifies the allocation routine, used to allocate a block of
  1014. memory to hold the value data
  1015. Free - Specifies the deallocation routine, used to free the block of
  1016. memory when an error is encountered.
  1017. Return Value:
  1018. A pointer to the registry data retrieved, or NULL if the key or value
  1019. does not exist, or if an error occurs. Call GetLastError for a failure code.
  1020. --*/
  1021. PBYTE
  1022. GetRegDataEx95A (
  1023. IN PCSTR KeyString,
  1024. IN PCSTR ValueName,
  1025. IN ALLOCATOR Alloc,
  1026. IN DEALLOCATOR Free
  1027. )
  1028. {
  1029. HKEY Key;
  1030. PBYTE Data;
  1031. Key = OpenRegKeyStr95A (KeyString);
  1032. if (!Key) {
  1033. return NULL;
  1034. }
  1035. Data = GetRegValueDataEx95A (Key, ValueName, Alloc, Free);
  1036. CloseRegKey95 (Key);
  1037. return Data;
  1038. }
  1039. PBYTE
  1040. GetRegDataEx95W (
  1041. IN PCWSTR KeyString,
  1042. IN PCWSTR ValueName,
  1043. IN ALLOCATOR Alloc,
  1044. IN DEALLOCATOR Free
  1045. )
  1046. {
  1047. HKEY Key;
  1048. PBYTE Data;
  1049. Key = OpenRegKeyStr95W (KeyString);
  1050. if (!Key) {
  1051. return NULL;
  1052. }
  1053. Data = GetRegValueDataEx95W (Key, ValueName, Alloc, Free);
  1054. CloseRegKey95 (Key);
  1055. return Data;
  1056. }
  1057. /*++
  1058. Routine Description:
  1059. OpenRegKey95A and OpenRegKey95W open a subkey.
  1060. Arguments:
  1061. ParentKey - Specifies a handle to the parent registry key to contain
  1062. the subkey.
  1063. KeyToOpen - Specifies the name of the subkey to open.
  1064. Return Value:
  1065. The handle to an open registry key upon success, or NULL if an
  1066. error occurred. Call GetLastError for a failure code.
  1067. --*/
  1068. HKEY
  1069. RealOpenRegKey95A (
  1070. IN HKEY ParentKey,
  1071. IN PCSTR KeyToOpen OPTIONAL
  1072. DEBUG_TRACKING_PARAMS
  1073. )
  1074. {
  1075. HKEY SubKey;
  1076. LONG rc;
  1077. rc = OurRegOpenKeyEx95A (
  1078. ParentKey,
  1079. KeyToOpen,
  1080. 0,
  1081. KEY_ALL_ACCESS,
  1082. &SubKey
  1083. DEBUG_TRACKING_ARGS
  1084. );
  1085. if (rc != ERROR_SUCCESS) {
  1086. SetLastError (rc);
  1087. return NULL;
  1088. }
  1089. return SubKey;
  1090. }
  1091. HKEY
  1092. RealOpenRegKey95W (
  1093. IN HKEY ParentKey,
  1094. IN PCWSTR KeyToOpen
  1095. DEBUG_TRACKING_PARAMS
  1096. )
  1097. {
  1098. LONG rc;
  1099. HKEY SubKey;
  1100. rc = OurRegOpenKeyEx95W (
  1101. ParentKey,
  1102. KeyToOpen,
  1103. 0,
  1104. KEY_ALL_ACCESS,
  1105. &SubKey
  1106. DEBUG_TRACKING_ARGS
  1107. );
  1108. if (rc != ERROR_SUCCESS) {
  1109. SetLastError (rc);
  1110. return NULL;
  1111. }
  1112. return SubKey;
  1113. }
  1114. LONG
  1115. RealCloseRegKey95 (
  1116. IN HKEY Key
  1117. )
  1118. /*++
  1119. Routine Description:
  1120. RealCloseRegKey95 closes the reg handle supplied, unless the handle is
  1121. a pre-defined Win32 handle. The CloseRegKey95 macro resolves directly
  1122. to this function in the free build, and to OurCloseRegKey95 in the
  1123. checked build.
  1124. Arguments:
  1125. Key - Specifies the reg handle to close
  1126. Return Value:
  1127. A standard Win32 error code indicating outcome.
  1128. --*/
  1129. {
  1130. if (GetOffsetOfRootKey (Key)) {
  1131. return ERROR_SUCCESS;
  1132. }
  1133. return Win95RegCloseKey (Key);
  1134. }