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.

213 lines
6.3 KiB

  1. #include "stdinc.h"
  2. #include "debmacro.h"
  3. #include "util.h"
  4. #include "fusionntdll.h"
  5. #if !FUSION_URT
  6. int
  7. FusionpCompareStrings(
  8. PCWSTR psz1,
  9. SIZE_T cch1,
  10. PCWSTR psz2,
  11. SIZE_T cch2,
  12. bool fCaseInsensitive
  13. )
  14. {
  15. UNICODE_STRING s1, s2;
  16. s1.Buffer = const_cast<PWSTR>(psz1);
  17. s1.Length = static_cast<USHORT>(cch1 * sizeof(WCHAR));
  18. s1.MaximumLength = s1.Length;
  19. s2.Buffer = const_cast<PWSTR>(psz2);
  20. s2.Length = static_cast<USHORT>(cch2 * sizeof(WCHAR));
  21. s2.MaximumLength = s2.Length;
  22. return ::FusionpRtlCompareUnicodeString(&s1, &s2, fCaseInsensitive);
  23. }
  24. int
  25. FusionpCompareStrings(
  26. const CBaseStringBuffer &rbuff1,
  27. PCWSTR psz2,
  28. SIZE_T cch2,
  29. bool fCaseInsensitive
  30. )
  31. {
  32. return ::FusionpCompareStrings(rbuff1, rbuff1.Cch(), psz2, cch2, fCaseInsensitive);
  33. }
  34. int
  35. FusionpCompareStrings(
  36. PCWSTR psz1,
  37. SIZE_T cch1,
  38. const CBaseStringBuffer &rbuff2,
  39. bool fCaseInsensitive
  40. )
  41. {
  42. return ::FusionpCompareStrings(psz1, cch1, rbuff2, rbuff2.Cch(), fCaseInsensitive);
  43. }
  44. int
  45. FusionpCompareStrings(
  46. const CBaseStringBuffer &rbuff1,
  47. const CBaseStringBuffer &rbuff2,
  48. bool fCaseInsensitive
  49. )
  50. {
  51. return ::FusionpCompareStrings(rbuff1, rbuff1.Cch(), rbuff2, rbuff2.Cch(), fCaseInsensitive);
  52. }
  53. #endif
  54. #if !FUSION_STATIC_NTDLL
  55. #define INIT_WITH_DOWNLEVEL(rettype, calltype, api, argsin, argsout) \
  56. rettype calltype Fusionp ## api ## _Init argsin; \
  57. rettype calltype Fusionp ## api ## _DownlevelFallback argsin; \
  58. rettype (calltype * g_Fusionp ## api) argsin = &::Fusionp ## api ## _Init; \
  59. rettype \
  60. calltype \
  61. Fusionp ## api ## _Init argsin \
  62. { \
  63. InterlockedExchangePointer((PVOID *) &g_Fusionp ## api, ::GetProcAddress(::GetModuleHandleW(L"NTDLL.DLL"), #api)); \
  64. if (g_Fusionp ## api == NULL) \
  65. InterlockedExchangePointer((PVOID *) &g_Fusionp ## api, &::Fusionp ## api ## _DownlevelFallback); \
  66. return (*g_Fusionp ## api) argsout; \
  67. }
  68. __declspec(noreturn)
  69. void FusionpFailNtdllDynlink(const char* s)
  70. {
  71. DWORD dwLastError = ::GetLastError();
  72. char buf[64];
  73. buf[sizeof(buf) - 1] = 0;
  74. _snprintf(buf, RTL_NUMBER_OF(buf) - 1, "SXS2000: Ntdll dynlink %s failed\n", s);
  75. OutputDebugStringA(buf);
  76. TerminateProcess(GetCurrentProcess(), dwLastError);
  77. }
  78. #define INIT_NO_DOWNLEVEL(rettype, calltype, api, argsin, argsout) \
  79. rettype calltype Fusionp ## api ## _Init argsin; \
  80. rettype (calltype * g_Fusionp ## api) argsin = &::Fusionp ## api ## _Init; \
  81. rettype \
  82. calltype \
  83. Fusionp ## api ## _Init argsin \
  84. { \
  85. InterlockedExchangePointer((PVOID *) &g_Fusionp ## api, ::GetProcAddress(::GetModuleHandleW(L"NTDLL.DLL"), #api)); \
  86. if (g_Fusionp ## api == NULL) \
  87. ::FusionpFailNtdllDynlink(#api); \
  88. return (*g_Fusionp ## api) argsout; \
  89. }
  90. INIT_NO_DOWNLEVEL(WCHAR, NTAPI, RtlUpcaseUnicodeChar, (WCHAR wch), (wch))
  91. INIT_NO_DOWNLEVEL(WCHAR, NTAPI, RtlDowncaseUnicodeChar, (WCHAR wch), (wch))
  92. INIT_WITH_DOWNLEVEL(NTSTATUS, NTAPI, NtQueryDebugFilterState, (ULONG ComponentId, ULONG Level), (ComponentId, Level))
  93. INIT_NO_DOWNLEVEL(LONG, NTAPI, RtlCompareUnicodeString, (PCUNICODE_STRING String1, PCUNICODE_STRING String2, BOOLEAN CaseInSensitive), (String1, String2, CaseInSensitive))
  94. INIT_NO_DOWNLEVEL(LONG, NTAPI, RtlUnhandledExceptionFilter, (struct _EXCEPTION_POINTERS *ExceptionInfo), (ExceptionInfo))
  95. INIT_NO_DOWNLEVEL(NTSTATUS, NTAPI, NtAllocateLocallyUniqueId, (PLUID Luid), (Luid))
  96. 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))
  97. INIT_NO_DOWNLEVEL(DWORD, NTAPI, RtlNtStatusToDosError, (NTSTATUS st), (st))
  98. INIT_WITH_DOWNLEVEL(NTSTATUS, NTAPI, RtlHashUnicodeString, (const UNICODE_STRING *String, BOOLEAN CaseInSensitive, ULONG HashAlgorithm, PULONG HashValue), (String, CaseInSensitive, HashAlgorithm, HashValue))
  99. INIT_NO_DOWNLEVEL(NTSTATUS, NTAPI, RtlExpandEnvironmentStrings_U, (PVOID Environment, PUNICODE_STRING Source, PUNICODE_STRING Destination, PULONG ReturnedLength), (Environment, Source, Destination, ReturnedLength))
  100. INIT_NO_DOWNLEVEL(VOID, NTAPI, RtlAssert, (PVOID FailedAssertion, PVOID FileName, ULONG LineNumber, PCSTR Message), (FailedAssertion, FileName, LineNumber, Message))
  101. void
  102. FusionpInitializeNTDLLPtr(
  103. PVOID *ppv,
  104. PCSTR szFunctionName
  105. )
  106. {
  107. HMODULE hMod = ::GetModuleHandleW(L"NTDLL.DLL");
  108. PVOID pvTemp = ::GetProcAddress(hMod, szFunctionName);
  109. InterlockedExchangePointer(ppv, pvTemp);
  110. }
  111. ULONG
  112. NTAPI
  113. FusionpvDbgPrintExWithPrefix_DownlevelFallback(PCSTR Prefix, IN ULONG ComponentId, IN ULONG Level, IN PCSTR Format, va_list arglist)
  114. {
  115. CHAR Buffer[512]; // same as code in rtl 4/23/2001
  116. __try {
  117. SSIZE_T cb = ::strlen(Prefix);
  118. Buffer[sizeof(Buffer) - 1] = 0;
  119. strcpy(Buffer, Prefix);
  120. ::_vsnprintf(Buffer + cb , sizeof(Buffer) - cb - 1, Format, arglist);
  121. } __except (EXCEPTION_EXECUTE_HANDLER) {
  122. return GetExceptionCode();
  123. }
  124. ::OutputDebugStringA(Buffer);
  125. return STATUS_SUCCESS;
  126. }
  127. NTSTATUS
  128. NTAPI
  129. FusionpRtlHashUnicodeString_DownlevelFallback(
  130. const UNICODE_STRING *String,
  131. BOOLEAN CaseInSensitive,
  132. ULONG HashAlgorithm,
  133. PULONG HashValue
  134. )
  135. {
  136. NTSTATUS Status = STATUS_SUCCESS;
  137. ULONG TmpHashValue = 0;
  138. ULONG Chars;
  139. PCWSTR Buffer;
  140. if ((String == NULL) ||
  141. (HashValue == NULL))
  142. {
  143. Status = STATUS_INVALID_PARAMETER;
  144. goto Exit;
  145. }
  146. Buffer = String->Buffer;
  147. *HashValue = 0;
  148. Chars = String->Length / sizeof(WCHAR);
  149. switch (HashAlgorithm)
  150. {
  151. default:
  152. Status = STATUS_INVALID_PARAMETER;
  153. goto Exit;
  154. break;
  155. case HASH_STRING_ALGORITHM_DEFAULT:
  156. case HASH_STRING_ALGORITHM_X65599:
  157. if (CaseInSensitive)
  158. {
  159. while (Chars-- != 0)
  160. {
  161. WCHAR Char = *Buffer++;
  162. TmpHashValue = (TmpHashValue * 65599) + ::FusionpRtlUpcaseUnicodeChar(Char);
  163. }
  164. }
  165. else
  166. {
  167. while (Chars-- != 0)
  168. TmpHashValue = (TmpHashValue * 65599) + *Buffer++;
  169. }
  170. break;
  171. }
  172. *HashValue = TmpHashValue;
  173. Status = STATUS_SUCCESS;
  174. Exit:
  175. return Status;
  176. }
  177. NTSTATUS
  178. NTAPI
  179. FusionpNtQueryDebugFilterState_DownlevelFallback(ULONG ComponentId, ULONG Level)
  180. {
  181. return FALSE; // total abuse of NTSTATUS API but it's how NtQueryDebugFilterState is written...
  182. }
  183. #endif