From c4e2ad37ff710557b9c6156851156d3aa38806d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 3 Oct 2023 12:00:59 +0200 Subject: [PATCH] Windows: Avoid loading shell libraries during startup. --- Windows/W32Util/Misc.cpp | 28 ++++++++++++++++++++++++++++ Windows/W32Util/Misc.h | 1 + Windows/main.cpp | 23 ++++------------------- 3 files changed, 33 insertions(+), 19 deletions(-) diff --git a/Windows/W32Util/Misc.cpp b/Windows/W32Util/Misc.cpp index da061903c2..0583c5963f 100644 --- a/Windows/W32Util/Misc.cpp +++ b/Windows/W32Util/Misc.cpp @@ -168,6 +168,34 @@ namespace W32Util ExitProcess(0); } + bool ExecuteAndGetReturnCode(const wchar_t *executable, const wchar_t *cmdline, const wchar_t *currentDirectory, DWORD *exitCode) { + PROCESS_INFORMATION processInformation = { 0 }; + STARTUPINFO startupInfo = { 0 }; + startupInfo.cb = sizeof(startupInfo); + + std::wstring cmdlineW; + cmdlineW += L"PPSSPP "; // could also put the executable name as first argument, but concerned about escaping. + cmdlineW += cmdline; + + // Create the process + bool result = CreateProcess(executable, (LPWSTR)cmdlineW.c_str(), + NULL, NULL, FALSE, + NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW, + NULL, currentDirectory, &startupInfo, &processInformation); + + if (!result) { + // We failed. + return false; + } + + // Successfully created the process. Wait for it to finish. + WaitForSingleObject(processInformation.hProcess, INFINITE); + result = GetExitCodeProcess(processInformation.hProcess, exitCode); + CloseHandle(processInformation.hProcess); + CloseHandle(processInformation.hThread); + return result != 0; + } + void SpawnNewInstance(bool overrideArgs, const std::string &args) { // This preserves arguments (for example, config file) and working directory. std::wstring workingDirectory; diff --git a/Windows/W32Util/Misc.h b/Windows/W32Util/Misc.h index 4e0dbf6d58..cd20db75ea 100644 --- a/Windows/W32Util/Misc.h +++ b/Windows/W32Util/Misc.h @@ -14,6 +14,7 @@ namespace W32Util void MakeTopMost(HWND hwnd, bool topMost); void ExitAndRestart(bool overrideArgs = false, const std::string &args = ""); void SpawnNewInstance(bool overrideArgs = false, const std::string &args = ""); + bool ExecuteAndGetReturnCode(const wchar_t *executable, const wchar_t *cmdline, const wchar_t *currentDirectory, DWORD *exitCode); void GetSelfExecuteParams(std::wstring &workingDirectory, std::wstring &moduleFilename); void GetWindowRes(HWND hWnd, int *xres, int *yres); diff --git a/Windows/main.cpp b/Windows/main.cpp index 8fa045b24d..bea08fe54e 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -694,28 +694,13 @@ static bool DetectVulkanInExternalProcess() { const wchar_t *cmdline = L"--vulkan-available-check"; - SHELLEXECUTEINFO info{ sizeof(SHELLEXECUTEINFO) }; - info.fMask = SEE_MASK_NOCLOSEPROCESS; - info.lpFile = moduleFilename.c_str(); - info.lpParameters = cmdline; - info.lpDirectory = workingDirectory.c_str(); - info.nShow = SW_HIDE; - if (ShellExecuteEx(&info) != TRUE) { - return false; - } - if (info.hProcess == nullptr) { - return false; - } - - DWORD result = WaitForSingleObject(info.hProcess, 10000); DWORD exitCode = 0; - if (result == WAIT_FAILED || GetExitCodeProcess(info.hProcess, &exitCode) == 0) { - CloseHandle(info.hProcess); + if (W32Util::ExecuteAndGetReturnCode(moduleFilename.c_str(), cmdline, workingDirectory.c_str(), &exitCode)) { + return exitCode == EXIT_CODE_VULKAN_WORKS; + } else { + ERROR_LOG(G3D, "Failed to detect Vulkan in external process somehow"); return false; } - CloseHandle(info.hProcess); - - return exitCode == EXIT_CODE_VULKAN_WORKS; } #endif