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.

415 lines
12 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. regclass.h
  5. Abstract:
  6. This file contains declarations needed for manipulating
  7. the portion of the registry that contains class registrations
  8. Author:
  9. Adam Edwards (adamed) 14-Nov-1997
  10. Notes:
  11. --*/
  12. #if defined( LOCAL )
  13. //
  14. // Declarations
  15. //
  16. #define LENGTH( str ) ( sizeof( str ) - sizeof( UNICODE_NULL ))
  17. #define INIT_SPECIALKEY(x) {LENGTH(x), LENGTH(x), x}
  18. #define REG_CLASSES_FIRST_DISTINCT_ICH 10
  19. #define REG_CHAR_SIZE sizeof(WCHAR)
  20. #define REG_USER_HIVE_NAME L"\\Registry\\User"
  21. #define REG_USER_HIVE_NAMELEN LENGTH(REG_USER_HIVE_NAME)
  22. #define REG_USER_HIVE_NAMECCH (REG_USER_HIVE_NAMELEN / REG_CHAR_SIZE)
  23. #define REG_USER_HIVE_CLASSES_SUFFIX L"_Classes"
  24. #define REG_USER_HIVE_CLASSES_SUFFIXLEN LENGTH(REG_USER_HIVE_CLASSES_SUFFIX)
  25. #define REG_USER_HIVE_CLASSES_SUFFIXCCH (REG_USER_HIVE_CLASSES_SUFFIXLEN / REG_CHAR_SIZE)
  26. #define REG_MACHINE_CLASSES_HIVE_NAME L"\\Registry\\Machine\\Software\\Classes"
  27. #define REG_MACHINE_CLASSES_HIVE_NAMELEN LENGTH(REG_MACHINE_CLASSES_HIVE_NAME)
  28. #define REG_MACHINE_CLASSES_HIVE_NAMECCH (REG_MACHINE_CLASSES_HIVE_NAMELEN / REG_CHAR_SIZE)
  29. #define REG_USER_HIVE_LINK_TREE L"\\Software\\Classes"
  30. #define REG_CLASSES_HIVE_MIN_NAMELEN REG_USER_HIVE_CLASSES_SUFFIXLEN + REG_USER_HIVE_NAMELEN
  31. //
  32. // The difference between these two paths
  33. // \Registry\User\<sid>_Classes and
  34. // \Registry\User\<siid>\Software\Classes
  35. //
  36. // plus extra for the translation from machine to user -- take into account the sid
  37. //
  38. #define REG_CLASSES_SUBTREE_PADDING 128
  39. #define REG_MAX_CLASSKEY_LEN 384
  40. #define REG_MAX_CLASSKEY_CCH (REG_MAX_CLASSKEY_LEN / REG_CHAR_SIZE)
  41. #define REG_MAX_KEY_LEN 512
  42. #define REG_MAX_KEY_CCH (REG_MAX_KEY_LEN / REG_CHAR_SIZE)
  43. #define REG_MAX_KEY_PATHLEN 65535
  44. //
  45. // HKCR Handle Tags for Per-user Class Registration.
  46. //
  47. // Subkeys of HKCR up to and including a class registration parent key are tagged
  48. // by setting two free bits in their handle value (the lower two bits of a handle
  49. // are free to be used as tags). This makes it easy to tell if a key is in
  50. // HKCR and needs special treatment. After the class registration part of a path,
  51. // this marker is not needed since such keys do not require special treatment
  52. // for enumeration, opening, and deletion.
  53. //
  54. //
  55. // Note that for the sake of speed we are using 1 bit instead of a specific pattern of
  56. // two bits. Currently, bit 0 is used to mark remote handles. Bit 2 is used in the
  57. // server only to mark restricted keys. Locally, we use it to mark hkcr keys. More
  58. // Here is a list of valid combinations -- unused bits must be 0. Invalid means that
  59. // in the current implementation, you should never see it in that part of the registry.
  60. //
  61. //
  62. // Local Server Client (application sees these)
  63. // 00 (non HKCR, unused) 00 (unrestricted, unused) 00 (non HKCR, local)
  64. // 01 Invalid (HKCR, unused) 01 Invalid (unrestricted, unused) 01 (non HKCR, remote)
  65. // 10 (HKCR, unused) 10 (restricted, unused) 10 (HKCR, local)
  66. // 11 Invalid (HKCR, unused) 11 Invalid (restricted, unused) 11 Invalid (HKCR, remote)
  67. //
  68. //
  69. // Note that we could use either 10 or 11 to mark HKCR handles -- we chose 10 for simplicity's
  70. // sake since it simply involves oring in a bit. This can be changed in the future
  71. // if yet another bit pattern is needed. Otherwise, clients never see 11 -- they only see
  72. // 00, 01, and 10. Note that these bits must be propagated to the local portion. This is done
  73. // simply by leaving the bits as-is, because local doesn't use any of the bits. Note that
  74. // we would be broken if the bits needed to propagate to server for some reason, since it
  75. // is using bit 2 already. We do not allow HKCR as a remote handle, however, so this is
  76. // not a problem.
  77. //
  78. #define REG_CLASS_HANDLE_MASK 0x3
  79. #define REG_CLASS_HANDLE_VALUE 0x2
  80. #define REG_CLASS_IS_SPECIAL_KEY( Handle ) ( (LONG) ( ( (ULONG_PTR) (Handle) ) & REG_CLASS_HANDLE_VALUE ) )
  81. #define REG_CLASS_SET_SPECIAL_KEY( Handle ) ( (HANDLE) ( ( (ULONG_PTR) (Handle) ) | \
  82. REG_CLASS_HANDLE_VALUE ) )
  83. #define REG_CLASS_RESET_SPECIAL_KEY( Handle ) ( (HANDLE) ( ( ( (ULONG_PTR) (Handle) ) & ~REG_CLASS_HANDLE_MASK )))
  84. #if defined(_REGCLASS_MALLOC_INSTRUMENTED_)
  85. extern RTL_CRITICAL_SECTION gRegClassHeapCritSect;
  86. extern DWORD gcbAllocated;
  87. extern DWORD gcAllocs;
  88. extern DWORD gcbMaxAllocated;
  89. extern DWORD gcMaxAllocs;
  90. extern PVOID gpvAllocs;
  91. __inline PVOID RegClassHeapAlloc(SIZE_T cbSize)
  92. {
  93. PVOID pvAllocation;
  94. pvAllocation = RtlAllocateHeap(RtlProcessHeap(), 0, cbSize + sizeof(SIZE_T));
  95. RtlEnterCriticalSection(&gRegClassHeapCritSect);
  96. if (pvAllocation) {
  97. gcbAllocated += cbSize;
  98. gcAllocs ++;
  99. (ULONG_PTR) gpvAllocs ^= (ULONG_PTR) pvAllocation;
  100. if (gcAllocs > gcMaxAllocs) {
  101. gcMaxAllocs = gcAllocs;
  102. }
  103. if (gcbAllocated > gcbMaxAllocated) {
  104. gcbMaxAllocated = gcbAllocated;
  105. }
  106. }
  107. RtlLeaveCriticalSection(&gRegClassHeapCritSect);
  108. *((SIZE_T*) pvAllocation) = cbSize;
  109. ((SIZE_T*) pvAllocation) ++;
  110. return pvAllocation;
  111. }
  112. __inline BOOLEAN RegClassHeapFree(PVOID pvAllocation)
  113. {
  114. BOOLEAN bRetVal;
  115. SIZE_T cbSize;
  116. ((SIZE_T*) pvAllocation) --;
  117. cbSize = *((SIZE_T*) pvAllocation);
  118. bRetVal = RtlFreeHeap(RtlProcessHeap(), 0, pvAllocation);
  119. RtlEnterCriticalSection(&gRegClassHeapCritSect);
  120. gcbAllocated -= cbSize;
  121. gcAllocs --;
  122. (ULONG_PTR) gpvAllocs ^= (ULONG_PTR) pvAllocation;
  123. RtlLeaveCriticalSection(&gRegClassHeapCritSect);
  124. if (!bRetVal) {
  125. DbgBreakPoint();
  126. }
  127. return bRetVal;
  128. }
  129. #else // defined(_REGCLASS_MALLOC_INSTRUMENTED_)
  130. #define RegClassHeapAlloc(x) RtlAllocateHeap(RtlProcessHeap(), 0, x)
  131. #define RegClassHeapFree(x) RtlFreeHeap(RtlProcessHeap(), 0, x)
  132. #endif // defined(_REGCLASS_MALLOC_INSTRUMENTED_)
  133. enum
  134. {
  135. LOCATION_MACHINE = 0x1,
  136. LOCATION_USER = 0x2,
  137. LOCATION_BOTH = 0x3
  138. };
  139. //
  140. // SKeySemantics
  141. //
  142. // This structure is the result of parsing a registry key full path
  143. //
  144. // ATTENTION: This structure, along with the current parsing code, needs to
  145. // be overhauled. Originally, it was designed to do one thing. Now, it
  146. // identifies several parts of keys. The original goal was speed --
  147. // we attempted to touch the least amount of string (memory) possible.
  148. // As more functionality was added to the parser, this became more complex.
  149. // A better solution would pay more attention to a generic, straightforward
  150. // way of parsing the key -- things have become far too convoluted in
  151. // an attempt to be fast.
  152. //
  153. typedef struct _SKeySemantics
  154. {
  155. /* out */ unsigned _fUser : 1; // this key is rooted in the user hive
  156. /* out */ unsigned _fMachine : 1; // this key is rooted in the machine hive
  157. /* out */ unsigned _fCombinedClasses : 1; // this key is rooted in the combined classes hive
  158. /* out */ unsigned _fClassRegistration : 1; // this key is a class registration key
  159. /* out */ unsigned _fClassRegParent : 1; // this key is a special key (parent of a class reg key)
  160. /* out */ unsigned _fAllocedNameBuf : 1; // nonzero if _pFullPath was realloc'd and needs to be freed
  161. /* out */ USHORT _ichKeyStart; // index to start of a class reg after
  162. // \\software\\classes in the returned full path
  163. /* out */ USHORT _cbPrefixLen; // length of prefix
  164. /* out */ USHORT _cbSpecialKey; // length of special key
  165. /* out */ USHORT _cbClassRegKey; // length of class reg key name
  166. /* in, out */ ULONG _cbFullPath; // size of the KEY_NAME_INFORMATION passed in
  167. /* out */ PKEY_NAME_INFORMATION _pFullPath; // address of an OBJECT_NAME_INFORMATION structure
  168. } SKeySemantics;
  169. //
  170. // External Prototypes
  171. //
  172. //
  173. // Opens the HKCR predefined handle with the combined view
  174. //
  175. error_status_t OpenCombinedClassesRoot(
  176. IN REGSAM samDesired,
  177. OUT HANDLE * phKey);
  178. //
  179. // Parses a registry key and returns results
  180. //
  181. NTSTATUS BaseRegGetKeySemantics(
  182. HKEY hkParent,
  183. PUNICODE_STRING pSubKey,
  184. SKeySemantics* pKeySemantics);
  185. //
  186. // Frees resources associated with an SKeySemantics structure
  187. //
  188. void BaseRegReleaseKeySemantics(SKeySemantics* pKeySemantics);
  189. //
  190. // Opens a class key that exists in either
  191. // HKLM or HKCU
  192. //
  193. NTSTATUS BaseRegOpenClassKey(
  194. HKEY hKey,
  195. PUNICODE_STRING lpSubKey,
  196. DWORD dwOptions,
  197. REGSAM samDesired,
  198. PHKEY phkResult);
  199. //
  200. // Opens a class key from a specified set
  201. // of locations
  202. //
  203. NTSTATUS BaseRegOpenClassKeyFromLocation(
  204. SKeySemantics* pKeyInfo,
  205. HKEY hKey,
  206. PUNICODE_STRING lpSubKey,
  207. REGSAM samDesired,
  208. DWORD dwLocation,
  209. HKEY* phkResult);
  210. //
  211. // Returns key objects for the user and machine
  212. // versions of a key
  213. //
  214. NTSTATUS BaseRegGetUserAndMachineClass(
  215. SKeySemantics* pKeySemantics,
  216. HKEY Key,
  217. REGSAM samDesired,
  218. PHKEY phkMachine,
  219. PHKEY phkUser);
  220. //
  221. // Internal Prototypes
  222. //
  223. USHORT BaseRegGetUserPrefixLength(
  224. PUNICODE_STRING pFullPath);
  225. USHORT BaseRegCchSpecialKeyLen(
  226. PUNICODE_STRING pFullPath,
  227. USHORT ichSpecialKeyStart,
  228. SKeySemantics* pKeySemantics);
  229. NTSTATUS BaseRegTranslateToMachineClassKey(
  230. SKeySemantics* pKeyInfo,
  231. PUNICODE_STRING pMachineClassKey,
  232. USHORT* pPrefixLen);
  233. NTSTATUS BaseRegTranslateToUserClassKey(
  234. SKeySemantics* pKeyInfo,
  235. PUNICODE_STRING pUserClassKey,
  236. USHORT* pPrefixLen);
  237. NTSTATUS BaseRegOpenClassKeyRoot(
  238. SKeySemantics* pKeyInfo,
  239. PHKEY phkClassRoot,
  240. PUNICODE_STRING pClassKeyPath,
  241. BOOL fMachine);
  242. NTSTATUS BaseRegMapClassRegistrationKey(
  243. HKEY hKey,
  244. PUNICODE_STRING pSubKey,
  245. SKeySemantics* pKeyInfo,
  246. PUNICODE_STRING pDestSubKey,
  247. BOOL* pfRetryOnAccessDenied,
  248. PHKEY phkDestResult,
  249. PUNICODE_STRING* ppSubKeyResult);
  250. NTSTATUS BaseRegMapClassOnAccessDenied(
  251. SKeySemantics* pKeySemantics,
  252. PHKEY phkDest,
  253. PUNICODE_STRING pDestSubKey,
  254. BOOL* pfRetryOnAccessDenied);
  255. NTSTATUS CreateMultipartUserClassKey(
  256. IN HKEY hKey,
  257. OUT PHKEY phkResult);
  258. NTSTATUS GetFixedKeyInfo(
  259. HKEY hkUser,
  260. HKEY hkMachine,
  261. LPDWORD pdwUserValues,
  262. LPDWORD pdwMachineValues,
  263. LPDWORD pdwUserMaxDataLen,
  264. LPDWORD pdwMachineMaxDataLen,
  265. LPDWORD pdwMaxValueNameLen);
  266. BOOL InitializeClassesNameSpace();
  267. extern BOOL gbCombinedClasses;
  268. //
  269. // Inline functions
  270. //
  271. enum
  272. {
  273. REMOVEPREFIX_DISCARD_INITIAL_PATHSEP = 0,
  274. REMOVEPREFIX_KEEP_INITIAL_PATHSEP = 1
  275. };
  276. __inline void KeySemanticsRemovePrefix(
  277. SKeySemantics* pKeyInfo,
  278. PUNICODE_STRING pDestination,
  279. DWORD dwFlags)
  280. {
  281. BOOL fMoveBack;
  282. fMoveBack = (dwFlags & REMOVEPREFIX_KEEP_INITIAL_PATHSEP) &&
  283. (pKeyInfo->_pFullPath->Name[pKeyInfo->_ichKeyStart]);
  284. pDestination->Buffer = &(pKeyInfo->_pFullPath->Name[pKeyInfo->_ichKeyStart -
  285. (fMoveBack ? 1 : 0)]);
  286. pDestination->Length = (USHORT) pKeyInfo->_pFullPath->NameLength -
  287. ((pKeyInfo->_ichKeyStart - (fMoveBack ? 1 : 0)) * REG_CHAR_SIZE);
  288. }
  289. __inline void KeySemanticsGetSid(
  290. SKeySemantics* pKeyInfo,
  291. PUNICODE_STRING pSidString)
  292. {
  293. pSidString->Buffer = &(pKeyInfo->_pFullPath->Name[REG_USER_HIVE_NAMECCH]);
  294. pSidString->Length = pKeyInfo->_cbPrefixLen -
  295. (REG_USER_HIVE_CLASSES_SUFFIXLEN + REG_USER_HIVE_NAMELEN);
  296. }
  297. __inline void KeySemanticsTruncatePrefixToClassReg(
  298. SKeySemantics* pKeyInfo,
  299. USHORT PrefixLen,
  300. PUNICODE_STRING pDestination)
  301. {
  302. pDestination->Length = PrefixLen + (pKeyInfo->_fClassRegistration ? REG_CHAR_SIZE : 0) +
  303. pKeyInfo->_cbSpecialKey + pKeyInfo->_cbClassRegKey;
  304. }
  305. BOOL
  306. ExtractClassKey(
  307. IN OUT HKEY *phKey,
  308. IN OUT PUNICODE_STRING lpSubKey);
  309. #else // LOCAL
  310. #define REG_CLASS_IS_SPECIAL_KEY( Handle ) 0
  311. #define REG_CLASS_SET_SPECIAL_KEY( Handle ) (Handle)
  312. #define REG_CLASS_RESET_SPECIAL_KEY( Handle ) (Handle)
  313. #endif // LOCAL