diff --git a/src/Tgstation.Server.Host/IO/WindowsSymlinkFactory.cs b/src/Tgstation.Server.Host/IO/WindowsSymlinkFactory.cs
index d6b0da449c..e1b54d7eca 100644
--- a/src/Tgstation.Server.Host/IO/WindowsSymlinkFactory.cs
+++ b/src/Tgstation.Server.Host/IO/WindowsSymlinkFactory.cs
@@ -21,11 +21,23 @@ namespace Tgstation.Server.Host.IO
throw new ArgumentNullException(nameof(linkPath));
//check if its not a file
- var flags = File.Exists(targetPath) ? 2 : 3; //SYMBOLIC_LINK_FLAG_DIRECTORY and SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE on win10 1607+ developer mode
+ var flags = File.Exists(targetPath) ? NativeMethods.CreateSymbolicLinkFlags.None : NativeMethods.CreateSymbolicLinkFlags.Directory;
+
+ flags |= NativeMethods.CreateSymbolicLinkFlags.AllowUnprivilegedCreate;
cancellationToken.ThrowIfCancellationRequested();
if (!NativeMethods.CreateSymbolicLink(linkPath, targetPath, flags))
- throw new Win32Exception(Marshal.GetLastWin32Error());
+ {
+ var error = Marshal.GetLastWin32Error();
+ if (error == 87) //INVALID_PARAMETER, SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE isn't supported
+ {
+ flags &= ~NativeMethods.CreateSymbolicLinkFlags.AllowUnprivilegedCreate;
+ if (NativeMethods.CreateSymbolicLink(linkPath, targetPath, flags))
+ return;
+ error = Marshal.GetLastWin32Error();
+ }
+ throw new Win32Exception(error);
+ }
}, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
}
}
diff --git a/src/Tgstation.Server.Host/NativeMethods.cs b/src/Tgstation.Server.Host/NativeMethods.cs
index 6b130f9aac..bcc1865686 100644
--- a/src/Tgstation.Server.Host/NativeMethods.cs
+++ b/src/Tgstation.Server.Host/NativeMethods.cs
@@ -9,6 +9,17 @@ namespace Tgstation.Server.Host
///
static class NativeMethods
{
+ ///
+ /// See https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-createsymboliclinka#parameters
+ ///
+ [Flags]
+ public enum CreateSymbolicLinkFlags : int
+ {
+ None = 0,
+ Directory = 1,
+ AllowUnprivilegedCreate = 2
+ }
+
///
/// See https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getwindowthreadprocessid
///
@@ -54,6 +65,6 @@ namespace Tgstation.Server.Host
/// See https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-createsymboliclinkw
///
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
- public static extern bool CreateSymbolicLink(string lpSymlinkFileName, string lpTargetFileName, int dwFlags);
+ public static extern bool CreateSymbolicLink(string lpSymlinkFileName, string lpTargetFileName, CreateSymbolicLinkFlags dwFlags);
}
}