@@ -270,6 +270,7 @@ int mingw_core_config(const char *var, const char *value)
270270 return 0 ;
271271}
272272
273+ static DWORD symlink_file_flags = 0 , symlink_directory_flags = 1 ;
273274DECLARE_PROC_ADDR (kernel32 .dll , BOOLEAN , CreateSymbolicLinkW , LPCWSTR , LPCWSTR , DWORD );
274275
275276enum phantom_symlink_result {
@@ -314,7 +315,8 @@ static enum phantom_symlink_result process_phantom_symlink(
314315 return PHANTOM_SYMLINK_DONE ;
315316
316317 /* otherwise recreate the symlink with directory flag */
317- if (DeleteFileW (wlink ) && CreateSymbolicLinkW (wlink , wtarget , 1 ))
318+ if (DeleteFileW (wlink ) &&
319+ CreateSymbolicLinkW (wlink , wtarget , symlink_directory_flags ))
318320 return PHANTOM_SYMLINK_DIRECTORY ;
319321
320322 errno = err_win_to_posix (GetLastError ());
@@ -2607,7 +2609,7 @@ int symlink(const char *target, const char *link)
26072609 wtarget [len ] = '\\' ;
26082610
26092611 /* create file symlink */
2610- if (!CreateSymbolicLinkW (wlink , wtarget , 0 )) {
2612+ if (!CreateSymbolicLinkW (wlink , wtarget , symlink_file_flags )) {
26112613 errno = err_win_to_posix (GetLastError ());
26122614 return -1 ;
26132615 }
@@ -3129,6 +3131,24 @@ static void maybe_redirect_std_handles(void)
31293131 GENERIC_WRITE , FILE_FLAG_NO_BUFFERING );
31303132}
31313133
3134+ static void adjust_symlink_flags (void )
3135+ {
3136+ /*
3137+ * Starting with Windows 10 Build 14972, symbolic links can be created
3138+ * using CreateSymbolicLink() without elevation by passing the flag
3139+ * SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE (0x02) as last
3140+ * parameter, provided the Developer Mode has been enabled. Some
3141+ * earlier Windows versions complain about this flag with an
3142+ * ERROR_INVALID_PARAMETER, hence we have to test the build number
3143+ * specifically.
3144+ */
3145+ if (GetVersion () >= 14972 << 16 ) {
3146+ symlink_file_flags |= 2 ;
3147+ symlink_directory_flags |= 2 ;
3148+ }
3149+
3150+ }
3151+
31323152#if defined(_MSC_VER )
31333153
31343154#ifdef _DEBUG
@@ -3168,6 +3188,7 @@ int msc_startup(int argc, wchar_t **w_argv, wchar_t **w_env)
31683188#endif
31693189
31703190 maybe_redirect_std_handles ();
3191+ adjust_symlink_flags ();
31713192
31723193 /* determine size of argv conversion buffer */
31733194 maxlen = wcslen (_wpgmptr );
@@ -3234,6 +3255,7 @@ void mingw_startup(void)
32343255 _startupinfo si ;
32353256
32363257 maybe_redirect_std_handles ();
3258+ adjust_symlink_flags ();
32373259
32383260 /* get wide char arguments and environment */
32393261 si .newmode = 0 ;
0 commit comments