Skip to content

Commit a0aedba

Browse files
author
Git for Windows Build Agent
committed
Merge pull request #1188 from dscho/unprivileged-symlinks
Support creating symlinks outside elevated sessions
2 parents 5cb40bb + 521dfef commit a0aedba

File tree

1 file changed

+24
-2
lines changed

1 file changed

+24
-2
lines changed

compat/mingw.c

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -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;
273274
DECLARE_PROC_ADDR(kernel32.dll, BOOLEAN, CreateSymbolicLinkW, LPCWSTR, LPCWSTR, DWORD);
274275

275276
enum 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());
@@ -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

Comments
 (0)