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.

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