83 lines
2.7 KiB
C++
83 lines
2.7 KiB
C++
#include "prx/libc/include/Shutdown.hpp"
|
|
#include "prx/libc/include/general/VabiMacros.hpp"
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
#include <filesystem>
|
|
#include <string>
|
|
#include <system_error>
|
|
#include <stdexcept>
|
|
#include <windows.h>
|
|
|
|
extern "C" int APS5_VABI sceSystemServiceLoadExec(const char*, const char* const*);
|
|
|
|
namespace {
|
|
|
|
void Require(bool value) {
|
|
if (!value) std::abort();
|
|
}
|
|
|
|
[[noreturn]] void UnexpectedLaunch() {
|
|
std::_Exit(86);
|
|
}
|
|
|
|
int Probe(const char* name) {
|
|
LibcRegisterShutdown_nid_postfix(UnexpectedLaunch);
|
|
const std::string path = std::string("/app0/..\\") + name;
|
|
try {
|
|
sceSystemServiceLoadExec(path.c_str(), nullptr);
|
|
} catch (const std::runtime_error& error) {
|
|
return std::string(error.what()).find(path) != std::string::npos ? 0 : 2;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
DWORD RunProbe(const std::filesystem::path& executable, const std::string& name) {
|
|
STARTUPINFOW startup{};
|
|
startup.cb = sizeof(startup);
|
|
PROCESS_INFORMATION process{};
|
|
std::wstring command = L"\"" + executable.wstring() + L"\" --probe ";
|
|
command.append(name.begin(), name.end());
|
|
Require(CreateProcessW(executable.c_str(), command.data(), nullptr, nullptr, TRUE, 0, nullptr, nullptr, &startup, &process) != 0);
|
|
const DWORD waitResult = WaitForSingleObject(process.hProcess, 10000);
|
|
if (waitResult != WAIT_OBJECT_0) {
|
|
TerminateProcess(process.hProcess, ERROR_TIMEOUT);
|
|
WaitForSingleObject(process.hProcess, 5000);
|
|
CloseHandle(process.hThread);
|
|
CloseHandle(process.hProcess);
|
|
return ERROR_TIMEOUT;
|
|
}
|
|
DWORD code = 1;
|
|
if (!GetExitCodeProcess(process.hProcess, &code)) code = ERROR_GEN_FAILURE;
|
|
CloseHandle(process.hThread);
|
|
CloseHandle(process.hProcess);
|
|
return code;
|
|
}
|
|
|
|
int Test() {
|
|
std::wstring executable(32768, L'\0');
|
|
const DWORD length = GetModuleFileNameW(nullptr, executable.data(), static_cast<DWORD>(executable.size()));
|
|
Require(length > 0 && length < executable.size());
|
|
executable.resize(length);
|
|
const std::filesystem::path own(executable);
|
|
const std::string name = "anyps5-path-boundary-" + std::to_string(GetCurrentProcessId()) + "-" + std::to_string(GetTickCount64());
|
|
const auto fixture = own.parent_path().parent_path() / (name + own.extension().string());
|
|
struct Cleanup {
|
|
std::filesystem::path path;
|
|
~Cleanup() {
|
|
std::error_code error;
|
|
std::filesystem::remove(path, error);
|
|
}
|
|
} cleanup{fixture};
|
|
std::filesystem::copy_file(own, fixture);
|
|
Require(RunProbe(own, name) == 0);
|
|
return 0;
|
|
}
|
|
|
|
}
|
|
|
|
int main(int argc, char** argv) {
|
|
if (argc == 3 && std::strcmp(argv[1], "--probe") == 0) return Probe(argv[2]);
|
|
Require(argc == 1);
|
|
return Test();
|
|
}
|