diff --git a/stratosphere/loader/source/ipc_templating.hpp b/stratosphere/loader/source/ipc_templating.hpp index 2bafb7a7e..eb9504851 100644 --- a/stratosphere/loader/source/ipc_templating.hpp +++ b/stratosphere/loader/source/ipc_templating.hpp @@ -105,9 +105,14 @@ struct is_ipc_buffer { || is_specialization_of::value; }; +template +struct is_ipc_handle { + static const size_t value = (std::is_same::value || std::is_same::value) ? 1 : 0; +}; + template struct size_in_raw_data { - static const size_t value = (is_ipc_buffer::value) ? 0 : ((sizeof(T) < sizeof(u32)) ? sizeof(u32) : (sizeof(T) + 3) & (~3)); + static const size_t value = (is_ipc_buffer::value || is_ipc_handle::value) ? 0 : ((sizeof(T) < sizeof(u32)) ? sizeof(u32) : (sizeof(T) + 3) & (~3)); }; template @@ -165,12 +170,6 @@ struct num_inoutbuffers_in_arguments { static const size_t value = (is_ipc_inoutbuffer::value + ... + 0); }; - -template -struct is_ipc_handle { - static const size_t value = (std::is_same::value || std::is_same::value) ? 1 : 0; -}; - template struct num_handles_in_arguments { static const size_t value = (is_ipc_handle::value + ... + 0); @@ -329,6 +328,26 @@ constexpr size_t GetAndUpdateOffsetIntoRawData(size_t& offset) { return old; } +template +void EncodeValueIntoIpcMessageBeforePrepare(IpcCommand *c, T value) { + if constexpr (std::is_same::value) { + ipcSendHandleMove(c, value.handle); + } else if constexpr (std::is_same::value) { + ipcSendHandleCopy(c, value.handle); + } else if constexpr (std::is_same::value) { + ipcSendPid(c); + } +} + +template +void EncodeValueIntoIpcMessageAfterPrepare(u8 *cur_out, T value) { + if constexpr (is_ipc_handle::value || std::is_same::value) { + /* Do nothing. */ + } else { + *((T *)(cur_out)) = value; + } +} + template struct Encoder> { IpcCommand &out_command; @@ -339,7 +358,9 @@ struct Encoder> { u8 *tls = (u8 *)armGetTls(); - std::fill(tls, tls + 0x100, 0x100); + std::fill(tls, tls + 0x100, 0x00); + + ((EncodeValueIntoIpcMessageBeforePrepare(&out_command, args)), ...); /* Remove the extra space resulting from first Result type. */ struct { @@ -350,14 +371,20 @@ struct Encoder> { raw->magic = SFCO_MAGIC; u8 *raw_data = (u8 *)&raw->result; - - ((*((Args *)(raw_data + GetAndUpdateOffsetIntoRawData(offset))) = (args)), ...); - if (R_FAILED(raw->result)) { - ipcPrepareHeader(&out_command, sizeof(raw)); + ((EncodeValueIntoIpcMessageAfterPrepare(raw_data + GetAndUpdateOffsetIntoRawData(offset), args)), ...); + + Result rc = raw->result; + + if (R_FAILED(rc)) { + std::fill(tls, tls + 0x100, 0x00); + ipcInitialize(&out_command); + raw = (decltype(raw))ipcPrepareHeader(&out_command, sizeof(raw)); + raw->magic = SFCO_MAGIC; + raw->result = rc; } - return raw->result; + return rc; } }; diff --git a/stratosphere/loader/source/ldr_process_manager.cpp b/stratosphere/loader/source/ldr_process_manager.cpp index c22494311..a26c4f1c2 100644 --- a/stratosphere/loader/source/ldr_process_manager.cpp +++ b/stratosphere/loader/source/ldr_process_manager.cpp @@ -28,9 +28,10 @@ Result ProcessManagerService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u return rc; } -std::tuple ProcessManagerService::create_process() { +std::tuple ProcessManagerService::create_process(u64 flags, u64 title_id, CopiedHandle reslimit_h) { /* TODO */ - return std::make_tuple(0xF601); + fprintf(stderr, "CreateProcess(%016lx, %016lx, %08x);\n", flags, title_id, reslimit_h.handle); + return std::make_tuple(0xF601, MovedHandle{0x00}); } std::tuple ProcessManagerService::get_program_info(Registration::TidSid tid_sid, OutPointerWithServerSize out_program_info) { diff --git a/stratosphere/loader/source/ldr_process_manager.hpp b/stratosphere/loader/source/ldr_process_manager.hpp index 79a4205f9..8f3af5667 100644 --- a/stratosphere/loader/source/ldr_process_manager.hpp +++ b/stratosphere/loader/source/ldr_process_manager.hpp @@ -32,7 +32,7 @@ class ProcessManagerService : IServiceObject { private: /* Actual commands. */ - std::tuple create_process(); + std::tuple create_process(u64 flags, u64 title_id, CopiedHandle reslimit_h); std::tuple get_program_info(Registration::TidSid tid_sid, OutPointerWithServerSize out_program_info); std::tuple register_title(Registration::TidSid tid_sid); std::tuple unregister_title(u64 index);