nsis-service-20040320
authorJeffrey Altman <jaltman@mit.edu>
Sun, 21 Mar 2004 05:24:19 +0000 (05:24 +0000)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Sun, 21 Mar 2004 05:24:19 +0000 (05:24 +0000)
Incorporate a new NSIS library ServiceLib.nsh which will allow us
to avoid using the Service.exe which we must build from Service.cpp

src/WINNT/install/NSIS/OpenAFS.nsi
src/WINNT/install/NSIS/ServiceLib.nsh [new file with mode: 0644]

index 9497359..26bed31 100644 (file)
@@ -32,7 +32,7 @@ VIAddVersionKey "CompanyName" "OpenAFS.org"
 VIAddVersionKey "ProductVersion" ${AFS_VERSION}
 VIAddVersionKey "FileVersion" ${AFS_VERSION}
 VIAddVersionKey "FileDescription" "OpenAFS for Windows Installer"
-VIAddVersionKey "LegalCopyright" "(C)2000-2004"
+VIAddVersionKey "LegalCopyright" "(C)2004"
 !ifdef DEBUG
 VIAddVersionKey "PrivateBuild" "Checked/Debug"
 !endif               ; End DEBUG
@@ -281,6 +281,9 @@ VIAddVersionKey "PrivateBuild" "Checked/Debug"
   !insertmacro MUI_RESERVEFILE_LANGDLL ;Language selection dialog
 ;--------------------------------
 ; Macros
+
+!include "ServiceLib.nsh"
+
 ; Macro - Upgrade DLL File
 ; Written by Joost Verburg
 ; ------------------------
@@ -455,6 +458,13 @@ var REG_DATA_3
 Section "AFS Client" secClient
 
   SetShellVarContext all
+  
+  ; Check for bad previous installation (if we are doing a new install)
+  Call IsAnyAFSInstalled
+  Pop $R0
+  StrCmp $R0 "0" +1 skipCheck
+  Call CheckPathForAFS
+skipCheck:
   ; Stop any running services or we can't replace the files
   ; Stop the running processes
   GetTempFileName $R0
@@ -468,8 +478,8 @@ Section "AFS Client" secClient
   ;nsExec::Exec '$R0 krbcc32s.exe'
 !ENDIF
 
-  nsExec::Exec "net stop TransarcAFSDaemon"
-  nsExec::Exec "net stop TransarcAFSServer"
+  !insertmacro SERVICE "stop" "TransarcAFSDaemon" ""
+  !insertmacro SERVICE "stop" "TransarcAFSServer" ""
   
    ; Do client components
   SetOutPath "$INSTDIR\Client\Program"
@@ -613,15 +623,16 @@ Section "AFS Client" secClient
    
   ; Create the AFS service
   SetOutPath "$INSTDIR\Common"
-  File "${AFS_WININSTALL_DIR}\Service.exe"
-  nsExec::Exec "net stop TransarcAFSDaemon"
+  ;File "${AFS_WININSTALL_DIR}\Service.exe"
+  !insertmacro SERVICE "stop" "TransarcAFSDaemon" ""
   ;IMPORTANT!  If we are not refreshing the config files, do NOT remove the service
   ;Don't re-install because it must be present or we wouldn't have passed the Reg check
  
   ReadRegStr $R2 HKLM "SYSTEM\CurrentControlSet\Services\TransarcAFSDaemon\Parameters" "Cell"
   StrCmp $R2 "" +1 skipremove
-  nsExec::Exec '$INSTDIR\Common\Service.exe u TransarcAFSDaemon'
+  !insertmacro SERVICE "delete" "TransarcAFSDaemon" ""
   nsExec::Exec '$INSTDIR\Common\Service.exe TransarcAFSDaemon "$INSTDIR\Client\Program\afsd_service.exe" "OpenAFS Client Service"'
+  ;insertmacro SERVICE "create" "TransarcAFSDaemon" "path=$INSTDIR\Client\Program\afsd_service.exe;autostart=1;interact=1;machine=;user=;password="
 skipremove:
   Delete "$INSTDIR\Common\service.exe"
 
@@ -632,6 +643,10 @@ skipremove:
   WriteRegStr HKLM "SYSTEM\CurrentControlSet\Services\TransarcAFSDaemon\NetworkProvider" "AuthentProviderPath" "$INSTDIR\Client\Program\afslogon.dll"
   WriteRegDWORD HKLM "SYSTEM\CurrentControlSet\Services\TransarcAFSDaemon\NetworkProvider" "Class" 2
   WriteRegDWORD HKLM "SYSTEM\CurrentControlSet\Services\TransarcAFSDaemon\NetworkProvider" "VerboseLogging" 10
+  ; Must also add HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\NetworkProvider\HwOrder
+  ; and HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\NetworkProvider\Order
+  ; to also include the service name.
+  Call AddProvider
   ReadINIStr $R0 $1 "Field 7" "State"
   ReadINIStr $R1 $1 "Field 9" "State"
   ; Complicated way to do $R1 = ($R1 *2) + $R0
@@ -649,7 +664,7 @@ skipremove:
   WriteRegDWORD HKLM "SYSTEM\CurrentControlSet\Services\TransarcAFSDaemon\Parameters" "SecurityLevel" $R0
   ReadINIStr $R0 $1 "Field 5" "State"  
   WriteRegDWORD HKLM "SYSTEM\CurrentControlSet\Services\TransarcAFSDaemon\Parameters" "FreelanceClient" $R0
-  ReadINIStr $R0 $1 "Field 11" "State"  
+  ReadINIStr $R0 $1 "Field 11" "State"   
   WriteRegDWORD HKLM "SYSTEM\CurrentControlSet\Services\TransarcAFSDaemon\Parameters" "UseDNS" $R0
   WriteRegStr HKLM "SYSTEM\CurrentControlSet\Services\TransarcAFSDaemon\Parameters" "NetbiosName" "AFS"
   WriteRegStr HKLM "SYSTEM\CurrentControlSet\Services\TransarcAFSDaemon\Parameters" "MountRoot" "/afs"
@@ -802,7 +817,8 @@ Section "AFS Server" secServer
   File "${AFS_WININSTALL_DIR}\Service.pdb"
 !endif
   ;Don't want to whack existing settings... Make users un-install and then re-install if they want that
-  ;nsExec::Exec '$INSTDIR\Common\service.exe u TransarcAFSServer'
+  !insertmacro SERVICE "delete" "TransarcAFSServer" ""
+  ;insertmacro SERVICE "create" "TransarcAFSServer" "path=$INSTDIR\Server\usr\afs\bin\bosctlsvc.exe;autostart=1"
   nsExec::Exec '$INSTDIR\Common\service.exe TransarcAFSServer "$INSTDIR\Server\usr\afs\bin\bosctlsvc.exe" "OpenAFS AFS Server"'
   Delete "$INSTDIR\Common\service.exe"
   
@@ -1600,16 +1616,15 @@ StartRemove:
 !ENDIF
 
   ; Delete the AFS service
-  GetTempFileName $R0
-  File /oname=$R0 "${AFS_WININSTALL_DIR}\Service.exe"
-  nsExec::Exec "net stop TransarcAFSDaemon"
-  nsExec::Exec "net stop TransarcAFSServer"
-  nsExec::Exec '$R0 u TransarcAFSDaemon'
-  ; After we stop the service, but before we delete it, we have to remove the volume data
-  ; This is because the storage locations are in the registry under the service key.
-  ; Call un.RemoveAFSVolumes
-  nsExec::Exec '$R0 u TransarcAFSServer'
-  Delete $R0
+  ; New method for service manipulation
+  !undef "UN"
+  !define "UN" "un."
+  !insertmacro SERVICE "stop" "TransarcAFSDaemon" ""
+  !insertmacro SERVICE "stop" "TransarcAFSDaemon" ""
+  !insertmacro SERVICE "delete" "TransarcAFSDaemon" ""
+  !insertmacro SERVICE "delete" "TransarcAFSServer" ""
+  
+  Call un.RemoveProvider
   
   Push "$INSTDIR\Client\Program"
   Call un.RemoveFromPath
@@ -2009,8 +2024,8 @@ StrCmp $R0 "1" done
 ReadINIStr $R0 $0 "Field 3" "State"
 StrCmp $R0 "1" UsePackaged
 
-ReadINIStr $R0 $0 "Field 6" "State"
-StrCmp $R0 "1" CheckOther
+ReadINIStr $R0 $0 "Field 6" "State" 
+   StrCmp $R0 "1" CheckOther 
 
 ; If none of these, grab file from other location
 goto UsePackaged
@@ -3591,4 +3606,118 @@ noClose:
   Pop $2
   Pop $1
   Exch $R0
-FunctionEnd
\ No newline at end of file
+FunctionEnd
+
+Function AddProvider
+   Push $R0
+   Push $R1
+   ReadRegStr $R0 HKLM "SYSTEM\CurrentControlSet\Control\NetworkProvider\HWOrder" "ProviderOrder"
+   Push $R0
+   StrCpy $R0 "TransarcAFSDaemon"
+   Push $R0
+   Call StrStr
+   Pop $R0
+   StrCmp $R0 "" +1 DoOther
+   ReadRegStr $R1 HKLM "SYSTEM\CurrentControlSet\Control\NetworkProvider\HWOrder" "ProviderOrder"   
+   StrCpy $R0 "$R1,TransarcAFSDaemon"
+   WriteRegStr HKLM "SYSTEM\CurrentControlSet\Control\NetworkProvider\HWOrder" "ProviderOrder" $R0
+DoOther:
+   ReadRegStr $R0 HKLM "SYSTEM\CurrentControlSet\Control\NetworkProvider\Order" "ProviderOrder"
+   Push $R0
+   StrCpy $R0 "TransarcAFSDaemon"
+   Push $R0
+   Call StrStr
+   Pop $R0
+   StrCmp $R0 "" +1 End
+   ReadRegStr $R1 HKLM "SYSTEM\CurrentControlSet\Control\NetworkProvider\Order" "ProviderOrder"   
+   StrCpy $R0 "$R1,TransarcAFSDaemon"
+   WriteRegStr HKLM "SYSTEM\CurrentControlSet\Control\NetworkProvider\Order" "ProviderOrder" $R0   
+End:
+   Pop $R1
+   Pop $R0
+FunctionEnd
+
+Function un.RemoveProvider
+   Push $R0
+   StrCpy $R0 "TransarcAFSDaemon"
+   Push $R0
+   StrCpy $R0 "SYSTEM\CurrentControlSet\Control\NetworkProvider\HWOrder"
+   Call un.RemoveFromProvider
+   StrCpy $R0 "TransarcAFSDaemon"
+   Push $R0
+   StrCpy $R0 "SYSTEM\CurrentControlSet\Control\NetworkProvider\Order"
+   Call un.RemoveFromProvider
+   Pop $R0
+FunctionEnd
+
+Function un.RemoveFromProvider
+  Exch $0
+  Push $1
+  Push $2
+  Push $3
+  Push $4
+  Push $5
+  Push $6
+
+  ReadRegStr $1 HKLM "$R0" "ProviderOrder"
+    StrCpy $5 $1 1 -1 # copy last char
+    StrCmp $5 "," +2 # if last char != ,
+      StrCpy $1 "$1," # append ,
+    Push $1
+    Push "$0,"
+    Call un.StrStr ; Find `$0,` in $1
+    Pop $2 ; pos of our dir
+    StrCmp $2 "" unRemoveFromPath_done
+      ; else, it is in path
+      # $0 - path to add
+      # $1 - path var
+      StrLen $3 "$0,"
+      StrLen $4 $2
+      StrCpy $5 $1 -$4 # $5 is now the part before the path to remove
+      StrCpy $6 $2 "" $3 # $6 is now the part after the path to remove
+      StrCpy $3 $5$6
+
+      StrCpy $5 $3 1 -1 # copy last char
+      StrCmp $5 "," 0 +2 # if last char == ,
+        StrCpy $3 $3 -1 # remove last char
+
+      WriteRegStr HKLM "$R0" "ProviderOrder" $3
+      
+  unRemoveFromPath_done:
+    Pop $6
+    Pop $5
+    Pop $4
+    Pop $3
+    Pop $2
+    Pop $1
+    Pop $0
+FunctionEnd
+
+Function CheckPathForAFS
+   Push $0
+   Push $1
+   Push $2
+   Push $3
+   ReadRegStr $1 HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH"
+   StrCpy $1 "$1;"
+loop:
+   Push $1
+   Push ";"
+   Call StrStr
+   Pop $0
+   StrLen $2 $0
+   StrCpy $3 $1 -$2
+   IfFileExists "$3\afsd_service.exe" Error
+   StrCpy $1 $0 32768 1
+   StrLen $2 $1
+   IntCmp $2 0 Done Done loop
+   goto Done
+Error:
+   MessageBox MB_ICONSTOP|MB_OK|MB_TOPMOST "This installer is unable to upgrade the previous version of AFS. Please uninstall the current AFS version before continuing."
+   Abort "Unable to install OpenAFS"
+Done:
+   Pop $3
+   Pop $2
+   Pop $1
+   Pop $0
+FunctionEnd
diff --git a/src/WINNT/install/NSIS/ServiceLib.nsh b/src/WINNT/install/NSIS/ServiceLib.nsh
new file mode 100644 (file)
index 0000000..bf07a7f
--- /dev/null
@@ -0,0 +1,342 @@
+
+; NSIS SERVICE LIBRARY - servicelib.nsh
+; Version 1.2 - 02/29/2004
+; Questions/Comments - dselkirk@hotmail.com
+;
+; Description:
+;   Provides an interface to window services
+;
+; Inputs:
+;   action     - systemlib action ie. create, delete, start, stop, pause,
+;              continue, installed, running, status
+;   name       - name of service to manipulate
+;   param      - action parameters; usage: var1=value1;var2=value2;...etc.
+;
+; Actions:
+;   create     - creates a new windows service
+;              Parameters:
+;                path  - path to service executable
+;                autostart     - automatically start with system ie. 1|0
+;                interact      - interact with the desktop ie. 1|0
+;                machine       - machine name where to install service
+;                user          - user that runs the service
+;                password      - password of the above user
+;
+;   delete     - deletes a windows service
+;   start      - start a stopped windows service
+;   stop       - stops a running windows service
+;   pause      - pauses a running windows service
+;   continue   - continues a paused windows service
+;   installed  - is the provided service installed
+;              Parameters:
+;                action        - if true then invokes the specified action
+;   running    - is the provided service running
+;              Parameters:
+;                action        - if true then invokes the specified action
+;   status     - check the status of the provided service
+;
+; If run from uninstall define "UN" as "un." gefore running.
+;
+; Usage:
+;   Method 1:
+;     Push "action"
+;     Push "name"
+;     Push "param"
+;     Call Service
+;     Pop $0 ;response
+;
+;   Method 2:
+;     !insertmacro SERVICE "action" "name" "param"
+;
+; History:
+;              1.0 - 09/15/2003 - Initial release
+;              1.1 - 09/16/2003 - Changed &l to i, thx brainsucker
+;              1.2 - 02/29/2004 - Fixed documentation.
+
+!ifndef SERVICELIB
+  !define SERVICELIB
+
+  !define SC_MANAGER_ALL_ACCESS 0x3F
+  !define SERVICE_ALL_ACCESS 0xF01FF
+
+  !define SERVICE_CONTROL_STOP  1
+  !define SERVICE_CONTROL_PAUSE  2
+  !define SERVICE_CONTROL_CONTINUE  3
+
+  !define SERVICE_STOPPED 0x1
+  !define SERVICE_START_PENDING 0x2
+  !define SERVICE_STOP_PENDING 0x3
+  !define SERVICE_RUNNING 0x4
+  !define SERVICE_CONTINUE_PENDING 0x5
+  !define SERVICE_PAUSE_PENDING 0x6
+  !define SERVICE_PAUSED 0x7
+
+  !ifndef UN
+    !define UN ""
+  !endif
+
+  !macro SERVICE ACTION NAME PARAM
+    Push '${ACTION}'
+    Push '${NAME}'
+    Push '${PARAM}'
+    Call ${UN}Service
+  !macroend
+
+  !macro FUNC_GETPARAM
+    Push $0
+    Push $1
+    Push $2
+    Push $3
+    Push $4
+    Push $5
+    Push $6
+    Push $7
+    Exch 8
+    Pop $1 ;name
+    Exch 8
+    Pop $2 ;source
+    StrCpy $0 ""
+    StrLen $7 $2
+    StrCpy $3 0
+    lbl_loop:
+      IntCmp $3 $7 0 0 lbl_done
+      StrLen $4 "$1="
+      StrCpy $5 $2 $4 $3
+      StrCmp $5 "$1=" 0 lbl_next
+      IntOp $5 $3 + $4
+      StrCpy $3 $5
+      lbl_loop2:
+        IntCmp $3 $7 0 0 lbl_done
+        StrCpy $6 $2 1 $3
+        StrCmp $6 ";" 0 lbl_next2
+        IntOp $6 $3 - $5
+        StrCpy $0 $2 $6 $5
+        Goto lbl_done
+        lbl_next2:
+        IntOp $3 $3 + 1
+        Goto lbl_loop2
+      lbl_next:
+      IntOp $3 $3 + 1
+      Goto lbl_loop
+    lbl_done:
+    Pop $5
+    Pop $4
+    Pop $3
+    Pop $2
+    Pop $1
+    Exch 2
+    Pop $6
+    Pop $7
+    Exch $0
+  !macroend
+
+  !macro CALL_GETPARAM VAR NAME DEFAULT LABEL
+    Push $1
+    Push ${NAME}
+    Call ${UN}GETPARAM
+    Pop $6
+    StrCpy ${VAR} "${DEFAULT}"
+    StrCmp $6 "" "${LABEL}" 0
+    StrCpy ${VAR} $6
+  !macroend
+
+  !macro FUNC_SERVICE UN
+    Push $0
+    Push $1
+    Push $2
+    Push $3
+    Push $4
+    Push $5
+    Push $6
+    Push $7
+    Exch 8
+    Pop $1 ;param
+    Exch 8
+    Pop $2 ;name
+    Exch 8
+    Pop $3 ;action
+    ;$0 return
+    ;$4 OpenSCManager
+    ;$5 OpenService
+
+
+    StrCpy $0 "false"
+    System::Call 'advapi32::OpenSCManagerA(n, n, i ${SC_MANAGER_ALL_ACCESS}) i.r4'
+    IntCmp $4 0 lbl_done
+    StrCmp $3 "create" lbl_create
+    System::Call 'advapi32::OpenServiceA(i r4, t r2, i ${SERVICE_ALL_ACCESS}) i.r5'
+    IntCmp $5 0 lbl_done
+
+    lbl_select:
+    StrCmp $3 "delete" lbl_delete
+    StrCmp $3 "start" lbl_start
+    StrCmp $3 "stop" lbl_stop
+    StrCmp $3 "pause" lbl_pause
+    StrCmp $3 "continue" lbl_continue
+    StrCmp $3 "installed" lbl_installed
+    StrCmp $3 "running" lbl_running
+    StrCmp $3 "status" lbl_status
+    Goto lbl_done
+
+    ; create service
+    lbl_create:
+      Push $R1 ;machine
+      Push $R2 ;user
+      Push $R3 ;password
+      Push $R4 ;interact
+      Push $R5 ;autostart
+      Push $R6 ;path
+
+      !insertmacro CALL_GETPARAM $R1 "machine" "n" "lbl_machine"
+      lbl_machine:
+
+      !insertmacro CALL_GETPARAM $R2 "user" "n" "lbl_user"
+      lbl_user:
+
+      !insertmacro CALL_GETPARAM $R3 "password" "n" "lbl_password"
+      lbl_password:
+
+      !insertmacro CALL_GETPARAM $R4 "interact" "0x10" "lbl_interact"
+        StrCpy $6 0x10
+        IntCmp $R4 0 +2
+        IntOp $R4 $6 | 0x100
+        StrCpy $R4 $6
+      lbl_interact:
+
+      !insertmacro CALL_GETPARAM $R5 "autostart" "0x3" "lbl_autostart"
+        StrCpy $6 0x3
+        IntCmp $R5 0 +2
+        StrCpy $6 0x2
+        StrCpy $R5 $6
+      lbl_autostart:
+
+      !insertmacro CALL_GETPARAM $R6 "path" "n" "lbl_path"
+      lbl_path:
+
+      System::Call 'advapi32::CreateServiceA(i r4, t r2, t r2, i ${SERVICE_ALL_ACCESS}, i R4, i R5, i 0, t R6, n, n, R1, R2, R3) i.r6'
+      Pop $R6
+      Pop $R5
+      Pop $R4
+      Pop $R3
+      Pop $R2
+      Pop $R1
+      StrCmp $6 0 lbl_done lbl_good
+
+    ; delete service
+    lbl_delete:
+      System::Call 'advapi32::DeleteService(i r5) i.r6'
+      StrCmp $6 0 lbl_done lbl_good
+
+    ; start service
+    lbl_start:
+      System::Call 'advapi32::StartServiceA(i r5, i 0, i 0) i.r6'
+      StrCmp $6 0 lbl_done lbl_good
+
+    ; stop service
+    lbl_stop:
+      Push $R1
+      System::Call '*(i,i,i,i,i,i,i) i.R1'
+      System::Call 'advapi32::ControlService(i r5, i ${SERVICE_CONTROL_STOP}, i $R1) i'
+      System::Free $R1
+      Pop $R1
+      StrCmp $6 0 lbl_done lbl_good
+
+    ; pause service
+    lbl_pause:
+      Push $R1
+      System::Call '*(i,i,i,i,i,i,i) i.R1'
+      System::Call 'advapi32::ControlService(i r5, i ${SERVICE_CONTROL_PAUSE}, i $R1) i'
+      System::Free $R1
+      Pop $R1
+      StrCmp $6 0 lbl_done lbl_good
+
+    ; continue service
+    lbl_continue:
+      Push $R1
+      System::Call '*(i,i,i,i,i,i,i) i.R1'
+      System::Call 'advapi32::ControlService(i r5, i ${SERVICE_CONTROL_CONTINUE}, i $R1) i'
+      System::Free $R1
+      Pop $R1
+      StrCmp $6 0 lbl_done lbl_good
+
+    ; is installed
+    lbl_installed:
+      !insertmacro CALL_GETPARAM $7 "action" "" "lbl_good"
+        StrCpy $3 $7
+        Goto lbl_select
+
+    ; is service running
+    lbl_running:
+      Push $R1
+      System::Call '*(i,i,i,i,i,i,i) i.R1'
+      System::Call 'advapi32::QueryServiceStatus(i r5, i $R1) i'
+      System::Call '*$R1(i, i.r6)'
+      System::Free $R1
+      Pop $R1
+      IntFmt $6 "0x%X" $6
+      StrCmp $6 ${SERVICE_RUNNING} 0 lbl_done
+      !insertmacro CALL_GETPARAM $7 "action" "" "lbl_good"
+        StrCpy $3 $7
+        Goto lbl_select
+
+    lbl_status:
+      Push $R1
+      System::Call '*(i,i,i,i,i,i,i) i.R1'
+      System::Call 'advapi32::QueryServiceStatus(i r5, i $R1) i'
+      System::Call '*$R1(i, i .r6)'
+      System::Free $R1
+      Pop $R1
+      IntFmt $6 "0x%X" $6
+      StrCpy $0 "running"
+      IntCmp $6 ${SERVICE_RUNNING} lbl_done
+      StrCpy $0 "stopped"
+      IntCmp $6 ${SERVICE_STOPPED} lbl_done
+      StrCpy $0 "start_pending"
+      IntCmp $6 ${SERVICE_START_PENDING} lbl_done
+      StrCpy $0 "stop_pending"
+      IntCmp $6 ${SERVICE_STOP_PENDING} lbl_done
+      StrCpy $0 "running"
+      IntCmp $6 ${SERVICE_RUNNING} lbl_done
+      StrCpy $0 "continue_pending"
+      IntCmp $6 ${SERVICE_CONTINUE_PENDING} lbl_done
+      StrCpy $0 "pause_pending"
+      IntCmp $6 ${SERVICE_PAUSE_PENDING} lbl_done
+      StrCpy $0 "paused"
+      IntCmp $6 ${SERVICE_PAUSED} lbl_done
+      StrCpy $0 "unknown"
+
+    lbl_good:
+    StrCpy $0 "true"
+    lbl_done:
+    IntCmp $5 0 +2
+    System::Call 'advapi32::CloseServiceHandle(i r5) n'
+    IntCmp $4 0 +2
+    System::Call 'advapi32::CloseServiceHandle(i r4) n'
+    Pop $4
+    Pop $3
+    Pop $2
+    Pop $1
+    Exch 3
+    Pop $5
+    Pop $6
+    Pop $7
+    Exch $0
+  !macroend
+
+  Function Service
+    !insertmacro FUNC_SERVICE ""
+  FunctionEnd
+
+  Function un.Service
+    !insertmacro FUNC_SERVICE "un."
+  FunctionEnd
+
+  Function GetParam
+    !insertmacro FUNC_GETPARAM
+  FunctionEnd
+
+  Function un.GetParam
+    !insertmacro FUNC_GETPARAM
+  FunctionEnd
+
+!endif