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.

239 lines
6.7 KiB

  1. //
  2. // REGEKEY.C
  3. //
  4. // Copyright (C) Microsoft Corporation, 1995
  5. //
  6. // Implementation of RegEnumKey and supporting functions.
  7. //
  8. #include "pch.h"
  9. //
  10. // RgLookupKeyByIndex
  11. //
  12. // lpKeyName, points to a buffer that receives the name of the subkey,
  13. // including the null terminator. May be NULL.
  14. // lpcbKeyName, on entry, specifies the size in characters of the buffer
  15. // pointed to be lpKeyName, and on return, specifies the size of the
  16. // indexed subkey. May not be NULL.
  17. //
  18. int
  19. INTERNAL
  20. RgLookupKeyByIndex(
  21. HKEY hKey,
  22. UINT Index,
  23. LPSTR lpKeyName,
  24. LPDWORD lpcbKeyName,
  25. UINT Flags
  26. )
  27. {
  28. int ErrorCode;
  29. LPFILE_INFO lpFileInfo;
  30. UINT KeysToSkip;
  31. DWORD KeynodeIndex;
  32. DWORD TempOffset;
  33. LPKEYNODE lpKeynode;
  34. LPKEY_RECORD lpKeyRecord;
  35. #ifdef WANT_HIVE_SUPPORT
  36. LPHIVE_INFO lpHiveInfo;
  37. #endif
  38. #ifdef REALMODE
  39. BOOL secondTry;
  40. #endif
  41. lpFileInfo = hKey-> lpFileInfo;
  42. KeysToSkip = Index;
  43. //
  44. // Check if we've cached the keynode index of the last key index
  45. // (confusing?) from a previous call to this function. If so, then we can
  46. // skip ahead a bit and avoid touching a bunch of keynode pages.
  47. //
  48. if ((hKey-> Flags & KEYF_ENUMKEYCACHED) &&
  49. (!(hKey-> Flags & KEYF_ENUMEXTENTCACHED) == !(Flags & LK_BIGKEYEXT)) &&
  50. (Index >= hKey-> LastEnumKeyIndex)) {
  51. KeysToSkip -= hKey-> LastEnumKeyIndex;
  52. KeynodeIndex = hKey-> LastEnumKeyKeynodeIndex;
  53. }
  54. else
  55. KeynodeIndex = hKey-> ChildKeynodeIndex;
  56. //
  57. // Loop over the child keys of this key until we find our index or run out
  58. // of children.
  59. //
  60. while (!IsNullKeynodeIndex(KeynodeIndex)) {
  61. #ifdef REALMODE
  62. secondTry = FALSE;
  63. tryAgain:
  64. #endif // REALMODE
  65. if ((ErrorCode = RgLockInUseKeynode(lpFileInfo, KeynodeIndex,
  66. &lpKeynode)) != ERROR_SUCCESS)
  67. return ErrorCode;
  68. ASSERT(hKey-> KeynodeIndex == lpKeynode-> ParentIndex);
  69. if (!(Flags & LK_BIGKEYEXT) == !(lpKeynode-> Flags & KNF_BIGKEYEXT) &&
  70. KeysToSkip == 0) {
  71. if ((ErrorCode = RgLockKeyRecord(lpFileInfo, lpKeynode-> BlockIndex,
  72. (BYTE) lpKeynode-> KeyRecordIndex, &lpKeyRecord)) ==
  73. ERROR_SUCCESS) {
  74. if (!IsNullPtr(lpKeyName)) {
  75. if (*lpcbKeyName <= lpKeyRecord-> NameLength)
  76. ErrorCode = ERROR_MORE_DATA;
  77. else {
  78. MoveMemory(lpKeyName, lpKeyRecord-> Name, lpKeyRecord->
  79. NameLength);
  80. lpKeyName[lpKeyRecord-> NameLength] = '\0';
  81. }
  82. }
  83. // Does not include terminating null.
  84. *lpcbKeyName = lpKeyRecord-> NameLength;
  85. RgUnlockDatablock(lpFileInfo, lpKeynode-> BlockIndex, FALSE);
  86. }
  87. #ifdef REALMODE
  88. else if (!secondTry)
  89. {
  90. // What happens in real mode, is that we get wedged with the
  91. // Keynode block allocated and locked in the middle of the free
  92. // space, and there is not a free block large enough for the data block.
  93. // We have already free'd up everything that isn't locked.
  94. // So, by unlocking and freeing the Keynode block and then restarting
  95. // the operation, the Keynode block gets allocated at the bottom of the
  96. // heap, leaving room for the data block.
  97. secondTry = TRUE;
  98. RgUnlockKeynode(lpFileInfo, KeynodeIndex, FALSE);
  99. RgEnumFileInfos(RgSweepFileInfo);
  100. RgEnumFileInfos(RgSweepFileInfo);
  101. goto tryAgain;
  102. }
  103. #endif // REALMODE
  104. RgUnlockKeynode(lpFileInfo, KeynodeIndex, FALSE);
  105. // Cache our current position because the caller is likely to turn
  106. // around and ask for the next index.
  107. hKey-> LastEnumKeyIndex = Index;
  108. hKey-> LastEnumKeyKeynodeIndex = KeynodeIndex;
  109. hKey-> Flags |= KEYF_ENUMKEYCACHED;
  110. if (Flags & LK_BIGKEYEXT)
  111. hKey-> Flags |= KEYF_ENUMEXTENTCACHED;
  112. else
  113. hKey-> Flags &= ~KEYF_ENUMEXTENTCACHED;
  114. return ErrorCode;
  115. }
  116. TempOffset = lpKeynode-> NextIndex;
  117. RgUnlockKeynode(lpFileInfo, KeynodeIndex, FALSE);
  118. KeynodeIndex = TempOffset;
  119. if (!(Flags & LK_BIGKEYEXT) == !(lpKeynode-> Flags & KNF_BIGKEYEXT))
  120. {
  121. KeysToSkip--;
  122. }
  123. }
  124. #ifdef WANT_HIVE_SUPPORT
  125. //
  126. // Loop over the hives of this key until we find our index or run out of
  127. // hives.
  128. //
  129. if (hKey-> Flags & KEYF_HIVESALLOWED) {
  130. lpHiveInfo = hKey-> lpFileInfo-> lpHiveInfoList;
  131. while (!IsNullPtr(lpHiveInfo)) {
  132. if (KeysToSkip == 0) {
  133. ErrorCode = ERROR_SUCCESS;
  134. if (!IsNullPtr(lpKeyName)) {
  135. if (*lpcbKeyName <= lpHiveInfo-> NameLength)
  136. ErrorCode = ERROR_MORE_DATA;
  137. else {
  138. MoveMemory(lpKeyName, lpHiveInfo-> Name, lpHiveInfo->
  139. NameLength);
  140. lpKeyName[lpHiveInfo-> NameLength] = '\0';
  141. }
  142. }
  143. // Does not include terminating null.
  144. *lpcbKeyName = lpHiveInfo-> NameLength;
  145. // We don't worry about the enum key cache if we find a
  146. // hit in this code. This is a rare case and already the cache
  147. // that we do have is much better then Win95.
  148. return ErrorCode;
  149. }
  150. lpHiveInfo = lpHiveInfo-> lpNextHiveInfo;
  151. KeysToSkip--;
  152. }
  153. }
  154. #endif
  155. return ERROR_NO_MORE_ITEMS;
  156. }
  157. //
  158. // VMMRegEnumKey
  159. //
  160. // See Win32 documentation for a description of the behavior.
  161. //
  162. LONG
  163. REGAPI
  164. VMMRegEnumKey(
  165. HKEY hKey,
  166. DWORD Index,
  167. LPSTR lpKeyName,
  168. DWORD cbKeyName
  169. )
  170. {
  171. int ErrorCode;
  172. if (IsBadHugeWritePtr(lpKeyName, cbKeyName))
  173. return ERROR_INVALID_PARAMETER;
  174. if (IsEnumIndexTooBig(Index))
  175. return ERROR_NO_MORE_ITEMS;
  176. if (!RgLockRegistry())
  177. return ERROR_LOCK_FAILED;
  178. if ((ErrorCode = RgValidateAndConvertKeyHandle(&hKey)) == ERROR_SUCCESS)
  179. ErrorCode = RgLookupKeyByIndex(hKey, (UINT) Index, lpKeyName,
  180. &cbKeyName, 0);
  181. RgUnlockRegistry();
  182. return ErrorCode;
  183. }