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.

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