ShadowCopyHandling.psm1

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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
function Get-ShadowCopy {
    <#
    .SYNOPSIS
    Show all Shadow Copies
    .DESCRIPTION
    Shows all Shadow Copies on a system
    .NOTES
    A function for each message type is present so addition tasks can be competed when a message of a specific type is written.
 
    Copyright (C) MosaicMK Software LLC - All Rights Reserved
    Unauthorized copying of this application via any medium is strictly prohibited Proprietary and confidential
    Written by MosaicMK Software LLC (contact@mosaicmk.com)
 
    By using this software you agree to the following:
    Agreement Permission is hereby granted, free of charge, to any person or organization obtaining a copy of this software and associated documentation files (the "Software"),
    to deal in the Software and the rights to use and distribute the software so long a no licensing and or documentation files are remove, revised or modified
    the Software is furnished to do so, subject to the following conditions:
    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
    DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
    IN THE SOFTWARE.
 
    Contact: Contact@MosaicMK.com
    Version 1.0.0
    .LINK
    https://www.mosaicmk.com/2019/04/shadow-copy-handling-module.html
    #>

    $ShadowCopys = Get-CimInstance -ClassName Win32_ShadowCopy
    Foreach ($item in $ShadowCopys){
        $ID = $item.ID
        $Shadow = Get-ItemProperty -Path HKLM:\SOFTWARE\ShadowCopyHandling\$ID -ErrorAction SilentlyContinue
        $ShadowCopy = New-Object -TypeName psobject
        $ShadowCopy | Add-Member -MemberType NoteProperty -Name DateCreated -Value $Item.InstallDate
        $ShadowCopy | Add-Member -MemberType NoteProperty -Name ClientAccessible -Value $Item.ClientAccessible
        $ShadowCopy | Add-Member -MemberType NoteProperty -Name Location -Value $Item.DeviceObject
        $ShadowCopy | Add-Member -MemberType NoteProperty -Name ID -Value $Item.ID
        $ShadowCopy | Add-Member -MemberType NoteProperty -Name MountPoint -Value $Shadow.MountPoint
        $ShadowCopy | Add-Member -MemberType NoteProperty -Name Status -Value $Shadow.Status
        $ShadowCopy | Add-Member -MemberType NoteProperty -Name Drive -Value $Shadow.Drive
        $ShadowCopy
    }
}

function New-ShadowCopy {
    <#
    .SYNOPSIS
    Create a new shadow copy
    .DESCRIPTION
    Create a shadow copy of a volume
    .PARAMETER Drive
    The Drive letter of the volume to create a shadow copy of
    .EXAMPLE
    New-ShadowCopy -Drive C
    Creates a shadow copy of the c drive
    .NOTES
    Copyright (C) MosaicMK Software LLC - All Rights Reserved
    Unauthorized copying of this application via any medium is strictly prohibited Proprietary and confidential
    Written by MosaicMK Software LLC (contact@mosaicmk.com)
 
    By using this software you agree to the following:
    Agreement Permission is hereby granted, free of charge, to any person or organization obtaining a copy of this software and associated documentation files (the "Software"),
    to deal in the Software and the rights to use and distribute the software so long a no licensing and or documentation files are remove, revised or modified
    the Software is furnished to do so, subject to the following conditions:
    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
    DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
    IN THE SOFTWARE.
 
    Contact: Contact@MosaicMK.com
    Version 1.0.0
    .LINK
    https://www.mosaicmk.com/2019/04/shadow-copy-handling-module.html
    #>

    PARAM(
        [Parameter(Mandatory=$True,ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)]
        [Alias("DriveLetter","Name")]
        [String]$Drive
    )
    process{
        $Drive = $Drive[0]
        IF (Get-Volume -DriveLetter $Drive -ErrorAction SilentlyContinue){
            $WmiShadowCopyClass = [WMICLASS]"root\cimv2:win32_shadowcopy"
            $WmiShadowCopyResult = $WmiShadowCopyClass.create("${Drive}:\", "ClientAccessible")
            $ReturnValue = $WmiShadowCopyResult.ReturnValue
            $ID = $WmiShadowCopyResult.ShadowID
            if ($ReturnValue -NE 0) {
                if ($ReturnValue -lt $NewErrorMessages.Count) {$Message = $NewErrorMessages[$ReturnValue]} else {$Message = "Unknown error $ReturnValue"}
                Throw "Failed to create a shadow copy of drive ${Drive}: $Message."
            }
            New-Item "HKLM:\SOFTWARE\ShadowCopyHandling\$ID" -Force | Out-Null
            New-ItemProperty HKLM:\SOFTWARE\ShadowCopyHandling\$ID -Name Status -Value "Unmounted" | Out-Null
            New-ItemProperty HKLM:\SOFTWARE\ShadowCopyHandling\$ID -Name MountPoint -Value $null | Out-Null
            New-ItemProperty HKLM:\SOFTWARE\ShadowCopyHandling\$ID -Name Drive -Value $Drive | Out-Null
        } Else {Throw "Cannot find Drive $Drive"}
    }
}

function Mount-ShadowCopy {
    <#
    .SYNOPSIS
    Mount a Shadow copy
    .DESCRIPTION
    Mount a shadow copy to a symbloic link
    .PARAMETER ShadowCopyID
    ID of the shadow copy to mount
    .PARAMETER MountPoint
    Path to where the shadow copy will be mounted
    .EXAMPLE
    Mount-ShadowCopy -ShadowCopyID "{418D332B-AB85-4865-AC07-7AA3DDBEE46D}" -MountPoint C:\Mount
    Mounts the shadow copy to C:\mount
    .NOTES
    Copyright (C) MosaicMK Software LLC - All Rights Reserved
    Unauthorized copying of this application via any medium is strictly prohibited Proprietary and confidential
    Written by MosaicMK Software LLC (contact@mosaicmk.com)
 
    By using this software you agree to the following:
    Agreement Permission is hereby granted, free of charge, to any person or organization obtaining a copy of this software and associated documentation files (the "Software"),
    to deal in the Software and the rights to use and distribute the software so long a no licensing and or documentation files are remove, revised or modified
    the Software is furnished to do so, subject to the following conditions:
    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
    DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
    IN THE SOFTWARE.
 
    Contact: Contact@MosaicMK.com
    Version 1.0.0
    .LINK
    https://www.mosaicmk.com/2019/04/shadow-copy-handling-module.html
    #>

    PARAM(
        [Parameter(Mandatory=$True,ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)]
        [Alias("ID","ShadowID")]
        [string]$ShadowCopyID,
        [Parameter(Mandatory=$True)]
        [string]$MountPoint
    )
    IF (Test-Path $MountPoint -ErrorAction SilentlyContinue){Throw "$MountPoint Already exisit"} Else {
        IF ((Get-ShadowCopy | Where-Object -Property ID -EQ "$ShadowCopyID").Status -eq "mounted"){Throw "$ShadowCopyID is already mounted"}
        $ShadowCopyPath = "$((Get-ShadowCopy | Where-Object -Property ID -eq "$ShadowCopyID").Location)\"
        Try {$null = [Win32.SymLink]} Catch {
        Add-Type @"
using System;
using System.Runtime.InteropServices;
 
namespace Win32 {
public class SymLink {
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern bool CreateSymbolicLink(string lpSymlinkFileName, string lpTargetFileName, int dwFlags);
[DllImport("kernel32.dll")]
public static extern uint GetLastError();
 
public static uint Create(string lpSymlinkFileName, string lpTargetFileName, int dwFlags) {
bool done = CreateSymbolicLink(lpSymlinkFileName, lpTargetFileName, dwFlags);
if (done) {
return 0;
} else {
return GetLastError();
}
}
}
}
"@

    }
        $Error = [Win32.SymLink]::Create($MountPoint,$ShadowCopyPath,1)
        if ($error) {Throw "Could not create a symbolic link : $_"}
        If (!(Test-Path "HKLM:\SOFTWARE\ShadowCopyHandling\$ShadowCopyID" -ErrorAction SilentlyContinue)) {New-Item "HKLM:\SOFTWARE\ShadowCopyHandling\$ShadowCopyID" -Force | Out-Null}
        Set-ItemProperty HKLM:\SOFTWARE\ShadowCopyHandling\$ShadowCopyID -Name Status -Value "Mounted" | Out-Null
        Set-ItemProperty HKLM:\SOFTWARE\ShadowCopyHandling\$ShadowCopyID -Name MountPoint -Value $MountPoint | Out-Null
    }
}

Function Dismount-ShadowCopy{
    <#
    .SYNOPSIS
    dismount a Shadow copy
    .DESCRIPTION
    Dismount a shadow copy from a symbloic link
    .PARAMETER ShadowCopyID
    ID of the shadow copy to dismount
    .EXAMPLE
    Dismount-ShadowCopy -ShadowCopyID "{418D332B-AB85-4865-AC07-7AA3DDBEE46D}"
    .NOTES
    Copyright (C) MosaicMK Software LLC - All Rights Reserved
    Unauthorized copying of this application via any medium is strictly prohibited Proprietary and confidential
    Written by MosaicMK Software LLC (contact@mosaicmk.com)
 
    By using this software you agree to the following:
    Agreement Permission is hereby granted, free of charge, to any person or organization obtaining a copy of this software and associated documentation files (the "Software"),
    to deal in the Software and the rights to use and distribute the software so long a no licensing and or documentation files are remove, revised or modified
    the Software is furnished to do so, subject to the following conditions:
    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
    DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
    IN THE SOFTWARE.
 
    Contact: Contact@MosaicMK.com
    Version 1.0.0
    .LINK
    https://www.mosaicmk.com/2019/04/shadow-copy-handling-module.html
    #>

    PARAM(
        [Parameter(Mandatory=$True,ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)]
        [Alias("ID","ShadowID")]
        [string]$ShadowCopyID
    )
    $MountPoint = (Get-ShadowCopy | Where-Object -Property ID -eq "$ShadowCopyID").MountPoint
    IF (!(Test-path $MountPoint)){Throw "Could not find mount point $MountPoint"} else {
        if ((Get-Item -Path $MountPoint).Attributes -band [System.IO.FileAttributes]::ReparsePoint){
            try {
            $MountPoint = Resolve-Path $MountPoint
            [System.IO.Directory]::Delete($MountPoint, $false) | Out-Null
            Set-ItemProperty HKLM:\SOFTWARE\ShadowCopyHandling\$ShadowCopyID -Name Status -Value "Unmounted"
            Set-ItemProperty HKLM:\SOFTWARE\ShadowCopyHandling\$ShadowCopyID -Name MountPoint -Value $null
            } catch {Throw "Failed to dismount $MountPoint : $($_.Exception.Message)"}
        } else {Throw "There is no Shadow Copy mounted at $MountPoint"}
    }
}

Function Remove-ShadowCopy{
    <#
    .SYNOPSIS
    Removes a Shoadow Copy
    .DESCRIPTION
    Removes a shadow copy using the vssadmin
    .NOTES
    A function for each message type is present so addition tasks can be competed when a message of a specific type is written.
 
    Copyright (C) MosaicMK Software LLC - All Rights Reserved
    Unauthorized copying of this application via any medium is strictly prohibited Proprietary and confidential
    Written by MosaicMK Software LLC (contact@mosaicmk.com)
 
    By using this software you agree to the following:
    Agreement Permission is hereby granted, free of charge, to any person or organization obtaining a copy of this software and associated documentation files (the "Software"),
    to deal in the Software and the rights to use and distribute the software so long a no licensing and or documentation files are remove, revised or modified
    the Software is furnished to do so, subject to the following conditions:
    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
    DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
    IN THE SOFTWARE.
 
    Contact: Contact@MosaicMK.com
    Version 1.0.0
    .LINK
    https://www.mosaicmk.com/2019/04/shadow-copy-handling-module.html
    #>

    Param(
        [Parameter(Mandatory=$True,ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)]
        [Alias("ID","ShadowID")]
        [string]$ShadowCopyID,
        [switch]$Force
    )
    process{
        IF (!($Force)){$a = Read-Host "Are you sure you want to remove Shadow copy $ShadowCopyID, This proccess can not be undone (y,n)"}else{$a="y"}
        IF ($a -like "*y*"){
            $ID = (Get-ShadowCopy | Where-Object -Property ID -EQ "$ShadowCopyID").ID
            if ($ID -eq "$null"){Throw "There is no ShadowCopy with ID $ShadowCopyID"}else{
                vssadmin delete shadows /shadow=$ID /quiet | Out-Null
                IF ($LASTEXITCODE -ne 0){Throw "Could not delete shadow copy"}
                Remove-Item HKLM:\SOFTWARE\ShadowCopyHandling\$ShadowCopyID -ErrorAction SilentlyContinue -Recurse -Force | out-null
            }
        }
    }
}