diff --git a/CHANGELOG.md b/CHANGELOG.md
index 298c734..400aaba 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -83,5 +83,7 @@ The format is based on
denied access
- Fix `Copy-Item2`, which failed with a `DirectoryNotFoundException` when it
copied a folder that contained files
+- Fix `Disable-Privileges`, which couldn't disable the privileges when the
+ module setting `EnablePrivileges` was `$false`
[Unreleased]: https://github.com/raandree/NTFSSecurity/compare/4.2.6...HEAD
diff --git a/Docs/Cmdlets/Disable-Privileges.md b/Docs/Cmdlets/Disable-Privileges.md
index 97b1fcc..0d48b8f 100644
--- a/Docs/Cmdlets/Disable-Privileges.md
+++ b/Docs/Cmdlets/Disable-Privileges.md
@@ -99,6 +99,8 @@ With `-PassThru`, the cmdlet writes the privilege collection of the current proc
When the module setting `EnablePrivileges` is `$true` (the default in the `PrivateData` section of NTFSSecurity.psd1), the file system cmdlets of the module try to enable the Backup, Restore, Take Ownership, and Security privileges while they run and disable the privileges they enabled when they finish. You therefore need `Disable-Privileges` only after an explicit `Enable-Privileges`. These privileges are only available in an elevated session of an account that holds them, such as a member of the local Administrators group.
+Before 5.0.0, when `EnablePrivileges` was `$false`, the cmdlet wrote warnings that it could not disable the privileges and left them enabled.
+
## RELATED LINKS
[Enable-Privileges](Enable-Privileges.md)
diff --git a/NTFSSecurity/BaseCmdlets.cs b/NTFSSecurity/BaseCmdlets.cs
index 7480a2a..0a5eb49 100644
--- a/NTFSSecurity/BaseCmdlets.cs
+++ b/NTFSSecurity/BaseCmdlets.cs
@@ -278,7 +278,8 @@ namespace NTFSSecurity
protected void DisableFileSystemPrivileges()
{
- var privileges = privControl.GetPrivileges();
+ // Refreshes the field that DisablePrivilege reads; it is null when BeginProcessing enabled nothing.
+ privileges = privControl.GetPrivileges();
if (privileges.Where(p => p.Privilege == Privilege.TakeOwnership) != null)
if (!TryDisablePrivilege(Privilege.TakeOwnership))
diff --git a/NTFSSecurity/en-US/NTFSSecurity.dll-Help.xml b/NTFSSecurity/en-US/NTFSSecurity.dll-Help.xml
index daf7f72..5731ff5 100644
--- a/NTFSSecurity/en-US/NTFSSecurity.dll-Help.xml
+++ b/NTFSSecurity/en-US/NTFSSecurity.dll-Help.xml
@@ -2788,6 +2788,7 @@ PS C:\> Set-NTFSSecurityDescriptor -SecurityDescriptor $sd
When the module setting `EnablePrivileges` is `$true` (the default in the `PrivateData` section of NTFSSecurity.psd1), the file system cmdlets of the module try to enable the Backup, Restore, Take Ownership, and Security privileges while they run and disable the privileges they enabled when they finish. You therefore need `Disable-Privileges` only after an explicit `Enable-Privileges`. These privileges are only available in an elevated session of an account that holds them, such as a member of the local Administrators group.
+ Before 5.0.0, when `EnablePrivileges` was `$false`, the cmdlet wrote warnings that it could not disable the privileges and left them enabled.
diff --git a/Tests/Privileges.Tests.ps1 b/Tests/Privileges.Tests.ps1
new file mode 100644
index 0000000..5070758
--- /dev/null
+++ b/Tests/Privileges.Tests.ps1
@@ -0,0 +1,63 @@
+<#
+ Tests how the cmdlets of the module built in NTFSSecurity\bin\Release handle the Backup, Restore, Take Ownership,
+ and Security privileges. These tests need an access token that holds the privileges, so they skip without them
+ and run in CI, whose runners are elevated. They change only the privileges of the test process and restore the
+ module setting EnablePrivileges.
+#>
+[Diagnostics.CodeAnalysis.SuppressMessageAttribute(
+ 'PSUseDeclaredVarsMoreThanAssignments', '', Justification = 'Pester shares variables between blocks.'
+)]
+param ()
+
+BeforeDiscovery {
+ Import-Module -Name (Join-Path -Path $PSScriptRoot -ChildPath 'TestHelpers.psm1') -Force
+ $missingPrivileges = @('SeBackupPrivilege', 'SeRestorePrivilege', 'SeTakeOwnershipPrivilege', 'SeSecurityPrivilege') |
+ Where-Object -FilterScript { -not (Test-PrivilegeHeld -Name $_) }
+ $holdsPrivileges = -not $missingPrivileges
+}
+
+BeforeAll {
+ Import-Module -Name (Join-Path -Path $PSScriptRoot -ChildPath 'TestHelpers.psm1') -Force
+ $modulePath = Join-Path -Path $PSScriptRoot -ChildPath '..\NTFSSecurity\bin\Release\NTFSSecurity.psd1'
+ Import-Module -Name $modulePath -Force -ErrorAction Stop
+ $sandbox = New-TestSandbox -Name 'Privileges'
+ Push-Location -LiteralPath $sandbox
+
+ $privateData = (Get-Module -Name NTFSSecurity).PrivateData
+ $enablePrivileges = $privateData['EnablePrivileges']
+
+ function Get-BackupPrivilegeState {
+ (Get-Privileges | Where-Object -Property Privilege -EQ -Value 'Backup').PrivilegeState
+ }
+}
+
+AfterAll {
+ $privateData['EnablePrivileges'] = $enablePrivileges
+ Disable-Privileges -ErrorAction SilentlyContinue -WarningAction SilentlyContinue
+ Pop-Location
+ Remove-TestSandbox -Sandbox $sandbox
+ Remove-Module -Name NTFSSecurity -Force -ErrorAction SilentlyContinue
+}
+
+Describe 'Disable-Privileges' {
+ Context 'When the module setting EnablePrivileges is $false' {
+ BeforeAll {
+ $privateData['EnablePrivileges'] = $false
+ }
+
+ AfterAll {
+ $privateData['EnablePrivileges'] = $enablePrivileges
+ }
+
+ # Before 5.0.0, the cmdlet warned that it could not disable the privileges and left them enabled.
+ It 'Should disable the privileges that Enable-Privileges enabled' -Skip:(-not $holdsPrivileges) {
+ Enable-Privileges
+ Get-BackupPrivilegeState | Should -Be 'Enabled'
+
+ Disable-Privileges -WarningVariable privilegeWarnings -WarningAction SilentlyContinue
+
+ $privilegeWarnings | Should -BeNullOrEmpty
+ Get-BackupPrivilegeState | Should -Be 'Disabled'
+ }
+ }
+}