@@ -270,7 +270,8 @@ int mingw_core_config(const char *var, const char *value)
270270 return 0 ;
271271}
272272
273- DECLARE_PROC_ADDR (kernel32 .dll , BOOL , CreateSymbolicLinkW , LPCWSTR , LPCWSTR , DWORD );
273+ static DWORD symlink_file_flags = 0 , symlink_directory_flags = 1 ;
274+ DECLARE_PROC_ADDR (kernel32 .dll , BOOLEAN , CreateSymbolicLinkW , LPCWSTR , LPCWSTR , DWORD );
274275
275276enum phantom_symlink_result {
276277 PHANTOM_SYMLINK_RETRY ,
@@ -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 ());
@@ -2656,7 +2658,7 @@ int symlink(const char *target, const char *link)
26562658 wtarget [len ] = '\\' ;
26572659
26582660 /* create file symlink */
2659- if (!CreateSymbolicLinkW (wlink , wtarget , 0 )) {
2661+ if (!CreateSymbolicLinkW (wlink , wtarget , symlink_file_flags )) {
26602662 errno = err_win_to_posix (GetLastError ());
26612663 return -1 ;
26622664 }
@@ -3178,6 +3180,24 @@ static void maybe_redirect_std_handles(void)
31783180 GENERIC_WRITE , FILE_FLAG_NO_BUFFERING );
31793181}
31803182
3183+ static void adjust_symlink_flags (void )
3184+ {
3185+ /*
3186+ * Starting with Windows 10 Build 14972, symbolic links can be created
3187+ * using CreateSymbolicLink() without elevation by passing the flag
3188+ * SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE (0x02) as last
3189+ * parameter, provided the Developer Mode has been enabled. Some
3190+ * earlier Windows versions complain about this flag with an
3191+ * ERROR_INVALID_PARAMETER, hence we have to test the build number
3192+ * specifically.
3193+ */
3194+ if (GetVersion () >= 14972 << 16 ) {
3195+ symlink_file_flags |= 2 ;
3196+ symlink_directory_flags |= 2 ;
3197+ }
3198+
3199+ }
3200+
31813201#if defined(_MSC_VER )
31823202
31833203#ifdef _DEBUG
@@ -3217,6 +3237,7 @@ int msc_startup(int argc, wchar_t **w_argv, wchar_t **w_env)
32173237#endif
32183238
32193239 maybe_redirect_std_handles ();
3240+ adjust_symlink_flags ();
32203241
32213242 /* determine size of argv conversion buffer */
32223243 maxlen = wcslen (_wpgmptr );
@@ -3283,6 +3304,7 @@ void mingw_startup(void)
32833304 _startupinfo si ;
32843305
32853306 maybe_redirect_std_handles ();
3307+ adjust_symlink_flags ();
32863308
32873309 /* get wide char arguments and environment */
32883310 si .newmode = 0 ;
0 commit comments