aboutsummaryrefslogtreecommitdiff
path: root/compat
diff options
context:
space:
mode:
Diffstat (limited to 'compat')
-rw-r--r--compat/mingw.c26
1 files changed, 24 insertions, 2 deletions
diff --git a/compat/mingw.c b/compat/mingw.c
index 59a32e454e..3e2110a87a 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -331,6 +331,8 @@ static const wchar_t *make_relative_to(const wchar_t *path,
return out;
}
+static DWORD symlink_file_flags = 0, symlink_directory_flags = 1;
+
enum phantom_symlink_result {
PHANTOM_SYMLINK_RETRY,
PHANTOM_SYMLINK_DONE,
@@ -381,7 +383,8 @@ process_phantom_symlink(const wchar_t *wtarget, const wchar_t *wlink)
return PHANTOM_SYMLINK_DONE;
/* otherwise recreate the symlink with directory flag */
- if (DeleteFileW(wlink) && CreateSymbolicLinkW(wlink, wtarget, 1))
+ if (DeleteFileW(wlink) &&
+ CreateSymbolicLinkW(wlink, wtarget, symlink_directory_flags))
return PHANTOM_SYMLINK_DIRECTORY;
errno = err_win_to_posix(GetLastError());
@@ -2846,7 +2849,7 @@ int symlink(const char *target, const char *link)
wtarget[len] = '\\';
/* create file symlink */
- if (!CreateSymbolicLinkW(wlink, wtarget, 0)) {
+ if (!CreateSymbolicLinkW(wlink, wtarget, symlink_file_flags)) {
errno = err_win_to_posix(GetLastError());
return -1;
}
@@ -3523,6 +3526,24 @@ static void maybe_redirect_std_handles(void)
GENERIC_WRITE, FILE_FLAG_NO_BUFFERING);
}
+static void adjust_symlink_flags(void)
+{
+ /*
+ * Starting with Windows 10 Build 14972, symbolic links can be created
+ * using CreateSymbolicLink() without elevation by passing the flag
+ * SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE (0x02) as last
+ * parameter, provided the Developer Mode has been enabled. Some
+ * earlier Windows versions complain about this flag with an
+ * ERROR_INVALID_PARAMETER, hence we have to test the build number
+ * specifically.
+ */
+ if (GetVersion() >= 14972 << 16) {
+ symlink_file_flags |= 2;
+ symlink_directory_flags |= 2;
+ }
+
+}
+
#ifdef _MSC_VER
#ifdef _DEBUG
#include <crtdbg.h>
@@ -3558,6 +3579,7 @@ int wmain(int argc, const wchar_t **wargv)
#endif
maybe_redirect_std_handles();
+ adjust_symlink_flags();
/* determine size of argv and environ conversion buffer */
maxlen = wcslen(wargv[0]);