-
Notifications
You must be signed in to change notification settings - Fork 0
/
Invoke-UnlockFile.ps1
81 lines (75 loc) · 3.57 KB
/
Invoke-UnlockFile.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
<#
.Synopsis
Take ownership and grant full access to current user.
.DESCRIPTION
Take ownership and grant full access to current user. This is needed when accessing "protected" files in the system.
.EXAMPLE
$InfoNeededWhenLockingFile = Invoke-UnlockFile -Path 'Path to file'
.INPUTS
Path is the path to the file to handle
.OUTPUTS
Outputs a PSObject containing OriginalOwner and ACLPath which contains the path to the file where the original ACL was stored.
#>
function Invoke-UnlockFile {
param(
[Parameter(Mandatory=$true,
ValueFromPipeline=$true)]
[ValidateNotNullOrEmpty()]
[string]$Path
)
begin {
If (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]"Administrator"))
{
Write-Error "You need to run as admin!"
}
$SystemRoot = [Environment]::GetFolderPath("System")
function Get-TemporaryFilename {
$TempFileName = [System.IO.Path]::GetTempFileName()
#Remove-Item -Path $TempFileName -Force -ErrorAction Stop
Write-Output $TempFileName
}
$BaseParameters = @{
ErrorAction = 'SilentlyContinue'
NoNewWindow = $true
Wait = $true
Passthru = $true
}
$CurrentUser = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
}
process {
$OriginalOwner = Get-Acl -Path $Path | Select-Object -ExpandProperty Owner
$OriginalACLPath = Get-TemporaryFilename
$TakeownProc = Start-Process @BaseParameters -FilePath "$SystemRoot\takeown.exe" -ArgumentList "/f $Path"
if ($TakeownProc.ExitCode -ne 0) {
Write-Error "Failed to take ownership of '$Path' ($SystemRoot\takeown.exe exitcode '$($TakeownProc.ExitCode)')"
}
# Save the old ACL, to avoid leaving records in the ACL when we are done
$ACLSaveProc = Start-Process @BaseParameters -FilePath "$SystemRoot\icacls.exe" -ArgumentList "$Path /save $OriginalACLPath"
if ($ACLSaveProc.ExitCode -ne 0) {
# We failed, Restore owner
$SetownProc = Start-Process @BaseParameters -FilePath "$SystemRoot\icacls.exe" -ArgumentList "$Path /setowner `"$OriginalOwner`""
if ($SetownProc.ExitCode -ne 0) {
Write-Error "Could not restore owner to '$OriginalOwner'!"
}
Write-Error "Failed to save original ACL of '$Path' ($SystemRoot\icacls.exe exitcode '$($ACLSaveProc.ExitCode)')"
}
# Add current user with Full Control
$GrantProc = Start-Process @BaseParameters -FilePath "$SystemRoot\icacls.exe" -ArgumentList "$Path /Grant $($CurrentUser):(F)"
if ($GrantProc.ExitCode -ne 0) {
# We failed, Restore owner
$SetownProc = Start-Process @BaseParameters -FilePath "$SystemRoot\icacls.exe" -ArgumentList "$Path /setowner `"$OriginalOwner`""
if ($SetownProc.ExitCode -ne 0) {
Write-Error "Could not restore owner to '$OriginalOwner'!"
}
Write-Error "Failed to grant access for '$CurrentUser' to '$Path' ($SystemRoot\icacls.exe exitcode '$($GrantProc.ExitCode)')"
}
}
end {
if ($OriginalOwner -and $OriginalACLPath) {
$return = New-Object psobject
$return | Add-Member -NotePropertyName OriginalOwner -NotePropertyValue $OriginalOwner
$return | Add-Member -NotePropertyName ACLPath -NotePropertyValue $OriginalACLPath
$return
}
}
}