Stratosphere: Add handle/pid output to IPC templating, fix failure condition message preparation.

This commit is contained in:
Michael Scire 2018-04-21 05:17:31 -06:00
parent b6ba7b94b9
commit 878d68f7e0
3 changed files with 44 additions and 16 deletions

View file

@ -105,9 +105,14 @@ struct is_ipc_buffer {
|| is_specialization_of<T, OutPointerWithClientSize>::value; || is_specialization_of<T, OutPointerWithClientSize>::value;
}; };
template <typename T>
struct is_ipc_handle {
static const size_t value = (std::is_same<T, MovedHandle>::value || std::is_same<T, CopiedHandle>::value) ? 1 : 0;
};
template <typename T> template <typename T>
struct size_in_raw_data { struct size_in_raw_data {
static const size_t value = (is_ipc_buffer<T>::value) ? 0 : ((sizeof(T) < sizeof(u32)) ? sizeof(u32) : (sizeof(T) + 3) & (~3)); static const size_t value = (is_ipc_buffer<T>::value || is_ipc_handle<T>::value) ? 0 : ((sizeof(T) < sizeof(u32)) ? sizeof(u32) : (sizeof(T) + 3) & (~3));
}; };
template <typename ...Args> template <typename ...Args>
@ -165,12 +170,6 @@ struct num_inoutbuffers_in_arguments {
static const size_t value = (is_ipc_inoutbuffer<Args>::value + ... + 0); static const size_t value = (is_ipc_inoutbuffer<Args>::value + ... + 0);
}; };
template <typename T>
struct is_ipc_handle {
static const size_t value = (std::is_same<T, MovedHandle>::value || std::is_same<T, CopiedHandle>::value) ? 1 : 0;
};
template <typename ...Args> template <typename ...Args>
struct num_handles_in_arguments { struct num_handles_in_arguments {
static const size_t value = (is_ipc_handle<Args>::value + ... + 0); static const size_t value = (is_ipc_handle<Args>::value + ... + 0);
@ -329,6 +328,26 @@ constexpr size_t GetAndUpdateOffsetIntoRawData(size_t& offset) {
return old; return old;
} }
template<typename T>
void EncodeValueIntoIpcMessageBeforePrepare(IpcCommand *c, T value) {
if constexpr (std::is_same<T, MovedHandle>::value) {
ipcSendHandleMove(c, value.handle);
} else if constexpr (std::is_same<T, CopiedHandle>::value) {
ipcSendHandleCopy(c, value.handle);
} else if constexpr (std::is_same<T, PidDescriptor>::value) {
ipcSendPid(c);
}
}
template<typename T>
void EncodeValueIntoIpcMessageAfterPrepare(u8 *cur_out, T value) {
if constexpr (is_ipc_handle<T>::value || std::is_same<T, PidDescriptor>::value) {
/* Do nothing. */
} else {
*((T *)(cur_out)) = value;
}
}
template<typename... Args> template<typename... Args>
struct Encoder<std::tuple<Args...>> { struct Encoder<std::tuple<Args...>> {
IpcCommand &out_command; IpcCommand &out_command;
@ -339,7 +358,9 @@ struct Encoder<std::tuple<Args...>> {
u8 *tls = (u8 *)armGetTls(); u8 *tls = (u8 *)armGetTls();
std::fill(tls, tls + 0x100, 0x100); std::fill(tls, tls + 0x100, 0x00);
((EncodeValueIntoIpcMessageBeforePrepare<Args>(&out_command, args)), ...);
/* Remove the extra space resulting from first Result type. */ /* Remove the extra space resulting from first Result type. */
struct { struct {
@ -351,13 +372,19 @@ struct Encoder<std::tuple<Args...>> {
u8 *raw_data = (u8 *)&raw->result; u8 *raw_data = (u8 *)&raw->result;
((*((Args *)(raw_data + GetAndUpdateOffsetIntoRawData<Args>(offset))) = (args)), ...); ((EncodeValueIntoIpcMessageAfterPrepare<Args>(raw_data + GetAndUpdateOffsetIntoRawData<Args>(offset), args)), ...);
if (R_FAILED(raw->result)) { Result rc = raw->result;
ipcPrepareHeader(&out_command, sizeof(raw));
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;
} }
}; };

View file

@ -28,9 +28,10 @@ Result ProcessManagerService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u
return rc; return rc;
} }
std::tuple<Result> ProcessManagerService::create_process() { std::tuple<Result, MovedHandle> ProcessManagerService::create_process(u64 flags, u64 title_id, CopiedHandle reslimit_h) {
/* TODO */ /* 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<Result> ProcessManagerService::get_program_info(Registration::TidSid tid_sid, OutPointerWithServerSize<ProcessManagerService::ProgramInfo, 0x1> out_program_info) { std::tuple<Result> ProcessManagerService::get_program_info(Registration::TidSid tid_sid, OutPointerWithServerSize<ProcessManagerService::ProgramInfo, 0x1> out_program_info) {

View file

@ -32,7 +32,7 @@ class ProcessManagerService : IServiceObject {
private: private:
/* Actual commands. */ /* Actual commands. */
std::tuple<Result> create_process(); std::tuple<Result, MovedHandle> create_process(u64 flags, u64 title_id, CopiedHandle reslimit_h);
std::tuple<Result> get_program_info(Registration::TidSid tid_sid, OutPointerWithServerSize<ProcessManagerService::ProgramInfo, 0x1> out_program_info); std::tuple<Result> get_program_info(Registration::TidSid tid_sid, OutPointerWithServerSize<ProcessManagerService::ProgramInfo, 0x1> out_program_info);
std::tuple<Result, u64> register_title(Registration::TidSid tid_sid); std::tuple<Result, u64> register_title(Registration::TidSid tid_sid);
std::tuple<Result> unregister_title(u64 index); std::tuple<Result> unregister_title(u64 index);