mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-23 12:26:56 +02:00
implement LoadExec (windows)
This commit is contained in:
committed by
nmzik
parent
4084a008ea
commit
6f0cddd440
@@ -83,7 +83,8 @@ struct ConfigOptions {
|
|||||||
bool red_zone_protection_enabled = false;
|
bool red_zone_protection_enabled = false;
|
||||||
#endif
|
#endif
|
||||||
Keymap keymap;
|
Keymap keymap;
|
||||||
std::vector<std::string> guest_arguments;
|
// Ordinary boots need a non-null argv[0]; --guest-exec supplies the caller's arguments.
|
||||||
|
std::vector<std::string> guest_arguments {""};
|
||||||
};
|
};
|
||||||
|
|
||||||
void Load(const ConfigOptions& cfg);
|
void Load(const ConfigOptions& cfg);
|
||||||
|
|||||||
+85
-18
@@ -1,59 +1,126 @@
|
|||||||
#include "emulator.h"
|
|
||||||
|
|
||||||
#include "common/file.h"
|
#include "common/file.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
|
#include "emulator.h"
|
||||||
#include "kernel/fileSystem.h"
|
#include "kernel/fileSystem.h"
|
||||||
#include "libs/errno.h"
|
#include "libs/errno.h"
|
||||||
|
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#if KYTY_PLATFORM == KYTY_PLATFORM_LINUX
|
#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <windows.h>
|
||||||
|
#elif KYTY_PLATFORM == KYTY_PLATFORM_LINUX
|
||||||
#include <linux/close_range.h>
|
#include <linux/close_range.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace Emulator {
|
namespace Emulator {
|
||||||
|
|
||||||
|
#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS
|
||||||
|
static std::wstring QuoteArgument(std::wstring_view argument) {
|
||||||
|
std::wstring quoted = L"\"";
|
||||||
|
size_t slashes = 0;
|
||||||
|
for (wchar_t c: argument) {
|
||||||
|
if (c == L'\\') {
|
||||||
|
++slashes;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
quoted.append(c == L'"' ? slashes * 2 + 1 : slashes, L'\\');
|
||||||
|
quoted += c;
|
||||||
|
slashes = 0;
|
||||||
|
}
|
||||||
|
quoted.append(slashes * 2, L'\\');
|
||||||
|
return quoted + L'"';
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int LoadExec(const char* path, const char* const argv[]) {
|
int LoadExec(const char* path, const char* const argv[]) {
|
||||||
using namespace Libs::SystemService;
|
using namespace Libs::SystemService;
|
||||||
if (path == nullptr || !std::string_view(path).starts_with("/app0/") ||
|
if (path == nullptr || !std::string_view(path).starts_with("/app0/") ||
|
||||||
!Common::File::IsFileExisting(Libs::LibKernel::FileSystem::GetRealFilename(path))) {
|
!Common::File::IsFileExisting(Libs::LibKernel::FileSystem::GetRealFilename(path))) {
|
||||||
return SYSTEM_SERVICE_ERROR_PARAMETER;
|
return SYSTEM_SERVICE_ERROR_PARAMETER;
|
||||||
}
|
}
|
||||||
#if KYTY_PLATFORM == KYTY_PLATFORM_LINUX
|
#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS || KYTY_PLATFORM == KYTY_PLATFORM_LINUX
|
||||||
std::ifstream command("/proc/self/cmdline", std::ios::binary);
|
std::vector<std::string> arguments {"--guest-exec", path};
|
||||||
std::vector<std::string> arguments;
|
size_t bytes = 0;
|
||||||
for (std::string argument; std::getline(command, argument, '\0') && argument != "--guest-exec";) {
|
|
||||||
arguments.push_back(std::move(argument));
|
|
||||||
}
|
|
||||||
if (arguments.empty()) {
|
|
||||||
return SYSTEM_SERVICE_ERROR_INTERNAL;
|
|
||||||
}
|
|
||||||
arguments.insert(arguments.end(), {"--guest-exec", path});
|
|
||||||
size_t bytes = 0;
|
|
||||||
for (size_t i = 0; argv != nullptr && argv[i] != nullptr; ++i) {
|
for (size_t i = 0; argv != nullptr && argv[i] != nullptr; ++i) {
|
||||||
const auto size = strnlen(argv[i], 4096 - bytes) + 1;
|
const auto size = strnlen(argv[i], 4096 - bytes) + 1;
|
||||||
if (size > 4096 - bytes) {
|
if (size > 4096 - bytes) {
|
||||||
return SYSTEM_SERVICE_ERROR_PARAMETER;
|
return SYSTEM_SERVICE_ERROR_PARAMETER;
|
||||||
}
|
}
|
||||||
bytes += size;
|
bytes += size;
|
||||||
arguments.emplace_back(argv[i]);
|
arguments.emplace_back(argv[i], size - 1);
|
||||||
}
|
}
|
||||||
|
LOGF("LoadExec: %s\n", path);
|
||||||
|
Log::Flush();
|
||||||
|
#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS
|
||||||
|
wchar_t executable[32768] {};
|
||||||
|
const auto length = GetModuleFileNameW(nullptr, executable, 32768);
|
||||||
|
if (length == 0 || length >= 32768) {
|
||||||
|
return SYSTEM_SERVICE_ERROR_INTERNAL;
|
||||||
|
}
|
||||||
|
if (__wargv == nullptr) {
|
||||||
|
return SYSTEM_SERVICE_ERROR_INTERNAL;
|
||||||
|
}
|
||||||
|
std::wstring command = QuoteArgument(executable);
|
||||||
|
for (int i = 1; i < __argc && __wargv[i] != nullptr; ++i) {
|
||||||
|
if (std::wstring_view(__wargv[i]) == L"--guest-exec") {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
command += L" " + QuoteArgument(__wargv[i]);
|
||||||
|
}
|
||||||
|
for (const auto& argument: arguments) {
|
||||||
|
const int size =
|
||||||
|
MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, argument.c_str(), -1, nullptr, 0);
|
||||||
|
if (size == 0) {
|
||||||
|
return SYSTEM_SERVICE_ERROR_PARAMETER;
|
||||||
|
}
|
||||||
|
std::wstring wide(size, L'\0');
|
||||||
|
if (MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, argument.c_str(), -1, wide.data(),
|
||||||
|
size) == 0) {
|
||||||
|
return SYSTEM_SERVICE_ERROR_PARAMETER;
|
||||||
|
}
|
||||||
|
wide.resize(size - 1);
|
||||||
|
command += L" " + QuoteArgument(wide);
|
||||||
|
}
|
||||||
|
STARTUPINFOW startup {};
|
||||||
|
startup.cb = sizeof(startup);
|
||||||
|
PROCESS_INFORMATION process {};
|
||||||
|
if (!CreateProcessW(executable, command.data(), nullptr, nullptr, FALSE, CREATE_NO_WINDOW,
|
||||||
|
nullptr, nullptr, &startup, &process)) {
|
||||||
|
LOGF("LoadExec: process creation failed: %lu\n", GetLastError());
|
||||||
|
return SYSTEM_SERVICE_ERROR_INTERNAL;
|
||||||
|
}
|
||||||
|
CloseHandle(process.hThread);
|
||||||
|
CloseHandle(process.hProcess);
|
||||||
|
std::fflush(nullptr);
|
||||||
|
std::quick_exit(0);
|
||||||
|
#else
|
||||||
|
std::ifstream command("/proc/self/cmdline", std::ios::binary);
|
||||||
|
std::vector<std::string> host_arguments;
|
||||||
|
for (std::string argument;
|
||||||
|
std::getline(command, argument, '\0') && argument != "--guest-exec";) {
|
||||||
|
host_arguments.push_back(std::move(argument));
|
||||||
|
}
|
||||||
|
if (host_arguments.empty()) {
|
||||||
|
return SYSTEM_SERVICE_ERROR_INTERNAL;
|
||||||
|
}
|
||||||
|
host_arguments.insert(host_arguments.end(), arguments.begin(), arguments.end());
|
||||||
std::vector<char*> host_argv;
|
std::vector<char*> host_argv;
|
||||||
for (auto& argument: arguments) {
|
for (auto& argument: host_arguments) {
|
||||||
host_argv.push_back(argument.data());
|
host_argv.push_back(argument.data());
|
||||||
}
|
}
|
||||||
host_argv.push_back(nullptr);
|
host_argv.push_back(nullptr);
|
||||||
LOGF("LoadExec: %s\n", path);
|
|
||||||
Log::Flush();
|
|
||||||
if (close_range(3, ~0u, CLOSE_RANGE_UNSHARE | CLOSE_RANGE_CLOEXEC) == 0) {
|
if (close_range(3, ~0u, CLOSE_RANGE_UNSHARE | CLOSE_RANGE_CLOEXEC) == 0) {
|
||||||
execvp(host_argv[0], host_argv.data());
|
execvp(host_argv[0], host_argv.data());
|
||||||
}
|
}
|
||||||
LOGF("LoadExec failed: %s\n", std::strerror(errno));
|
LOGF("LoadExec failed: %s\n", std::strerror(errno));
|
||||||
|
#endif
|
||||||
return SYSTEM_SERVICE_ERROR_INTERNAL;
|
return SYSTEM_SERVICE_ERROR_INTERNAL;
|
||||||
#else
|
#else
|
||||||
return SYSTEM_SERVICE_ERROR_UNAVAILABLE;
|
return SYSTEM_SERVICE_ERROR_UNAVAILABLE;
|
||||||
|
|||||||
Reference in New Issue
Block a user