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.

645 lines
16 KiB

  1. //
  2. // REGKYLST.C
  3. //
  4. // Copyright (C) Microsoft Corporation, 1995
  5. //
  6. // Declares the predefined key structures and manages dynamic HKEY structures.
  7. //
  8. #include "pch.h"
  9. #include <limits.h>
  10. // We would rather just have one definition a
  11. #ifdef WANT_DYNKEY_SUPPORT
  12. #define INITED_PREDEFINED_KEY(index, flags) \
  13. { \
  14. KEY_SIGNATURE, \
  15. KEYF_PREDEFINED | KEYF_INVALID | (flags), \
  16. 0, \
  17. NULL, \
  18. REG_NULL, \
  19. REG_NULL, \
  20. 0, \
  21. 0, \
  22. (index), \
  23. NULL, \
  24. NULL, \
  25. (UINT) -1, \
  26. REG_NULL, \
  27. NULL \
  28. }
  29. #else
  30. #define INITED_PREDEFINED_KEY(index, flags) \
  31. { \
  32. KEY_SIGNATURE, \
  33. KEYF_PREDEFINED | KEYF_INVALID | (flags), \
  34. 0, \
  35. NULL, \
  36. REG_NULL, \
  37. REG_NULL, \
  38. 0, \
  39. 0, \
  40. (index), \
  41. NULL, \
  42. NULL, \
  43. (UINT) -1, \
  44. REG_NULL \
  45. }
  46. #endif
  47. KEY g_RgLocalMachineKey =
  48. INITED_PREDEFINED_KEY(INDEX_LOCAL_MACHINE, KEYF_HIVESALLOWED);
  49. KEY g_RgUsersKey = INITED_PREDEFINED_KEY(INDEX_USERS, KEYF_HIVESALLOWED);
  50. #ifdef WANT_DYNKEY_SUPPORT
  51. KEY g_RgDynDataKey = INITED_PREDEFINED_KEY(INDEX_DYN_DATA, 0);
  52. #endif
  53. HKEY g_RgPredefinedKeys[] = {
  54. NULL, // HKEY_CLASSES_ROOT
  55. NULL, // HKEY_CURRENT_USER
  56. &g_RgLocalMachineKey, // HKEY_LOCAL_MACHINE
  57. &g_RgUsersKey, // HKEY_USERS
  58. NULL, // HKEY_PERFORMANCE_DATA
  59. NULL, // HKEY_CURRENT_CONFIG
  60. #ifdef WANT_DYNKEY_SUPPORT
  61. &g_RgDynDataKey, // HKEY_DYN_DATA
  62. #endif
  63. };
  64. #define NUMBER_PREDEF_KEYS (sizeof(g_RgPredefinedKeys) / sizeof(HKEY))
  65. #ifdef WANT_STATIC_KEYS
  66. #define NUMBER_STATIC_KEYS 32
  67. HKEY g_RgStaticKeyArray = NULL;
  68. #endif
  69. // List of all dynamically allocated keys.
  70. HKEY g_RgDynamicKeyList = NULL;
  71. const char g_RgClassesRootSubKey[] = "SOFTWARE\\CLASSES";
  72. const char g_RgCurrentUserSubKey[] = ".DEFAULT";
  73. #ifdef WANT_STATIC_KEYS
  74. //
  75. // RgAllocKeyHandleStructures
  76. //
  77. BOOL
  78. INTERNAL
  79. RgAllocKeyHandleStructures(
  80. VOID
  81. )
  82. {
  83. UINT Index;
  84. HKEY hKey;
  85. ASSERT(IsNullPtr(g_RgStaticKeyArray));
  86. ASSERT(IsNullPtr(g_RgDynamicKeyList));
  87. //
  88. // Allocate and initialize the static key table.
  89. //
  90. g_RgStaticKeyArray = RgSmAllocMemory(NUMBER_STATIC_KEYS * sizeof(KEY));
  91. if (IsNullPtr(g_RgStaticKeyArray))
  92. return FALSE;
  93. for (Index = NUMBER_STATIC_KEYS, hKey = g_RgStaticKeyArray; Index > 0;
  94. Index--, hKey++) {
  95. hKey-> Signature = KEY_SIGNATURE;
  96. hKey-> Flags = KEYF_STATIC | KEYF_INVALID;
  97. hKey-> ReferenceCount = 0;
  98. }
  99. return TRUE;
  100. }
  101. #endif
  102. #ifdef WANT_FULL_MEMORY_CLEANUP
  103. //
  104. // RgFreeKeyHandleStructures
  105. //
  106. // Releases resources allocated by RgAllocKeyHandleStructures.
  107. //
  108. VOID
  109. INTERNAL
  110. RgFreeKeyHandleStructures(
  111. VOID
  112. )
  113. {
  114. HKEY hTempKey;
  115. HKEY hKey;
  116. //
  117. // Delete all of the dynamically allocated keys.
  118. //
  119. hKey = g_RgDynamicKeyList;
  120. if (!IsNullPtr(hKey)) {
  121. do {
  122. hTempKey = hKey;
  123. hKey = hKey-> lpNext;
  124. #ifdef WANT_DYNKEY_SUPPORT
  125. if (!IsNullPtr(hTempKey-> pProvider))
  126. RgSmFreeMemory(hTempKey-> pProvider);
  127. #endif
  128. RgSmFreeMemory(hTempKey);
  129. } while (hKey != g_RgDynamicKeyList);
  130. }
  131. g_RgDynamicKeyList = NULL;
  132. #ifdef WANT_STATIC_KEYS
  133. //
  134. // Delete the static key table.
  135. //
  136. if (!IsNullPtr(g_RgStaticKeyArray)) {
  137. RgSmFreeMemory(g_RgStaticKeyArray);
  138. g_RgStaticKeyArray = NULL;
  139. }
  140. #endif
  141. }
  142. #endif
  143. //
  144. // RgCreateKeyHandle
  145. //
  146. // Allocates one KEY structure, initializes some of its members, and links it
  147. // to the list of open key handles.
  148. //
  149. HKEY
  150. INTERNAL
  151. RgCreateKeyHandle(
  152. VOID
  153. )
  154. {
  155. #ifdef WANT_STATIC_KEYS
  156. UINT Index;
  157. #endif
  158. HKEY hKey;
  159. #ifdef WANT_STATIC_KEYS
  160. //
  161. // Check if any keys are available in the static pool.
  162. //
  163. if (!IsNullPtr(g_RgStaticKeyArray)) {
  164. for (Index = NUMBER_STATIC_KEYS, hKey = g_RgStaticKeyArray; Index > 0;
  165. Index--, hKey++) {
  166. if (hKey-> Flags & KEYF_INVALID) {
  167. ASSERT(hKey-> ReferenceCount == 0);
  168. hKey-> Flags &= ~(KEYF_INVALID | KEYF_DELETED |
  169. KEYF_ENUMKEYCACHED);
  170. return hKey;
  171. }
  172. }
  173. }
  174. #endif
  175. //
  176. // Must allocate a dynamic key. Initialize it and add it to our list.
  177. //
  178. hKey = (HKEY) RgSmAllocMemory(sizeof(KEY));
  179. if (!IsNullPtr(hKey)) {
  180. hKey-> Signature = KEY_SIGNATURE;
  181. hKey-> Flags = 0;
  182. hKey-> ReferenceCount = 0;
  183. #ifdef WANT_DYNKEY_SUPPORT
  184. hKey-> pProvider = NULL;
  185. #endif
  186. if (IsNullPtr(g_RgDynamicKeyList)) {
  187. hKey-> lpPrev = hKey;
  188. hKey-> lpNext = hKey;
  189. }
  190. else if (hKey != g_RgDynamicKeyList) {
  191. hKey-> lpNext = g_RgDynamicKeyList;
  192. hKey-> lpPrev = g_RgDynamicKeyList-> lpPrev;
  193. hKey-> lpPrev-> lpNext = hKey;
  194. g_RgDynamicKeyList-> lpPrev = hKey;
  195. }
  196. g_RgDynamicKeyList = hKey;
  197. }
  198. return hKey;
  199. }
  200. //
  201. // RgDeleteKeyHandle
  202. //
  203. // Decrements the reference count on the given key handle. If the count
  204. // reaches zero and the key was dynamically allocated, then the key is unlinked
  205. // from the key list and the key is freed.
  206. //
  207. VOID
  208. INTERNAL
  209. RgDestroyKeyHandle(
  210. HKEY hKey
  211. )
  212. {
  213. ASSERT(!IsNullPtr(hKey));
  214. // Don't allow the reference count to underflow for predefined keys or
  215. // keys marked "never delete".
  216. if (hKey-> ReferenceCount > 0)
  217. hKey-> ReferenceCount--;
  218. if (hKey-> ReferenceCount == 0) {
  219. if (!(hKey-> Flags & (KEYF_PREDEFINED | KEYF_NEVERDELETE))) {
  220. #ifdef WANT_STATIC_KEYS
  221. if (hKey-> Flags & KEYF_STATIC) {
  222. hKey-> Flags |= KEYF_INVALID;
  223. return;
  224. }
  225. #endif
  226. if (hKey == hKey-> lpNext)
  227. g_RgDynamicKeyList = NULL;
  228. else {
  229. hKey-> lpPrev-> lpNext = hKey-> lpNext;
  230. hKey-> lpNext-> lpPrev = hKey-> lpPrev;
  231. if (hKey == g_RgDynamicKeyList)
  232. g_RgDynamicKeyList = hKey-> lpNext;
  233. }
  234. #ifdef WANT_DYNKEY_SUPPORT
  235. if (!IsNullPtr(hKey-> pProvider))
  236. RgSmFreeMemory(hKey-> pProvider);
  237. #endif
  238. hKey-> Signature = 0;
  239. RgSmFreeMemory(hKey);
  240. }
  241. }
  242. }
  243. //
  244. // RgValidateAndConvertKeyHandle
  245. //
  246. // Verifies the the given key handle is valid. If the handle is one of the
  247. // special predefined constants, then it is converted to the handle of the
  248. // real KEY structure.
  249. //
  250. int
  251. INTERNAL
  252. RgValidateAndConvertKeyHandle(
  253. LPHKEY lphKey
  254. )
  255. {
  256. HKEY hKey;
  257. UINT Index;
  258. HKEY hRootKey;
  259. LPCSTR lpSubKey;
  260. hKey = *lphKey;
  261. //
  262. // Check if this is one of the predefined key handles.
  263. //
  264. if ((DWORD) HKEY_CLASSES_ROOT <= (DWORD) hKey &&
  265. (DWORD) hKey < (DWORD) HKEY_CLASSES_ROOT + NUMBER_PREDEF_KEYS) {
  266. Index = (UINT) ((DWORD) hKey - (DWORD) HKEY_CLASSES_ROOT);
  267. hKey = g_RgPredefinedKeys[Index];
  268. // If the predefined handle is not valid, we'll try to (re)open it for
  269. // use. This isn't pretty, but in the typical case, this code path is
  270. // only executed once per handle.
  271. if (IsNullPtr(hKey) || (hKey-> Flags & KEYF_DELETED)) {
  272. if (Index == INDEX_CLASSES_ROOT) {
  273. hRootKey = &g_RgLocalMachineKey;
  274. lpSubKey = g_RgClassesRootSubKey;
  275. }
  276. else if (Index == INDEX_CURRENT_USER) {
  277. hRootKey = &g_RgUsersKey;
  278. lpSubKey = g_RgCurrentUserSubKey;
  279. }
  280. else if (Index == INDEX_USERS) {
  281. goto ReturnKeyAndSuccess;
  282. }
  283. else
  284. return ERROR_BADKEY;
  285. // Extremely rare case: somebody has deleted one of the predefined
  286. // key paths. We'll clear the predefined bit on this key and throw
  287. // it away.
  288. if (!IsNullPtr(hKey)) {
  289. g_RgPredefinedKeys[Index] = NULL;
  290. hKey-> Flags &= ~KEYF_PREDEFINED;
  291. RgDestroyKeyHandle(hKey);
  292. }
  293. // If the base root key for this predefined key is valid, attempt
  294. // to open the key. Mark the key as predefined so that bad apps
  295. // can't close a key more times then it has opened it.
  296. if (!(hRootKey-> Flags & KEYF_INVALID) && RgLookupKey(hRootKey,
  297. lpSubKey, &hKey, LK_CREATE) == ERROR_SUCCESS) {
  298. g_RgPredefinedKeys[Index] = hKey;
  299. hKey-> Flags |= KEYF_PREDEFINED;
  300. hKey-> PredefinedKeyIndex = (BYTE) Index;
  301. goto ReturnKeyAndSuccess;
  302. }
  303. return ERROR_BADKEY;
  304. }
  305. ReturnKeyAndSuccess:
  306. *lphKey = hKey;
  307. return (hKey-> Flags & KEYF_INVALID) ? ERROR_BADKEY : ERROR_SUCCESS;
  308. }
  309. else {
  310. if (IsBadHugeReadPtr(hKey, sizeof(KEY)) || hKey-> Signature !=
  311. KEY_SIGNATURE || (hKey-> Flags & KEYF_INVALID))
  312. return ERROR_BADKEY;
  313. return (hKey-> Flags & KEYF_DELETED) ? ERROR_KEY_DELETED :
  314. ERROR_SUCCESS;
  315. }
  316. }
  317. //
  318. // RgIncrementKeyReferenceCount
  319. //
  320. // Safely increments the reference count of the specified KEY. If the count
  321. // overflows, then the key is marked as "never delete" since the usage count
  322. // is now unknown.
  323. //
  324. VOID
  325. INTERNAL
  326. RgIncrementKeyReferenceCount(
  327. HKEY hKey
  328. )
  329. {
  330. if (hKey-> ReferenceCount != UINT_MAX)
  331. hKey-> ReferenceCount++;
  332. else {
  333. if (!(hKey-> Flags & KEYF_NEVERDELETE)) {
  334. TRACE(("RgIncrementKeyReferenceCount: handle %lx has overflowed\n",
  335. hKey));
  336. }
  337. hKey-> Flags |= KEYF_NEVERDELETE;
  338. }
  339. }
  340. //
  341. // RgFindOpenKeyHandle
  342. //
  343. // Searches the list of currently opened keys for a key that refers to the same
  344. // FILE_INFO structure and keynode offset. If found, the HKEY is returned, or
  345. // if not, NULL.
  346. //
  347. HKEY
  348. INTERNAL
  349. RgFindOpenKeyHandle(
  350. LPFILE_INFO lpFileInfo,
  351. DWORD KeynodeIndex
  352. )
  353. {
  354. UINT Index;
  355. LPHKEY lphKey;
  356. HKEY hKey;
  357. ASSERT(!IsNullKeynodeIndex(KeynodeIndex));
  358. //
  359. // Check if this is one of the predefined key handles.
  360. //
  361. for (Index = NUMBER_PREDEF_KEYS, lphKey = g_RgPredefinedKeys; Index > 0;
  362. Index--, lphKey++) {
  363. hKey = *lphKey;
  364. if (!IsNullPtr(hKey) && hKey-> lpFileInfo == lpFileInfo && hKey->
  365. KeynodeIndex == KeynodeIndex && !(hKey-> Flags & (KEYF_DELETED |
  366. KEYF_INVALID)))
  367. return hKey;
  368. }
  369. #ifdef WANT_STATIC_KEYS
  370. //
  371. // Check if this is one of the static key handles.
  372. //
  373. if (!IsNullPtr(g_RgStaticKeyArray)) {
  374. for (Index = NUMBER_STATIC_KEYS, hKey = g_RgStaticKeyArray; Index > 0;
  375. Index--, hKey++) {
  376. if (hKey-> lpFileInfo == lpFileInfo && hKey-> KeynodeIndex ==
  377. KeynodeIndex && !(hKey-> Flags & (KEYF_DELETED | KEYF_INVALID)))
  378. return hKey;
  379. }
  380. }
  381. #endif
  382. //
  383. // Check if this is one of the dynamic key handles.
  384. //
  385. if (!IsNullPtr((hKey = g_RgDynamicKeyList))) {
  386. do {
  387. if (hKey-> KeynodeIndex == KeynodeIndex && hKey-> lpFileInfo ==
  388. lpFileInfo && !(hKey-> Flags & KEYF_DELETED))
  389. return hKey;
  390. hKey = hKey-> lpNext;
  391. } while (hKey != g_RgDynamicKeyList);
  392. }
  393. return NULL;
  394. }
  395. //
  396. // RgInvalidateKeyHandles
  397. //
  398. // Generic routine to invalidate key handles based on a set of criteria.
  399. // If any key handle meets any of the given criteria, then it's marked invalid.
  400. //
  401. VOID
  402. INTERNAL
  403. RgInvalidateKeyHandles(
  404. LPFILE_INFO lpFileInfo,
  405. UINT PredefinedKeyIndex
  406. )
  407. {
  408. UINT Index;
  409. LPHKEY lphKey;
  410. HKEY hKey;
  411. //
  412. // Invalidate predefined key handles.
  413. //
  414. for (Index = NUMBER_PREDEF_KEYS, lphKey = g_RgPredefinedKeys; Index > 0;
  415. Index--, lphKey++) {
  416. hKey = *lphKey;
  417. if (!IsNullPtr(hKey)) {
  418. if (hKey-> lpFileInfo == lpFileInfo || hKey-> PredefinedKeyIndex ==
  419. (BYTE) PredefinedKeyIndex)
  420. hKey-> Flags |= (KEYF_DELETED | KEYF_INVALID);
  421. }
  422. }
  423. #ifdef WANT_STATIC_KEYS
  424. //
  425. // Invalidate static key handles.
  426. //
  427. if (!IsNullPtr(g_RgStaticKeyArray)) {
  428. for (Index = NUMBER_STATIC_KEYS, hKey = g_RgStaticKeyArray; Index > 0;
  429. Index--, hKey++) {
  430. if (hKey-> lpFileInfo == lpFileInfo || hKey-> PredefinedKeyIndex ==
  431. PredefinedKeyIndex)
  432. hKey-> Flags |= (KEYF_DELETED | KEYF_INVALID);
  433. }
  434. }
  435. #endif
  436. //
  437. // Invalidate dynamic key handles.
  438. //
  439. if (!IsNullPtr((hKey = g_RgDynamicKeyList))) {
  440. do {
  441. if (hKey-> lpFileInfo == lpFileInfo || hKey-> PredefinedKeyIndex ==
  442. (BYTE) PredefinedKeyIndex)
  443. hKey-> Flags |= (KEYF_DELETED | KEYF_INVALID);
  444. hKey = hKey-> lpNext;
  445. } while (hKey != g_RgDynamicKeyList);
  446. }
  447. }
  448. #ifdef VXD
  449. #pragma VxD_RARE_CODE_SEG
  450. #endif
  451. //
  452. // VMMRegMapPredefKeyToKey
  453. //
  454. LONG
  455. REGAPI
  456. VMMRegMapPredefKeyToKey(
  457. HKEY hTargetKey,
  458. HKEY hPredefKey
  459. )
  460. {
  461. int ErrorCode;
  462. UINT PredefinedKeyIndex;
  463. HKEY hOldKey;
  464. if (!RgLockRegistry())
  465. return ERROR_LOCK_FAILED;
  466. if ((ErrorCode = RgValidateAndConvertKeyHandle(&hTargetKey)) ==
  467. ERROR_SUCCESS) {
  468. if ((hPredefKey == HKEY_CURRENT_USER && hTargetKey->
  469. PredefinedKeyIndex == INDEX_USERS) || (hPredefKey ==
  470. HKEY_CURRENT_CONFIG && hTargetKey-> PredefinedKeyIndex ==
  471. INDEX_LOCAL_MACHINE)) {
  472. PredefinedKeyIndex = (UINT) ((DWORD) hPredefKey - (DWORD)
  473. HKEY_CLASSES_ROOT);
  474. hOldKey = g_RgPredefinedKeys[PredefinedKeyIndex];
  475. if (!IsNullPtr(hOldKey)) {
  476. // Invalidate open handles based off the existing predefined
  477. // key handle. Win95 behavior.
  478. RgInvalidateKeyHandles((LPFILE_INFO) -1L, (BYTE)
  479. PredefinedKeyIndex);
  480. hOldKey-> Flags &= ~KEYF_PREDEFINED;
  481. RgDestroyKeyHandle(hOldKey);
  482. }
  483. hTargetKey-> Flags |= KEYF_PREDEFINED;
  484. RgIncrementKeyReferenceCount(hTargetKey);
  485. g_RgPredefinedKeys[PredefinedKeyIndex] = hTargetKey;
  486. }
  487. else {
  488. DEBUG_OUT(("VMMRegMapPredefKeyToKey: invalid hTargetKey\n"));
  489. ErrorCode = ERROR_BADKEY;
  490. }
  491. }
  492. RgUnlockRegistry();
  493. return ErrorCode;
  494. }