ntdll/NtDeleteValueKey.ps1
function NtDeleteValueKey { <# .SYNOPSIS Deletes a value entry matching a name from an open key in the registry. If no such entry exists, an error is returned. .PARAMETER KeyHandle A HANDLE to an open registry key. Use NtCreateKey to get a registry key handle. This handle must have sufficient DesiredAccess to delete the key (e.g. KEY_ALL_ACCESS) .PARAMETER ValueName The name of the value entry to delete. .NOTES Author: Jared Atkinson (@jaredcatkinson), Brian Reitz (@brian_psu) License: BSD 3-Clause Required Dependencies: PSReflect, UNICODE_STRING (Enumeration) Optional Dependencies: None (func ntdll NtDeleteValueKey ([UInt32]) @( [IntPtr], #_In_ HANDLE KeyHandle, $UNICODE_STRING.MakeByRefType() #_In_ PUNICODE_STRING ValueName ) -EntryPoint NtDeleteValueKey) .LINK https://msdn.microsoft.com/en-us/library/windows/hardware/ff566439(v=vs.85).aspx .EXAMPLE #> param ( [Parameter(Mandatory = $true)] [IntPtr] $KeyHandle, [Parameter(Mandatory = $true)] [string] $ValueName ) # Create a $UNICODE_STRING structure and a pointer to it. $vName = [Activator]::CreateInstance($UNICODE_STRING) $vName.Length = $ValueName.Length * 2 $vName.MaximumLength = $ValueName.Length * 2 $vName.Buffer = [System.Runtime.InteropServices.Marshal]::StringToCoTaskMemUni($ValueName) $pValueName = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($UNICODE_STRING::GetSize()) [System.Runtime.InteropServices.Marshal]::StructureToPtr($vName, $pValueName, $true) $Success = $ntdll::NtDeleteValueKey($KeyHandle, [ref]$pValueName); $LastError = [Runtime.InteropServices.Marshal]::GetLastWin32Error() if(-not $Success) { Write-Debug "NtDeleteValueKey Error: $(([ComponentModel.Win32Exception] $LastError).Message)" } # free our memory after allocation # Cannot convert argument "hglobal", with value: "UNICODE_STRING", for "FreeHGlobal" to type "System.IntPtr" # [System.Runtime.InteropServices.Marshal]::FreeHGlobal($pValueName) } |