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.

1197 lines
24 KiB

  1. /*++
  2. Copyright (c) 1997-2001 Microsoft Corporation
  3. Module Name:
  4. regenum.c
  5. Abstract:
  6. Implements utilties to enumerate the registry.
  7. Author:
  8. Jim Schmidt (jimschm) 20-Mar-1997
  9. Revisions:
  10. <alias> <date> <comment>
  11. --*/
  12. #include "pch.h"
  13. #include "regp.h"
  14. #define DBG_REG "Reg"
  15. //
  16. // Private prototypes
  17. //
  18. BOOL
  19. pPopRegKeyInfoA (
  20. IN PREGTREE_ENUMA EnumPtr
  21. );
  22. BOOL
  23. pPopRegKeyInfoW (
  24. IN PREGTREE_ENUMW EnumPtr
  25. );
  26. /*++
  27. Routine Description:
  28. EnumFirstRegKeyA and EnumFirstRegKeyW begin an enumeration of registry
  29. subkeys. They initialize the registy enumeration structure and
  30. call the registry APIs to enumerate subkeys of the specified key handle.
  31. Arguments:
  32. EnumPtr - Receives the updated state of enumeration. The structure
  33. can be accessed directly.
  34. Key - Specifies the handle of the registry key to enumerate.
  35. Return Value:
  36. TRUE if successful, or FALSE if an error or if no more subkeys are available.
  37. Call GetLastError for the failure code.
  38. --*/
  39. BOOL
  40. EnumFirstRegKeyA (
  41. OUT PREGKEY_ENUMA EnumPtr,
  42. IN HKEY hKey
  43. )
  44. {
  45. ZeroMemory (EnumPtr, sizeof (REGKEY_ENUMA));
  46. EnumPtr->KeyHandle = hKey;
  47. return EnumNextRegKeyA (EnumPtr);
  48. }
  49. BOOL
  50. EnumFirstRegKeyW (
  51. OUT PREGKEY_ENUMW EnumPtr,
  52. IN HKEY hKey
  53. )
  54. {
  55. ZeroMemory (EnumPtr, sizeof (REGKEY_ENUMW));
  56. EnumPtr->KeyHandle = hKey;
  57. return EnumNextRegKeyW (EnumPtr);
  58. }
  59. /*++
  60. Routine Description:
  61. EnumFirstRegKeyStrA and EnumFirstRegKeyStrW start an enumeration of
  62. subkeys within the given key. In these functions, the key is specified
  63. via a string instead of an HKEY value.
  64. Arguments:
  65. EnumPtr - Receives the updated state of enumeration. The structure
  66. can be accessed directly.
  67. RegKey - Specifies the full path of the registry key to enumerate.
  68. Return Value:
  69. TRUE if successful, or FALSE if an error or if no more subkeys are available.
  70. Call GetLastError for the failure code.
  71. --*/
  72. BOOL
  73. RealEnumFirstRegKeyStrA (
  74. OUT PREGKEY_ENUMA EnumPtr,
  75. IN PCSTR RegKey
  76. DEBUG_TRACKING_PARAMS
  77. )
  78. {
  79. HKEY Key;
  80. BOOL b;
  81. Key = RealOpenRegKeyStrA (RegKey /* , */ DEBUG_TRACKING_ARGS);
  82. if (!Key) {
  83. return FALSE;
  84. }
  85. b = EnumFirstRegKeyA (EnumPtr, Key);
  86. if (!b) {
  87. CloseRegKey (Key);
  88. } else {
  89. EnumPtr->OpenedByEnum = TRUE;
  90. }
  91. return b;
  92. }
  93. BOOL
  94. RealEnumFirstRegKeyStrW (
  95. IN PREGKEY_ENUMW EnumPtr,
  96. IN PCWSTR RegKey
  97. DEBUG_TRACKING_PARAMS
  98. )
  99. {
  100. HKEY Key;
  101. BOOL b;
  102. Key = RealOpenRegKeyStrW (RegKey /* , */ DEBUG_TRACKING_ARGS);
  103. if (!Key) {
  104. return FALSE;
  105. }
  106. b = EnumFirstRegKeyW (EnumPtr, Key);
  107. if (!b) {
  108. CloseRegKey (Key);
  109. } else {
  110. EnumPtr->OpenedByEnum = TRUE;
  111. }
  112. return b;
  113. }
  114. /*++
  115. Routine Description:
  116. AbortRegKeyEnumA and AbortRegKeyEnumW release all resources associated
  117. with a registry subkey enumeration. Call this function to stop the
  118. enumeration before it completes by itself.
  119. Arguments:
  120. EnumPtr - Specifies the enumeration to stop. Receives the updated
  121. state of enumeration.
  122. Return Value:
  123. none
  124. --*/
  125. VOID
  126. AbortRegKeyEnumA (
  127. IN OUT PREGKEY_ENUMA EnumPtr
  128. )
  129. {
  130. if (EnumPtr->OpenedByEnum && EnumPtr->KeyHandle) {
  131. CloseRegKey (EnumPtr->KeyHandle);
  132. EnumPtr->KeyHandle = NULL;
  133. }
  134. }
  135. VOID
  136. AbortRegKeyEnumW (
  137. IN OUT PREGKEY_ENUMW EnumPtr
  138. )
  139. {
  140. if (EnumPtr->OpenedByEnum && EnumPtr->KeyHandle) {
  141. CloseRegKey (EnumPtr->KeyHandle);
  142. EnumPtr->KeyHandle = NULL;
  143. }
  144. }
  145. /*++
  146. Routine Description:
  147. EnumNextRegKeyA and EnumNextRegKeyW continue an enumeration started by
  148. one of the subkey enumeration routines above. If all items have been
  149. enumerated, this function cleans up all resources and returns FALSE.
  150. Arguments:
  151. EnumPtr - Specifies the enumeration to continue. Receives the updated
  152. state of enumeration. The structure can be accessed directly.
  153. Return Value:
  154. TRUE if successful, or FALSE if an error or if no more subkeys are available.
  155. Call GetLastError for the failure code.
  156. --*/
  157. BOOL
  158. EnumNextRegKeyA (
  159. IN OUT PREGKEY_ENUMA EnumPtr
  160. )
  161. {
  162. LONG rc;
  163. rc = RegEnumKeyA (
  164. EnumPtr->KeyHandle,
  165. EnumPtr->Index,
  166. EnumPtr->SubKeyName,
  167. MAX_REGISTRY_KEYA
  168. );
  169. if (rc != ERROR_SUCCESS) {
  170. if (EnumPtr->OpenedByEnum) {
  171. CloseRegKey (EnumPtr->KeyHandle);
  172. EnumPtr->KeyHandle = NULL;
  173. }
  174. if (rc == ERROR_NO_MORE_ITEMS) {
  175. SetLastError (ERROR_SUCCESS);
  176. } else {
  177. SetLastError (rc);
  178. }
  179. return FALSE;
  180. }
  181. EnumPtr->Index += 1;
  182. return TRUE;
  183. }
  184. BOOL
  185. EnumNextRegKeyW (
  186. IN OUT PREGKEY_ENUMW EnumPtr
  187. )
  188. {
  189. LONG rc;
  190. rc = RegEnumKeyW (
  191. EnumPtr->KeyHandle,
  192. EnumPtr->Index,
  193. EnumPtr->SubKeyName,
  194. MAX_REGISTRY_KEYW
  195. );
  196. if (rc != ERROR_SUCCESS) {
  197. if (EnumPtr->OpenedByEnum) {
  198. CloseRegKey (EnumPtr->KeyHandle);
  199. EnumPtr->KeyHandle = NULL;
  200. }
  201. if (rc == ERROR_NO_MORE_ITEMS) {
  202. SetLastError (ERROR_SUCCESS);
  203. } else {
  204. SetLastError (rc);
  205. }
  206. return FALSE;
  207. }
  208. EnumPtr->Index += 1;
  209. return TRUE;
  210. }
  211. BOOL
  212. pPushRegKeyInfoA (
  213. IN PREGTREE_ENUMA EnumPtr,
  214. IN PCSTR KeyName
  215. )
  216. {
  217. PREGKEYINFOA RetVal;
  218. PSTR p;
  219. RetVal = (PREGKEYINFOA) PoolMemGetAlignedMemory (
  220. EnumPtr->EnumPool,
  221. sizeof (REGKEYINFOA)
  222. );
  223. if (!RetVal) {
  224. return FALSE;
  225. }
  226. //
  227. // Initialize struct to zero
  228. //
  229. ZeroMemory (RetVal, sizeof (REGKEYINFOA));
  230. //
  231. // Link parent and child pointers
  232. //
  233. RetVal->Parent = EnumPtr->CurrentKey;
  234. if (EnumPtr->CurrentKey) {
  235. EnumPtr->CurrentKey->Child = RetVal;
  236. }
  237. EnumPtr->CurrentKey = RetVal;
  238. //
  239. // Prepare full key path by appending the key name to the existing
  240. // base
  241. //
  242. RetVal->BaseKeyBytes = EnumPtr->FullKeyNameBytes;
  243. p = (PSTR) ((PBYTE) EnumPtr->FullKeyName + RetVal->BaseKeyBytes);
  244. if (EnumPtr->FullKeyNameBytes) {
  245. StringCopyA (p, "\\");
  246. EnumPtr->FullKeyNameBytes += ByteCountA (p);
  247. p = _mbsinc (p);
  248. }
  249. _mbssafecpy (p, KeyName, MAX_REGISTRY_KEYA - EnumPtr->FullKeyNameBytes);
  250. EnumPtr->FullKeyNameBytes += ByteCountA (KeyName);
  251. //
  252. // Save the key name independent of the full registry path.
  253. // Also open the key.
  254. //
  255. _mbssafecpy (RetVal->KeyName, KeyName, MAX_REGISTRY_KEYA);
  256. RetVal->KeyHandle = OpenRegKeyStrA (EnumPtr->FullKeyName);
  257. if (!RetVal->KeyHandle) {
  258. pPopRegKeyInfoA (EnumPtr);
  259. return FALSE;
  260. }
  261. return TRUE;
  262. }
  263. BOOL
  264. pPushRegKeyInfoW (
  265. IN PREGTREE_ENUMW EnumPtr,
  266. IN PCWSTR KeyName
  267. )
  268. {
  269. PREGKEYINFOW RetVal;
  270. PWSTR p;
  271. RetVal = (PREGKEYINFOW) PoolMemGetAlignedMemory (
  272. EnumPtr->EnumPool,
  273. sizeof (REGKEYINFOW)
  274. );
  275. if (!RetVal) {
  276. return FALSE;
  277. }
  278. //
  279. // Initialize struct to zero
  280. //
  281. ZeroMemory (RetVal, sizeof (REGKEYINFOW));
  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 = (PWSTR) ((PBYTE) EnumPtr->FullKeyName + RetVal->BaseKeyBytes);
  296. if (EnumPtr->FullKeyNameBytes) {
  297. StringCopyW (p, L"\\");
  298. EnumPtr->FullKeyNameBytes += ByteCountW (p);
  299. p++;
  300. }
  301. _wcssafecpy (p, KeyName, MAX_REGISTRY_KEYW - (EnumPtr->FullKeyNameBytes / sizeof (WCHAR)));
  302. EnumPtr->FullKeyNameBytes += ByteCountW (KeyName);
  303. //
  304. // Save the key name independent of the full registry path.
  305. // Also open the key.
  306. //
  307. _wcssafecpy (RetVal->KeyName, KeyName, MAX_REGISTRY_KEYW);
  308. RetVal->KeyHandle = OpenRegKeyStrW (EnumPtr->FullKeyName);
  309. if (!RetVal->KeyHandle) {
  310. pPopRegKeyInfoW (EnumPtr);
  311. return FALSE;
  312. }
  313. return TRUE;
  314. }
  315. BOOL
  316. pPopRegKeyInfoA (
  317. IN PREGTREE_ENUMA EnumPtr
  318. )
  319. {
  320. PREGKEYINFOA FreeMe;
  321. PSTR p;
  322. FreeMe = EnumPtr->CurrentKey;
  323. //
  324. // Skip if nothing was ever pushed
  325. //
  326. if (!FreeMe) {
  327. return FALSE;
  328. }
  329. //
  330. // Trim the full key string
  331. //
  332. EnumPtr->CurrentKey = FreeMe->Parent;
  333. EnumPtr->FullKeyNameBytes = FreeMe->BaseKeyBytes;
  334. p = (PSTR) ((PBYTE) EnumPtr->FullKeyName + FreeMe->BaseKeyBytes);
  335. *p = 0;
  336. //
  337. // Adjust the linkage
  338. //
  339. if (EnumPtr->CurrentKey) {
  340. EnumPtr->CurrentKey->Child = NULL;
  341. }
  342. //
  343. // Clean up resources
  344. //
  345. if (FreeMe->KeyHandle) {
  346. CloseRegKey (FreeMe->KeyHandle);
  347. }
  348. AbortRegKeyEnumA (&FreeMe->KeyEnum);
  349. PoolMemReleaseMemory (EnumPtr->EnumPool, (PVOID) FreeMe);
  350. //
  351. // Return FALSE if last item was poped
  352. //
  353. return EnumPtr->CurrentKey != NULL;
  354. }
  355. BOOL
  356. pPopRegKeyInfoW (
  357. IN PREGTREE_ENUMW EnumPtr
  358. )
  359. {
  360. PREGKEYINFOW FreeMe;
  361. PWSTR p;
  362. FreeMe = EnumPtr->CurrentKey;
  363. //
  364. // Skip if nothing was ever pushed
  365. //
  366. if (!FreeMe) {
  367. return FALSE;
  368. }
  369. //
  370. // Trim the full key string
  371. //
  372. EnumPtr->CurrentKey = FreeMe->Parent;
  373. EnumPtr->FullKeyNameBytes = FreeMe->BaseKeyBytes;
  374. p = (PWSTR) ((PBYTE) EnumPtr->FullKeyName + FreeMe->BaseKeyBytes);
  375. *p = 0;
  376. //
  377. // Adjust the linkage
  378. //
  379. if (EnumPtr->CurrentKey) {
  380. EnumPtr->CurrentKey->Child = NULL;
  381. }
  382. //
  383. // Clean up resources
  384. //
  385. if (FreeMe->KeyHandle) {
  386. CloseRegKey (FreeMe->KeyHandle);
  387. }
  388. AbortRegKeyEnumW (&FreeMe->KeyEnum);
  389. PoolMemReleaseMemory (EnumPtr->EnumPool, (PVOID) FreeMe);
  390. //
  391. // Return FALSE if last item was poped
  392. //
  393. return EnumPtr->CurrentKey != NULL;
  394. }
  395. BOOL
  396. RealEnumFirstRegKeyInTreeA (
  397. OUT PREGTREE_ENUMA EnumPtr,
  398. IN PCSTR BaseKeyStr
  399. )
  400. {
  401. ZeroMemory (EnumPtr, sizeof (REGTREE_ENUMA));
  402. //
  403. // Allocate pool for enum structs
  404. //
  405. EnumPtr->EnumPool = PoolMemInitNamedPool ("RegKeyInTreeA");
  406. if (!EnumPtr->EnumPool) {
  407. return FALSE;
  408. }
  409. PoolMemSetMinimumGrowthSize (EnumPtr->EnumPool, 32768);
  410. PoolMemDisableTracking (EnumPtr->EnumPool);
  411. //
  412. // Push base key on the enum stack
  413. //
  414. if (!pPushRegKeyInfoA (EnumPtr, BaseKeyStr)) {
  415. DEBUGMSG ((DBG_REG, "EnumFirstRegKeyInTreeA failed to push base key"));
  416. AbortRegKeyTreeEnumA (EnumPtr);
  417. return FALSE;
  418. }
  419. EnumPtr->EnumBaseBytes = ByteCountA (BaseKeyStr);
  420. //
  421. // Set state so EnumNextRegKeyInTree knows what to do
  422. //
  423. EnumPtr->State = ENUMERATE_SUBKEY_BEGIN;
  424. return TRUE;
  425. }
  426. BOOL
  427. RealEnumFirstRegKeyInTreeW (
  428. OUT PREGTREE_ENUMW EnumPtr,
  429. IN PCWSTR BaseKeyStr
  430. )
  431. {
  432. ZeroMemory (EnumPtr, sizeof (REGTREE_ENUMW));
  433. //
  434. // Allocate pool for enum structs
  435. //
  436. EnumPtr->EnumPool = PoolMemInitNamedPool ("RegKeyInTreeW");
  437. if (!EnumPtr->EnumPool) {
  438. return FALSE;
  439. }
  440. PoolMemSetMinimumGrowthSize (EnumPtr->EnumPool, 32768);
  441. PoolMemDisableTracking (EnumPtr->EnumPool);
  442. //
  443. // Push base key on the enum stack
  444. //
  445. if (!pPushRegKeyInfoW (EnumPtr, BaseKeyStr)) {
  446. DEBUGMSG ((DBG_REG, "EnumFirstRegKeyInTreeW failed to push base key"));
  447. AbortRegKeyTreeEnumW (EnumPtr);
  448. return FALSE;
  449. }
  450. EnumPtr->EnumBaseBytes = ByteCountW (BaseKeyStr);
  451. //
  452. // Set state so EnumNextRegKeyInTree knows what to do
  453. //
  454. EnumPtr->State = ENUMERATE_SUBKEY_BEGIN;
  455. return TRUE;
  456. }
  457. BOOL
  458. RealEnumNextRegKeyInTreeA (
  459. IN OUT PREGTREE_ENUMA EnumPtr
  460. )
  461. {
  462. if (EnumPtr->State == NO_MORE_ITEMS) {
  463. return FALSE;
  464. }
  465. for (;;) {
  466. switch (EnumPtr->State) {
  467. case ENUMERATE_SUBKEY_BEGIN:
  468. //
  469. // Start enumeration
  470. //
  471. if (EnumFirstRegKeyA (
  472. &EnumPtr->CurrentKey->KeyEnum,
  473. EnumPtr->CurrentKey->KeyHandle
  474. )) {
  475. EnumPtr->State = ENUMERATE_SUBKEY_RETURN;
  476. } else {
  477. EnumPtr->State = ENUMERATE_SUBKEY_DONE;
  478. }
  479. break;
  480. case ENUMERATE_SUBKEY_NEXT:
  481. //
  482. // Continue enumerations
  483. //
  484. if (EnumNextRegKeyA (&EnumPtr->CurrentKey->KeyEnum)) {
  485. EnumPtr->State = ENUMERATE_SUBKEY_RETURN;
  486. } else {
  487. EnumPtr->State = ENUMERATE_SUBKEY_DONE;
  488. }
  489. break;
  490. case ENUMERATE_SUBKEY_DONE:
  491. //
  492. // Enumeration of this key is done; pop and continue.
  493. //
  494. if (!pPopRegKeyInfoA (EnumPtr)) {
  495. EnumPtr->State = NO_MORE_ITEMS;
  496. AbortRegKeyTreeEnumA (EnumPtr);
  497. } else {
  498. EnumPtr->State = ENUMERATE_SUBKEY_NEXT;
  499. }
  500. break;
  501. case ENUMERATE_SUBKEY_RETURN:
  502. //
  503. // Return enumerated item to caller
  504. //
  505. if (!pPushRegKeyInfoA (EnumPtr, EnumPtr->CurrentKey->KeyEnum.SubKeyName)) {
  506. DEBUGMSGA ((
  507. DBG_REG,
  508. "RealEnumNextRegKeyInTreeA failed to push sub key %s",
  509. EnumPtr->CurrentKey->KeyEnum.SubKeyName
  510. ));
  511. EnumPtr->State = ENUMERATE_SUBKEY_NEXT;
  512. break;
  513. }
  514. if (!EnumPtr->FirstEnumerated) {
  515. EnumPtr->FirstEnumerated = TRUE;
  516. EnumPtr->EnumBaseBytes += sizeof (CHAR);
  517. }
  518. EnumPtr->State = ENUMERATE_SUBKEY_BEGIN;
  519. return TRUE;
  520. default:
  521. MYASSERT (EnumPtr->State == NO_MORE_ITEMS);
  522. return FALSE;
  523. }
  524. }
  525. }
  526. BOOL
  527. RealEnumNextRegKeyInTreeW (
  528. IN OUT PREGTREE_ENUMW EnumPtr
  529. )
  530. {
  531. if (EnumPtr->State == NO_MORE_ITEMS) {
  532. return FALSE;
  533. }
  534. for (;;) {
  535. switch (EnumPtr->State) {
  536. case ENUMERATE_SUBKEY_BEGIN:
  537. //
  538. // Start enumeration
  539. //
  540. if (EnumFirstRegKeyW (
  541. &EnumPtr->CurrentKey->KeyEnum,
  542. EnumPtr->CurrentKey->KeyHandle
  543. )) {
  544. EnumPtr->State = ENUMERATE_SUBKEY_RETURN;
  545. } else {
  546. EnumPtr->State = ENUMERATE_SUBKEY_DONE;
  547. }
  548. break;
  549. case ENUMERATE_SUBKEY_NEXT:
  550. //
  551. // Continue enumerations
  552. //
  553. if (EnumNextRegKeyW (&EnumPtr->CurrentKey->KeyEnum)) {
  554. EnumPtr->State = ENUMERATE_SUBKEY_RETURN;
  555. } else {
  556. EnumPtr->State = ENUMERATE_SUBKEY_DONE;
  557. }
  558. break;
  559. case ENUMERATE_SUBKEY_DONE:
  560. //
  561. // Enumeration of this key is done; pop and continue.
  562. //
  563. if (!pPopRegKeyInfoW (EnumPtr)) {
  564. EnumPtr->State = NO_MORE_ITEMS;
  565. AbortRegKeyTreeEnumW (EnumPtr);
  566. } else {
  567. EnumPtr->State = ENUMERATE_SUBKEY_NEXT;
  568. }
  569. break;
  570. case ENUMERATE_SUBKEY_RETURN:
  571. //
  572. // Return enumerated item to caller
  573. //
  574. if (!pPushRegKeyInfoW (EnumPtr, EnumPtr->CurrentKey->KeyEnum.SubKeyName)) {
  575. DEBUGMSGW ((
  576. DBG_REG,
  577. "RealEnumNextRegKeyInTreeW failed to push sub key %s",
  578. EnumPtr->CurrentKey->KeyEnum.SubKeyName
  579. ));
  580. EnumPtr->State = ENUMERATE_SUBKEY_NEXT;
  581. break;
  582. }
  583. if (!EnumPtr->FirstEnumerated) {
  584. EnumPtr->FirstEnumerated = TRUE;
  585. EnumPtr->EnumBaseBytes += sizeof (WCHAR);
  586. }
  587. EnumPtr->State = ENUMERATE_SUBKEY_BEGIN;
  588. return TRUE;
  589. default:
  590. MYASSERT (EnumPtr->State == NO_MORE_ITEMS);
  591. return FALSE;
  592. }
  593. }
  594. }
  595. VOID
  596. AbortRegKeyTreeEnumA (
  597. IN OUT PREGTREE_ENUMA EnumPtr
  598. )
  599. {
  600. //
  601. // Free all resources
  602. //
  603. while (pPopRegKeyInfoA (EnumPtr)) {
  604. }
  605. PoolMemDestroyPool (EnumPtr->EnumPool);
  606. }
  607. VOID
  608. AbortRegKeyTreeEnumW (
  609. IN OUT PREGTREE_ENUMW EnumPtr
  610. )
  611. {
  612. //
  613. // Free all resources
  614. //
  615. while (pPopRegKeyInfoW (EnumPtr)) {
  616. }
  617. PoolMemDestroyPool (EnumPtr->EnumPool);
  618. }
  619. /*++
  620. Routine Description:
  621. EnumFirstRegValueA and EnumerateFirstRegvalueW enumerate the first registry
  622. value name in the specified subkey.
  623. Arguments:
  624. EnumPtr - Receives the updated state of enumeration. The structure
  625. can be accessed directly.
  626. hKey - Specifies handle of registry subkey to enumerate.
  627. Return Value:
  628. TRUE if successful, or FALSE if an error or if no more values are available.
  629. Call GetLastError for the failure code.
  630. --*/
  631. BOOL
  632. EnumFirstRegValueA (
  633. IN PREGVALUE_ENUMA EnumPtr,
  634. IN HKEY hKey
  635. )
  636. {
  637. ZeroMemory (EnumPtr, sizeof (REGVALUE_ENUMA));
  638. EnumPtr->KeyHandle = hKey;
  639. return EnumNextRegValueA (EnumPtr);
  640. }
  641. BOOL
  642. EnumFirstRegValueW (
  643. IN PREGVALUE_ENUMW EnumPtr,
  644. IN HKEY hKey
  645. )
  646. {
  647. ZeroMemory (EnumPtr, sizeof (REGVALUE_ENUMW));
  648. EnumPtr->KeyHandle = hKey;
  649. return EnumNextRegValueW (EnumPtr);
  650. }
  651. /*++
  652. Routine Description:
  653. EnumNextRegValueA and EnumNextRegValueW continue the enumeration started
  654. by EnumFirstRegValueA/W. The enumeration structure is updated to
  655. reflect the next value name in the subkey being enumerated.
  656. Arguments:
  657. EnumPtr - Specifies the registry subkey and enumeration position.
  658. Receives the updated state of enumeration. The structure
  659. can be accessed directly.
  660. Return Value:
  661. TRUE if successful, or FALSE if an error or if no more values are available.
  662. Call GetLastError for the failure code.
  663. --*/
  664. BOOL
  665. EnumNextRegValueA (
  666. IN OUT PREGVALUE_ENUMA EnumPtr
  667. )
  668. {
  669. LONG rc;
  670. DWORD ValueNameSize;
  671. ValueNameSize = MAX_REGISTRY_VALUE_NAMEA;
  672. rc = RegEnumValueA (
  673. EnumPtr->KeyHandle,
  674. EnumPtr->Index,
  675. EnumPtr->ValueName,
  676. &ValueNameSize,
  677. NULL,
  678. &EnumPtr->Type,
  679. NULL,
  680. &EnumPtr->DataSize
  681. );
  682. if (rc == ERROR_NO_MORE_ITEMS) {
  683. SetLastError (ERROR_SUCCESS);
  684. return FALSE;
  685. } else if (rc != ERROR_SUCCESS) {
  686. SetLastError (rc);
  687. return FALSE;
  688. }
  689. EnumPtr->Index += 1;
  690. return TRUE;
  691. }
  692. BOOL
  693. EnumNextRegValueW (
  694. IN OUT PREGVALUE_ENUMW EnumPtr
  695. )
  696. {
  697. LONG rc;
  698. DWORD ValueNameSize;
  699. ValueNameSize = MAX_REGISTRY_VALUE_NAMEW;
  700. rc = RegEnumValueW (
  701. EnumPtr->KeyHandle,
  702. EnumPtr->Index,
  703. EnumPtr->ValueName,
  704. &ValueNameSize,
  705. NULL,
  706. &EnumPtr->Type,
  707. NULL,
  708. &EnumPtr->DataSize
  709. );
  710. if (rc == ERROR_NO_MORE_ITEMS) {
  711. SetLastError (ERROR_SUCCESS);
  712. return FALSE;
  713. } else if (rc != ERROR_SUCCESS) {
  714. SetLastError (rc);
  715. return FALSE;
  716. }
  717. EnumPtr->Index += 1;
  718. return TRUE;
  719. }
  720. /*++
  721. Routine Description:
  722. DecodeRegistryString turns an encoded string back into a key, value name
  723. and tree flag.
  724. The caller must pass in buffers at least as big as MAX_REGISTRY_KEY and
  725. MAX_REGISTRY_VALUE_NAME.
  726. Arguments:
  727. RegString - Specifies the encoded registry string that contains a key name,
  728. and an optional value name or tree flag.
  729. KeyBuf - Receives the key name
  730. ValueBuf - Receives the value name
  731. TreeFlag - Receives the tree flag, TRUE if the encoded string indicates a
  732. registry key tree, FALSE otherwise.
  733. Return Value:
  734. TRUE if the encoded string contained a value, FALSE if it contained just a
  735. key or key tree.
  736. --*/
  737. BOOL
  738. DecodeRegistryStringA (
  739. IN PCSTR RegString,
  740. OUT PSTR KeyBuf, OPTIONAL
  741. OUT PSTR ValueBuf, OPTIONAL
  742. OUT PBOOL TreeFlag OPTIONAL
  743. )
  744. {
  745. CHAR TempKeyBuf[MAX_REGISTRY_KEY];
  746. PSTR End;
  747. CHAR TempValueNameBuf[MAX_REGISTRY_VALUE_NAME];
  748. BOOL TempTreeFlag = FALSE;
  749. MBCHAR ch;
  750. PSTR p;
  751. BOOL b = FALSE;
  752. //
  753. // Walk through encoded string, pulling out key name
  754. //
  755. TempKeyBuf[0] = 0;
  756. TempValueNameBuf[0] = 0;
  757. End = TempKeyBuf + ARRAYSIZE(TempKeyBuf) - 2;
  758. p = TempKeyBuf;
  759. while (*RegString && *RegString != '*' && *RegString != '[') {
  760. ch = GetNextRuleCharA (&RegString, NULL);
  761. *((PWORD) p) = (WORD)ch;
  762. p = _mbsinc (p);
  763. if (p >= End) {
  764. RegString = GetEndOfStringA (RegString);
  765. break;
  766. }
  767. }
  768. *p = 0;
  769. p = (PSTR) SkipSpaceRA (TempKeyBuf, p);
  770. *(_mbsinc (p)) = 0;
  771. if (*RegString == '*' && _mbsnextc (p) == '\\') {
  772. //
  773. // If a tree, stop here
  774. //
  775. TempTreeFlag = TRUE;
  776. *p = 0;
  777. } else if (*RegString == '[') {
  778. //
  779. // If a value name, parse it
  780. //
  781. RegString++;
  782. End = TempValueNameBuf + ARRAYSIZE(TempValueNameBuf) - 2;
  783. p = TempValueNameBuf;
  784. while (*RegString && *RegString != ']') {
  785. ch = GetNextRuleCharA (&RegString, NULL);
  786. *((PWORD) p) = (WORD)ch;
  787. p = _mbsinc (p);
  788. if (p >= End) {
  789. RegString = GetEndOfStringA (RegString);
  790. break;
  791. }
  792. }
  793. *p = 0;
  794. p = (PSTR) SkipSpaceRA (TempValueNameBuf, p);
  795. if (p) // Guard against empty or all-whitespace value name.
  796. *(p + 1) = 0;
  797. RemoveWackAtEndA (TempKeyBuf);
  798. b = TRUE;
  799. }
  800. if (KeyBuf) {
  801. StringCopyA (KeyBuf, TempKeyBuf);
  802. }
  803. if (ValueBuf) {
  804. StringCopyA (ValueBuf, TempValueNameBuf);
  805. }
  806. if (TreeFlag) {
  807. *TreeFlag = TempTreeFlag;
  808. }
  809. return b;
  810. }
  811. BOOL
  812. DecodeRegistryStringW (
  813. IN PCWSTR RegString,
  814. OUT PWSTR KeyBuf, OPTIONAL
  815. OUT PWSTR ValueBuf, OPTIONAL
  816. OUT PBOOL TreeFlag OPTIONAL
  817. )
  818. {
  819. WCHAR TempKeyBuf[MAX_REGISTRY_KEY];
  820. PWSTR End;
  821. WCHAR TempValueNameBuf[MAX_REGISTRY_VALUE_NAME];
  822. BOOL TempTreeFlag = FALSE;
  823. WCHAR ch;
  824. PWSTR p;
  825. BOOL b = FALSE;
  826. //
  827. // Walk through encoded string, pulling out key name
  828. //
  829. TempKeyBuf[0] = 0;
  830. TempValueNameBuf[0] = 0;
  831. End = TempKeyBuf + ARRAYSIZE(TempKeyBuf) - 2;
  832. p = TempKeyBuf;
  833. while (*RegString && *RegString != L'*' && *RegString != L'[') {
  834. ch = GetNextRuleCharW (&RegString, NULL);
  835. *((PWORD) p) = ch;
  836. p++;
  837. if (p >= End) {
  838. RegString = GetEndOfStringW (RegString);
  839. break;
  840. }
  841. }
  842. *p = 0;
  843. p = (PWSTR) SkipSpaceRW (TempKeyBuf, p);
  844. if (!p) {
  845. return FALSE;
  846. }
  847. *(p + 1) = 0;
  848. if (*RegString == L'*' && *p == L'\\') {
  849. //
  850. // If a tree, stop here
  851. //
  852. TempTreeFlag = TRUE;
  853. *p = 0;
  854. } else if (*RegString == L'[') {
  855. //
  856. // If a value name, parse it
  857. //
  858. RegString++;
  859. End = TempValueNameBuf + ARRAYSIZE(TempValueNameBuf) - 2;
  860. p = TempValueNameBuf;
  861. while (*RegString && *RegString != L']') {
  862. ch = GetNextRuleCharW (&RegString, NULL);
  863. *((PWORD) p) = ch;
  864. p++;
  865. if (p >= End) {
  866. RegString = GetEndOfStringW (RegString);
  867. break;
  868. }
  869. }
  870. *p = 0;
  871. p = (PWSTR) SkipSpaceRW (TempValueNameBuf, p);
  872. if (p) { // Guard against empty or all-whitespace value name.
  873. *(p + 1) = 0;
  874. }
  875. RemoveWackAtEndW (TempKeyBuf);
  876. b = TRUE;
  877. }
  878. if (KeyBuf) {
  879. StringCopyW (KeyBuf, TempKeyBuf);
  880. }
  881. if (ValueBuf) {
  882. StringCopyW (ValueBuf, TempValueNameBuf);
  883. }
  884. if (TreeFlag) {
  885. *TreeFlag = TempTreeFlag;
  886. }
  887. return b;
  888. }