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.

372 lines
12 KiB

  1. #include "stdinc.h"
  2. #include "util.h"
  3. #include "fusionhandle.h"
  4. #include "win32oneshot.h"
  5. #include "win32simplelock.h"
  6. #include "lhport.h"
  7. //
  8. // Comparison of unsigned numbers by subtraction does NOT work!
  9. //
  10. #define COMPARE_NUMBER(x, y) \
  11. (((x) < (y)) ? -1 : ((x) > (y)) ? +1 : 0)
  12. class CRegistryTypeInformation
  13. {
  14. public:
  15. DWORD Dword;
  16. PCWSTR String;
  17. PCWSTR PreferredString;
  18. };
  19. class CRegistryRootInformation
  20. {
  21. public:
  22. union
  23. {
  24. HKEY PseudoHandle;
  25. ULONG_PTR PseudoHandleInteger;
  26. };
  27. PCWSTR String;
  28. };
  29. typedef BYTE CRegistryTypeInformationIndex;
  30. typedef BYTE CRegistryRootInformationIndex;
  31. const CRegistryTypeInformation RegistryTypeInformation[] =
  32. {
  33. #define ENTRY(x) { x, L###x },
  34. #define ENTRY2(x,y) { x, L###x, L###x },
  35. ENTRY(REG_NONE)
  36. ENTRY(REG_SZ)
  37. ENTRY(REG_EXPAND_SZ)
  38. ENTRY(REG_BINARY)
  39. ENTRY2(REG_DWORD, REG_DWORD)
  40. ENTRY2(REG_DWORD_LITTLE_ENDIAN, REG_DWORD)
  41. ENTRY(REG_DWORD_BIG_ENDIAN)
  42. ENTRY(REG_LINK)
  43. ENTRY(REG_MULTI_SZ)
  44. ENTRY(REG_RESOURCE_LIST)
  45. ENTRY(REG_FULL_RESOURCE_DESCRIPTOR)
  46. ENTRY(REG_RESOURCE_REQUIREMENTS_LIST)
  47. ENTRY2(REG_QWORD, REG_QWORD)
  48. ENTRY2(REG_QWORD_LITTLE_ENDIAN, REG_QWORD)
  49. #undef ENTRY
  50. #undef ENTRY2
  51. };
  52. const CRegistryRootInformation RegistryRootInformation[] =
  53. {
  54. #define ENTRY(x) { x, L###x },
  55. ENTRY(HKEY_CLASSES_ROOT)
  56. ENTRY(HKEY_CURRENT_USER)
  57. ENTRY(HKEY_LOCAL_MACHINE)
  58. ENTRY(HKEY_USERS)
  59. ENTRY(HKEY_PERFORMANCE_DATA)
  60. ENTRY(HKEY_PERFORMANCE_TEXT)
  61. ENTRY(HKEY_PERFORMANCE_NLSTEXT)
  62. ENTRY(HKEY_CURRENT_CONFIG)
  63. ENTRY(HKEY_DYN_DATA)
  64. #undef ENTRY
  65. };
  66. CRegistryTypeInformationIndex RegistryTypeInformation_IndexedByDword[NUMBER_OF(RegistryTypeInformation)];
  67. CRegistryTypeInformationIndex RegistryTypeInformation_IndexedByString[NUMBER_OF(RegistryTypeInformation)];
  68. CRegistryRootInformationIndex RegistryRootInformation_IndexedByPseudoHandle[NUMBER_OF(RegistryRootInformation)];
  69. CRegistryRootInformationIndex RegistryRootInformation_IndexedByString[NUMBER_OF(RegistryRootInformation)];
  70. void InitializeIndexArray(BYTE * Index, BYTE Count)
  71. {
  72. BYTE i = 0;
  73. for ( i = 0 ; i != Count ; ++i)
  74. {
  75. Index[i] = i;
  76. }
  77. }
  78. int
  79. __cdecl
  80. RegistryTypeInformation_IndexedByDword_Compare_qsort(
  81. const void * VoidElem1,
  82. const void * VoidElem2
  83. )
  84. {
  85. const CRegistryTypeInformationIndex * Index1 = reinterpret_cast<const CRegistryTypeInformationIndex*>(VoidElem1);
  86. const CRegistryTypeInformationIndex * Index2 = reinterpret_cast<const CRegistryTypeInformationIndex*>(VoidElem2);
  87. return COMPARE_NUMBER(RegistryTypeInformation[*Index1].Dword, RegistryTypeInformation[*Index2].Dword);
  88. }
  89. int
  90. __cdecl
  91. RegistryTypeInformation_IndexedByString_Compare_qsort(
  92. const void * VoidElem1,
  93. const void * VoidElem2
  94. )
  95. {
  96. const CRegistryTypeInformationIndex * Index1 = reinterpret_cast<const CRegistryTypeInformationIndex*>(VoidElem1);
  97. const CRegistryTypeInformationIndex * Index2 = reinterpret_cast<const CRegistryTypeInformationIndex*>(VoidElem2);
  98. return FusionpStrCmpI(RegistryTypeInformation[*Index1].String, RegistryTypeInformation[*Index2].String);
  99. }
  100. int
  101. __cdecl
  102. RegistryTypeInformation_IndexedByDword_Compare_bsearch(
  103. const void * VoidKey,
  104. const void * VoidElem
  105. )
  106. {
  107. const CRegistryTypeInformation * Key = reinterpret_cast<const CRegistryTypeInformation*>(VoidKey);
  108. const CRegistryTypeInformationIndex * Index = reinterpret_cast<const CRegistryTypeInformationIndex*>(VoidElem);
  109. return COMPARE_NUMBER(Key->Dword, RegistryTypeInformation[*Index].Dword);
  110. }
  111. int
  112. __cdecl
  113. RegistryTypeInformation_IndexedByString_Compare_bsearch(
  114. const void * VoidKey,
  115. const void * VoidElem
  116. )
  117. {
  118. const CRegistryTypeInformation * Key = reinterpret_cast<const CRegistryTypeInformation*>(VoidKey);
  119. const CRegistryTypeInformationIndex * Index = reinterpret_cast<const CRegistryTypeInformationIndex*>(VoidElem);
  120. return FusionpStrCmpI(Key->String, RegistryTypeInformation[*Index].String);
  121. }
  122. int
  123. __cdecl
  124. RegistryRootInformation_IndexedByPseudoHandle_Compare_qsort(
  125. const void * VoidElem1,
  126. const void * VoidElem2
  127. )
  128. {
  129. const CRegistryRootInformationIndex * Index1 = reinterpret_cast<const CRegistryRootInformationIndex*>(VoidElem1);
  130. const CRegistryRootInformationIndex * Index2 = reinterpret_cast<const CRegistryRootInformationIndex*>(VoidElem2);
  131. return COMPARE_NUMBER(RegistryRootInformation[*Index1].PseudoHandleInteger, RegistryRootInformation[*Index2].PseudoHandleInteger);
  132. }
  133. int
  134. __cdecl
  135. RegistryRootInformation_IndexedByString_Compare_qsort(
  136. const void * VoidElem1,
  137. const void * VoidElem2
  138. )
  139. {
  140. const CRegistryRootInformationIndex * Index1 = reinterpret_cast<const CRegistryRootInformationIndex*>(VoidElem1);
  141. const CRegistryRootInformationIndex * Index2 = reinterpret_cast<const CRegistryRootInformationIndex*>(VoidElem2);
  142. return FusionpStrCmpI(RegistryRootInformation[*Index1].String, RegistryRootInformation[*Index2].String);
  143. }
  144. int
  145. __cdecl
  146. RegistryRootInformation_IndexedByPseudoHandle_Compare_bsearch(
  147. const void * VoidKey,
  148. const void * VoidElem
  149. )
  150. {
  151. const CRegistryRootInformation * Key = reinterpret_cast<const CRegistryRootInformation*>(VoidKey);
  152. const CRegistryRootInformationIndex * Index = reinterpret_cast<const CRegistryRootInformationIndex*>(VoidElem);
  153. return COMPARE_NUMBER(Key->PseudoHandleInteger, RegistryRootInformation[*Index].PseudoHandleInteger);
  154. }
  155. int
  156. __cdecl
  157. RegistryRootInformation_IndexedByString_Compare_bsearch(
  158. const void * VoidKey,
  159. const void * VoidElem
  160. )
  161. {
  162. const CRegistryRootInformation * Key = reinterpret_cast<const CRegistryRootInformation*>(VoidKey);
  163. const CRegistryRootInformationIndex * Index = reinterpret_cast<const CRegistryRootInformationIndex*>(VoidElem);
  164. return FusionpStrCmpI(Key->String, RegistryRootInformation[*Index].String);
  165. }
  166. WIN32_ONE_SHOT_OPAQUE_STATIC_STATE InitializeRegistryTypeInformation_Oneshot;
  167. void InitializeRegistryTypeInformation()
  168. {
  169. //
  170. // More than one init is ok, but multiple concurrent inits are not.
  171. // Contention could be reduced by copying into a local, sort local, copy back.
  172. //
  173. if (Win32EnterOneShotW(WIN32_ENTER_ONE_SHOT_FLAG_EXACTLY_ONCE, &InitializeRegistryTypeInformation_Oneshot))
  174. {
  175. __try
  176. {
  177. InitializeIndexArray(RegistryTypeInformation_IndexedByDword, NUMBER_OF(RegistryTypeInformation_IndexedByDword));
  178. CopyMemory(&RegistryTypeInformation_IndexedByString, &RegistryTypeInformation_IndexedByDword, sizeof(RegistryTypeInformation_IndexedByDword));
  179. qsort(
  180. RegistryTypeInformation_IndexedByDword,
  181. NUMBER_OF(RegistryTypeInformation_IndexedByDword),
  182. sizeof(RegistryTypeInformation_IndexedByDword[0]),
  183. RegistryTypeInformation_IndexedByDword_Compare_qsort
  184. );
  185. qsort(
  186. RegistryTypeInformation_IndexedByString,
  187. NUMBER_OF(RegistryTypeInformation_IndexedByString),
  188. sizeof(RegistryTypeInformation_IndexedByString[0]),
  189. RegistryTypeInformation_IndexedByString_Compare_qsort
  190. );
  191. //Win32RegisterDllNotification(Cleanup);
  192. }
  193. __finally
  194. {
  195. Win32LeaveOneShotW(0, &InitializeRegistryTypeInformation_Oneshot);
  196. }
  197. }
  198. else
  199. {
  200. ASSERT_NTC(F::GetLastWin32Error() == NO_ERROR);
  201. }
  202. }
  203. // oneshot vs. simplelock just for variety/coverage
  204. CWin32SimpleLock InitializeRegistryRootInformation_Lock = WIN32_INIT_SIMPLE_LOCK;
  205. void InitializeRegistryRootInformation()
  206. {
  207. CWin32SimpleLockHolder lock(&InitializeRegistryRootInformation_Lock);
  208. if (lock.m_Result & WIN32_ACQUIRE_SIMPLE_LOCK_WAS_FIRST_ACQUIRE)
  209. {
  210. InitializeIndexArray(RegistryRootInformation_IndexedByPseudoHandle, NUMBER_OF(RegistryRootInformation_IndexedByPseudoHandle));
  211. CopyMemory(&RegistryRootInformation_IndexedByString, &RegistryRootInformation_IndexedByPseudoHandle, sizeof(RegistryRootInformation_IndexedByPseudoHandle));
  212. qsort(
  213. RegistryRootInformation_IndexedByPseudoHandle,
  214. NUMBER_OF(RegistryRootInformation_IndexedByPseudoHandle),
  215. sizeof(RegistryRootInformation_IndexedByPseudoHandle[0]),
  216. RegistryRootInformation_IndexedByPseudoHandle_Compare_qsort
  217. );
  218. qsort(
  219. RegistryRootInformation_IndexedByString,
  220. NUMBER_OF(RegistryRootInformation_IndexedByString),
  221. sizeof(RegistryRootInformation_IndexedByString[0]),
  222. RegistryRootInformation_IndexedByString_Compare_qsort
  223. );
  224. }
  225. }
  226. const CRegistryTypeInformation *
  227. FindRegistryType(
  228. const CRegistryTypeInformation * Key,
  229. const CRegistryTypeInformationIndex * Array,
  230. int (__cdecl * ComparisonFunction)(const void *, const void *)
  231. )
  232. {
  233. InitializeRegistryTypeInformation();
  234. const CRegistryTypeInformationIndex * Index = reinterpret_cast<const CRegistryTypeInformationIndex *>(
  235. bsearch(
  236. Key,
  237. Array,
  238. sizeof(RegistryTypeInformation_IndexedByDword),
  239. sizeof(RegistryTypeInformation_IndexedByDword[0]),
  240. ComparisonFunction
  241. ));
  242. if (Index == NULL)
  243. {
  244. F::SetLastWin32Error(ERROR_NOT_FOUND);
  245. return NULL;
  246. }
  247. return &RegistryTypeInformation[*Index];
  248. }
  249. BOOL F::RegistryTypeDwordToString(DWORD Dword, PCWSTR & String)
  250. {
  251. FN_PROLOG_WIN32;
  252. const CRegistryTypeInformation * TypeInfo = NULL;
  253. CRegistryTypeInformation Key;
  254. Key.Dword = Dword;
  255. IFW32NULL_EXIT(TypeInfo = FindRegistryType(
  256. &Key,
  257. RegistryTypeInformation_IndexedByDword,
  258. RegistryTypeInformation_IndexedByDword_Compare_bsearch));
  259. if (TypeInfo->PreferredString != NULL)
  260. String = TypeInfo->PreferredString;
  261. else
  262. String = TypeInfo->String;
  263. FN_EPILOG;
  264. }
  265. BOOL F::RegistryTypeStringToDword(PCWSTR String, DWORD & Dword)
  266. {
  267. FN_PROLOG_WIN32;
  268. const CRegistryTypeInformation * TypeInfo = NULL;
  269. CRegistryTypeInformation Key;
  270. Key.String = String;
  271. IFW32NULL_EXIT(TypeInfo = FindRegistryType(
  272. &Key,
  273. RegistryTypeInformation_IndexedByString,
  274. RegistryTypeInformation_IndexedByString_Compare_bsearch));
  275. Dword = TypeInfo->Dword;
  276. FN_EPILOG;
  277. }
  278. const CRegistryRootInformation *
  279. FindRegistryRoot(
  280. const CRegistryRootInformation * Key,
  281. const CRegistryRootInformationIndex * Array,
  282. int (__cdecl * ComparisonFunction)(const void *, const void *)
  283. )
  284. {
  285. InitializeRegistryRootInformation();
  286. const CRegistryRootInformationIndex * Index = reinterpret_cast<const CRegistryRootInformationIndex *>(
  287. bsearch(
  288. Key,
  289. Array,
  290. sizeof(RegistryRootInformation_IndexedByPseudoHandle),
  291. sizeof(RegistryRootInformation_IndexedByPseudoHandle[0]),
  292. ComparisonFunction
  293. ));
  294. if (Index == NULL)
  295. {
  296. ::SetLastError(ERROR_NOT_FOUND);
  297. return NULL;
  298. }
  299. return &RegistryRootInformation[*Index];
  300. }
  301. BOOL F::RegistryBuiltinRootToString(HKEY PseudoHandle, PCWSTR & String)
  302. {
  303. FN_PROLOG_WIN32;
  304. const CRegistryRootInformation * RootInfo = NULL;
  305. CRegistryRootInformation Key;
  306. Key.PseudoHandle = PseudoHandle;
  307. IFW32NULL_EXIT(RootInfo = FindRegistryRoot(
  308. &Key,
  309. RegistryRootInformation_IndexedByString,
  310. RegistryRootInformation_IndexedByString_Compare_bsearch));
  311. String = RootInfo->String;
  312. FN_EPILOG;
  313. }
  314. BOOL F::RegistryBuiltinStringToRoot(PCWSTR String, HKEY & PseudoHandle)
  315. {
  316. FN_PROLOG_WIN32;
  317. const CRegistryRootInformation * RootInfo = NULL;
  318. CRegistryRootInformation Key;
  319. Key.String = String;
  320. IFW32NULL_EXIT(RootInfo = FindRegistryRoot(
  321. &Key,
  322. RegistryRootInformation_IndexedByString,
  323. RegistryRootInformation_IndexedByString_Compare_bsearch));
  324. PseudoHandle = RootInfo->PseudoHandle;
  325. FN_EPILOG;
  326. }