Escape ARP Job With New Process
From NSIS Wiki
Jump to navigationJump to search
Author: Anders (talk, contrib) |
This function tries to set the JOB_OBJECT_LIMIT_BREAKAWAY_OK flag on the job object the Add/Remove programs application creates for an uninstall process so the user can interact with the ARP applet even when there are running child processes created by the uninstaller.
WARNING: This code has only been tested on XP SP2, before using this code you should check Windows2000 and Vista to make sure one has access to the job object on these systems (and that the name of the object is the same)
WARNING2: This code uses System::Store to try to preserve the registers, but the WinVer macros do not use the /NOUNLOAD flag, you might want to use SetPluginUnload alwaysoff
, or replace the ${AtLeastWin2000} macro
!include WinVer.nsh Function un.ExecExitARPJob ;_exec System::Store /NOUNLOAD S pop $R1 StrCpy $9 0 ;hJob StrCpy $R0 1 ;error? ${If} ${AtLeastWin2000} System::Call /NOUNLOAD 'kernel32::OpenJobObject(i 2,i 0,t "ARP Job")i.r9 ?e' ;JOB_OBJECT_SET_ATTRIBUTES=2 pop $R0 ${If} $9 != 0 StrCpy $R0 1 ;reset error System::Alloc /NOUNLOAD 112 pop $4 ${IfThen} $4 = 0 ${|} goto again ${|} System::Call /NOUNLOAD "*$4(i,i,i,i,i 0x800)" ;JOB_OBJECT_LIMIT_BREAKAWAY_OK=0x800 System::Call /NOUNLOAD 'kernel32::SetInformationJobObject(i $9,i 9,i $4,i 112)i.r0' ;JobObjectExtendedLimitInformation=9 System::Free /NOUNLOAD $4 System::Call /NOUNLOAD '*(i,i,i,i)i.r1' System::Alloc /NOUNLOAD 72 pop $4 System::Call /NOUNLOAD "*$4(i 72)" System::Call /NOUNLOAD 'kernel32::CreateProcess(i0,t R1,i0,i0,i0,i 0x01000000,i0,i0,i $4,i $1)i.r0 ?e' ;CREATE_BREAKAWAY_FROM_JOB=0x1000000 pop $R0 System::Free /NOUNLOAD $4 System::Call /NOUNLOAD "*$1(i.r3,i.r4,i,i)" System::Free /NOUNLOAD $1 ${IfThen} $0 = 0 ${|} goto again ${|} System::Call /NOUNLOAD 'kernel32::CloseHandle(i $3)' System::Call /NOUNLOAD 'kernel32::CloseHandle(i $4)' StrCpy $R0 0 ${EndIf} ${EndIf} again: ${If} $R0 != 0 ClearErrors Exec '$R1' ${Unless} ${Errors} StrCpy $R0 0 ${EndIf} ${EndIf} ${IfThen} $9 != 0 ${|} System::Call /NOUNLOAD "kernel32::CloseHandle(i $9)" ${|} ;push $R0 ;push result to stack, 0 on success System::Store L FunctionEnd Section Uninstall push "notepad.exe" call un.ExecExitARPJob SectionEnd