diff --git a/src/xenia/kernel/xboxkrnl_io.cc b/src/xenia/kernel/xboxkrnl_io.cc index 365a76b94..d3da2aea1 100644 --- a/src/xenia/kernel/xboxkrnl_io.cc +++ b/src/xenia/kernel/xboxkrnl_io.cc @@ -25,11 +25,52 @@ namespace kernel { using namespace xe::kernel::fs; +// TODO(benvanik): replace X_OBJECT_ATTRIBUTES with new style and remove this. +class X_ANSI_STRING_OLD { + private: + uint16_t length; + uint16_t maximum_length; + const char* buffer; + + public: + X_ANSI_STRING_OLD() { Zero(); } + X_ANSI_STRING_OLD(const uint8_t* base, uint32_t p) { Read(base, p); } + void Read(const uint8_t* base, uint32_t p) { + length = xe::load_and_swap(base + p); + maximum_length = xe::load_and_swap(base + p + 2); + if (maximum_length) { + buffer = (const char*)(base + xe::load_and_swap(base + p + 4)); + } else { + buffer = 0; + } + } + void Zero() { + length = maximum_length = 0; + buffer = 0; + } + char* Duplicate() { + if (!buffer || !length) { + return nullptr; + } + auto copy = (char*)calloc(length + 1, sizeof(char)); + std::strncpy(copy, buffer, length); + return copy; + } + std::string to_string() { + if (!buffer || !length) { + return ""; + } + std::string result(buffer, length); + return result; + } +}; +// static_assert_size(X_ANSI_STRING, 8); + class X_OBJECT_ATTRIBUTES { public: uint32_t root_directory; uint32_t object_name_ptr; - X_ANSI_STRING object_name; + X_ANSI_STRING_OLD object_name; uint32_t attributes; X_OBJECT_ATTRIBUTES() { Zero(); } @@ -51,7 +92,6 @@ class X_OBJECT_ATTRIBUTES { attributes = 0; } }; -static_assert_size(X_OBJECT_ATTRIBUTES, 12 + sizeof(X_ANSI_STRING)); struct FileDisposition { static const uint32_t X_FILE_SUPERSEDE = 0x00000000; @@ -699,22 +739,17 @@ SHIM_CALL NtQueryDirectoryFile_shim(PPCContext* ppc_context, uint32_t file_name_ptr = SHIM_GET_ARG_32(7); uint32_t restart_scan = SHIM_GET_ARG_32(8); - char* file_name = NULL; - if (file_name_ptr != 0) { - X_ANSI_STRING xas(SHIM_MEM_BASE, file_name_ptr); - file_name = xas.Duplicate(); - } + auto file_name = X_ANSI_STRING::to_string(SHIM_MEM_BASE, file_name_ptr); XELOGD( "NtQueryDirectoryFile(%.8X, %.8X, %.8X, %.8X, %.8X, %.8X, %d, %.8X(%s), " "%d)", file_handle, event_handle, apc_routine, apc_context, io_status_block_ptr, - file_info_ptr, length, file_name_ptr, !file_name ? "(null)" : file_name, - restart_scan); + file_info_ptr, length, file_name_ptr, + !file_name.empty() ? file_name.c_str() : "(null)", restart_scan); if (length < 72) { SHIM_SET_RETURN_32(X_STATUS_INFO_LENGTH_MISMATCH); - free(file_name); return; } @@ -725,8 +760,8 @@ SHIM_CALL NtQueryDirectoryFile_shim(PPCContext* ppc_context, if (file) { X_FILE_DIRECTORY_INFORMATION* dir_info = (X_FILE_DIRECTORY_INFORMATION*)calloc(length, 1); - result = - file->QueryDirectory(dir_info, length, file_name, restart_scan != 0); + result = file->QueryDirectory(dir_info, length, file_name.c_str(), + restart_scan != 0); if (XSUCCEEDED(result)) { dir_info->Write(SHIM_MEM_BASE, file_info_ptr); info = length; @@ -744,7 +779,6 @@ SHIM_CALL NtQueryDirectoryFile_shim(PPCContext* ppc_context, SHIM_SET_MEM_32(io_status_block_ptr + 4, info); // Information } - free(file_name); SHIM_SET_RETURN_32(result); } diff --git a/src/xenia/kernel/xboxkrnl_ob.cc b/src/xenia/kernel/xboxkrnl_ob.cc index a3ddc4507..b428fd9e2 100644 --- a/src/xenia/kernel/xboxkrnl_ob.cc +++ b/src/xenia/kernel/xboxkrnl_ob.cc @@ -33,9 +33,8 @@ SHIM_CALL ObOpenObjectByName_shim(PPCContext* ppc_context, uint32_t unk = SHIM_GET_ARG_32(2); uint32_t handle_ptr = SHIM_GET_ARG_32(3); - uint32_t name_str_ptr = SHIM_MEM_32(obj_attributes_ptr + 4); - X_ANSI_STRING name_str(SHIM_MEM_BASE, name_str_ptr); - auto name = name_str.to_string(); + auto name = + X_ANSI_STRING::to_string_indirect(SHIM_MEM_BASE, obj_attributes_ptr + 4); XELOGD("ObOpenObjectByName(%.8X(name=%s), %.8X, %.8X, %.8X)", obj_attributes_ptr, name.c_str(), object_type_ptr, unk, handle_ptr); diff --git a/src/xenia/kernel/xboxkrnl_threading.cc b/src/xenia/kernel/xboxkrnl_threading.cc index ab90e3365..1eee343d7 100644 --- a/src/xenia/kernel/xboxkrnl_threading.cc +++ b/src/xenia/kernel/xboxkrnl_threading.cc @@ -70,12 +70,9 @@ void AssertNoNameCollision(KernelState* kernel_state, if (!obj_attributes_ptr) { return; } - uint32_t name_str_ptr = xe::load_and_swap( - kernel_state->memory()->TranslateVirtual(obj_attributes_ptr + 4)); - if (name_str_ptr) { - X_ANSI_STRING name_str(kernel_state->memory()->virtual_membase(), - name_str_ptr); - auto name = name_str.to_string(); + auto name = X_ANSI_STRING::to_string_indirect( + kernel_state->memory()->virtual_membase(), obj_attributes_ptr + 4); + if (!name.empty()) { X_HANDLE handle = X_INVALID_HANDLE_VALUE; X_RESULT result = kernel_state->object_table()->GetObjectByName(name, &handle); @@ -477,7 +474,7 @@ SHIM_CALL NtCreateEvent_shim(PPCContext* ppc_context, // obj_attributes may have a name inside of it, if != NULL. if (obj_attributes_ptr) { - ev->SetAttributes(SHIM_MEM_ADDR(obj_attributes_ptr)); + ev->SetAttributes(obj_attributes_ptr); } if (handle_ptr) { @@ -641,7 +638,7 @@ SHIM_CALL NtCreateSemaphore_shim(PPCContext* ppc_context, // obj_attributes may have a name inside of it, if != NULL. if (obj_attributes_ptr) { - sem->SetAttributes(SHIM_MEM_ADDR(obj_attributes_ptr)); + sem->SetAttributes(obj_attributes_ptr); } if (handle_ptr) { @@ -738,7 +735,7 @@ SHIM_CALL NtCreateMutant_shim(PPCContext* ppc_context, // obj_attributes may have a name inside of it, if != NULL. if (obj_attributes_ptr) { - mutant->SetAttributes(SHIM_MEM_ADDR(obj_attributes_ptr)); + mutant->SetAttributes(obj_attributes_ptr); } if (handle_ptr) { @@ -800,7 +797,7 @@ SHIM_CALL NtCreateTimer_shim(PPCContext* ppc_context, // obj_attributes may have a name inside of it, if != NULL. if (obj_attributes_ptr) { - timer->SetAttributes(SHIM_MEM_ADDR(obj_attributes_ptr)); + timer->SetAttributes(obj_attributes_ptr); } if (handle_ptr) { diff --git a/src/xenia/kernel/xobject.cc b/src/xenia/kernel/xobject.cc index 29639316f..61a6d479c 100644 --- a/src/xenia/kernel/xobject.cc +++ b/src/xenia/kernel/xobject.cc @@ -88,15 +88,15 @@ X_STATUS XObject::Delete() { } } -void XObject::SetAttributes(const uint8_t* obj_attrs_ptr) { - if (!obj_attrs_ptr) { +void XObject::SetAttributes(uint32_t obj_attributes_ptr) { + if (!obj_attributes_ptr) { return; } - uint32_t name_str_ptr = xe::load_and_swap(obj_attrs_ptr + 4); - if (name_str_ptr) { - X_ANSI_STRING name_str(memory()->virtual_membase(), name_str_ptr); - name_ = name_str.to_string(); + auto name = X_ANSI_STRING::to_string_indirect(memory()->virtual_membase(), + obj_attributes_ptr + 4); + if (!name.empty()) { + name_ = std::move(name); kernel_state_->object_table()->AddNameMapping(name_, handle_); } } diff --git a/src/xenia/kernel/xobject.h b/src/xenia/kernel/xobject.h index 36107a5c3..26412c997 100644 --- a/src/xenia/kernel/xobject.h +++ b/src/xenia/kernel/xobject.h @@ -126,7 +126,7 @@ class XObject { // Reference() // Dereference() - void SetAttributes(const uint8_t* obj_attrs_ptr); + void SetAttributes(uint32_t obj_attributes_ptr); X_STATUS Wait(uint32_t wait_reason, uint32_t processor_mode, uint32_t alertable, uint64_t* opt_timeout); diff --git a/src/xenia/xbox.h b/src/xenia/xbox.h index 3f169541b..a14616631 100644 --- a/src/xenia/xbox.h +++ b/src/xenia/xbox.h @@ -139,6 +139,8 @@ typedef uint32_t X_HRESULT; #define X_INVALID_SOCKET (uint32_t)(~0) #define X_SOCKET_ERROR (uint32_t)(-1) +// clang-format on + enum X_FILE_ATTRIBUTES : uint32_t { X_FILE_ATTRIBUTE_NONE = 0x0000, X_FILE_ATTRIBUTE_READONLY = 0x0001, @@ -235,45 +237,53 @@ inline void XOverlappedSetExtendedError(void* ptr, uint32_t value) { xe::store_and_swap(&p[6], value); } -class X_ANSI_STRING { - private: - uint16_t length; - uint16_t maximum_length; - const char* buffer; +struct X_ANSI_STRING { + xe::be length; + xe::be maximum_length; + xe::be pointer; - public: - X_ANSI_STRING() { Zero(); } - X_ANSI_STRING(const uint8_t* base, uint32_t p) { Read(base, p); } - void Read(const uint8_t* base, uint32_t p) { - length = xe::load_and_swap(base + p); - maximum_length = xe::load_and_swap(base + p + 2); - if (maximum_length) { - buffer = (const char*)(base + xe::load_and_swap(base + p + 4)); - } else { - buffer = 0; - } - } - void Zero() { - length = maximum_length = 0; - buffer = 0; - } - char* Duplicate() { - if (!buffer || !length) { + static X_ANSI_STRING* Translate(uint8_t* membase, uint32_t guest_address) { + if (!guest_address) { return nullptr; } - auto copy = (char*)calloc(length + 1, sizeof(char)); - std::strncpy(copy, buffer, length); - return copy; + return reinterpret_cast(membase + guest_address); } - std::string to_string() { - if (!buffer || !length) { + + static X_ANSI_STRING* TranslateIndirect(uint8_t* membase, + uint32_t guest_address_ptr) { + if (!guest_address_ptr) { + return nullptr; + } + uint32_t guest_address = + xe::load_and_swap(membase + guest_address_ptr); + return Translate(membase, guest_address); + } + + static std::string to_string(uint8_t* membase, uint32_t guest_address) { + auto str = Translate(membase, guest_address); + return str ? str->to_string(membase) : ""; + } + + static std::string to_string_indirect(uint8_t* membase, + uint32_t guest_address_ptr) { + auto str = TranslateIndirect(membase, guest_address_ptr); + return str ? str->to_string(membase) : ""; + } + + void reset() { + length = 0; + maximum_length = 0; + pointer = 0; + } + + std::string to_string(uint8_t* membase) const { + if (!length) { return ""; } - std::string result(buffer, length); - return result; + return std::string(reinterpret_cast(membase + pointer), + length); } }; -// static_assert_size(X_ANSI_STRING, 8); // http://pastebin.com/SMypYikG typedef uint32_t XNotificationID;