Two registry functions. First is a RegKeyExists function that will determine if a reg key exists without using the Registry plugin. The next one builds on that function, and can use SetACL to reset permissions on a key to allow you to delete it, ie the Enum\Root\LEGACY_ keys.
Should be self-explanatory how to use them. They use the same format as the Registry plugin, ie a full key path.
Release Notes:
Update 2008-04-06
-
Rewrote the functions so they no longer rely on the NSIS builtin registry functions. These functions are limited in that they cannot accept variables, and must be hardcoded.
I'll probably be updating this fairly regularly, adding new functions.
/************************************************************** * Copyright Erik Pilsits 2008 *************************************************************** * ${RegKeyExists} "[full key path]" $var * * $var 0 - key does not exist * 1 - key exists *************************************************************** * Var setacl * StrCpy $setacl "X:\path\to\SetACL.exe" * * ${SetACL_DeleteKey} "[full key path]" $var1 $var2 * * $var1 [number] - nsExec return code * "fail" - operation failed (key does not exist) * $var2 0 - delete succeeded * non-zero | "fail" - delete failed *************************************************************** * LONG WINAPI RegOpenKeyEx( * __in HKEY hKey, * __in_opt LPCTSTR lpSubKey, * __reserved DWORD ulOptions, * __in REGSAM samDesired, * __out PHKEY phkResult * ); * * LONG WINAPI RegCloseKey( * __in HKEY hKey * ); * * LSTATUS SHDeleteKey( * __in HKEY hkey, * __in LPCTSTR pszSubKey * ); ***************************************************************/ !include LogicLib.nsh !include WordFunc.nsh !insertmacro WordFind !define KEY_ALL_ACCESS "0xF003F" !define KEY_CREATE_SUB_KEY "0x0004" !define KEY_ENUMERATE_SUB_KEYS "0x0008" !define KEY_QUERY_VALUE "0x0001" !define KEY_READ "0x20019" !define KEY_SET_VALUE "0x0002" !define KEY_WRITE "0x20006" !define HKCR "0x80000000" !define HKCU "0x80000001" !define HKLM "0x80000002" !define HKU "0x80000003" !define HKPD "0x80000004" !define HKCC "0x80000005" !define HKDD "0x80000006" !define RegKeyExists "!insertmacro _RegKeyExists" !define SetACL_DeleteKey "!insertmacro _SetACL_DeleteKey" Function SplitKeyPath Exch $0 ; save $0, Pop keypath Push $1 ${WordFind} $0 "\" "+1" $1 ; key root Push $1 Exch 2 ${WordFind} $0 "\" "+1}" $1 ; subkey Pop $0 ; put root key and subkey on stack Exch $1 FunctionEnd Function GetRootHandle Exch $0 ; save $0, Pop root key ${Select} $0 ${Case2} "HKCR" "HKEY_CLASSES_ROOT" StrCpy $0 ${HKCR} ${Case2} "HKCU" "HKEY_CURRENT_USER" StrCpy $0 ${HKCU} ${Case2} "HKLM" "HKEY_LOCAL_MACHINE" StrCpy $0 ${HKLM} ${Case2} "HKU" "HKEY_USERS" StrCpy $0 ${HKU} ${Case2} "HKPD" "HKEY_PERFORMANCE_DATA" StrCpy $0 ${HKPD} ${Case2} "HKCC" "HKEY_CURRENT_CONFIG" StrCpy $0 ${HKCC} ${Case2} "HKDD" "HKEY_DYN_DATA" StrCpy $0 ${HKDD} ${EndSelect} Exch $0 ; put handle on stack FunctionEnd !macro _RegKeyExists keypath outVar Push $0 Push $1 Push "${keypath}" Call SplitKeyPath Pop $1 ; subkey ; stack already has root key Call GetRootHandle Pop $0 ; root key handle ; try to open key System::Call /NOUNLOAD 'Advapi32::RegOpenKeyEx(i r0, t r1, i 0, i ${KEY_READ}, *i .r1) i .r0' ; return values ${If} $0 = 0 ; success Push 1 System::Call 'Advapi32::RegCloseKey(i r1)' ; close handle ${Else} Push 0 System::Free 0 ; unload system dll ${EndIf} Exch 2 Pop $0 Pop $1 Pop ${outVar} !macroend !macro _SetACL_DeleteKey keypath outVar1 outVar2 Push $0 Push $1 ${RegKeyExists} "${keypath}" $0 ${If} $0 = 1 ; set permissions on key nsExec::Exec '"$setacl" -on "${keypath}" -ot reg -rec yes \ -actn clear -clr "dacl" \ -actn setowner -ownr "n:Administrators" \ -actn ace -ace "n:Everyone;p:full"' Push "${keypath}" Call SplitKeyPath Pop $1 ; subkey ; stack already has root key Call GetRootHandle Pop $0 ; root key handle ; delete key System::Call 'shlwapi::SHDeleteKey(i r0, t r1)i .s' ${Else} Push "fail" Push "fail" ${EndIf} Exch 3 Pop $0 Exch Pop $1 Pop ${outVar1} Pop ${outVar2} !macroend
Updated.