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;
};
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>
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>
@ -165,12 +170,6 @@ struct num_inoutbuffers_in_arguments {
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>
struct num_handles_in_arguments {
static const size_t value = (is_ipc_handle<Args>::value + ... + 0);
@ -329,6 +328,26 @@ constexpr size_t GetAndUpdateOffsetIntoRawData(size_t& offset) {
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>
struct Encoder<std::tuple<Args...>> {
IpcCommand &out_command;
@ -339,7 +358,9 @@ struct Encoder<std::tuple<Args...>> {
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. */
struct {
@ -350,14 +371,20 @@ struct Encoder<std::tuple<Args...>> {
raw->magic = SFCO_MAGIC;
u8 *raw_data = (u8 *)&raw->result;
((*((Args *)(raw_data + GetAndUpdateOffsetIntoRawData<Args>(offset))) = (args)), ...);
if (R_FAILED(raw->result)) {
ipcPrepareHeader(&out_command, sizeof(raw));
((EncodeValueIntoIpcMessageAfterPrepare<Args>(raw_data + GetAndUpdateOffsetIntoRawData<Args>(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;
}
};

View file

@ -28,9 +28,10 @@ Result ProcessManagerService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u
return rc;
}
std::tuple<Result> ProcessManagerService::create_process() {
std::tuple<Result, MovedHandle> 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<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:
/* 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, u64> register_title(Registration::TidSid tid_sid);
std::tuple<Result> unregister_title(u64 index);