diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index ffe4815d66..c77f398af2 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -7255,6 +7255,8 @@ os_symlink_impl(PyObject *module, path_t *src, path_t *dst, Py_BEGIN_ALLOW_THREADS /* if src is a directory, ensure target_is_directory==1 */ target_is_directory |= _check_dirW(src->wide, dst->wide); + // Allow non-admin symlinks if system allows it: + target_is_directory |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE; result = Py_CreateSymbolicLinkW(dst->wide, src->wide, target_is_directory); Py_END_ALLOW_THREADS @@ -12342,6 +12344,9 @@ enable_symlink() HANDLE tok; TOKEN_PRIVILEGES tok_priv; LUID luid; + HKEY hKey; + DWORD dwSize = sizeof(DWORD); + DWORD devMode = 0; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &tok)) return 0; @@ -12359,7 +12364,19 @@ enable_symlink() return 0; /* ERROR_NOT_ALL_ASSIGNED returned when the privilege can't be assigned. */ - return GetLastError() == ERROR_NOT_ALL_ASSIGNED ? 0 : 1; + if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) + { + // Check if in developer mode, as privelege is then not required + // https://blogs.windows.com/buildingapps/2016/12/02/symlinks-windows-10/ + + auto err = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppModelUnlock", 0, KEY_READ, &hKey); + if (err != ERROR_SUCCESS) + return 0; + err = RegQueryValueExW(hKey, L"AllowDevelopmentWithoutDevLicense", NULL, NULL, (LPBYTE) &devMode, &dwSize); + RegCloseKey(hKey); + return (err == ERROR_SUCCESS && devMode != 0) ? 1 : 0; + } + return 1; } #endif /* defined(HAVE_SYMLINK) && defined(MS_WINDOWS) */ diff --git a/Modules/winreparse.h b/Modules/winreparse.h index 28049c9af9..a33f717752 100644 --- a/Modules/winreparse.h +++ b/Modules/winreparse.h @@ -45,6 +45,9 @@ typedef struct { FIELD_OFFSET(_Py_REPARSE_DATA_BUFFER, GenericReparseBuffer) #define _Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE ( 16 * 1024 ) +// According to https://blogs.windows.com/buildingapps/2016/12/02/symlinks-windows-10/ : +#define SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE 0x2 + #ifdef __cplusplus } #endif