From 40145b8dbb6ed41abb3bcf51b50cf5cc75543e5c Mon Sep 17 00:00:00 2001 From: emoose Date: Sat, 17 Nov 2018 23:47:53 +0000 Subject: [PATCH] [Kernel] Implement XamProfileEnumerate functions --- src/xenia/kernel/xam/xam_user.cc | 99 ++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) diff --git a/src/xenia/kernel/xam/xam_user.cc b/src/xenia/kernel/xam/xam_user.cc index 3cdc35425..96aac1f61 100644 --- a/src/xenia/kernel/xam/xam_user.cc +++ b/src/xenia/kernel/xam/xam_user.cc @@ -21,6 +21,105 @@ namespace xe { namespace kernel { namespace xam { +// from https://github.com/xemio/testdev/blob/master/xkelib/xam/_xamext.h +#pragma pack(push, 4) +struct X_XAMACCOUNTINFO { + xe::be reserved; + xe::be live_flags; + wchar_t gamertag[0x10]; + xe::be xuid_online; // 09.... + xe::be user_flags; + xe::be network_id; + char passcode[4]; + char online_domain[0x14]; + char online_kerberos_realm[0x18]; + char online_key[0x10]; + char passport_membername[0x72]; + char passport_password[0x20]; + char owner_passport_membername[0x72]; +}; +static_assert_size(X_XAMACCOUNTINFO, 0x17C); +#pragma pack(pop) + +struct X_PROFILEENUMRESULT { + xe::be xuid_offline; // E0..... + X_XAMACCOUNTINFO account; + xe::be device_id; +}; +static_assert_size(X_PROFILEENUMRESULT, 0x188); + +dword_result_t XamProfileCreateEnumerator(dword_t device_id, + lpdword_t handle_out) { + assert_not_null(handle_out); + + auto e = + new XStaticEnumerator(kernel_state(), 1, sizeof(X_PROFILEENUMRESULT)); + + e->Initialize(); + + const auto& user_profile = kernel_state()->user_profile(); + + X_PROFILEENUMRESULT* profile = (X_PROFILEENUMRESULT*)e->AppendItem(); + memset(profile, 0, sizeof(X_PROFILEENUMRESULT)); + profile->xuid_offline = user_profile->xuid(); + profile->device_id = 0xF00D0000; + + auto tag = xe::to_wstring(user_profile->name()); + xe::copy_and_swap(profile->account.gamertag, tag.c_str(), + tag.length()); + profile->account.xuid_online = user_profile->xuid(); + + *handle_out = e->handle(); + return X_ERROR_SUCCESS; +} +DECLARE_XAM_EXPORT(XamProfileCreateEnumerator, + ExportTag::kUserProfiles | ExportTag::kImplemented); + +dword_result_t XamProfileEnumerate(dword_t handle, dword_t flags, + lpvoid_t buffer, + pointer_t overlapped) { + assert_true(flags == 0); + + auto e = kernel_state()->object_table()->LookupObject(handle); + if (!e) { + if (overlapped) { + kernel_state()->CompleteOverlappedImmediateEx( + overlapped, X_ERROR_INVALID_HANDLE, X_ERROR_INVALID_HANDLE, 0); + return X_ERROR_IO_PENDING; + } else { + return X_ERROR_INVALID_HANDLE; + } + } + + buffer.Zero(sizeof(X_PROFILEENUMRESULT)); + + X_RESULT result; + + if (e->current_item() >= e->item_count()) { + result = X_ERROR_NO_MORE_FILES; + } else { + auto item_buffer = buffer.as(); + if (!e->WriteItem(item_buffer)) { + result = X_ERROR_NO_MORE_FILES; + } else { + result = X_ERROR_SUCCESS; + } + } + + // Return X_ERROR_NO_MORE_FILES in HRESULT form. + X_HRESULT extended_result = result != 0 ? X_HRESULT_FROM_WIN32(result) : 0; + if (overlapped) { + kernel_state()->CompleteOverlappedImmediateEx( + overlapped, result, extended_result, result == X_ERROR_SUCCESS ? 1 : 0); + return X_ERROR_IO_PENDING; + } else { + assert_always(); + return X_ERROR_INVALID_PARAMETER; + } +} +DECLARE_XAM_EXPORT(XamProfileEnumerate, + ExportTag::kUserProfiles | ExportTag::kImplemented); + X_HRESULT_result_t XamUserGetXUID(dword_t user_index, dword_t unk, lpqword_t xuid_ptr) { if (user_index) {