xbox kernel RTL cleanup

This commit is contained in:
Dr. Chat 2015-06-28 20:32:42 -05:00
parent b663b615bf
commit d809af5902
1 changed files with 72 additions and 216 deletions

View File

@ -25,21 +25,10 @@ namespace xe {
namespace kernel { namespace kernel {
// http://msdn.microsoft.com/en-us/library/ff561778 // http://msdn.microsoft.com/en-us/library/ff561778
SHIM_CALL RtlCompareMemory_shim(PPCContext* ppc_context, dword_result_t RtlCompareMemory(lpvoid_t source1, lpvoid_t source2,
KernelState* kernel_state) { dword_t length) {
uint32_t source1_ptr = SHIM_GET_ARG_32(0); uint8_t* p1 = source1;
uint32_t source2_ptr = SHIM_GET_ARG_32(1); uint8_t* p2 = source2;
uint32_t length = SHIM_GET_ARG_32(2);
XELOGD("RtlCompareMemory(%.8X, %.8X, %d)", source1_ptr, source2_ptr, length);
// SIZE_T
// _In_ const VOID *Source1,
// _In_ const VOID *Source2,
// _In_ SIZE_T Length
uint8_t* p1 = SHIM_MEM_ADDR(source1_ptr);
uint8_t* p2 = SHIM_MEM_ADDR(source2_ptr);
// Note that the return value is the number of bytes that match, so it's best // Note that the return value is the number of bytes that match, so it's best
// we just do this ourselves vs. using memcmp. // we just do this ourselves vs. using memcmp.
@ -52,232 +41,120 @@ SHIM_CALL RtlCompareMemory_shim(PPCContext* ppc_context,
} }
} }
SHIM_SET_RETURN_32(c); return c;
} }
DECLARE_XBOXKRNL_EXPORT(RtlCompareMemory, ExportTag::kImplemented);
// http://msdn.microsoft.com/en-us/library/ff552123 // http://msdn.microsoft.com/en-us/library/ff552123
SHIM_CALL RtlCompareMemoryUlong_shim(PPCContext* ppc_context, dword_result_t RtlCompareMemoryUlong(lpvoid_t source, dword_t length,
KernelState* kernel_state) { dword_t pattern) {
uint32_t source_ptr = SHIM_GET_ARG_32(0); // Return 0 if source/length not aligned
uint32_t length = SHIM_GET_ARG_32(1); if (source.guest_address() % 4 || length % 4) {
uint32_t pattern = SHIM_GET_ARG_32(2); return 0;
XELOGD("RtlCompareMemoryUlong(%.8X, %d, %.8X)", source_ptr, length, pattern);
// SIZE_T
// _In_ PVOID Source,
// _In_ SIZE_T Length,
// _In_ ULONG Pattern
if ((source_ptr % 4) || (length % 4)) {
SHIM_SET_RETURN_32(0);
return;
} }
uint8_t* p = SHIM_MEM_ADDR(source_ptr); uint32_t n = 0;
for (uint32_t i = 0; i < (length / 4); i++) {
// Swap pattern. // FIXME: This assumes as_array returns xe::be
// TODO(benvanik): ensure byte order of pattern is correct. uint32_t val = source.as_array<uint32_t>()[i];
// Since we are doing byte-by-byte comparison we may not want to swap. if (val == pattern) {
// GET_ARG swaps, so this is a swap back. Ugly. n++;
const uint32_t pb32 = xe::byte_swap(pattern);
const uint8_t* pb = (uint8_t*)&pb32;
uint32_t c = 0;
for (uint32_t n = 0; n < length; n++, p++) {
if (*p == pb[n % 4]) {
c++;
} }
} }
SHIM_SET_RETURN_32(c); return n;
} }
DECLARE_XBOXKRNL_EXPORT(RtlCompareMemoryUlong, ExportTag::kImplemented);
// http://msdn.microsoft.com/en-us/library/ff552263 // http://msdn.microsoft.com/en-us/library/ff552263
SHIM_CALL RtlFillMemoryUlong_shim(PPCContext* ppc_context, void RtlFillMemoryUlong(lpvoid_t destination, dword_t length, dword_t pattern) {
KernelState* kernel_state) {
uint32_t destination_ptr = SHIM_GET_ARG_32(0);
uint32_t length = SHIM_GET_ARG_32(1);
uint32_t pattern = SHIM_GET_ARG_32(2);
XELOGD("RtlFillMemoryUlong(%.8X, %d, %.8X)", destination_ptr, length,
pattern);
// VOID
// _Out_ PVOID Destination,
// _In_ SIZE_T Length,
// _In_ ULONG Pattern
// NOTE: length must be % 4, so we can work on uint32s. // NOTE: length must be % 4, so we can work on uint32s.
uint32_t* p = (uint32_t*)SHIM_MEM_ADDR(destination_ptr);
// TODO(benvanik): ensure byte order is correct - we're writing back the
// swapped arg value.
uint32_t count = length >> 2; uint32_t count = length >> 2;
uint32_t native_pattern = xe::byte_swap(pattern);
// TODO: unroll loop?
uint32_t* p = destination.as<uint32_t*>();
for (uint32_t n = 0; n < count; n++, p++) { for (uint32_t n = 0; n < count; n++, p++) {
*p = native_pattern; *p = xe::byte_swap((uint32_t)pattern);
} }
} }
DECLARE_XBOXKRNL_EXPORT(RtlFillMemoryUlong, ExportTag::kImplemented);
SHIM_CALL RtlCompareString_shim(PPCContext* ppc_context, dword_result_t RtlCompareString(lpstring_t string_1, lpstring_t string_2,
KernelState* kernel_state) { dword_t case_insensitive) {
uint32_t string_1_ptr = SHIM_GET_ARG_32(0);
uint32_t string_2_ptr = SHIM_GET_ARG_32(1);
uint32_t case_insensitive = SHIM_GET_ARG_32(2);
XELOGD("RtlCompareString(%.8X, %.8X, %d)", string_1_ptr, string_2_ptr,
case_insensitive);
auto string_1 = reinterpret_cast<const char*>(SHIM_MEM_ADDR(string_1_ptr));
auto string_2 = reinterpret_cast<const char*>(SHIM_MEM_ADDR(string_2_ptr));
int ret = case_insensitive ? strcasecmp(string_1, string_2) int ret = case_insensitive ? strcasecmp(string_1, string_2)
: std::strcmp(string_1, string_2); : std::strcmp(string_1, string_2);
SHIM_SET_RETURN_32(ret); return ret;
} }
DECLARE_XBOXKRNL_EXPORT(RtlCompareString, ExportTag::kImplemented);
SHIM_CALL RtlCompareStringN_shim(PPCContext* ppc_context, dword_result_t RtlCompareStringN(lpstring_t string_1, dword_t string_1_len,
KernelState* kernel_state) { lpstring_t string_2, dword_t string_2_len,
uint32_t string_1_ptr = SHIM_GET_ARG_32(0); dword_t case_insensitive) {
uint32_t string_1_len = SHIM_GET_ARG_32(1); uint32_t len1 = string_1_len;
uint32_t string_2_ptr = SHIM_GET_ARG_32(2); uint32_t len2 = string_2_len;
uint32_t string_2_len = SHIM_GET_ARG_32(3);
uint32_t case_insensitive = SHIM_GET_ARG_32(4);
XELOGD("RtlCompareStringN(%.8X, %d, %.8X, %d, %d)", string_1_ptr,
string_1_len, string_2_ptr, string_2_len, case_insensitive);
auto string_1 = reinterpret_cast<const char*>(SHIM_MEM_ADDR(string_1_ptr));
auto string_2 = reinterpret_cast<const char*>(SHIM_MEM_ADDR(string_2_ptr));
if (string_1_len == 0xFFFF) { if (string_1_len == 0xFFFF) {
string_1_len = uint32_t(std::strlen(string_1)); len1 = uint32_t(std::strlen(string_1));
} }
if (string_2_len == 0xFFFF) { if (string_2_len == 0xFFFF) {
string_2_len = uint32_t(std::strlen(string_2)); len2 = uint32_t(std::strlen(string_2));
} }
auto len = std::min(string_1_len, string_2_len); auto len = std::min(string_1_len, string_2_len);
int ret = case_insensitive ? strncasecmp(string_1, string_2, len) int ret = case_insensitive ? strncasecmp(string_1, string_2, len)
: std::strncmp(string_1, string_2, len); : std::strncmp(string_1, string_2, len);
SHIM_SET_RETURN_32(ret); return ret;
} }
DECLARE_XBOXKRNL_EXPORT(RtlCompareStringN, ExportTag::kImplemented);
// typedef struct _STRING {
// USHORT Length;
// USHORT MaximumLength;
// PCHAR Buffer;
// } ANSI_STRING, *PANSI_STRING;
// http://msdn.microsoft.com/en-us/library/ff561918 // http://msdn.microsoft.com/en-us/library/ff561918
SHIM_CALL RtlInitAnsiString_shim(PPCContext* ppc_context, void RtlInitAnsiString(pointer_t<X_ANSI_STRING> destination,
KernelState* kernel_state) { lpstring_t source) {
uint32_t destination_ptr = SHIM_GET_ARG_32(0); if (source) {
uint32_t source_ptr = SHIM_GET_ARG_32(1);
const char* source = source_ptr ? (char*)SHIM_MEM_ADDR(source_ptr) : nullptr;
XELOGD("RtlInitAnsiString(%.8X, %.8X = %s)", destination_ptr, source_ptr,
source ? source : "<null>");
// VOID
// _Out_ PANSI_STRING DestinationString,
// _In_opt_ PCSZ SourceString
if (source_ptr != 0) {
uint16_t length = (uint16_t)strlen(source); uint16_t length = (uint16_t)strlen(source);
SHIM_SET_MEM_16(destination_ptr + 0, length); destination->length = length;
SHIM_SET_MEM_16(destination_ptr + 2, length + 1); destination->maximum_length = length + 1;
} else { } else {
SHIM_SET_MEM_16(destination_ptr + 0, 0); destination->reset();
SHIM_SET_MEM_16(destination_ptr + 2, 0);
} }
SHIM_SET_MEM_32(destination_ptr + 4, source_ptr);
destination->pointer = source.guest_address();
} }
DECLARE_XBOXKRNL_EXPORT(RtlInitAnsiString, ExportTag::kImplemented);
// http://msdn.microsoft.com/en-us/library/ff561899 // http://msdn.microsoft.com/en-us/library/ff561899
SHIM_CALL RtlFreeAnsiString_shim(PPCContext* ppc_context, void RtlFreeAnsiString(pointer_t<X_ANSI_STRING> string) {
KernelState* kernel_state) { if (string->pointer) {
uint32_t string_ptr = SHIM_GET_ARG_32(0); kernel_memory()->SystemHeapFree(string->pointer);
XELOGD("RtlFreeAnsiString(%.8X)", string_ptr);
// VOID
// _Inout_ PANSI_STRING AnsiString
uint32_t buffer = SHIM_MEM_32(string_ptr + 4);
if (!buffer) {
return;
} }
uint32_t length = SHIM_MEM_16(string_ptr + 2);
kernel_state->memory()->SystemHeapFree(buffer);
SHIM_SET_MEM_16(string_ptr + 0, 0); string->reset();
SHIM_SET_MEM_16(string_ptr + 2, 0);
SHIM_SET_MEM_32(string_ptr + 4, 0);
} }
DECLARE_XBOXKRNL_EXPORT(RtlFreeAnsiString, ExportTag::kImplemented);
// typedef struct _UNICODE_STRING {
// USHORT Length;
// USHORT MaximumLength;
// PWSTR Buffer;
// } UNICODE_STRING, *PUNICODE_STRING;
// http://msdn.microsoft.com/en-us/library/ff561934 // http://msdn.microsoft.com/en-us/library/ff561934
SHIM_CALL RtlInitUnicodeString_shim(PPCContext* ppc_context, void RtlInitUnicodeString(pointer_t<X_UNICODE_STRING> destination,
KernelState* kernel_state) { lpwstring_t source) {
uint32_t destination_ptr = SHIM_GET_ARG_32(0); if (source) {
uint32_t source_ptr = SHIM_GET_ARG_32(1); destination->length = (uint16_t)source.value().size() * 2;
destination->maximum_length = (uint16_t)(source.value().size() + 1) * 2;
auto source = source_ptr destination->pointer = source.guest_address();
? xe::load_and_swap<std::wstring>(SHIM_MEM_ADDR(source_ptr))
: L"";
XELOGD("RtlInitUnicodeString(%.8X, %.8X = %ls)", destination_ptr, source_ptr,
source.empty() ? L"<null>" : source.c_str());
// VOID
// _Out_ PUNICODE_STRING DestinationString,
// _In_opt_ PCWSTR SourceString
if (source.size()) {
SHIM_SET_MEM_16(destination_ptr + 0,
static_cast<uint16_t>(source.size() * 2));
SHIM_SET_MEM_16(destination_ptr + 2,
static_cast<uint16_t>((source.size() + 1) * 2));
SHIM_SET_MEM_32(destination_ptr + 4, source_ptr);
} else { } else {
SHIM_SET_MEM_16(destination_ptr + 0, 0); destination->reset();
SHIM_SET_MEM_16(destination_ptr + 2, 0);
SHIM_SET_MEM_32(destination_ptr + 4, 0);
} }
} }
DECLARE_XBOXKRNL_EXPORT(RtlInitUnicodeString, ExportTag::kImplemented);
// http://msdn.microsoft.com/en-us/library/ff561903 // http://msdn.microsoft.com/en-us/library/ff561903
SHIM_CALL RtlFreeUnicodeString_shim(PPCContext* ppc_context, void RtlFreeUnicodeString(pointer_t<X_UNICODE_STRING> string) {
KernelState* kernel_state) { if (string->pointer) {
uint32_t string_ptr = SHIM_GET_ARG_32(0); kernel_memory()->SystemHeapFree(string->pointer);
XELOGD("RtlFreeUnicodeString(%.8X)", string_ptr);
// VOID
// _Inout_ PUNICODE_STRING UnicodeString
uint32_t buffer = SHIM_MEM_32(string_ptr + 4);
if (!buffer) {
return;
} }
uint32_t length = SHIM_MEM_16(string_ptr + 2);
kernel_state->memory()->SystemHeapFree(buffer);
SHIM_SET_MEM_16(string_ptr + 0, 0); string->reset();
SHIM_SET_MEM_16(string_ptr + 2, 0);
SHIM_SET_MEM_32(string_ptr + 4, 0);
} }
DECLARE_XBOXKRNL_EXPORT(RtlFreeUnicodeString, ExportTag::kImplemented);
// http://msdn.microsoft.com/en-us/library/ff562969 // http://msdn.microsoft.com/en-us/library/ff562969
SHIM_CALL RtlUnicodeStringToAnsiString_shim(PPCContext* ppc_context, SHIM_CALL RtlUnicodeStringToAnsiString_shim(PPCContext* ppc_context,
@ -380,25 +257,17 @@ SHIM_CALL RtlUnicodeToMultiByteN_shim(PPCContext* ppc_context,
SHIM_SET_RETURN_32(0); SHIM_SET_RETURN_32(0);
} }
SHIM_CALL RtlImageXexHeaderField_shim(PPCContext* ppc_context, pointer_result_t RtlImageXexHeaderField(pointer_t<xex2_header> xex_header,
KernelState* kernel_state) { dword_t field_dword) {
uint32_t xex_header_base = SHIM_GET_ARG_32(0);
uint32_t image_field = SHIM_GET_ARG_32(1);
XELOGD("RtlImageXexHeaderField(%.8X, %.8X)", xex_header_base, image_field);
auto header =
kernel_memory()->TranslateVirtual<xex2_header*>(xex_header_base);
if (!header) {
SHIM_SET_RETURN_32(0);
return;
}
uint32_t field_value = 0; uint32_t field_value = 0;
XUserModule::GetOptHeader(SHIM_MEM_BASE, header, uint32_t field = field_dword; // VS acts weird going from dword_t -> enum
xe_xex2_header_keys(image_field), &field_value);
SHIM_SET_RETURN_32(field_value); XUserModule::GetOptHeader(kernel_memory()->virtual_membase(), xex_header,
xe_xex2_header_keys(field), &field_value);
return field_value;
} }
DECLARE_XBOXKRNL_EXPORT(RtlImageXexHeaderField, ExportTag::kImplemented);
// Unfortunately the Windows RTL_CRITICAL_SECTION object is bigger than the one // Unfortunately the Windows RTL_CRITICAL_SECTION object is bigger than the one
// on the 360 (32b vs. 28b). This means that we can't do in-place splatting of // on the 360 (32b vs. 28b). This means that we can't do in-place splatting of
@ -650,17 +519,6 @@ SHIM_CALL RtlTimeFieldsToTime_shim(PPCContext* ppc_context,
void xe::kernel::xboxkrnl::RegisterRtlExports( void xe::kernel::xboxkrnl::RegisterRtlExports(
xe::cpu::ExportResolver* export_resolver, KernelState* kernel_state) { xe::cpu::ExportResolver* export_resolver, KernelState* kernel_state) {
SHIM_SET_MAPPING("xboxkrnl.exe", RtlCompareMemory, state);
SHIM_SET_MAPPING("xboxkrnl.exe", RtlCompareMemoryUlong, state);
SHIM_SET_MAPPING("xboxkrnl.exe", RtlFillMemoryUlong, state);
SHIM_SET_MAPPING("xboxkrnl.exe", RtlCompareString, state);
SHIM_SET_MAPPING("xboxkrnl.exe", RtlCompareStringN, state);
SHIM_SET_MAPPING("xboxkrnl.exe", RtlInitAnsiString, state);
SHIM_SET_MAPPING("xboxkrnl.exe", RtlFreeAnsiString, state);
SHIM_SET_MAPPING("xboxkrnl.exe", RtlInitUnicodeString, state);
SHIM_SET_MAPPING("xboxkrnl.exe", RtlFreeUnicodeString, state);
SHIM_SET_MAPPING("xboxkrnl.exe", RtlUnicodeStringToAnsiString, state); SHIM_SET_MAPPING("xboxkrnl.exe", RtlUnicodeStringToAnsiString, state);
SHIM_SET_MAPPING("xboxkrnl.exe", RtlMultiByteToUnicodeN, state); SHIM_SET_MAPPING("xboxkrnl.exe", RtlMultiByteToUnicodeN, state);
SHIM_SET_MAPPING("xboxkrnl.exe", RtlUnicodeToMultiByteN, state); SHIM_SET_MAPPING("xboxkrnl.exe", RtlUnicodeToMultiByteN, state);
@ -668,8 +526,6 @@ void xe::kernel::xboxkrnl::RegisterRtlExports(
SHIM_SET_MAPPING("xboxkrnl.exe", RtlTimeToTimeFields, state); SHIM_SET_MAPPING("xboxkrnl.exe", RtlTimeToTimeFields, state);
SHIM_SET_MAPPING("xboxkrnl.exe", RtlTimeFieldsToTime, state); SHIM_SET_MAPPING("xboxkrnl.exe", RtlTimeFieldsToTime, state);
SHIM_SET_MAPPING("xboxkrnl.exe", RtlImageXexHeaderField, state);
SHIM_SET_MAPPING("xboxkrnl.exe", RtlInitializeCriticalSection, state); SHIM_SET_MAPPING("xboxkrnl.exe", RtlInitializeCriticalSection, state);
SHIM_SET_MAPPING("xboxkrnl.exe", RtlInitializeCriticalSectionAndSpinCount, SHIM_SET_MAPPING("xboxkrnl.exe", RtlInitializeCriticalSectionAndSpinCount,
state); state);