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.

417 lines
12 KiB

  1. /*
  2. Copyright (c) Microsoft Corporation
  3. */
  4. #include "stdinc.h"
  5. #define dllimport /* nothing */
  6. #include "debmacro.h"
  7. #include "util.h"
  8. #include "fusionntdll.h"
  9. #if !FUSION_STATIC_NTDLL
  10. #include "win32simplelock.h"
  11. #endif
  12. #if !FUSION_URT
  13. //
  14. // ISSUE:2002-03-14:jonwis - Wow, this is bogus. We should fix this so that we error out
  15. // on large input strings (ie: numerical overflow, etc.) As it is, we'll either
  16. // wrap around when comparing, or we'll do something else equally gross and maybe
  17. // miscompare strings. (Consider "foo" vs. "[32k of whatever]foo" - they should
  18. // compare equal in this case.) We really should revamp this so that the comparison
  19. // result is an OUT, and so this can 'fail' on bad input parameters.
  20. //
  21. int
  22. FusionpCompareStrings(
  23. PCWSTR psz1,
  24. SIZE_T cch1,
  25. PCWSTR psz2,
  26. SIZE_T cch2,
  27. bool fCaseInsensitive
  28. )
  29. {
  30. UNICODE_STRING s1, s2;
  31. s1.Buffer = const_cast<PWSTR>(psz1);
  32. s1.Length = static_cast<USHORT>(cch1 * sizeof(WCHAR));
  33. s1.MaximumLength = s1.Length;
  34. s2.Buffer = const_cast<PWSTR>(psz2);
  35. s2.Length = static_cast<USHORT>(cch2 * sizeof(WCHAR));
  36. s2.MaximumLength = s2.Length;
  37. return ::FusionpRtlCompareUnicodeString(&s1, &s2, fCaseInsensitive);
  38. }
  39. //
  40. // This is not inline in the headers because CGenericBaseStringBuffer
  41. // is not defined early enough; it is only forward declared.
  42. // 2002-05-16:Jaykrell
  43. //
  44. int
  45. FusionpCompareStrings(
  46. const CBaseStringBuffer &rbuff1,
  47. PCWSTR psz2,
  48. SIZE_T cch2,
  49. bool fCaseInsensitive
  50. )
  51. {
  52. return ::FusionpCompareStrings(rbuff1, rbuff1.Cch(), psz2, cch2, fCaseInsensitive);
  53. }
  54. //
  55. // This is not inline in the headers because CGenericBaseStringBuffer
  56. // is not defined early enough; it is only forward declared.
  57. // 2002-05-16:Jaykrell
  58. //
  59. int
  60. FusionpCompareStrings(
  61. PCWSTR psz1,
  62. SIZE_T cch1,
  63. const CBaseStringBuffer &rbuff2,
  64. bool fCaseInsensitive
  65. )
  66. {
  67. return ::FusionpCompareStrings(psz1, cch1, rbuff2, rbuff2.Cch(), fCaseInsensitive);
  68. }
  69. //
  70. // This is not inline in the headers because CGenericBaseStringBuffer
  71. // is not defined early enough; it is only forward declared.
  72. // 2002-05-16:Jaykrell
  73. //
  74. int
  75. FusionpCompareStrings(
  76. const CBaseStringBuffer &rbuff1,
  77. const CBaseStringBuffer &rbuff2,
  78. bool fCaseInsensitive
  79. )
  80. {
  81. return ::FusionpCompareStrings(rbuff1, rbuff1.Cch(), rbuff2, rbuff2.Cch(), fCaseInsensitive);
  82. }
  83. //
  84. // This is not inline in the headers because CGenericBaseStringBuffer
  85. // is not defined early enough; it is only forward declared.
  86. // 2002-05-16:Jaykrell
  87. //
  88. // FUTURE:2002-03-14:jonwis - Consider removing the I versions of these functions entirely.
  89. bool
  90. FusionpEqualStringsI(
  91. const CGenericBaseStringBuffer<CUnicodeCharTraits> &rbuff1,
  92. PCWSTR psz2,
  93. SIZE_T cch2
  94. )
  95. {
  96. return ::FusionpEqualStringsI(static_cast<PCWSTR>(rbuff1), rbuff1.Cch(), psz2, cch2);
  97. }
  98. //
  99. // This is not inline in the headers because CGenericBaseStringBuffer
  100. // is not defined early enough; it is only forward declared.
  101. // 2002-05-16:Jaykrell
  102. //
  103. bool
  104. FusionpEqualStringsI(
  105. PCWSTR psz1,
  106. SIZE_T cch1,
  107. const CGenericBaseStringBuffer<CUnicodeCharTraits> &rbuff2
  108. )
  109. {
  110. return ::FusionpEqualStringsI(psz1, cch1, static_cast<PCWSTR>(rbuff2), rbuff2.Cch());
  111. }
  112. //
  113. // This is not inline in the headers because CGenericBaseStringBuffer
  114. // is not defined early enough; it is only forward declared.
  115. // 2002-05-16:Jaykrell
  116. //
  117. bool
  118. FusionpEqualStringsI(
  119. const CGenericBaseStringBuffer<CUnicodeCharTraits> &rbuff1,
  120. const CGenericBaseStringBuffer<CUnicodeCharTraits> &rbuff2
  121. )
  122. {
  123. return ::FusionpEqualStringsI(static_cast<PCWSTR>(rbuff1), rbuff1.Cch(),
  124. static_cast<PCWSTR>(rbuff2), rbuff2.Cch());
  125. }
  126. //
  127. // This is not inline in the headers because CGenericBaseStringBuffer
  128. // is not defined early enough; it is only forward declared.
  129. // 2002-06-18:Jaykrell
  130. //
  131. bool
  132. FusionpEqualStrings(
  133. PCWSTR psz1,
  134. SIZE_T cch1,
  135. const CGenericBaseStringBuffer<CUnicodeCharTraits> &rbuff2,
  136. bool fCaseInsensitive
  137. )
  138. {
  139. return ::FusionpEqualStrings(psz1, cch1,
  140. static_cast<PCWSTR>(rbuff2), rbuff2.Cch(),
  141. fCaseInsensitive);
  142. }
  143. //
  144. // This is not inline in the headers because CGenericBaseStringBuffer
  145. // is not defined early enough; it is only forward declared.
  146. // 2002-06-18:Jaykrell
  147. //
  148. bool
  149. FusionpEqualStrings(
  150. const CGenericBaseStringBuffer<CUnicodeCharTraits> &rbuff1,
  151. PCWSTR psz2,
  152. SIZE_T cch2,
  153. bool fCaseInsensitive
  154. )
  155. {
  156. return ::FusionpEqualStrings(static_cast<PCWSTR>(rbuff1), rbuff1.Cch(),
  157. psz2, cch2,
  158. fCaseInsensitive);
  159. }
  160. #endif
  161. #if !FUSION_STATIC_NTDLL
  162. // ISSUE:
  163. #define INIT_WITH_DOWNLEVEL(rettype, calltype, api, argsin, argsout) \
  164. rettype calltype Fusionp ## api ## _Init argsin; \
  165. rettype calltype Fusionp ## api ## _DownlevelFallback argsin; \
  166. rettype (calltype * g_Fusionp ## api) argsin = &::Fusionp ## api ## _Init; \
  167. rettype \
  168. calltype \
  169. Fusionp ## api ## _Init argsin \
  170. { \
  171. InterlockedExchangePointer((PVOID *) &g_Fusionp ## api, ::GetProcAddress(::GetModuleHandleW(L"NTDLL.DLL"), #api)); \
  172. if (g_Fusionp ## api == NULL) \
  173. InterlockedExchangePointer((PVOID *) &g_Fusionp ## api, &::Fusionp ## api ## _DownlevelFallback); \
  174. return (*g_Fusionp ## api) argsout; \
  175. }
  176. __declspec(noreturn)
  177. void FusionpFailNtdllDynlink(const char* s)
  178. {
  179. DWORD dwLastError = ::GetLastError();
  180. char buf[64];
  181. buf[sizeof(buf) - 1] = 0;
  182. ::_snprintf(buf, NUMBER_OF(buf) - 1, "SXS2000: Ntdll dynlink %s failed\n", s);
  183. ::OutputDebugStringA(buf);
  184. ::TerminateProcess(GetCurrentProcess(), dwLastError);
  185. }
  186. #define INIT_NO_DOWNLEVEL(rettype, calltype, api, argsin, argsout) \
  187. rettype calltype Fusionp ## api ## _Init argsin; \
  188. rettype (calltype * g_Fusionp ## api) argsin = &::Fusionp ## api ## _Init; \
  189. rettype \
  190. calltype \
  191. Fusionp ## api ## _Init argsin \
  192. { \
  193. InterlockedExchangePointer((PVOID *) &g_Fusionp ## api, ::GetProcAddress(::GetModuleHandleW(L"NTDLL.DLL"), #api)); \
  194. if (g_Fusionp ## api == NULL) \
  195. ::FusionpFailNtdllDynlink(#api); \
  196. return (*g_Fusionp ## api) argsout; \
  197. }
  198. INIT_WITH_DOWNLEVEL(WCHAR, NTAPI, RtlUpcaseUnicodeChar, (WCHAR wch), (wch))
  199. INIT_NO_DOWNLEVEL(WCHAR, NTAPI, RtlDowncaseUnicodeChar, (WCHAR wch), (wch))
  200. INIT_WITH_DOWNLEVEL(NTSTATUS, NTAPI, NtQueryDebugFilterState, (ULONG ComponentId, ULONG Level), (ComponentId, Level))
  201. INIT_WITH_DOWNLEVEL(LONG, NTAPI, RtlCompareUnicodeString, (PCUNICODE_STRING String1, PCUNICODE_STRING String2, BOOLEAN CaseInSensitive), (String1, String2, CaseInSensitive))
  202. INIT_NO_DOWNLEVEL(LONG, NTAPI, RtlUnhandledExceptionFilter, (struct _EXCEPTION_POINTERS *ExceptionInfo), (ExceptionInfo))
  203. INIT_NO_DOWNLEVEL(NTSTATUS, NTAPI, NtAllocateLocallyUniqueId, (PLUID Luid), (Luid))
  204. INIT_WITH_DOWNLEVEL(ULONG, NTAPI, vDbgPrintExWithPrefix, (PCSTR Prefix, IN ULONG ComponentId, IN ULONG Level, IN PCSTR Format, va_list arglist), (Prefix, ComponentId, Level, Format, arglist))
  205. INIT_NO_DOWNLEVEL(DWORD, NTAPI, RtlNtStatusToDosError, (NTSTATUS st), (st))
  206. INIT_WITH_DOWNLEVEL(NTSTATUS, NTAPI, RtlHashUnicodeString, (const UNICODE_STRING *String, BOOLEAN CaseInSensitive, ULONG HashAlgorithm, PULONG HashValue), (String, CaseInSensitive, HashAlgorithm, HashValue))
  207. INIT_NO_DOWNLEVEL(NTSTATUS, NTAPI, RtlExpandEnvironmentStrings_U, (PVOID Environment, PUNICODE_STRING Source, PUNICODE_STRING Destination, PULONG ReturnedLength), (Environment, Source, Destination, ReturnedLength))
  208. INIT_NO_DOWNLEVEL(VOID, NTAPI, RtlAssert, (PVOID FailedAssertion, PVOID FileName, ULONG LineNumber, PCSTR Message), (FailedAssertion, FileName, LineNumber, Message))
  209. INIT_WITH_DOWNLEVEL(VOID, NTAPI, RtlAcquirePebLock, (VOID), ())
  210. INIT_WITH_DOWNLEVEL(VOID, NTAPI, RtlReleasePebLock, (VOID), ())
  211. //
  212. // Note:
  213. // actually, ntdll.dll of win2k and winxp implement this function,
  214. // but win9x does not(we use this func on win98 for FusionWin32_msi_installed
  215. // assembly : however win9x does not support unicode at all, so this is just
  216. // a simple version
  217. //
  218. WCHAR FusionpRtlUpcaseUnicodeChar_DownlevelFallback(
  219. IN WCHAR wch)
  220. {
  221. if (((wch) >= 'a') && ((wch) <= 'z'))
  222. return ((wch) - ('a'-'A'));
  223. else
  224. return wch;
  225. }
  226. LONG
  227. FusionpRtlCompareUnicodeString_DownlevelFallback(
  228. IN PCUNICODE_STRING String1,
  229. IN PCUNICODE_STRING String2,
  230. IN BOOLEAN CaseInSensitive
  231. )
  232. {
  233. WCHAR c1 = 0;
  234. WCHAR c2 = 0;
  235. PCWSTR s1 = String1->Buffer;
  236. PCWSTR s2 = String2->Buffer;
  237. const LONG n1 = String1->Length;
  238. const LONG n2 = String2->Length;
  239. ASSERT_NTC((n1 & 1) == 0);
  240. ASSERT_NTC((n2 & 1) == 0);
  241. ASSERT_NTC(!(((((ULONG_PTR)s1 & 1) != 0) || (((ULONG_PTR)s2 & 1) != 0)) && (n1 != 0) && (n2 != 0)));
  242. PCWSTR Limit = (PWCHAR)((PCHAR)s1 + (n1 <= n2 ? n1 : n2));
  243. if (CaseInSensitive) {
  244. while (s1 < Limit) {
  245. c1 = *s1++;
  246. c2 = *s2++;
  247. if (c1 != c2) {
  248. //
  249. // Note that this needs to reference the translation table!
  250. //
  251. c1 = ::FusionpRtlUpcaseUnicodeChar_DownlevelFallback(c1);
  252. c2 = ::FusionpRtlUpcaseUnicodeChar_DownlevelFallback(c2);
  253. if (c1 != c2) {
  254. return (LONG)(c1) - (LONG)(c2);
  255. }
  256. }
  257. }
  258. } else {
  259. while (s1 < Limit) {
  260. c1 = *s1++;
  261. c2 = *s2++;
  262. if (c1 != c2) {
  263. return (LONG)(c1) - (LONG)(c2);
  264. }
  265. }
  266. }
  267. return n1 - n2;
  268. }
  269. //
  270. // BUGBUG:jonwis:2002-03-14 - The original code here had several bugs, see #577148
  271. //
  272. ULONG
  273. NTAPI
  274. FusionpvDbgPrintExWithPrefix_DownlevelFallback(PCSTR Prefix, IN ULONG ComponentId, IN ULONG Level, IN PCSTR Format, va_list arglist)
  275. {
  276. CHAR Buffer[512]; // same as code in rtl 4/23/2001
  277. const SSIZE_T cb = ::strlen(Prefix);
  278. if (cb > (NUMBER_OF(Buffer) - 1))
  279. return (ULONG)STATUS_INVALID_PARAMETER;
  280. ::_vsnprintf(Buffer + cb , NUMBER_OF(Buffer) - cb - 1, Format, arglist);
  281. Buffer[NUMBER_OF(Buffer) - 1] = 0;
  282. ::OutputDebugStringA(Buffer);
  283. return STATUS_SUCCESS;
  284. }
  285. NTSTATUS
  286. NTAPI
  287. FusionpRtlHashUnicodeString_DownlevelFallback(
  288. const UNICODE_STRING *String,
  289. BOOLEAN CaseInSensitive,
  290. ULONG HashAlgorithm,
  291. PULONG HashValue
  292. )
  293. {
  294. NTSTATUS Status = STATUS_SUCCESS;
  295. ULONG TmpHashValue = 0;
  296. ULONG Chars = 0;
  297. PCWSTR Buffer = NULL;
  298. if ((String == NULL) ||
  299. (HashValue == NULL))
  300. {
  301. Status = STATUS_INVALID_PARAMETER;
  302. goto Exit;
  303. }
  304. Buffer = String->Buffer;
  305. *HashValue = 0;
  306. Chars = String->Length / sizeof(WCHAR);
  307. switch (HashAlgorithm)
  308. {
  309. default:
  310. Status = STATUS_INVALID_PARAMETER;
  311. goto Exit;
  312. break;
  313. case HASH_STRING_ALGORITHM_DEFAULT:
  314. case HASH_STRING_ALGORITHM_X65599:
  315. if (CaseInSensitive)
  316. {
  317. while (Chars-- != 0)
  318. {
  319. WCHAR Char = *Buffer++;
  320. TmpHashValue = (TmpHashValue * 65599) + ::FusionpRtlUpcaseUnicodeChar(Char);
  321. }
  322. }
  323. else
  324. {
  325. while (Chars-- != 0)
  326. TmpHashValue = (TmpHashValue * 65599) + *Buffer++;
  327. }
  328. break;
  329. }
  330. *HashValue = TmpHashValue;
  331. Status = STATUS_SUCCESS;
  332. Exit:
  333. return Status;
  334. }
  335. NTSTATUS
  336. NTAPI
  337. FusionpNtQueryDebugFilterState_DownlevelFallback(ULONG ComponentId, ULONG Level)
  338. {
  339. return FALSE; // total abuse of NTSTATUS API but it's how NtQueryDebugFilterState is written...
  340. }
  341. CWin32SimpleLock g_DownlevelPeblock = WIN32_INIT_SIMPLE_LOCK;
  342. VOID
  343. NTAPI
  344. FusionpRtlAcquirePebLock_DownlevelFallback(
  345. )
  346. {
  347. g_DownlevelPeblock.Acquire();
  348. }
  349. VOID
  350. NTAPI
  351. FusionpRtlReleasePebLock_DownlevelFallback(
  352. )
  353. {
  354. g_DownlevelPeblock.Release();
  355. }
  356. #undef ASSERT
  357. #define ASSERT(x) /* nothing */
  358. #undef RTL_VERIFY
  359. #define RTL_VERIFY(exp) ((exp) ? TRUE : FALSE)
  360. #define _NTOS_
  361. #undef LOBYTE
  362. #undef HIBYTE
  363. extern "C"
  364. {
  365. #include "ntrtlp.h"
  366. #define RtlDowncaseUnicodeChar FusionpRtlDowncaseUnicodeChar
  367. #include "rtlfindcharinunicodestring.c"
  368. #include "rtlvalidateunicodestring.c"
  369. }
  370. #endif // #if !FUSION_STATIC_NTDLL