diff options
Diffstat (limited to 'platform')
-rw-r--r-- | platform/SCsub | 6 | ||||
-rw-r--r-- | platform/linuxbsd/freedesktop_portal_desktop.cpp | 17 | ||||
-rw-r--r-- | platform/windows/console_wrapper_windows.cpp | 4 | ||||
-rw-r--r-- | platform/windows/detect.py | 70 | ||||
-rw-r--r-- | platform/windows/display_server_windows.cpp | 46 | ||||
-rw-r--r-- | platform/windows/godot_res_wrap.rc | 5 | ||||
-rw-r--r-- | platform/windows/os_windows.cpp | 186 | ||||
-rw-r--r-- | platform/windows/os_windows.h | 1 |
8 files changed, 266 insertions, 69 deletions
diff --git a/platform/SCsub b/platform/SCsub index b07023efed..cdaa6074ba 100644 --- a/platform/SCsub +++ b/platform/SCsub @@ -15,12 +15,12 @@ def export_icon_builder(target, source, env): src_path = Path(str(source[0])) src_name = src_path.stem platform = src_path.parent.parent.stem - with open(str(source[0]), "rb") as file: - svg = "".join([f"\\{hex(x)[1:]}" for x in file.read()]) + with open(str(source[0]), "r") as file: + svg = file.read() with methods.generated_wrapper(target, prefix=platform) as file: file.write( f"""\ -static const char *_{platform}_{src_name}_svg = "{svg}"; +static const char *_{platform}_{src_name}_svg = {methods.to_raw_cstring(svg)}; """ ) diff --git a/platform/linuxbsd/freedesktop_portal_desktop.cpp b/platform/linuxbsd/freedesktop_portal_desktop.cpp index 671da7fc2a..2b98fda0d5 100644 --- a/platform/linuxbsd/freedesktop_portal_desktop.cpp +++ b/platform/linuxbsd/freedesktop_portal_desktop.cpp @@ -377,17 +377,26 @@ Error FreeDesktopPortalDesktop::file_dialog_show(DisplayServer::WindowID p_windo String flt = tokens[0].strip_edges(); if (!flt.is_empty()) { if (tokens.size() == 2) { - filter_exts.push_back(flt); + if (flt == "*.*") { + filter_exts.push_back("*"); + } else { + filter_exts.push_back(flt); + } filter_names.push_back(tokens[1]); } else { - filter_exts.push_back(flt); - filter_names.push_back(flt); + if (flt == "*.*") { + filter_exts.push_back("*"); + filter_names.push_back(RTR("All Files")); + } else { + filter_exts.push_back(flt); + filter_names.push_back(flt); + } } } } } if (filter_names.is_empty()) { - filter_exts.push_back("*.*"); + filter_exts.push_back("*"); filter_names.push_back(RTR("All Files")); } diff --git a/platform/windows/console_wrapper_windows.cpp b/platform/windows/console_wrapper_windows.cpp index 133711a9ea..1ba09b236b 100644 --- a/platform/windows/console_wrapper_windows.cpp +++ b/platform/windows/console_wrapper_windows.cpp @@ -40,8 +40,8 @@ int main(int argc, char *argv[]) { // Get executable name. - WCHAR exe_name[MAX_PATH] = {}; - if (!GetModuleFileNameW(nullptr, exe_name, MAX_PATH)) { + WCHAR exe_name[32767] = {}; + if (!GetModuleFileNameW(nullptr, exe_name, 32767)) { wprintf(L"GetModuleFileName failed, error %d\n", GetLastError()); return -1; } diff --git a/platform/windows/detect.py b/platform/windows/detect.py index 11dd4548f1..82a98655c0 100644 --- a/platform/windows/detect.py +++ b/platform/windows/detect.py @@ -13,40 +13,33 @@ if TYPE_CHECKING: # To match other platforms STACK_SIZE = 8388608 +STACK_SIZE_SANITIZERS = 30 * 1024 * 1024 def get_name(): return "Windows" -def try_cmd(test, prefix, arch): +def try_cmd(test, prefix, arch, check_clang=False): + archs = ["x86_64", "x86_32", "arm64", "arm32"] if arch: + archs = [arch] + + for a in archs: try: out = subprocess.Popen( - get_mingw_bin_prefix(prefix, arch) + test, + get_mingw_bin_prefix(prefix, a) + test, shell=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE, ) - out.communicate() + outs, errs = out.communicate() if out.returncode == 0: + if check_clang and not outs.startswith(b"clang"): + return False return True except Exception: pass - else: - for a in ["x86_64", "x86_32", "arm64", "arm32"]: - try: - out = subprocess.Popen( - get_mingw_bin_prefix(prefix, a) + test, - shell=True, - stderr=subprocess.PIPE, - stdout=subprocess.PIPE, - ) - out.communicate() - if out.returncode == 0: - return True - except Exception: - pass return False @@ -203,6 +196,7 @@ def get_opts(): BoolVariable("use_llvm", "Use the LLVM compiler", False), BoolVariable("use_static_cpp", "Link MinGW/MSVC C++ runtime libraries statically", True), BoolVariable("use_asan", "Use address sanitizer (ASAN)", False), + BoolVariable("use_ubsan", "Use LLVM compiler undefined behavior sanitizer (UBSAN)", False), BoolVariable("debug_crt", "Compile with MSVC's debug CRT (/MDd)", False), BoolVariable("incremental_link", "Use MSVC incremental linking. May increase or decrease build times.", False), BoolVariable("silence_msvc", "Silence MSVC's cl/link stdout bloat, redirecting any errors to stderr.", True), @@ -507,6 +501,7 @@ def configure_msvc(env: "SConsEnvironment", vcvars_msvc_config): if env["use_asan"]: env.extra_suffix += ".san" prebuilt_lib_extra_suffix = ".san" + env.AppendUnique(CPPDEFINES=["SANITIZERS_ENABLED"]) env.Append(CCFLAGS=["/fsanitize=address"]) env.Append(LINKFLAGS=["/INFERASANLIBS"]) @@ -628,7 +623,11 @@ def configure_msvc(env: "SConsEnvironment", vcvars_msvc_config): env["BUILDERS"]["Program"] = methods.precious_program env.Append(LINKFLAGS=["/NATVIS:platform\\windows\\godot.natvis"]) - env.AppendUnique(LINKFLAGS=["/STACK:" + str(STACK_SIZE)]) + + if env["use_asan"]: + env.AppendUnique(LINKFLAGS=["/STACK:" + str(STACK_SIZE_SANITIZERS)]) + else: + env.AppendUnique(LINKFLAGS=["/STACK:" + str(STACK_SIZE)]) def configure_mingw(env: "SConsEnvironment"): @@ -644,6 +643,10 @@ def configure_mingw(env: "SConsEnvironment"): if env["use_llvm"] and not try_cmd("clang --version", env["mingw_prefix"], env["arch"]): env["use_llvm"] = False + if not env["use_llvm"] and try_cmd("gcc --version", env["mingw_prefix"], env["arch"], True): + print("Detected GCC to be a wrapper for Clang.") + env["use_llvm"] = True + # TODO: Re-evaluate the need for this / streamline with common config. if env["target"] == "template_release": if env["arch"] != "arm64": @@ -721,7 +724,10 @@ def configure_mingw(env: "SConsEnvironment"): env.Append(CCFLAGS=["-flto"]) env.Append(LINKFLAGS=["-flto"]) - env.Append(LINKFLAGS=["-Wl,--stack," + str(STACK_SIZE)]) + if env["use_asan"]: + env.Append(LINKFLAGS=["-Wl,--stack," + str(STACK_SIZE_SANITIZERS)]) + else: + env.Append(LINKFLAGS=["-Wl,--stack," + str(STACK_SIZE)]) ## Compile flags @@ -732,6 +738,32 @@ def configure_mingw(env: "SConsEnvironment"): if not env["use_llvm"]: env.Append(CCFLAGS=["-mwindows"]) + if env["use_asan"] or env["use_ubsan"]: + if not env["use_llvm"]: + print("GCC does not support sanitizers on Windows.") + sys.exit(255) + if env["arch"] not in ["x86_32", "x86_64"]: + print("Sanitizers are only supported for x86_32 and x86_64.") + sys.exit(255) + + env.extra_suffix += ".san" + env.AppendUnique(CPPDEFINES=["SANITIZERS_ENABLED"]) + san_flags = [] + if env["use_asan"]: + san_flags.append("-fsanitize=address") + if env["use_ubsan"]: + san_flags.append("-fsanitize=undefined") + # Disable the vptr check since it gets triggered on any COM interface calls. + san_flags.append("-fno-sanitize=vptr") + env.Append(CFLAGS=san_flags) + env.Append(CCFLAGS=san_flags) + env.Append(LINKFLAGS=san_flags) + + if env["use_llvm"] and os.name == "nt" and methods._colorize: + env.Append(CCFLAGS=["$(-fansi-escape-codes$)", "$(-fcolor-diagnostics$)"]) + + env.Append(ARFLAGS=["--thin"]) + env.Append(CPPDEFINES=["WINDOWS_ENABLED", "WASAPI_ENABLED", "WINMIDI_ENABLED"]) env.Append( CPPDEFINES=[ diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index 6fa3f2c9d6..8bcd556c22 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -133,9 +133,17 @@ String DisplayServerWindows::get_name() const { } void DisplayServerWindows::_set_mouse_mode_impl(MouseMode p_mode) { + if (p_mode == MOUSE_MODE_HIDDEN || p_mode == MOUSE_MODE_CAPTURED || p_mode == MOUSE_MODE_CONFINED_HIDDEN) { + // Hide cursor before moving. + if (hCursor == nullptr) { + hCursor = SetCursor(nullptr); + } else { + SetCursor(nullptr); + } + } + if (windows.has(MAIN_WINDOW_ID) && (p_mode == MOUSE_MODE_CAPTURED || p_mode == MOUSE_MODE_CONFINED || p_mode == MOUSE_MODE_CONFINED_HIDDEN)) { // Mouse is grabbed (captured or confined). - WindowID window_id = _get_focused_window_or_popup(); if (!windows.has(window_id)) { window_id = MAIN_WINDOW_ID; @@ -165,13 +173,8 @@ void DisplayServerWindows::_set_mouse_mode_impl(MouseMode p_mode) { _register_raw_input_devices(INVALID_WINDOW_ID); } - if (p_mode == MOUSE_MODE_HIDDEN || p_mode == MOUSE_MODE_CAPTURED || p_mode == MOUSE_MODE_CONFINED_HIDDEN) { - if (hCursor == nullptr) { - hCursor = SetCursor(nullptr); - } else { - SetCursor(nullptr); - } - } else { + if (p_mode == MOUSE_MODE_VISIBLE || p_mode == MOUSE_MODE_CONFINED) { + // Show cursor. CursorShape c = cursor_shape; cursor_shape = CURSOR_MAX; cursor_set_shape(c); @@ -314,7 +317,7 @@ public: if (!lpw_path) { return S_FALSE; } - String path = String::utf16((const char16_t *)lpw_path).simplify_path(); + String path = String::utf16((const char16_t *)lpw_path).replace("\\", "/").trim_prefix(R"(\\?\)").simplify_path(); if (!path.begins_with(root.simplify_path())) { return S_FALSE; } @@ -539,7 +542,26 @@ void DisplayServerWindows::_thread_fd_monitor(void *p_ud) { pfd->SetOptions(flags | FOS_FORCEFILESYSTEM); pfd->SetTitle((LPCWSTR)fd->title.utf16().ptr()); - String dir = fd->current_directory.replace("/", "\\"); + String dir = ProjectSettings::get_singleton()->globalize_path(fd->current_directory); + if (dir == ".") { + dir = OS::get_singleton()->get_executable_path().get_base_dir(); + } + if (dir.is_relative_path() || dir == ".") { + Char16String current_dir_name; + size_t str_len = GetCurrentDirectoryW(0, nullptr); + current_dir_name.resize(str_len + 1); + GetCurrentDirectoryW(current_dir_name.size(), (LPWSTR)current_dir_name.ptrw()); + if (dir == ".") { + dir = String::utf16((const char16_t *)current_dir_name.get_data()).trim_prefix(R"(\\?\)").replace("\\", "/"); + } else { + dir = String::utf16((const char16_t *)current_dir_name.get_data()).trim_prefix(R"(\\?\)").replace("\\", "/").path_join(dir); + } + } + dir = dir.simplify_path(); + dir = dir.replace("/", "\\"); + if (!dir.is_network_share_path() && !dir.begins_with(R"(\\?\)")) { + dir = R"(\\?\)" + dir; + } IShellItem *shellitem = nullptr; hr = SHCreateItemFromParsingName((LPCWSTR)dir.utf16().ptr(), nullptr, IID_IShellItem, (void **)&shellitem); @@ -582,7 +604,7 @@ void DisplayServerWindows::_thread_fd_monitor(void *p_ud) { PWSTR file_path = nullptr; hr = result->GetDisplayName(SIGDN_FILESYSPATH, &file_path); if (SUCCEEDED(hr)) { - file_names.push_back(String::utf16((const char16_t *)file_path)); + file_names.push_back(String::utf16((const char16_t *)file_path).replace("\\", "/").trim_prefix(R"(\\?\)")); CoTaskMemFree(file_path); } result->Release(); @@ -596,7 +618,7 @@ void DisplayServerWindows::_thread_fd_monitor(void *p_ud) { PWSTR file_path = nullptr; hr = result->GetDisplayName(SIGDN_FILESYSPATH, &file_path); if (SUCCEEDED(hr)) { - file_names.push_back(String::utf16((const char16_t *)file_path)); + file_names.push_back(String::utf16((const char16_t *)file_path).replace("\\", "/").trim_prefix(R"(\\?\)")); CoTaskMemFree(file_path); } result->Release(); diff --git a/platform/windows/godot_res_wrap.rc b/platform/windows/godot_res_wrap.rc index 27ad26cbc5..61e6100497 100644 --- a/platform/windows/godot_res_wrap.rc +++ b/platform/windows/godot_res_wrap.rc @@ -1,6 +1,11 @@ #include "core/version.h" +#ifndef RT_MANIFEST +#define RT_MANIFEST 24 +#endif + GODOT_ICON ICON platform/windows/godot_console.ico +1 RT_MANIFEST "godot.manifest" 1 VERSIONINFO FILEVERSION VERSION_MAJOR,VERSION_MINOR,VERSION_PATCH,0 diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 40b265785f..bc42b234be 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -90,6 +90,23 @@ __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1; #define GetProcAddress (void *)GetProcAddress #endif +static String fix_path(const String &p_path) { + String path = p_path; + if (p_path.is_relative_path()) { + Char16String current_dir_name; + size_t str_len = GetCurrentDirectoryW(0, nullptr); + current_dir_name.resize(str_len + 1); + GetCurrentDirectoryW(current_dir_name.size(), (LPWSTR)current_dir_name.ptrw()); + path = String::utf16((const char16_t *)current_dir_name.get_data()).trim_prefix(R"(\\?\)").replace("\\", "/").path_join(path); + } + path = path.simplify_path(); + path = path.replace("/", "\\"); + if (!path.is_network_share_path() && !path.begins_with(R"(\\?\)")) { + path = R"(\\?\)" + path; + } + return path; +} + static String format_error_message(DWORD id) { LPWSTR messageBuffer = nullptr; size_t size = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, @@ -166,15 +183,9 @@ void OS_Windows::initialize_debugging() { static void _error_handler(void *p_self, const char *p_func, const char *p_file, int p_line, const char *p_error, const char *p_errorexp, bool p_editor_notify, ErrorHandlerType p_type) { String err_str; if (p_errorexp && p_errorexp[0]) { - err_str = String::utf8(p_errorexp); + err_str = String::utf8(p_errorexp) + "\n"; } else { - err_str = String::utf8(p_file) + ":" + itos(p_line) + " - " + String::utf8(p_error); - } - - if (p_editor_notify) { - err_str += " (User)\n"; - } else { - err_str += "\n"; + err_str = String::utf8(p_file) + ":" + itos(p_line) + " - " + String::utf8(p_error) + "\n"; } OutputDebugStringW((LPCWSTR)err_str.utf16().ptr()); @@ -306,7 +317,7 @@ Error OS_Windows::get_entropy(uint8_t *r_buffer, int p_bytes) { } #ifdef DEBUG_ENABLED -void debug_dynamic_library_check_dependencies(const String &p_root_path, const String &p_path, HashSet<String> &r_checked, HashSet<String> &r_missing) { +void debug_dynamic_library_check_dependencies(const String &p_path, HashSet<String> &r_checked, HashSet<String> &r_missing) { if (r_checked.has(p_path)) { return; } @@ -348,15 +359,15 @@ void debug_dynamic_library_check_dependencies(const String &p_root_path, const S const IMAGE_IMPORT_DESCRIPTOR *import_desc = (const IMAGE_IMPORT_DESCRIPTOR *)ImageDirectoryEntryToData((HMODULE)loaded_image.MappedAddress, false, IMAGE_DIRECTORY_ENTRY_IMPORT, &size); if (import_desc) { for (; import_desc->Name && import_desc->FirstThunk; import_desc++) { - char16_t full_name_wc[MAX_PATH]; + char16_t full_name_wc[32767]; const char *name_cs = (const char *)ImageRvaToVa(loaded_image.FileHeader, loaded_image.MappedAddress, import_desc->Name, nullptr); String name = String(name_cs); if (name.begins_with("api-ms-win-")) { r_checked.insert(name); - } else if (SearchPathW(nullptr, (LPCWSTR)name.utf16().get_data(), nullptr, MAX_PATH, (LPWSTR)full_name_wc, nullptr)) { - debug_dynamic_library_check_dependencies(p_root_path, String::utf16(full_name_wc), r_checked, r_missing); - } else if (SearchPathW((LPCWSTR)(p_path.get_base_dir().utf16().get_data()), (LPCWSTR)name.utf16().get_data(), nullptr, MAX_PATH, (LPWSTR)full_name_wc, nullptr)) { - debug_dynamic_library_check_dependencies(p_root_path, String::utf16(full_name_wc), r_checked, r_missing); + } else if (SearchPathW(nullptr, (LPCWSTR)name.utf16().get_data(), nullptr, 32767, (LPWSTR)full_name_wc, nullptr)) { + debug_dynamic_library_check_dependencies(String::utf16(full_name_wc), r_checked, r_missing); + } else if (SearchPathW((LPCWSTR)(p_path.get_base_dir().utf16().get_data()), (LPCWSTR)name.utf16().get_data(), nullptr, 32767, (LPWSTR)full_name_wc, nullptr)) { + debug_dynamic_library_check_dependencies(String::utf16(full_name_wc), r_checked, r_missing); } else { r_missing.insert(name); } @@ -373,7 +384,7 @@ void debug_dynamic_library_check_dependencies(const String &p_root_path, const S #endif Error OS_Windows::open_dynamic_library(const String &p_path, void *&p_library_handle, GDExtensionData *p_data) { - String path = p_path.replace("/", "\\"); + String path = p_path; if (!FileAccess::exists(path)) { //this code exists so gdextension can load .dll files from within the executable path @@ -419,11 +430,13 @@ Error OS_Windows::open_dynamic_library(const String &p_path, void *&p_library_ha bool has_dll_directory_api = ((add_dll_directory != nullptr) && (remove_dll_directory != nullptr)); DLL_DIRECTORY_COOKIE cookie = nullptr; + String dll_dir = ProjectSettings::get_singleton()->globalize_path(load_path.get_base_dir()); + String wpath = fix_path(dll_dir); if (p_data != nullptr && p_data->also_set_library_path && has_dll_directory_api) { - cookie = add_dll_directory((LPCWSTR)(load_path.get_base_dir().utf16().get_data())); + cookie = add_dll_directory((LPCWSTR)(wpath.get_base_dir().utf16().get_data())); } - p_library_handle = (void *)LoadLibraryExW((LPCWSTR)(load_path.utf16().get_data()), nullptr, (p_data != nullptr && p_data->also_set_library_path && has_dll_directory_api) ? LOAD_LIBRARY_SEARCH_DEFAULT_DIRS : 0); + p_library_handle = (void *)LoadLibraryExW((LPCWSTR)(wpath.utf16().get_data()), nullptr, (p_data != nullptr && p_data->also_set_library_path && has_dll_directory_api) ? LOAD_LIBRARY_SEARCH_DEFAULT_DIRS : 0); if (!p_library_handle) { if (p_data != nullptr && p_data->generate_temp_files) { DirAccess::remove_absolute(load_path); @@ -434,7 +447,7 @@ Error OS_Windows::open_dynamic_library(const String &p_path, void *&p_library_ha HashSet<String> checked_libs; HashSet<String> missing_libs; - debug_dynamic_library_check_dependencies(load_path, load_path, checked_libs, missing_libs); + debug_dynamic_library_check_dependencies(wpath, checked_libs, missing_libs); if (!missing_libs.is_empty()) { String missing; for (const String &E : missing_libs) { @@ -622,6 +635,72 @@ Vector<String> OS_Windows::get_video_adapter_driver_info() const { return info; } +bool OS_Windows::get_user_prefers_integrated_gpu() const { + // On Windows 10, the preferred GPU configured in Windows Settings is + // stored in the registry under the key + // `HKEY_CURRENT_USER\SOFTWARE\Microsoft\DirectX\UserGpuPreferences` + // with the name being the app ID or EXE path. The value is in the form of + // `GpuPreference=1;`, with the value being 1 for integrated GPU and 2 + // for discrete GPU. On Windows 11, there may be more flags, separated + // by semicolons. + + // If this is a packaged app, use the "application user model ID". + // Otherwise, use the EXE path. + WCHAR value_name[32768]; + bool is_packaged = false; + { + HMODULE kernel32 = GetModuleHandleW(L"kernel32.dll"); + if (kernel32) { + using GetCurrentApplicationUserModelIdPtr = LONG(WINAPI *)(UINT32 * length, PWSTR id); + GetCurrentApplicationUserModelIdPtr GetCurrentApplicationUserModelId = (GetCurrentApplicationUserModelIdPtr)GetProcAddress(kernel32, "GetCurrentApplicationUserModelId"); + + if (GetCurrentApplicationUserModelId) { + UINT32 length = sizeof(value_name) / sizeof(value_name[0]); + LONG result = GetCurrentApplicationUserModelId(&length, value_name); + if (result == ERROR_SUCCESS) { + is_packaged = true; + } + } + } + } + if (!is_packaged && GetModuleFileNameW(nullptr, value_name, sizeof(value_name) / sizeof(value_name[0])) >= sizeof(value_name) / sizeof(value_name[0])) { + // Paths should never be longer than 32767, but just in case. + return false; + } + + LPCWSTR subkey = L"SOFTWARE\\Microsoft\\DirectX\\UserGpuPreferences"; + HKEY hkey = nullptr; + LSTATUS result = RegOpenKeyExW(HKEY_CURRENT_USER, subkey, 0, KEY_READ, &hkey); + if (result != ERROR_SUCCESS) { + return false; + } + + DWORD size = 0; + result = RegGetValueW(hkey, nullptr, value_name, RRF_RT_REG_SZ, nullptr, nullptr, &size); + if (result != ERROR_SUCCESS || size == 0) { + RegCloseKey(hkey); + return false; + } + + Vector<WCHAR> buffer; + buffer.resize(size / sizeof(WCHAR)); + result = RegGetValueW(hkey, nullptr, value_name, RRF_RT_REG_SZ, nullptr, (LPBYTE)buffer.ptrw(), &size); + if (result != ERROR_SUCCESS) { + RegCloseKey(hkey); + return false; + } + + RegCloseKey(hkey); + const String flags = String::utf16((const char16_t *)buffer.ptr(), size / sizeof(WCHAR)); + + for (const String &flag : flags.split(";", false)) { + if (flag == "GpuPreference=1") { + return true; + } + } + return false; +} + OS::DateTime OS_Windows::get_datetime(bool p_utc) const { SYSTEMTIME systemtime; if (p_utc) { @@ -822,7 +901,7 @@ Dictionary OS_Windows::execute_with_pipe(const String &p_path, const List<String Dictionary ret; - String path = p_path.replace("/", "\\"); + String path = p_path.is_absolute_path() ? fix_path(p_path) : p_path; String command = _quote_command_line_argument(path); for (const String &E : p_arguments) { command += " " + _quote_command_line_argument(E); @@ -871,7 +950,19 @@ Dictionary OS_Windows::execute_with_pipe(const String &p_path, const List<String DWORD creation_flags = NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW; - if (!CreateProcessW(nullptr, (LPWSTR)(command.utf16().ptrw()), nullptr, nullptr, true, creation_flags, nullptr, nullptr, si_w, &pi.pi)) { + Char16String current_dir_name; + size_t str_len = GetCurrentDirectoryW(0, nullptr); + current_dir_name.resize(str_len + 1); + GetCurrentDirectoryW(current_dir_name.size(), (LPWSTR)current_dir_name.ptrw()); + if (current_dir_name.size() >= MAX_PATH) { + Char16String current_short_dir_name; + str_len = GetShortPathNameW((LPCWSTR)current_dir_name.ptr(), nullptr, 0); + current_short_dir_name.resize(str_len); + GetShortPathNameW((LPCWSTR)current_dir_name.ptr(), (LPWSTR)current_short_dir_name.ptrw(), current_short_dir_name.size()); + current_dir_name = current_short_dir_name; + } + + if (!CreateProcessW(nullptr, (LPWSTR)(command.utf16().ptrw()), nullptr, nullptr, true, creation_flags, nullptr, (LPWSTR)current_dir_name.ptr(), si_w, &pi.pi)) { CLEAN_PIPES ERR_FAIL_V_MSG(ret, "Could not create child process: " + command); } @@ -901,7 +992,7 @@ Dictionary OS_Windows::execute_with_pipe(const String &p_path, const List<String } Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments, String *r_pipe, int *r_exitcode, bool read_stderr, Mutex *p_pipe_mutex, bool p_open_console) { - String path = p_path.replace("/", "\\"); + String path = p_path.is_absolute_path() ? fix_path(p_path) : p_path; String command = _quote_command_line_argument(path); for (const String &E : p_arguments) { command += " " + _quote_command_line_argument(E); @@ -939,7 +1030,19 @@ Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments, creation_flags |= CREATE_NO_WINDOW; } - int ret = CreateProcessW(nullptr, (LPWSTR)(command.utf16().ptrw()), nullptr, nullptr, inherit_handles, creation_flags, nullptr, nullptr, si_w, &pi.pi); + Char16String current_dir_name; + size_t str_len = GetCurrentDirectoryW(0, nullptr); + current_dir_name.resize(str_len + 1); + GetCurrentDirectoryW(current_dir_name.size(), (LPWSTR)current_dir_name.ptrw()); + if (current_dir_name.size() >= MAX_PATH) { + Char16String current_short_dir_name; + str_len = GetShortPathNameW((LPCWSTR)current_dir_name.ptr(), nullptr, 0); + current_short_dir_name.resize(str_len); + GetShortPathNameW((LPCWSTR)current_dir_name.ptr(), (LPWSTR)current_short_dir_name.ptrw(), current_short_dir_name.size()); + current_dir_name = current_short_dir_name; + } + + int ret = CreateProcessW(nullptr, (LPWSTR)(command.utf16().ptrw()), nullptr, nullptr, inherit_handles, creation_flags, nullptr, (LPWSTR)current_dir_name.ptr(), si_w, &pi.pi); if (!ret && r_pipe) { CloseHandle(pipe[0]); // Cleanup pipe handles. CloseHandle(pipe[1]); @@ -1003,7 +1106,7 @@ Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments, } Error OS_Windows::create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id, bool p_open_console) { - String path = p_path.replace("/", "\\"); + String path = p_path.is_absolute_path() ? fix_path(p_path) : p_path; String command = _quote_command_line_argument(path); for (const String &E : p_arguments) { command += " " + _quote_command_line_argument(E); @@ -1022,7 +1125,19 @@ Error OS_Windows::create_process(const String &p_path, const List<String> &p_arg creation_flags |= CREATE_NO_WINDOW; } - int ret = CreateProcessW(nullptr, (LPWSTR)(command.utf16().ptrw()), nullptr, nullptr, false, creation_flags, nullptr, nullptr, si_w, &pi.pi); + Char16String current_dir_name; + size_t str_len = GetCurrentDirectoryW(0, nullptr); + current_dir_name.resize(str_len + 1); + GetCurrentDirectoryW(current_dir_name.size(), (LPWSTR)current_dir_name.ptrw()); + if (current_dir_name.size() >= MAX_PATH) { + Char16String current_short_dir_name; + str_len = GetShortPathNameW((LPCWSTR)current_dir_name.ptr(), nullptr, 0); + current_short_dir_name.resize(str_len); + GetShortPathNameW((LPCWSTR)current_dir_name.ptr(), (LPWSTR)current_short_dir_name.ptrw(), current_short_dir_name.size()); + current_dir_name = current_short_dir_name; + } + + int ret = CreateProcessW(nullptr, (LPWSTR)(command.utf16().ptrw()), nullptr, nullptr, false, creation_flags, nullptr, (LPWSTR)current_dir_name.ptr(), si_w, &pi.pi); ERR_FAIL_COND_V_MSG(ret == 0, ERR_CANT_FORK, "Could not create child process: " + command); ProcessID pid = pi.pi.dwProcessId; @@ -1390,8 +1505,8 @@ Vector<String> OS_Windows::get_system_font_path_for_text(const String &p_font_na continue; } - WCHAR file_path[MAX_PATH]; - hr = loader->GetFilePathFromKey(reference_key, reference_key_size, &file_path[0], MAX_PATH); + WCHAR file_path[32767]; + hr = loader->GetFilePathFromKey(reference_key, reference_key_size, &file_path[0], 32767); if (FAILED(hr)) { continue; } @@ -1469,8 +1584,8 @@ String OS_Windows::get_system_font_path(const String &p_font_name, int p_weight, continue; } - WCHAR file_path[MAX_PATH]; - hr = loader->GetFilePathFromKey(reference_key, reference_key_size, &file_path[0], MAX_PATH); + WCHAR file_path[32767]; + hr = loader->GetFilePathFromKey(reference_key, reference_key_size, &file_path[0], 32767); if (FAILED(hr)) { continue; } @@ -1576,7 +1691,7 @@ Error OS_Windows::shell_show_in_file_manager(String p_path, bool p_open_folder) if (!p_path.is_quoted()) { p_path = p_path.quote(); } - p_path = p_path.replace("/", "\\"); + p_path = fix_path(p_path); INT_PTR ret = OK; if (open_folder) { @@ -1901,6 +2016,19 @@ String OS_Windows::get_system_ca_certificates() { OS_Windows::OS_Windows(HINSTANCE _hInstance) { hInstance = _hInstance; + // Reset CWD to ensure long path is used. + Char16String current_dir_name; + size_t str_len = GetCurrentDirectoryW(0, nullptr); + current_dir_name.resize(str_len + 1); + GetCurrentDirectoryW(current_dir_name.size(), (LPWSTR)current_dir_name.ptrw()); + + Char16String new_current_dir_name; + str_len = GetLongPathNameW((LPCWSTR)current_dir_name.get_data(), nullptr, 0); + new_current_dir_name.resize(str_len + 1); + GetLongPathNameW((LPCWSTR)current_dir_name.get_data(), (LPWSTR)new_current_dir_name.ptrw(), new_current_dir_name.size()); + + SetCurrentDirectoryW((LPCWSTR)new_current_dir_name.get_data()); + #ifndef WINDOWS_SUBSYSTEM_CONSOLE RedirectIOToConsole(); #endif diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h index b6a21ed42d..9c7b98d7fd 100644 --- a/platform/windows/os_windows.h +++ b/platform/windows/os_windows.h @@ -172,6 +172,7 @@ public: virtual String get_version() const override; virtual Vector<String> get_video_adapter_driver_info() const override; + virtual bool get_user_prefers_integrated_gpu() const override; virtual void initialize_joypads() override {} |