Topic 5.1

Overview

An Overview of the Custom.nsh File

In this section I'll be talking about the custom.nsh file and it's many implimentations. The custom.nsh file is used by PAL for anything that the launcher cannot handle itself. It allows the developer the ability to incorporate NSIS code into the launcher while maintaining the PAL framework and it's structure. While it is not required for use with the original builds?The idea behind PAL in the beginning was to make it much easier for the end-user to make PAF compliant portable applications with knowing little about NSIS or knowing nothing at all. of PAL, it is however an essential part of FukenGruven's build of the launcher. This file, for the most part, should be your main focus if you're building with FukenGruven's PAL for it's where the real magic happens.

Below is the custom.nsh file I wrote to be used with my Process Hacker Portable. For the purpose of this section I'll go ahead and explain in detail everything that I wrote, used, and why in the making of this portable application..

Note
I'll be explaining the custom.nsh as it pertains to how I use PAL. All the portable applications that I make are made using my own edit of FukenGruven's PAL?I use his version released on March 15th, 2017 which may be found here.. The explainations or written below the following code block.
;= LAUNCHER
;= ################
; !define UAC true
; !define REPLACE true
; !define REGISTRY true
; !define SERVICES true
; !define DIRECTORIES_MOVE true
; !define FILES_MOVE true
; !define TrimString true

;= VARIABLES 
;= ################
 
;= DEFINES
;= ################
!define APP         ProcessHacker
!define FULLNAME	`Process Hacker`
!define APPDIR		`$EXEDIR\App\${APP}\x86`
!define APPDIR64	`$EXEDIR\App\${APP}\x64`
!define XML         `${SET}\ProcessHacker.exe.settings.xml`
!define DEFXML		`${DEFSET}\ProcessHacker.exe.settings.xml`
!define SVC         `KProcessHacker3`
!define KPH         `${APPDIR}\kprocesshacker.sys`
!define KPH64		`${APPDIR64}\kprocesshacker.sys`
!define SVCKEY		SYSTEM\CurrentControlSet\services\${SVC}
!define HKLM		HKLM\${SCKEY}
!define TASK		`SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\taskmgr.exe`
!define GETV		`Kernel32::GetVolumeInformation(t,t,i,*i,*i,*i,t,i) i`
!define GET         `${GETV}("$0",,${NSIS_MAX_STRLEN},.r0,,,,${NSIS_MAX_STRLEN})`
!define ID			`Kernel32::SetEnvironmentVariable(t "LastUniqueID", t "$0")`
!define IMPORT		`"$SYSDIR\certutil.exe" -importpfx -p "" "$PLUGINSDIR\PortableAppz.p12"`
!define SET32		`Kernel32::SetEnvironmentVariable(t "PROHACK", t "x86")`
!define SET64		`Kernel32::SetEnvironmentVariable(t "PROHACK", t "x64")`

;= FUNCTIONS
;= ################
Function ReadS
	!macro _ReadS _FILE _ENTRY _RESULT
		Push `${_FILE}`
		Push `${_ENTRY}`
		Call ReadS
		Pop ${_RESULT}
	!macroend
	!define ReadS `!insertmacro _ReadS`
	!insertmacro TextFunc_BOM
	Exch $1
	Exch
	Exch $0
	Exch
	Push $2
	Push $3
	Push $4
	Push $5
	ClearErrors
	FileOpen $2 $0 r
	IfErrors +22
	FileReadWord $2 $5
	IntCmp $5 0xFEFF +4
	FileSeek $2 0 SET
	StrCpy $TextFunc_BOM 0
	Goto +2
	StrCpy $TextFunc_BOM FFFE
	StrLen $0 $1
	StrCmpS $0 0 +14
	IntCmp $5 0xFEFF +3
	FileRead $2 $3
	Goto +2
	FileReadUTF16LE $2 $3
	IfErrors +9
	StrCpy $4 $3 $0
	StrCmpS $4 $1 0 -6
	StrCpy $0 $3 '' $0
	StrCpy $4 $0 1 -1
	StrCmpS $4 '$\r' +2
	StrCmpS $4 '$\n' 0 +5
	StrCpy $0 $0 -1
	Goto -4
	SetErrors
	StrCpy $0 ''
	FileClose $2
	Pop $5
	Pop $4
	Pop $3
	Pop $2
	Pop $1
	Exch $0
FunctionEnd

;= MACROS
;= ################
!define ImportDigitalSignature "!insertmacro _ImportDigitalSignature"
!macro _ImportDigitalSignature
	SetOutPath `$PLUGINSDIR`
	File PortableAppz.p12
	ExecDos::Exec /TOSTACK `${IMPORT}`
!macroend
!define MsgBox "!insertmacro MsgBox"
!macro MsgBox
	StrCpy $0 `Windows XP +`
	MessageBox MB_ICONSTOP|MB_TOPMOST `$(MINREQ)`
	Call Unload
	Quit
!macroend

;= CUSTOM 
;= ################
${SegmentFile}
${Segment.OnInit}
	StrCmp $Bit 64 +3
	System::Call `${SET32}`
	Goto +2
	System::Call `${SET64}`
!macroend
!macro RunAsAdmin
	${If} ${ProcessExists} ${APP}.exe
		Return
	${Else}
		Elevate:
		!insertmacro UAC_RunElevated
		${Switch} $0
			${Case} 0
				${IfThen} $1 = 1 ${|} Quit ${|}
				${If} $3 <> 0
					${Break}
				${EndIf}
				${If} $1 = 3
					MessageBox MB_RETRYCANCEL|MB_ICONINFORMATION|MB_TOPMOST|MB_SETFOREGROUND "$(LauncherRequiresAdmin)$\r$\n$\r$\n$(LauncherNotAdminTryAgain)" IDRETRY Elevate
					Quit
				${EndIf}
			${CaseUACCodeAlert} 1223 \
				"$(LauncherRequiresAdmin)" \
				"$(LauncherNotAdminLimitedFunctionality)"
			${CaseUACCodeAlert} 1062 \
				"$(LauncherAdminLogonServiceNotRunning)" \
				"$(LauncherNotAdminLimitedFunctionality)"
			${CaseUACCodeAlert} "" \
				"$(LauncherAdminError)$\r$\n$(LauncherRequiresAdmin)" \
				"$(LauncherAdminError)$\r$\n$(LauncherNotAdminLimitedFunctionality)"
		${EndSwitch}
	${EndIf}
!macroend
!macro RunAsAdminOverride
	${If} $SecondaryLaunch != true
	${AndIf} ${ProcessExists} ProcessHacker.exe
		Quit
	${EndIf}
!macroend
!macro OS
	Push $0
	${If} ${IsNT}
		${If} ${IsWinXP}
			${IfNot} ${AtLeastServicePack} 2
				MessageBox MB_ICONSTOP|MB_TOPMOST `${PORTABLEAPPNAME} requires Service Pack 2 or newer`
				Call Unload
				Quit
			${EndIf}
		${ElseIfNot} ${AtLeastWinXP}
			${MsgBox}
		${EndIf}
	${Else}
		${MsgBox}
	${EndIf}
	Pop $0
!macroend
!macro Init
	IfFileExists `${XML}` +2
	CopyFiles /SILENT `${DEFXML}` `${XML}`
!macroend
${SegmentInit}
	${If} ${IsAdmin}
		ClearErrors
		Push `${SETINI}`
		Push LastUniqueID=
		Call ReadS
		Pop $0
		IfErrors +6
		StrCmpS $0 "" 0 +4
		StrCpy $0 $WINDIR 3
		System::Call `${GET}`
		IntFmt $0 "%08X" $0
		System::Call `${ID}`
	${EndIf}
!macroend
${SegmentPreExec}
	${If} ${IsAdmin}
		StrCpy $0 $WINDIR 3
		System::Call `${GET}`
		IntFmt $0 "%08X" $0
		WriteINIStr `${SETINI}` ${APPNAME}Settings LastUniqueID $0
		ReadEnvStr $1 LastUniqueID
		StrCmpS $0 $1 +2
		${ImportDigitalSignature}
	${EndIf}
!macroend
!macro PreServices
	${If} ${AtLeastWin7}
		ClearErrors
		EnumRegKey $0 HKLM `${SVCKEY}` 0
		IfErrors +4
		${WriteRuntimeData} ${PAL} ${SVC} 1
		${Registry::BackupKey} `${HKLM}` $0
	${EndIf}
!macroend
!macro PrePrimaryServices
	${If} ${AtLeastWin7}
		${If} $Bit == 64
			${SC::Create} ${SVC} `${KPH64}` kernel driver "" /DISABLEFSR $1 $2
			${SC::Start} ${SVC} /DISABLEFSR $1 $2
		${Else}
			${SC::Create} ${SVC} `${KPH}` kernel driver "" /DISABLEFSR $1 $2
			${SC::Start} ${SVC} /DISABLEFSR $1 $2
		${EndIf}
	${EndIf}
!macroend
!macro PostPrimaryServices
	${If} ${AtLeastWin7}
		${SC::Stop} ${SVC} /DISABLEFSR $1 $2
		ClearErrors
		${ReadRuntimeData} $0 ${PAL} ${SVC}
		${If} ${Errors}
			${SC::Delete} ${SVC} /DISABLEFSR $1 $2
		${EndIf}
		${Registry::RestoreBackupKey} `${HKLM}` $0
	${EndIf}
!macroend
!macro PreReg
	Push $0
	ClearErrors
	ReadRegStr $0 HKLM `${TASK}` Debugger
	IfErrors +4
	${WriteRuntimeData} ${PAL} Debugger `$0`
	Pop $0
!macroend
!macro PostReg
	Push $0
	Push $1
	ReadRegStr $0 HKLM `${TASK}` Debugger
	ReadEnvStr $1 ${APP}
	${If} $0 == `"${EXE}"`
		DeleteRegKey HKLM `${TASK}`
		ClearErrors
		${ReadRuntimeData} $0 ${PAL} Debugger
		IfErrors +2
		WriteRegStr HKLM `${TASK}` Debugger `$0`
	${EndIf}
	Pop $1
	Pop $0
!macroend
Launcher

This section has two purposes. The first purpose is for anyone who wants to recompile one of my PAFs. It let's them know that I've used a build by FukenGruven and what I have uncommented in the Custom Defines section of the PortableApps.comLauncher.nsi file. If you do not see this section in one of my PAFs it means I used an original release of PAL provided by PortableApps.com to compile it.

Up until recently this section only had one purpose which was explained in the paragraph above but now it has another purpose which is to tell the PortableApps.comLauncher.nsi file which defines to use. You had to manually edit the PortableApps.comLauncher.nsi file which is a hassle. It's why you would see an extra folder inside the ..\App\AppInfo\Launcher directory called Source if you've ever used a PAF made by FukenGruven. For more on how to use this within your own builds read here.

Variables

Defines

Functions

Macros

Custom