Allow Windows users in developer mode to create symlinks without elevation (#8534)
This commit is contained in:
parent
c1920da410
commit
d6000fdea8
|
@ -2434,9 +2434,16 @@ namespace Microsoft.PowerShell.Commands
|
|||
|
||||
private static bool WinCreateSymbolicLink(string path, string strTargetPath, bool isDirectory)
|
||||
{
|
||||
int created = NativeMethods.CreateSymbolicLink(path, strTargetPath, (isDirectory ? 1 : 0));
|
||||
bool success = (created == 1) ? true : false;
|
||||
return success;
|
||||
// The new AllowUnprivilegedCreate is only available on Win10 build 14972 or newer
|
||||
var flags = isDirectory ? NativeMethods.SymbolicLinkFlags.Directory : NativeMethods.SymbolicLinkFlags.File;
|
||||
if (Environment.OSVersion.Version.Major == 10 && Environment.OSVersion.Version.Build >= 14972 ||
|
||||
Environment.OSVersion.Version.Major >= 11)
|
||||
{
|
||||
flags |= NativeMethods.SymbolicLinkFlags.AllowUnprivilegedCreate;
|
||||
}
|
||||
|
||||
int created = NativeMethods.CreateSymbolicLink(path, strTargetPath, flags);
|
||||
return (created == 1) ? true : false;
|
||||
}
|
||||
|
||||
private static bool WinCreateHardLink(string path, string strTargetPath)
|
||||
|
@ -7014,10 +7021,32 @@ namespace Microsoft.PowerShell.Commands
|
|||
/// </summary>
|
||||
/// <param name="name">Path of the symbolic link.</param>
|
||||
/// <param name="destination">Path of the target of the symbolic link.</param>
|
||||
/// <param name="destinationType">0 for destination as file and 1 for destination as directory.</param>
|
||||
/// <param name="symbolicLinkFlags">Flag values from SymbolicLinkFlags enum.</param>
|
||||
/// <returns>1 on successful creation.</returns>
|
||||
[DllImport(PinvokeDllNames.CreateSymbolicLinkDllName, CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
internal static extern int CreateSymbolicLink(string name, string destination, int destinationType);
|
||||
internal static extern int CreateSymbolicLink(string name, string destination, SymbolicLinkFlags symbolicLinkFlags);
|
||||
|
||||
/// <summary>
|
||||
/// Flags used when creating a symbolic link.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
internal enum SymbolicLinkFlags
|
||||
{
|
||||
/// <summary>
|
||||
/// Symbolic link is a file.
|
||||
/// </summary>
|
||||
File = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Symbolic link is a directory.
|
||||
/// </summary>
|
||||
Directory = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Allow creation of symbolic link without elevation. Requires Developer mode.
|
||||
/// </summary>
|
||||
AllowUnprivilegedCreate = 2
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a hard link using the native API.
|
||||
|
|
|
@ -256,19 +256,27 @@ Describe "New-Item with links" -Tags @('CI', 'RequireAdminOnWindows') {
|
|||
}
|
||||
}
|
||||
|
||||
Describe "New-Item with links fails for non elevated user." -Tags "CI" {
|
||||
Describe "New-Item with links fails for non elevated user if developer mode not enabled on Windows." -Tags "CI" {
|
||||
BeforeAll {
|
||||
$tmpDirectory = $TestDrive
|
||||
$testfile = "testfile.txt"
|
||||
$testfolder = "newDirectory"
|
||||
$testlink = "testlink"
|
||||
$FullyQualifiedFile = Join-Path -Path $tmpDirectory -ChildPath $testfile
|
||||
$FullyQualifiedFolder = Join-Path -Path $tmpDirectory -ChildPath $testfolder
|
||||
$FullyQualifiedFile = Join-Path -Path $TestDrive -ChildPath $testfile
|
||||
$TestFilePath = Join-Path -Path $TestDrive -ChildPath $testlink
|
||||
$developerMode = (Get-ItemProperty HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock -ErrorAction SilentlyContinue).AllowDevelopmentWithoutDevLicense -eq 1
|
||||
}
|
||||
|
||||
It "Should error correctly when failing to create a symbolic link" -Skip:(Test-IsRoot) {
|
||||
# This test expects that /sbin exists but is not writable by the user
|
||||
{ New-Item -ItemType SymbolicLink -Path "/sbin/powershell-test" -Target $FullyQualifiedFolder -ErrorAction Stop } |
|
||||
AfterEach {
|
||||
Remove-Item -Path $testFilePath -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
It "Should error correctly when failing to create a symbolic link and not in developer mode" -Skip:(!$IsWindows -or $developerMode -or (Test-IsElevated)) {
|
||||
{ New-Item -ItemType SymbolicLink -Path $TestFilePath -Target $FullyQualifiedFile -ErrorAction Stop } |
|
||||
Should -Throw -ErrorId "NewItemSymbolicLinkElevationRequired,Microsoft.PowerShell.Commands.NewItemCommand"
|
||||
$TestFilePath | Should -Not -Exist
|
||||
}
|
||||
|
||||
It "Should succeed to create a symbolic link without elevation and in developer mode" -Skip:(!$IsWindows -or !$developerMode -or (Test-IsElevated)) {
|
||||
{ New-Item -ItemType SymbolicLink -Path $TestFilePath -Target $FullyQualifiedFile -ErrorAction Stop } | Should -Not -Throw
|
||||
$TestFilePath | Should -Exist
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue