@ -8,8 +8,6 @@
# Requires -Module Ansible.ModuleUtils.Legacy
# Requires -Module Ansible.ModuleUtils.Legacy
# Requires -Module Ansible.ModuleUtils.PrivilegeUtil
# Requires -Module Ansible.ModuleUtils.PrivilegeUtil
$ErrorActionPreference = " Stop "
$params = Parse-Args -arguments $args -supports_check_mode $true
$params = Parse-Args -arguments $args -supports_check_mode $true
$check_mode = Get-AnsibleParam -obj $params -name " _ansible_check_mode " -type " bool " -default $false
$check_mode = Get-AnsibleParam -obj $params -name " _ansible_check_mode " -type " bool " -default $false
$diff_mode = Get-AnsibleParam -obj $params -name " _ansible_diff " -type " bool " -default $false
$diff_mode = Get-AnsibleParam -obj $params -name " _ansible_diff " -type " bool " -default $false
@ -31,7 +29,8 @@ $result = @{
if ( $diff_mode ) {
if ( $diff_mode ) {
$result . diff = @ {
$result . diff = @ {
prepared = " "
before = " "
after = " "
}
}
}
}
@ -40,12 +39,20 @@ using System;
using System . Collections . Generic ;
using System . Collections . Generic ;
using System . Runtime . InteropServices ;
using System . Runtime . InteropServices ;
namespace Ansible . RegE dit
namespace Ansible . WinRege dit
{
{
public enum HKEY : uint
internal class NativeMethods
{
{
LOCAL_MACHINE = 0x80000002 ,
[ DllImport ( " advapi32.dll " , CharSet = CharSet . Unicode ) ]
USERS = 0x80000003
public static extern int RegLoadKeyW (
UInt32 hKey ,
string lpSubKey ,
string lpFile ) ;
[ DllImport ( " advapi32.dll " , CharSet = CharSet . Unicode ) ]
public static extern int RegUnLoadKeyW (
UInt32 hKey ,
string lpSubKey ) ;
}
}
public class Win32Exception : System . ComponentModel . Win32Exception
public class Win32Exception : System . ComponentModel . Win32Exception
@ -60,41 +67,48 @@ namespace Ansible.RegEdit
public static explicit operator Win32Exception ( string message ) { return new Win32Exception ( message ) ; }
public static explicit operator Win32Exception ( string message ) { return new Win32Exception ( message ) ; }
}
}
public class Hive
public class Hive : IDisposable
{
{
[ DllImport ( " advapi32.dll " , CharSet = CharSet . Auto , SetLastError = true ) ]
private const UInt32 SCOPE = 0x80000002 ; / / HKLM
private static extern int RegLoadKey (
private string hiveKey ;
HKEY hKey ,
private bool loaded = false ;
string lpSubKey ,
string lpFile ) ;
[ DllImport ( " advapi32.dll " , CharSet = CharSet . Auto , SetLastError = true ) ]
public Hive ( string hiveKey , string hivePath )
private static extern int RegUnLoadKey (
HKEY hKey ,
string lpSubKey ) ;
public static void LoadHive ( string lpSubKey , string lpFile )
{
{
int ret ;
this . hiveKey = hiveKey ;
ret = RegLoadKey ( HKEY . LOCAL_MACHINE , lpSubKey , lpFile ) ;
int ret = NativeMethods . RegLoadKeyW ( SCOPE , hiveKey , hivePath ) ;
if ( ret ! = 0 )
if ( ret ! = 0 )
throw new Win32Exception ( ret , String . Format ( " Failed to load registry hive at {0} " , lpFile ) ) ;
throw new Win32Exception ( ret , String . Format ( " Failed to load registry hive at {0} " , hivePath ) ) ;
loaded = true ;
}
}
public static void UnloadHive ( string lpSub Key)
public static void UnloadHive ( string hive Key)
{
{
GC . Collect ( ) ;
int ret = NativeMethods . RegUnLoadKeyW ( SCOPE , hiveKey ) ;
int ret ;
ret = RegUnLoadKey ( HKEY . LOCAL_MACHINE , lpSubKey ) ;
if ( ret ! = 0 )
if ( ret ! = 0 )
throw new Win32Exception ( ret , String . Format ( " Failed to unload registry hive at {0} " , lpSubKey ) ) ;
throw new Win32Exception ( ret , String . Format ( " Failed to unload registry hive at {0} " , hiveKey ) ) ;
}
public void Dispose ( )
{
if ( loaded )
{
/ / Make sure the garbage collector disposes all unused handles and waits until it is complete
GC . Collect ( ) ;
GC . WaitForPendingFinalizers ( ) ;
UnloadHive ( hiveKey ) ;
loaded = false ;
}
GC . SuppressFinalize ( this ) ;
}
}
~ Hive ( ) { this . Dispose ( ) ; }
}
}
}
}
' @
' @
# fire a warning if the property name isn't specified, the (Default) key ($null) can only be a string
# fire a warning if the property name isn't specified, the (Default) key ($null) can only be a string
if ( $name -eq $null -and $type -ne " string " ) {
if ( $null -eq $name -and $type -ne " string " ) {
Add-Warning -obj $result -message " the data type when name is not specified can only be 'string', the type has automatically been converted "
Add-Warning -obj $result -message " the data type when name is not specified can only be 'string', the type has automatically been converted "
$type = " string "
$type = " string "
}
}
@ -104,16 +118,13 @@ if ($path -notmatch "^HK(CC|CR|CU|LM|U):\\") {
Fail-Json $result " path: $path is not a valid powershell path, see module documentation for examples. "
Fail-Json $result " path: $path is not a valid powershell path, see module documentation for examples. "
}
}
# Create the required PSDrives if missing
# Add a warning if the path does not contains a \ and is not the leaf path
$registry_hive = Split-Path -Path $path -Qualifier
$registry_path = ( Split-Path -Path $path -NoQualifier ) . Substring ( 1 ) # removes the hive: and leading \
if ( $registry_hive -eq " HKCR: " -and ( -not ( Test-Path HKCR : \ ) ) ) {
$registry_leaf = Split-Path -Path $path -Leaf
New-PSDrive -Name HKCR -PSProvider Registry -Root HKEY_CLASSES_ROOT
if ( $registry_path -ne $registry_leaf -and -not $registry_path . Contains ( '\' ) ) {
}
$msg = " path is not using '\' as a separator, support for '/' as a separator will be removed in a future Ansible version "
if ( $registry_hive -eq " HKU: " -and ( -not ( Test-Path HKU : \ ) ) ) {
Add-DeprecationWarning -obj $result -message $msg -version 2.12
New-PSDrive -Name HKU -PSProvider Registry -Root HKEY_USERS
$registry_path = $registry_path . Replace ( '/' , '\' )
}
if ( $registry_hive -eq " HKCC: " -and ( -not ( Test-Path HKCC : \ ) ) ) {
New-PSDrive -Name HKCC -PSProvider Registry -Root HKEY_CURRENT_CONFIG
}
}
# Simplified version of Convert-HexStringToByteArray from
# Simplified version of Convert-HexStringToByteArray from
@ -148,62 +159,202 @@ Function Convert-RegExportHexStringToByteArray($string) {
}
}
}
}
Function Test-RegistryProperty($path , $name ) {
Function Compare-RegistryProperties($existing , $new ) {
# will validate if the registry key contains the property, returns true
# Outputs $true if the property values don't match
# if the property exists and false if the property does not
if ( $existing -is [ Array ] ) {
( Compare-Object -ReferenceObject $existing -DifferenceObject $new -SyncWindow 0 ) . Length -ne 0
} else {
$existing -cne $new
}
}
Function Get-DiffValue {
param (
[ Parameter ( Mandatory = $true ) ] [ Microsoft.Win32.RegistryValueKind ] $Type ,
[ Parameter ( Mandatory = $true ) ] [ Object ] $Value
)
$diff = @ { type = $Type . ToString ( ) ; value = $Value }
$enum = [ Microsoft.Win32.RegistryValueKind ]
if ( $Type -in @ ( $enum :: Binary , $enum :: None ) ) {
$diff . value = [ System.Collections.Generic.List`1[String] ] @ ( )
foreach ( $dec_value in $Value ) {
$diff . value . Add ( " 0x{0:x2} " -f $dec_value )
}
} elseif ( $Type -eq $enum :: DWord ) {
$diff . value = " 0x{0:x8} " -f $Value
} elseif ( $Type -eq $enum :: QWord ) {
$diff . value = " 0x{0:x16} " -f $Value
}
return $diff
}
Function Set-StateAbsent {
param (
# Used for diffs and exception messages to match up against Ansible input
[ Parameter ( Mandatory = $true ) ] [ String ] $PrintPath ,
[ Parameter ( Mandatory = $true ) ] [ Microsoft.Win32.RegistryKey ] $Hive ,
[ Parameter ( Mandatory = $true ) ] [ String ] $Path ,
[ String ] $Name ,
[ Switch ] $DeleteKey
)
$key = $Hive . OpenSubKey ( $Path , $true )
if ( $null -eq $key ) {
# Key does not exist, no need to delete anything
return
}
try {
try {
$reg_key = Get-Item -Path $path
if ( $DeleteKey -and -not $Name ) {
$value = $reg_key . GetValue ( $name )
# delete_key=yes is set and name is null/empty, so delete the entire key
# need to do it this way return ($value -eq $null) does not work
$key . Dispose ( )
if ( $value -eq $null ) {
$key = $null
return $false
if ( -not $check_mode ) {
try {
$Hive . DeleteSubKeyTree ( $Path , $false )
} catch {
Fail-Json -obj $result -message " failed to delete registry key at $( $PrintPath ) : $( $_ . Exception . Message ) "
}
}
$result . changed = $true
if ( $diff_mode ) {
$result . diff . before = @ { $PrintPath = @ { } }
$result . diff . after = @ { }
}
} else {
} else {
return $true
# delete_key=no or name is not null/empty, delete the property not the full key
$property = $key . GetValue ( $Name )
if ( $null -eq $property ) {
# property does not exist
return
}
$property_type = $key . GetValueKind ( $Name ) # used for the diff
if ( -not $check_mode ) {
try {
$key . DeleteValue ( $Name )
} catch {
Fail-Json -obj $result -message " failed to delete registry property ' $Name ' at $( $PrintPath ) : $( $_ . Exception . Message ) "
}
}
$result . changed = $true
if ( $diff_mode ) {
$diff_value = Get-DiffValue -Type $property_type -Value $property
$result . diff . before = @ { $PrintPath = @ { $Name = $diff_value } }
$result . diff . after = @ { $PrintPath = @ { } }
}
}
}
} catch [ System.Management.Automation.ItemNotFoundException ] {
# key didn't exist so the property mustn't
return $false
} finally {
} finally {
if ( $reg_key ) {
if ( $key ) {
$reg_key . Close ( )
$key . Dispose ( )
}
}
}
}
}
}
Function Compare-RegistryProperties($existing , $new ) {
Function Set-StatePresent {
$mismatch = $false
param (
if ( $existing -is [ Array ] ) {
[ Parameter ( Mandatory = $true ) ] [ String ] $PrintPath ,
if ( ( Compare-Object -ReferenceObject $existing -DifferenceObject $new -SyncWindow 0 ) . Length -ne 0 ) {
[ Parameter ( Mandatory = $true ) ] [ Microsoft.Win32.RegistryKey ] $Hive ,
$mismatch = $true
[ Parameter ( Mandatory = $true ) ] [ String ] $Path ,
[ String ] $Name ,
[ Object ] $Data ,
[ Microsoft.Win32.RegistryValueKind ] $Type
)
$key = $Hive . OpenSubKey ( $Path , $true )
try {
if ( $null -eq $key ) {
# the key does not exist, create it so the next steps work
if ( -not $check_mode ) {
try {
$key = $Hive . CreateSubKey ( $Path )
} catch {
Fail-Json -obj $result -message " failed to create registry key at $( $PrintPath ) : $( $_ . Exception . Message ) "
}
}
$result . changed = $true
if ( $diff_mode ) {
$result . diff . before = @ { }
$result . diff . after = @ { $PrintPath = @ { } }
}
} elseif ( $diff_mode ) {
# Make sure the diff is in an expected state for the key
$result . diff . before = @ { $PrintPath = @ { } }
$result . diff . after = @ { $PrintPath = @ { } }
}
}
} else {
if ( $existing -cne $new ) {
if ( $null -eq $key -or $null -eq $Data ) {
$mismatch = $true
# Check mode and key was created above, we cannot do any more work, or $Data is $null which happens when
# we create a new key but haven't explicitly set the data
return
}
}
}
return $mismatch
$property = $key . GetValue ( $Name , $null , [ Microsoft.Win32.RegistryValueOptions ] :: DoNotExpandEnvironmentNames )
}
if ( $null -ne $property ) {
# property exists, need to compare the values and type
$existing_type = $key . GetValueKind ( $name )
$change_value = $false
Function Get-DiffValueString($type , $value ) {
if ( $Type -ne $existing_type ) {
$enum = [ Microsoft.Win32.RegistryValueKind ]
$change_value = $true
if ( $type -in @ ( $enum :: Binary , $enum :: None ) ) {
$result . data_type_changed = $true
$hex_values = @ ( )
$data_mismatch = Compare-RegistryProperties -existing $property -new $Data
foreach ( $dec_value in $value ) {
if ( $data_mismatch ) {
$hex_values + = " 0x $( " {0:x2} " -f $dec_value ) "
$result . data_changed = $true
}
} else {
$data_mismatch = Compare-RegistryProperties -existing $property -new $Data
if ( $data_mismatch ) {
$change_value = $true
$result . data_changed = $true
}
}
if ( $change_value ) {
if ( -not $check_mode ) {
try {
$key . SetValue ( $Name , $Data , $Type )
} catch {
Fail-Json -obj $result -message " failed to change registry property ' $Name ' at $( $PrintPath ) : $( $_ . Exception . Message ) "
}
}
$result . changed = $true
if ( $diff_mode ) {
$result . diff . before . $PrintPath . $Name = Get-DiffValue -Type $existing_type -Value $property
$result . diff . after . $PrintPath . $Name = Get-DiffValue -Type $Type -Value $Data
}
} elseif ( $diff_mode ) {
$diff_value = Get-DiffValue -Type $existing_type -Value $property
$result . diff . before . $PrintPath . $Name = $diff_value
$result . diff . after . $PrintPath . $Name = $diff_value
}
} else {
# property doesn't exist just create a new one
if ( -not $check_mode ) {
try {
$key . SetValue ( $Name , $Data , $Type )
} catch {
Fail-Json -obj $result -message " failed to create registry property ' $Name ' at $( $PrintPath ) : $( $_ . Exception . Message ) "
}
}
$result . changed = $true
if ( $diff_mode ) {
$result . diff . after . $PrintPath . $Name = Get-DiffValue -Type $Type -Value $Data
}
}
} finally {
if ( $key ) {
$key . Dispose ( )
}
}
$diff_value = " $( $type ) :[ $( $hex_values -join " , " ) ] "
} elseif ( $type -eq $enum :: DWord ) {
$diff_value = " $( $type ) :0x $( " {0:x8} " -f $value ) "
} elseif ( $type -eq $enum :: QWord ) {
$diff_value = " $( $type ) :0x $( " {0:x16} " -f $value ) "
} elseif ( $type -eq $enum :: MultiString ) {
$diff_value = " $( $type ) :[ $( $value -join " , " ) ] "
} else {
$diff_value = " $( $type ) : $value "
}
}
return $diff_value
}
}
# convert property names "" to $null as "" refers to (Default)
# convert property names "" to $null as "" refers to (Default)
@ -213,7 +364,7 @@ if ($name -eq "") {
# convert the data to the required format
# convert the data to the required format
if ( $type -in @ ( " binary " , " none " ) ) {
if ( $type -in @ ( " binary " , " none " ) ) {
if ( $data -eq $null ) {
if ( $null -eq $data ) {
$data = " "
$data = " "
}
}
@ -230,7 +381,7 @@ if ($type -in @("binary", "none")) {
}
}
} elseif ( $type -in @ ( " dword " , " qword " ) ) {
} elseif ( $type -in @ ( " dword " , " qword " ) ) {
# dword's and dword's don't allow null values, set to 0
# dword's and dword's don't allow null values, set to 0
if ( $data -eq $null ) {
if ( $null -eq $data ) {
$data = 0
$data = 0
}
}
@ -260,14 +411,15 @@ if ($type -in @("binary", "none")) {
}
}
$data = [ Int64 ] $data
$data = [ Int64 ] $data
}
}
} elseif ( $type -in @ ( " string " , " expandstring " ) ) {
} elseif ( $type -in @ ( " string " , " expandstring " ) -and $name ) {
# a null string or expandstring must be empty quotes
# a null string or expandstring must be empty quotes
if ( $data -eq $null ) {
# Only do this if $name has been defined (not the default key)
if ( $null -eq $data ) {
$data = " "
$data = " "
}
}
} elseif ( $type -eq " multistring " ) {
} elseif ( $type -eq " multistring " ) {
# convert the data for a multistring to a String[] array
# convert the data for a multistring to a String[] array
if ( $data -eq $null ) {
if ( $null -eq $data ) {
$data = [ String[] ] @ ( )
$data = [ String[] ] @ ( )
} elseif ( $data -isnot [ Array ] ) {
} elseif ( $data -isnot [ Array ] ) {
$new_data = New-Object -TypeName String [ ] -ArgumentList 1
$new_data = New-Object -TypeName String [ ] -ArgumentList 1
@ -285,209 +437,59 @@ if ($type -in @("binary", "none")) {
# convert the type string to the .NET class
# convert the type string to the .NET class
$type = [ System.Enum ] :: Parse ( [ Microsoft.Win32.RegistryValueKind ] , $type , $true )
$type = [ System.Enum ] :: Parse ( [ Microsoft.Win32.RegistryValueKind ] , $type , $true )
if ( $hive ) {
$registry_hive = switch ( Split-Path -Path $path -Qualifier ) {
if ( -not ( Test-Path $hive ) ) {
" HKCR: " { [ Microsoft.Win32.Registry ] :: ClassesRoot }
Fail-Json -obj $result -message " hive at path ' $hive ' is not valid or accessible, cannot load hive "
" HKCC: " { [ Microsoft.Win32.Registry ] :: CurrentConfig }
}
" HKCU: " { [ Microsoft.Win32.Registry ] :: CurrentUser }
" HKLM: " { [ Microsoft.Win32.Registry ] :: LocalMachine }
$original_tmp = $env:TMP
" HKU " { [ Microsoft.Win32.Registry ] :: Users }
$env:TMP = $_remote_tmp
}
Add-Type -TypeDefinition $registry_util
$loaded_hive = $null
$env:TMP = $original_tmp
try {
if ( $hive ) {
if ( -not ( Test-Path -LiteralPath $hive ) ) {
Fail-Json -obj $result -message " hive at path ' $hive ' is not valid or accessible, cannot load hive "
}
try {
$original_tmp = $env:TMP
Set-AnsiblePrivilege -Name SeBackupPrivilege -Value $true
$env:TMP = $_remote_tmp
Set-AnsiblePrivilege -Name SeRestorePrivilege -Value $true
Add-Type -TypeDefinition $registry_util
} catch [ System.ComponentModel.Win32Exception ] {
$env:TMP = $original_tmp
Fail-Json -obj $result -message " failed to enable SeBackupPrivilege and SeRestorePrivilege for the current process: $( $_ . Exception . Message ) "
}
if ( Test-Path -Path HKLM : \ ANSIBLE ) {
Add-Warning -obj $result -message " hive already loaded at HKLM:\ANSIBLE, had to unload hive for win_regedit to continue "
try {
try {
[ Ansible.RegEdit.Hive ] :: UnloadHive ( " ANSIBLE " )
Set-AnsiblePrivilege -Name SeBackupPrivilege -Value $true
Set-AnsiblePrivilege -Name SeRestorePrivilege -Value $true
} catch [ System.ComponentModel.Win32Exception ] {
} catch [ System.ComponentModel.Win32Exception ] {
Fail-Json -obj $result -message " failed to unload registry hive HKLM:\ANSIBLE from $( $hive ) : $( $_ . Exception . Message ) "
Fail-Json -obj $result -message " failed to enable SeBackupPrivilege and SeRestorePrivilege for the current process : $( $_ . Exception . Message ) "
}
}
}
try {
[ Ansible.RegEdit.Hive ] :: LoadHive ( " ANSIBLE " , $hive )
} catch [ System.ComponentModel.Win32Exception ] {
Fail-Json -obj $result -message " failed to load registry hive from ' $hive ' to HKLM:\ANSIBLE: $( $_ . Exception . Message ) "
}
}
try {
if ( Test-Path -Path HKLM : \ ANSIBLE ) {
if ( $state -eq " present " ) {
Add-Warning -obj $result -message " hive already loaded at HKLM:\ANSIBLE, had to unload hive for win_regedit to continue "
if ( -not ( Test-Path -path $path ) ) {
# the key doesn't exist, create it so the next steps work
try {
try {
$new_key = New-Item -Path $path -Type directory -Force -WhatIf: $check_mode
[ Ansible.WinRegedit.Hive ] :: UnloadHive ( " ANSIBLE " )
} catch {
} catch [ System.ComponentModel.Win32Exception ] {
Fail-Json $result " failed to create registry key at $( $path ) : $( $_ . Exception . Message ) "
Fail-Json -obj $result -message " failed to unload registry hive HKLM:\ANSIBLE from $( $hive ) : $( $_ . Exception . Message ) "
} finally {
if ( $new_key ) {
$new_key . Close ( )
}
}
$result . changed = $true
if ( $diff_mode ) {
$result . diff . prepared + = @ "
+ [ $path ]
" @
}
}
}
}
if ( Test-RegistryProperty -path $path -name $name ) {
try {
# property exists, need to compare the values and type
$loaded_hive = New-Object -TypeName Ansible . WinRegedit . Hive -ArgumentList " ANSIBLE " , $hive
$existing_key = Get-Item -Path $path
} catch [ System.ComponentModel.Win32Exception ] {
$existing_type = $existing_key . GetValueKind ( $name )
Fail-Json -obj $result -message " failed to load registry hive from ' $hive ' to HKLM:\ANSIBLE: $( $_ . Exception . Message ) "
$existing_data = $existing_key . GetValue ( $name , $false , [ Microsoft.Win32.RegistryValueOptions ] :: DoNotExpandEnvironmentNames )
$existing_key . Close ( )
$change_value = $false
if ( $type -ne $existing_type ) {
$change_value = $true
$result . data_type_changed = $true
$data_mismatch = Compare-RegistryProperties -existing $existing_data -new $data
if ( $data_mismatch ) {
$result . data_changed = $true
}
} else {
$data_mismatch = Compare-RegistryProperties -existing $existing_data -new $data
if ( $data_mismatch ) {
$change_value = $true
$result . data_changed = $true
}
}
if ( $change_value ) {
if ( -not $check_mode ) {
$reg_key = Get-Item -Path $path
try {
$sub_key = $reg_key . OpenSubKey ( $null , [ Microsoft.Win32.RegistryKeyPermissionCheck ] :: ReadWriteSubTree )
try {
$sub_key . SetValue ( $name , $data , $type )
} finally {
$sub_key . Close ( )
}
} catch {
Fail-Json $result " failed to change registry property ' $name ' at $( $path ) : $( $_ . Exception . Message ) "
} finally {
$reg_key . Close ( )
}
}
$result . changed = $true
if ( $diff_mode ) {
if ( $result . diff . prepared ) {
$key_prefix = " + "
} else {
$key_prefix = " "
}
$result . diff . prepared = @ "
$key_prefix [ $path ]
- " $name " = " $( Get-DiffValueString -type $existing_type -value $existing_data ) "
+ " $name " = " $( Get-DiffValueString -type $type -value $data ) "
" @
}
}
} else {
# property doesn't exist just create a new one
if ( -not $check_mode ) {
$reg_key = Get-Item -Path $path
try {
$sub_key = $reg_key . OpenSubKey ( $null , [ Microsoft.Win32.RegistryKeyPermissionCheck ] :: ReadWriteSubTree )
try {
$sub_key . SetValue ( $name , $data , $type )
} finally {
$sub_key . Close ( )
}
} catch {
Fail-Json $result " failed to change registry property ' $name ' at $( $path ) : $( $_ . Exception . Message ) "
} finally {
$reg_key . Close ( )
}
}
$result . changed = $true
if ( $diff_mode ) {
if ( $result . diff . prepared ) {
$key_prefix = " + "
} else {
$key_prefix = " "
}
$result . diff . prepared = @ "
$key_prefix [ $path ]
+ " $name " = " $( Get-DiffValueString -type $type -value $data ) "
" @
}
}
}
} else {
}
if ( Test-Path -path $path ) {
if ( $delete_key -and $name -eq $null ) {
# the clear_key flag is set and name is null so delete the entire key
try {
$null = Remove-Item -Path $path -Force -Recurse -WhatIf: $check_mode
} catch {
Fail-Json $result " failed to delete registry key at $( $path ) : $( $_ . Exception . Message ) "
}
$result . changed = $true
if ( $diff_mode ) {
$result . diff . prepared + = @ "
- [ $path ]
" @
}
} else {
# the clear_key flag is set or name is not null, check whether we need to delete a property
if ( Test-RegistryProperty -path $path -name $name ) {
$existing_key = Get-Item -Path $path
$existing_type = $existing_key . GetValueKind ( $name )
$existing_data = $existing_key . GetValue ( $name , $false , [ Microsoft.Win32.RegistryValueOptions ] :: DoNotExpandEnvironmentNames )
$existing_key . Close ( )
# cannot use Remove-ItemProperty as it fails when deleting the (Default) key ($name = $null)
if ( -not $check_mode ) {
$reg_key = Get-Item -Path $path
try {
$sub_key = $reg_key . OpenSubKey ( $null , [ Microsoft.Win32.RegistryKeyPermissionCheck ] :: ReadWriteSubTree )
try {
$sub_key . DeleteValue ( $name )
} finally {
$sub_key . Close ( )
}
} catch {
Fail-Json $result " failed to delete registry property ' $name ' at $( $path ) : $( $_ . Exception . Message ) "
} finally {
$reg_key . Close ( )
}
}
$result . changed = $true
if ( $diff_mode ) {
if ( $state -eq " present " ) {
$result . diff . prepared + = @ "
Set-StatePresent -PrintPath $path -Hive $registry_hive -Path $registry_path -Name $name -Data $data -Type $type
[ $path ]
} else {
- " $name " = " $( Get-DiffValueString -type $existing_type -value $existing_data ) "
Set-StateAbsent -PrintPath $path -Hive $registry_hive -Path $registry_path -Name $name -DeleteKey: $delete_key
" @
}
}
}
}
}
}
} finally {
} finally {
if ( $hive ) {
$registry_hive . Dispose ( )
[ GC ] :: Collect ( )
if ( $loaded_hive ) {
[ GC ] :: WaitForPendingFinalizers ( )
$loaded_hive . Dispose ( )
try {
[ Ansible.RegEdit.Hive ] :: UnloadHive ( " ANSIBLE " )
} catch [ System.ComponentModel.Win32Exception ] {
Fail-Json -obj $result -message " failed to unload registry hive HKLM:\ANSIBLE from $( $hive ) : $( $_ . Exception . Message ) "
}
}
}
}
}
Exit-Json $result
Exit-Json $result