You are here

NSIS Header RegOps2

2 posts / 0 new
Last post
wraithdu
Offline
Last seen: 10 years 11 months ago
Developer
Joined: 2007-06-27 20:22
NSIS Header RegOps2

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
wraithdu
Offline
Last seen: 10 years 11 months ago
Developer
Joined: 2007-06-27 20:22
Updated.

Updated.

Log in or register to post comments