summaryrefslogtreecommitdiffstats
path: root/drivers/windows
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/windows')
-rw-r--r--drivers/windows/dir_access_windows.cpp60
-rw-r--r--drivers/windows/dir_access_windows.h6
-rw-r--r--drivers/windows/file_access_windows.cpp65
3 files changed, 118 insertions, 13 deletions
diff --git a/drivers/windows/dir_access_windows.cpp b/drivers/windows/dir_access_windows.cpp
index 43dd62cdf6..63ba6a6c96 100644
--- a/drivers/windows/dir_access_windows.cpp
+++ b/drivers/windows/dir_access_windows.cpp
@@ -396,6 +396,66 @@ bool DirAccessWindows::is_case_sensitive(const String &p_path) const {
}
}
+bool DirAccessWindows::is_link(String p_file) {
+ String f = p_file;
+
+ if (!f.is_absolute_path()) {
+ f = get_current_dir().path_join(f);
+ }
+ f = fix_path(f);
+
+ DWORD attr = GetFileAttributesW((LPCWSTR)(f.utf16().get_data()));
+ if (attr == INVALID_FILE_ATTRIBUTES) {
+ return false;
+ }
+
+ return (attr & FILE_ATTRIBUTE_REPARSE_POINT);
+}
+
+String DirAccessWindows::read_link(String p_file) {
+ String f = p_file;
+
+ if (!f.is_absolute_path()) {
+ f = get_current_dir().path_join(f);
+ }
+ f = fix_path(f);
+
+ HANDLE hfile = CreateFileW((LPCWSTR)(f.utf16().get_data()), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
+ if (hfile == INVALID_HANDLE_VALUE) {
+ return f;
+ }
+
+ DWORD ret = GetFinalPathNameByHandleW(hfile, nullptr, 0, VOLUME_NAME_DOS | FILE_NAME_NORMALIZED);
+ if (ret == 0) {
+ return f;
+ }
+ Char16String cs;
+ cs.resize(ret + 1);
+ GetFinalPathNameByHandleW(hfile, (LPWSTR)cs.ptrw(), ret, VOLUME_NAME_DOS | FILE_NAME_NORMALIZED);
+ CloseHandle(hfile);
+
+ return String::utf16((const char16_t *)cs.ptr(), ret).trim_prefix(R"(\\?\)");
+}
+
+Error DirAccessWindows::create_link(String p_source, String p_target) {
+ if (p_target.is_relative_path()) {
+ p_target = get_current_dir().path_join(p_target);
+ }
+
+ p_source = fix_path(p_source);
+ p_target = fix_path(p_target);
+
+ DWORD file_attr = GetFileAttributesW((LPCWSTR)(p_source.utf16().get_data()));
+ bool is_dir = (file_attr & FILE_ATTRIBUTE_DIRECTORY);
+
+ DWORD flags = ((is_dir) ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0) | SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
+ if (CreateSymbolicLinkW((LPCWSTR)p_target.utf16().get_data(), (LPCWSTR)p_source.utf16().get_data(), flags) != 0) {
+ return OK;
+ } else {
+ return FAILED;
+ }
+}
+
DirAccessWindows::DirAccessWindows() {
p = memnew(DirAccessWindowsPrivate);
p->h = INVALID_HANDLE_VALUE;
diff --git a/drivers/windows/dir_access_windows.h b/drivers/windows/dir_access_windows.h
index 576ba18d9a..46755cbf33 100644
--- a/drivers/windows/dir_access_windows.h
+++ b/drivers/windows/dir_access_windows.h
@@ -77,9 +77,9 @@ public:
virtual Error rename(String p_path, String p_new_path) override;
virtual Error remove(String p_path) override;
- virtual bool is_link(String p_file) override { return false; };
- virtual String read_link(String p_file) override { return p_file; };
- virtual Error create_link(String p_source, String p_target) override { return FAILED; };
+ virtual bool is_link(String p_file) override;
+ virtual String read_link(String p_file) override;
+ virtual Error create_link(String p_source, String p_target) override;
uint64_t get_space_left() override;
diff --git a/drivers/windows/file_access_windows.cpp b/drivers/windows/file_access_windows.cpp
index 726e0fdc5a..9885d9d7ee 100644
--- a/drivers/windows/file_access_windows.cpp
+++ b/drivers/windows/file_access_windows.cpp
@@ -32,6 +32,7 @@
#include "file_access_windows.h"
+#include "core/config/project_settings.h"
#include "core/os/os.h"
#include "core/string/print_string.h"
@@ -121,19 +122,63 @@ Error FileAccessWindows::open_internal(const String &p_path, int p_mode_flags) {
// Windows is case insensitive, but all other platforms are sensitive to it
// To ease cross-platform development, we issue a warning if users try to access
// a file using the wrong case (which *works* on Windows, but won't on other
- // platforms).
- if (p_mode_flags == READ) {
- WIN32_FIND_DATAW d;
- HANDLE fnd = FindFirstFileW((LPCWSTR)(path.utf16().get_data()), &d);
- if (fnd != INVALID_HANDLE_VALUE) {
- String fname = String::utf16((const char16_t *)(d.cFileName));
- if (!fname.is_empty()) {
- String base_file = path.get_file();
- if (base_file != fname && base_file.findn(fname) == 0) {
- WARN_PRINT("Case mismatch opening requested file '" + base_file + "', stored as '" + fname + "' in the filesystem. This file will not open when exported to other case-sensitive platforms.");
+ // platforms), we only check for relative paths, or paths in res:// or user://,
+ // other paths aren't likely to be portable anyway.
+ if (p_mode_flags == READ && (p_path.is_relative_path() || get_access_type() != ACCESS_FILESYSTEM)) {
+ String base_path = path;
+ String working_path;
+ String proper_path;
+
+ if (get_access_type() == ACCESS_RESOURCES) {
+ if (ProjectSettings::get_singleton()) {
+ working_path = ProjectSettings::get_singleton()->get_resource_path();
+ if (!working_path.is_empty()) {
+ base_path = working_path.path_to_file(base_path);
}
}
+ proper_path = "res://";
+ } else if (get_access_type() == ACCESS_USERDATA) {
+ working_path = OS::get_singleton()->get_user_data_dir();
+ if (!working_path.is_empty()) {
+ base_path = working_path.path_to_file(base_path);
+ }
+ proper_path = "user://";
+ }
+
+ WIN32_FIND_DATAW d;
+ Vector<String> parts = base_path.split("/");
+
+ bool mismatch = false;
+
+ for (const String &part : parts) {
+ working_path = working_path.path_join(part);
+
+ // Skip if relative.
+ if (part == "." || part == "..") {
+ proper_path = proper_path.path_join(part);
+ continue;
+ }
+
+ HANDLE fnd = FindFirstFileW((LPCWSTR)(working_path.utf16().get_data()), &d);
+
+ if (fnd == INVALID_HANDLE_VALUE) {
+ mismatch = false;
+ break;
+ }
+
+ const String fname = String::utf16((const char16_t *)(d.cFileName));
+
FindClose(fnd);
+
+ if (!mismatch) {
+ mismatch = (part != fname && part.findn(fname) == 0);
+ }
+
+ proper_path = proper_path.path_join(fname);
+ }
+
+ if (mismatch) {
+ WARN_PRINT("Case mismatch opening requested file '" + p_path + "', stored as '" + proper_path + "' in the filesystem. This file will not open when exported to other case-sensitive platforms.");
}
}
#endif