;
; ooRexx Install Script, based on Modern Example Script Written by Joost Verburg
;
; This script requires a plugin added to your NSIS installation.  It needs to
; be put into ${NSISDIR}\Plugins directory:
;   ooRexxProcess.dll  -> http://sourceforge.net/projects/oorexx/files/  under oorexx-buildutils
;
!verbose 3

!define LONGNAME       "@CPACK_PACKAGE_LONG_NAME@"  ;Long Name (for descriptions)
!define SHORTNAME      "@CPACK_PACKAGE_NAME@"       ;Short name (no slash) of package
!define DISPLAYICON    "$INSTDIR\@CPACK_NSIS_INSTALLED_ICON_NAME@"
!define VERSION        "@ORX_VERSION_NSIS@"
!define CPU            "@NSIS_CPU@"
!define UNINSTALLER    "uninstall.exe"
!define KEYFILE1       "rexx.dll"
!define KEYFILE2       "rexx.exe"
!define KEYFILE3       "rxapi.exe"

; Default file extensions and ftypes
!define DefRexxExt       ".rex"
!define DefRexxFType     "RexxScript"
!define DefRexxHideExt   ".rexg"
!define DefRexxHideFType "RexxHide"
!define DefRexxPawsExt   ".rexp"
!define DefRexxPawsFType "RexxPaws"

Name "${LONGNAME} ${VERSION}"

!include "MUI2.nsh"
!include "Library.nsh"
!include "LogicLib.nsh"
!include "FileFunc.nsh"
!include "WordFunc.nsh"
!include "admin.nsh"
!include "newpath.nsh"
!include "WriteEnv.nsh"
!include "StrFunc.nsh"
!include "x64.nsh"

; Docs for the string functions say they need to be declared before use:
${StrTok}
${StrCase}
${UnStrTok}

!define MUI_ICON "@CPACK_NSIS_MUI_ICON@"
!define MUI_UNICON "@CPACK_NSIS_MUI_UNIICON@"

!define MUI_CUSTOMPAGECOMMANDS
!define MUI_WELCOMEFINISHPAGE_BITMAP "orange.bmp"
!define MUI_UNWELCOMEFINISHPAGE_BITMAP "orange-uninstall.bmp"

!define MUI_LICENSEPAGE
!define MUI_COMPONENTSPAGE
!define MUI_DIRECTORYPAGE

;---------- Finish page set up --------------------------
!define MUI_FINISHPAGE
!define MUI_FINISHPAGE_NOAUTOCLOSE

; Note that the finish page run function is used here to instead
; create a Desktop icon.  The 'run_function' is set to our create
; Desktop function, where we can do whatever we want.
!define MUI_FINISHPAGE_RUN
!define MUI_FINISHPAGE_RUN_NOTCHECKED
!define MUI_FINISHPAGE_RUN_TEXT "Create ${LONGNAME} Desktop Shortcut"
!define MUI_FINISHPAGE_RUN_FUNCTION CreateDesktopShortcut

!define MUI_FINISHPAGE_SHOWREADME $INSTDIR\doc\ReleaseNotes.txt
!define MUI_FINISHPAGE_SHOWREADME_NOTCHECKED
!define MUI_FINISHPAGE_SHOWREADME_TEXT "Show ${LONGNAME} Release Notes"
;!define MUI_FINISHPAGE_SHOWREADME_FUNCTION SomeFunctionToBeCreated

!define MUI_FINISHPAGE_LINK "Getting started with Windows ${LONGNAME}"
!define MUI_FINISHPAGE_LINK_LOCATION "http://www.rexxla.org/rexxlang/rexxtut.html"

!define MUI_ABORTWARNING

!define MUI_UNINSTALLER
!define MUI_UNCONFIRMPAGE
!define MUI_UNFINISHPAGE_NOAUTOCLOSE

!define MUI_CUSTOMFUNCTION_UNABORT un.onCancelButton

!define UninstLog "uninstall.log"
Var UninstLog

!define SHACF_FILESYSTEM 1  ; For SHAutoComplete()

!macro AddItem Path
 FileWrite $UninstLog "${Path}$\r$\n"
!macroend
!define AddItem "!insertmacro AddItem"

!macro File FilePath FileName
 FileWrite $UninstLog "$OUTDIR\${FileName}$\r$\n"
 File "${FilePath}${FileName}"
!macroend
!define File "!insertmacro File"

!macro CreateDirectory Path
 CreateDirectory "${Path}"
 FileWrite $UninstLog "${Path}$\r$\n"
!macroend
!define CreateDirectory "!insertmacro CreateDirectory"

!macro SetOutPath Path
 SetOutPath "${Path}"
 FileWrite $UninstLog "${Path}$\r$\n"
!macroend
!define SetOutPath "!insertmacro SetOutPath"

!macro WriteUninstaller Path
 WriteUninstaller "${Path}"
 FileWrite $UninstLog "${Path}$\r$\n"
!macroend
!define WriteUninstaller "!insertmacro WriteUninstaller"

# Create a shortcut using the information provided from CMake.  This versions simplifies
# the process of escaping all of the special characters in CMake
!macro ConfigureShortCut Name Program Arg Icon Icon_index
  CreateShortCut "$SMPROGRAMS\${LONGNAME}\${Name}.lnk" "$INSTDIR\${Program}" '"${Arg}"' "$INSTDIR\${Icon}" ${Icon_index}
  ${AddItem} "$SMPROGRAMS\${LONGNAME}\${Name}.lnk"
!macroend

# Create a shortcut for running a Rexx program using the information provided from CMake.  This versions simplifies
# the process of escaping all of the special characters in CMake
!macro ConfigureRexxShortCut Name Launcher RexxProgram
  CreateShortCut "$SMPROGRAMS\${LONGNAME}\${Name}.lnk" "$INSTDIR\${Launcher}.exe" '"${RexxProgram}"' "$INSTDIR\{Launcher}.exe"
  ${AddItem} "$SMPROGRAMS\${LONGNAME}\${Name}.lnk"
!macroend

# Create a shortcut for a documentation file (all come from the same directory)
!macro ConfigureDocShortCut Name File
  CreateShortCut "$SMPROGRAMS\${LONGNAME}\${SHORTNAME} Documentation\${Name}.lnk" "$INSTDIR\doc\${File}" "" "$INSTDIR\doc\${File}" 0
  ${AddItem} "$SMPROGRAMS\${LONGNAME}\${Name}.lnk"
!macroend

;--------------------------------
;Configuration

  ;General
  OutFile "@INSTALLER_FILE@"
  ShowInstdetails show
  ShowUninstDetails show
  SetOverwrite on
  SetPluginUnload alwaysoff
  RequestExecutionLevel admin
  InstallDir "$PROGRAMFILES\${SHORTNAME}"

  ;InstType "Default"
  ;InstType "Simple"
  ;InstType /COMPONENTSONLYONCUSTOM

;--------------------------------
;Pages
  /* Installer pages */
  !insertmacro MUI_PAGE_WELCOME
  !insertmacro MUI_PAGE_LICENSE "@CPACK_RESOURCE_FILE_LICENSE@"
  Page custom Uninstall_Old_ooRexx_page Uninstall_Old_ooRexx_Leave
  Page custom Uninstall_Type_page Uninstall_Type_Leave
  Page custom Ok_Stop_RxAPI_page Ok_Stop_RxAPI_leave

  !define MUI_PAGE_CUSTOMFUNCTION_PRE Components_Page_pre
  !define MUI_PAGE_CUSTOMFUNCTION_SHOW Components_Page_show
  !insertmacro MUI_PAGE_COMPONENTS

  !define MUI_PAGE_CUSTOMFUNCTION_PRE Directory_Page_pre
  !define MUI_PAGE_CUSTOMFUNCTION_SHOW Directory_Page_show
  !insertmacro MUI_PAGE_DIRECTORY

  Page custom File_Associations_page File_Associations_leave
  Page custom SendTo_Items_page SendTo_Items_leave
  Page custom Associate_rexx_page Associate_rexx_leave
  Page custom Associate_otherExes_page Associate_otherExes_leave
  Page custom Confirm_page

  !insertmacro MUI_PAGE_INSTFILES

  !define MUI_PAGE_CUSTOMFUNCTION_PRE Finish_Page_pre
  !define MUI_PAGE_CUSTOMFUNCTION_SHOW Finish_Page_show
  !insertmacro MUI_PAGE_FINISH

  /* Uninstaller pages */
  !insertmacro MUI_UNPAGE_WELCOME
  UninstPage custom un.Ok_Stop_RxAPI_page un.Ok_Stop_RxAPI_leave
  UninstPage custom un.Uninstall_By_Log_page un.Uninstall_By_Log_leave
  !define MUI_PAGE_CUSTOMFUNCTION_PRE un.Confirm_Page_pre
  !insertmacro MUI_UNPAGE_CONFIRM
  !insertmacro MUI_UNPAGE_INSTFILES
  !insertmacro MUI_UNPAGE_FINISH
;--------------------------------
;Language
!insertmacro MUI_LANGUAGE "English"

;--------------------------------
;Reserved files

;--------------------------------
; Variables
Var IsAdminUser                ; is the installer being run by an admin:           true / false
Var RxapiIsRunning             ; is rxapi running:                                 true / false

;
Var RegVal_uninstallString     ; uninstall string (program) found in regsitry
Var RegVal_uninstallLocation   ; location of uninstall program found in registry
Var RegVal_uninstallVersion    ; Version / level of uninstaller program.  This only exists at 410 or greater
Var RegVal_uninstallBitness    ; The uninstaller is 32 or 64 bit.  This only exists at 420 or greater.
Var RegVal_rexxAssociation     ; File association string for rexx.exe     (.ext / ftype - i.e. .rex RexxScript)
Var RegVal_rexxEditor          ; ... and editor file name
Var RegVal_rexxHideAssociation ; File association string for rexxhide.exe (.ext / ftype - i.e. .rexg RexxHide)
Var RegVal_rexxPawsAssociation ; File association string for rexxpaws.exe (.ext / ftype - i.e. .rexp RexxPaws)
Var RegVal_sendTo_rexx         ; Add / don't add Send To Rexx item
Var RegVal_sendTo_rexxHide     ; Add / don't add Send To rexxpaws item
Var RegVal_sendTo_rexxPaws     ; Add / don't add Send To rexxhide item
Var RegVal_desktop_icon        ; Create / don't create a Desktop icon

Var AssociationProgramName     ; Executable being associated  (i.e rexxpaws.exe, rexx.exe, etc..)
Var AssociationText            ; Descriptive text that goes in registry  (i.e. ooRexx Rexx GUI Program)
Var AssociationEditor          ; File path name of editor that goes in registry  (i.e. C:\Windows\system32\NotePad.exe)

Var PreviousVersionInstalled   ; A previous version is installed                   true / false
Var DoUpgrade                  ; try to do an upgrade install                      true / false
Var DoUpgradeQuick             ; don't show options pages with diasabled controls  true / false
Var UpgradeTypeAvailable       ; Level of uninstaller sufficient for upgrade type  true / false

Var KeyFileName                ; Used to contruct full path to key files.
Var CheckRxApiLock             ; Used to skipping checking if rxapi is locked.
Var UserRequestAbort           ; General purpose, set to true if User replies Ok, wanting to abort.

; Dialog variables
Var Dialog
Var Label_One
Var Label_Two

Var Uninstall_Previous_CK
Var Force_Install_CK

Var Do_Upgrade_Type_CK
Var Do_Upgrade_Type_CK_state
Var Do_Upgrade_Quick_CK
Var Do_Upgrade_Quick_CK_state

Var StopRxAPI_CK
Var StopRxAPI_CK_State

Var Use_File_Associations_CK
Var Use_File_Associations_CK_state

Var SendTo_rexx_CK
Var SendTo_rexx_CK_state
Var SendTo_rexxHide_CK
Var SendTo_rexxHide_CK_state
Var SendTo_rexxPaws_CK
Var SendTo_rexxPaws_CK_state

; rexx.exe file associations page controls
Var Rexx_editor_EDIT
Var Rexx_editor_text
Var Rexx_editor_PB
Var Associate_rexx_CK
Var Associate_rexx_CK_state
Var Rexx_ext_EDIT
Var Rexx_ext_text
Var Rexx_ftype_EDIT
Var Rexx_ftype_text

; rexxhide.exe file associations
Var Associate_rexxhide_CK
Var Associate_rexxhide_CK_state
Var RexxHide_ext_EDIT
Var RexxHide_ext_text
Var RexxHide_ftype_EDIT
Var RexxHide_ftype_text

; rexxpaws.exe file associations
Var Associate_rexxpaws_CK
Var Associate_rexxpaws_CK_state
Var RexxPaws_ext_EDIT
Var RexxPaws_ext_text
Var RexxPaws_ftype_EDIT
Var RexxPaws_ftype_text

; Uninstall variables
Var InStopRxapiPage
Var LogFileExists
Var Delete_ooRexx_Tree_CK
Var DeleteWholeTree

;===============================================================================
;Installer Sections
;===============================================================================

;-------------------------------------------------------------------------------
;  Hidden section to open the log file

Section -openlogfile
  CreateDirectory "$INSTDIR"
  Call OpenUninstallLog
SectionEnd

;-------------------------------------------------------------------------------
; Core components

Section "${LONGNAME} Core (required)" SecMain
  SectionIn 1 RO

  DetailPrint "Beginning installation of ooRexx"
  DetailPrint "  NSIS installer with max string length ${NSIS_MAX_STRLEN}"
  DetailPrint ""

  # pull in the component manifest from the Cmake installs
  !include "Core_component_manifest.nsh"

  ; Add the Start Menu folder and start adding the items.
  ${CreateDirectory} "$SMPROGRAMS\${LONGNAME}"

  # We always create the Uninstall link, regardless of what is configured in the cmake file
  CreateShortCut "$SMPROGRAMS\${LONGNAME}\Uninstall ${SHORTNAME}.lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0
  ${AddItem} "$SMPROGRAMS\${LONGNAME}\Uninstall ${SHORTNAME}.lnk"

  # pull in the short manifest from the Cmake installs

  !include "Core_shortcut_manifest.nsh"

  WriteINIStr "$SMPROGRAMS\${LONGNAME}\${SHORTNAME} Home Page.url" "InternetShortcut" "URL" "@CPACK_NSIS_URL_INFO_ABOUT@"
  ${AddItem} "$SMPROGRAMS\${LONGNAME}\${SHORTNAME} Home Page.url"

  ; If we are doing an upgrade, these settings are all left however they were.
  ${If} $DoUpgrade == 'false'
    ; Maybe create Send To items.
    Call DoSendToItems

    ; Do the file associations, like associate .rex with ooRexx (REXXScript).
    ; DoFileAssociations needs to run before DoEnvVariagles.
    Call DoFileAssociations

    ; Set the environment variables, PATH, REXX_HOME, etc..
    Call DoEnvVariables
  ${EndIf}


  ; Write the uninstall keys.  Note that the uninstaller always deletes these
  ; keys, even if doing an upgrade.  So we need to still write the file
  ; assoication keys.  For an upgrade install, these will be exactly what we
  ; read in on init.
  WriteRegExpandStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SHORTNAME}" "InstallLocation" '"$INSTDIR"'
  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SHORTNAME}" "DisplayName" "${LONGNAME}"
  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SHORTNAME}" "DisplayIcon" "${DISPLAYICON}"
  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SHORTNAME}" "HelpLink" "http://www.rexxla.org/support.html"
  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SHORTNAME}" "URLUpdateInfo" "http://sourceforge.net/project/showfiles.php?group_id=119701"
  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SHORTNAME}" "URLInfoAbout" "http://www.rexxla.org/"
  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SHORTNAME}" "DisplayVersion" "${VERSION}"
  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SHORTNAME}" "Publisher" "Rexx Language Association"

  WriteRegExpandStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SHORTNAME}" "UninstallString" '"$INSTDIR\${UNINSTALLER}"'
  WriteRegExpandStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SHORTNAME}" "UnInstallLocation" "$INSTDIR" ; dont quote it
  WriteRegStr       HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SHORTNAME}" "UninstallVersion" "${VERSION}"
  WriteRegStr       HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SHORTNAME}" "UninstallBitness" "${CPU}"
  WriteRegDWORD     HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SHORTNAME}" "NoModify" 0x00000001
  WriteRegDWORD     HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SHORTNAME}" "NoRepair" 0x00000001

  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SHORTNAME}" "RexxAssociation" $RegVal_rexxAssociation
  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SHORTNAME}" "RexxEditor" $RegVal_rexxEditor
  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SHORTNAME}" "RexxHideAssociation" $RegVal_rexxHideAssociation
  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SHORTNAME}" "RexxPawsAssociation" $RegVal_rexxPawsAssociation

  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SHORTNAME}" "SendToRexx" $RegVal_sendTo_rexx
  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SHORTNAME}" "SendToRexxHide" $RegVal_sendTo_rexxHide
  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SHORTNAME}" "SendToRexxPaws" $RegVal_sendTo_rexxPaws

  ${WriteUninstaller} "$INSTDIR\${UNINSTALLER}"

SectionEnd

;-------------------------------------------------------------------------------
; Sample programs

Section "${LONGNAME} Samples" SecDemo
  DetailPrint "********** Samples **********"

  # pull in the component manifest from the Cmake installs
  !include "Samples_component_manifest.nsh"
  ;
  ; Create start menu shortcuts for some of the example programs.
  ;

  ${CreateDirectory} "$SMPROGRAMS\${LONGNAME}\${SHORTNAME} Samples"

  # pull in the shortcut manifest from the Cmake installs

  !include "Samples_shortcut_manifest.nsh"

SectionEnd

;------------------------------------------------------------------------
; Development tools

Section "${LONGNAME} Development Kit" SecDev
  DetailPrint "********** Development Kit **********"

  # pull in the component manifest from the Cmake installs

  !include "DevLib_component_manifest.nsh"

; We don't currently have any of these, so we don't create the directory for this
; until we have something
;  ${CreateDirectory} "$SMPROGRAMS\${LONGNAME}\${SHORTNAME} Development Tools"
;  # pull in the shortcut manifest from the Cmake installs
;
;  !include "DevLib_shortcut_manifest.nsh"

SectionEnd

;------------------------------------------------------------------------
; Documentation

Section "${LONGNAME} Documentation" SecDoc
  DetailPrint "********** Documentation **********"

  # pull in the component manifest from the Cmake installs

  !include "Docs_component_manifest.nsh"

  ; Create start menu shortcuts
  ${CreateDirectory} "$SMPROGRAMS\${LONGNAME}\${SHORTNAME} Documentation"

  # pull in the short manifest from the Cmake installs

  !include "Docs_shortcut_manifest.nsh"

SectionEnd

;-------------------------------------------------------------------------------
;  Hidden section to close the log file

Section -closelogfile
 Call CloseUninstallLog
SectionEnd

;===============================================================================
;Installer Functions
;===============================================================================

/** .onInit()  Call back function
 *
 * Called by the installer before any page is shown.  We use it to check for a
 * previously installed ooRexx and to set execution variables.
 *
 * Note that if we end up doing an upgrade type of install,
 * RegVal_uninstallLocation needs to be copied to the INSTDIR variable so that
 * we install in the same place as previous.
 */
Function .onInit

  Call CheckStrLen
  ${If} $UserRequestAbort == 'true'
    abort
  ${EndIf}

  ${If} ${CPU} == "x86_64"
    ${If} ${RunningX64}
      strcpy $INSTDIR "$PROGRAMFILES64\${SHORTNAME}"
    ${else}
      ; If we install 64 bit binaries on a 32 bit OS, things won't work.
      MessageBox MB_OK \
        "The installer detected that this operating system is 32-bit.  This \
        installer contains 64-bit binaries.  These binaries will not \
        work on a 32-bit operating system.$\n$\n\
        The installer will quit.  Please use the 32-bit ooRexx installer \
        to install on this operating system." \
        /SD IDOK
        Abort
    ${endIf}
  ${EndIf}

  ;
  ; Install as All Users if an admin
  ;
  Call IsUserAdmin
  Pop $IsAdminUser
  ${If} $IsAdminUser == "true"
    SetShellVarContext all
  ${EndIf}

  ReadRegStr $RegVal_uninstallString HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SHORTNAME}" "UninstallString"
  ReadRegStr $RegVal_uninstallLocation HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SHORTNAME}" "UnInstallLocation"
  ReadRegStr $RegVal_uninstallVersion HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SHORTNAME}" "UninstallVersion"
  ReadRegStr $RegVal_uninstallBitness HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SHORTNAME}" "UninstallBitness"
  ReadRegStr $RegVal_rexxEditor HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SHORTNAME}" "RexxEditor"
  ReadRegStr $RegVal_rexxAssociation HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SHORTNAME}" "RexxAssociation"
  ReadRegStr $RegVal_rexxHideAssociation HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SHORTNAME}" "RexxHideAssociation"
  ReadRegStr $RegVal_rexxPawsAssociation HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SHORTNAME}" "RexxPawsAssociation"
  ReadRegStr $RegVal_sendTo_rexx HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SHORTNAME}" "SendToRexx"
  ReadRegStr $RegVal_sendTo_rexxHide HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SHORTNAME}" "SendToRexxHide"
  ReadRegStr $RegVal_sendTo_rexxPaws HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SHORTNAME}" "SendToRexxPaws"
  ReadRegStr $RegVal_desktop_icon HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SHORTNAME}" "CreateDesktopIcon"

  ; When the uninstaller and current installer are for different addressing
  ; modes, we have had reports of problems.  We try to prevent that by giving
  ; the user the chance to uninstall separately, then rerun the installer.  This
  ; can only happen if the current platform is 64-bit.
  ${If} ${RunningX64}
    Call CheckBitnessMatch
    ${If} $UserRequestAbort == 'true'
      abort
    ${EndIf}
  ${EndIf}

  ; Check for previous version and if the upgrade type of uninstall is available.
  Call CheckInstalledStatus

  ; If a previous version is installed, make sure the key files are not locked.
  ; If they are, we give the user a chance to retry, othwerwise we abort
  ;unconditionally.
  StrCpy $CheckRxApiLock 'false'
  ${If} $PreviousVersionInstalled == 'true'
    Call CheckLockedFiles
    ${If} $UserRequestAbort == 'true'
      abort
    ${EndIf}
  ${EndIf}

  ; Set the send to dialog control variables.
  Call SetSendToVars

  ; Set all the dialog control variables for doing file associations to their
  ; correct starting values.
  Call SetFileAssociationVars

  ; We never do an upgrade type of install unless the user requests it.  But, we
  ; set the default for doing it quick to true.
  StrCpy $DoUpgrade 'false'
  StrCpy $Do_Upgrade_Type_CK_state ${BST_UNCHECKED}
  StrCpy $DoUpgradeQuick 'true'
  StrCpy $Do_Upgrade_Quick_CK_state ${BST_CHECKED}

FunctionEnd

/** Uninstall_Old_ooRexx_page()  Custom page function.
 *
 * This page is show when a previously installed version ooRexx is detected.  It
 * explains to the user that it is necessary to uninstall the previous version
 * and forces the user to check a secondary check box to "force" the install to
 * continue without uninstalling the previous version.
 *
 * The intent is to make it difficult to not do the uninstall and ensure that
 * the user knows installing over the top of an existing install is not
 * supported.
 */
Function Uninstall_Old_ooRexx_page

  /* Skip this page if no previous version is present */
  ${If} $PreviousVersionInstalled == "false"
    Abort
  ${EndIf}

  !insertmacro MUI_HEADER_TEXT "Previous ooRexx Version." "A previous version of ${LONGNAME} is already installed."
  nsDialogs::Create /NOUNLOAD 1018
  Pop $Dialog

  ${If} $Dialog == error
    Abort
  ${EndIf}

  ${NSD_CreateLabel} 0 0 100% 40u \
    "A version of ${LONGNAME} is currently installed.  If the previous version is \
    not uninstalled it is almost certain to cause problems.$\n$\n\
    To uninstall the previous version check the check box. To skip the uninstall step, \
    uncheck the check box."
  Pop $Label_One

  ${NSD_CreateCheckBox} 0 44u 100% 8u "Uninstall previous version of ooRexx"
  Pop $Uninstall_Previous_CK
  ${NSD_Check} $Uninstall_Previous_CK
  ${NSD_OnClick} $Uninstall_Previous_CK ShowHideForceInstall

  ${NSD_CreateLabel} 0 70u 100% 48u \
    "There are very few cases where installing ${LONGNAME} without removing the previous \
    version will work.  The ${SHORTNAME} developers will not support this type of installation.$\n$\n\
    To proceed with the install without uninstalling the previous version of ${SHORTNAME} you must \
    check the Force install to continue check box."
  Pop $Label_Two
  ShowWindow $Label_Two ${SW_HIDE}

  ${NSD_CreateCheckBox} 0 122u 100% 8u "Force install to continue"
  Pop $Force_Install_CK
  ${NSD_Uncheck} $Force_Install_CK
  ShowWindow $Force_Install_CK ${SW_HIDE}

  nsDialogs::Show

FunctionEnd

/** ShowHideForceInstall()  Callback function.
 *
 * Called when the Unistall previous ooRexx version check box is clicked.
 *
 * If the check box is checked, the user wants to uninstall and we hide the
 * force check box.  If the user unchecks the uninstall check box we show the
 * force check box.
 */
Function ShowHideForceInstall
	Pop $Uninstall_Previous_CK
	${NSD_GetState} $Uninstall_Previous_CK $0

	${If} $0 == 1
		ShowWindow $Label_Two ${SW_HIDE}
		ShowWindow $Force_Install_CK ${SW_HIDE}
	${Else}
		ShowWindow $Label_Two ${SW_SHOW}
		ShowWindow $Force_Install_CK ${SW_SHOW}
    ${NSD_Uncheck} $Force_Install_CK
	${EndIf}
FunctionEnd

/** OpenUninstallLog()
 *
 * Opens up the uninstall log.  In the hidden OpenLogFile section, the $INSTDIR
 * must be created before this function is callled.
 */
Function OpenUninstallLog
  IfFileExists "$INSTDIR\${UninstLog}" +3
    FileOpen $UninstLog "$INSTDIR\${UninstLog}" w
    Goto +4
  SetFileAttributes "$INSTDIR\${UninstLog}" NORMAL
  FileOpen $UninstLog "$INSTDIR\${UninstLog}" a
  FileSeek $UninstLog 0 END
FunctionEnd

/** CloseUninstallLog()
 *
 * Closes up the uninstall log.
 */
Function CloseUninstallLog
  FileClose $UninstLog
  SetFileAttributes "$INSTDIR\${UninstLog}" READONLY|SYSTEM|HIDDEN
FunctionEnd

/** Uninstall_Old_ooRexx_Leave()  Callback function.
 *
 * The installer calls this function when the user presses the Next button on
 * the uninstall old ooRexx version page.
 */
Function Uninstall_Old_ooRexx_Leave
	${NSD_GetState} $Uninstall_Previous_CK $0
	${NSD_GetState} $Force_Install_CK $1

  /* If the user said to not uninstall the previous and did not check force the
   * install, then send them back to the page.
   */
  ${If} $0 == 0
  ${andif} $1 == 0
    MessageBox MB_OK \
      "To bypass uninstalling the previous version of ooRexx you must check \
      the Force install check box.  If it is not the intention to skip the \
      uninstall step, then the Uninstall previous version must be checked.$\n$\n\
      Please check the appropriate check boxes to continue." \
      /SD IDOK
      Abort
  ${EndIf}

  /* If the user said to not uninstall the previous and to force the install,
   * then we skip the uninstall.  To signal this we set the
   * PreviousVersionInstalled variable to false.
   */
  ${If} $0 == 0
  ${andif} $1 == 1
    StrCpy $PreviousVersionInstalled 'false'
  ${EndIf}

FunctionEnd

/** Uninstall_Type_page()  Custom page function.
 *
 * This page is show when a previously installed version ooRexx is detected,
 * and the uninstaller version is capable of doing an upgrade type of install.
 *
 * It gives the user the option of only deleting the installed files while
 * leaving the environment, registry, etc., setting untouched.
 */
Function Uninstall_Type_page

  /* Skip this page if no previous version is present */
  ${If} $PreviousVersionInstalled == "false"
    Abort
  ${EndIf}

  ${If} $UpgradeTypeAvailable == 'false'
    Call Do_The_Uninstall
    Abort
  ${EndIf}

  !insertmacro MUI_HEADER_TEXT "Upgrade previous ooRexx Version." "It is possible to do an 'upgrade' type of install."
  nsDialogs::Create /NOUNLOAD 1018
  Pop $Dialog

  ${If} $Dialog == error
    Abort
  ${EndIf}


  ${NSD_CreateLabel} 0u 0u 100% 64u \
    "An 'upgrade' type of install will remove all the previously installed files and install \
    the new version of ${SHORTNAME}.  However, it will not undo any of the environment, file \
    association, or registry settings done by the previous install.$\n$\n\
    Use this type of install to quickly replace the old version files with the new version \
    files. Or, when you have customized these types of settings and do not wish them changed.$\n$\n\
    Note: with this type of install, the install location and other settings can NOT be changed.$\n$\n\"
  Pop $Label_One

  ${NSD_CreateCheckBox} 0u 68u 100% 8u "Perform an upgrade type of install"
  Pop $Do_Upgrade_Type_CK

  ${NSD_CreateLabel} 0u 92u 100% 24u \
    "A quick upgrade type of install will skip the pages pertaining to options that can not be changed.  \
    Otherwise the option pages are shown so the value of the options can be seen, but it is still not \
    possible to change the values."
  Pop $Label_Two

  ${NSD_CreateCheckBox} 0u 120u 100% 8u "Perform a quick upgrade type of install"
  Pop $Do_Upgrade_Quick_CK

  ${NSD_OnBack} Uninstall_Type_onBack
  ${NSD_OnClick} $Do_Upgrade_Type_CK ShowHideQuickUninstall

	${NSD_SetState} $Do_Upgrade_Type_CK $Do_Upgrade_Type_CK_state
	${NSD_SetState} $Do_Upgrade_Quick_CK $Do_Upgrade_Quick_CK_state

  ${If} $Do_Upgrade_Type_CK_state == ${BST_UNCHECKED}
		ShowWindow $Label_Two ${SW_HIDE}
		ShowWindow $Do_Upgrade_Quick_CK ${SW_HIDE}
  ${EndIf}

  ; Set focus to the page dialog rather than the installer dialog, set focus to
  ; the check box, and then show the page dialog
  SendMessage $Dialog ${WM_SETFOCUS} $HWNDPARENT 0
  SendMessage $Dialog ${WM_NEXTDLGCTL} $Do_Upgrade_Type_CK 1

  nsDialogs::Show

FunctionEnd

/** Uninstall_Type_onBack()  Call back function
 *
 * Invoked when the user clicks the back button on the Uninstall type page.  We
 * save the state of the check boxes on the page.
 */
Function Uninstall_Type_onBack
	${NSD_GetState} $Do_Upgrade_Type_CK $Do_Upgrade_Type_CK_state
	${NSD_GetState} $Do_Upgrade_Quick_CK $Do_Upgrade_Quick_CK_state
FunctionEnd

/** Uninstall_Type_Leave()  Call back function.
 *
 * The installer calls this function when the user presses the Next button on
 * the uninstall type page.  We don't save the check box state because we
 * immediately run the uninstall and the user won't see this page again.
 * Rather, we set the DoUpgrade / DoUpgradeQuick variables to the proper values.
 */
Function Uninstall_Type_Leave
	${NSD_GetState} $Do_Upgrade_Type_CK $Do_Upgrade_Type_CK_state
	${NSD_GetState} $Do_Upgrade_Quick_CK $Do_Upgrade_Quick_CK_state

  ${If} $Do_Upgrade_Type_CK_state == ${BST_CHECKED}
    StrCpy $DoUpgrade 'true'

    ${If} $Do_Upgrade_Quick_CK_state = ${BST_CHECKED}
      StrCpy $DoUpgradeQuick 'true'
    ${else}
      StrCpy $DoUpgradeQuick 'false'
    ${EndIf}
  ${else}
    StrCpy $DoUpgrade 'false'
    StrCpy $DoUpgradeQuick 'false'
  ${EndIf}

  Call Do_The_Uninstall

FunctionEnd

/** ShowHideQuickUninstall() Call back function
 *
 * Invoked when the user clicks the Perform an upgrade type of install check
 * box.  Shows or hides the Perform a quick upgrade type of install check box.
 */
Function ShowHideQuickUninstall
	Pop $Do_Upgrade_Type_CK
	${NSD_GetState} $Do_Upgrade_Type_CK $0

	${If} $0 == ${BST_CHECKED}
		ShowWindow $Label_Two ${SW_SHOW}
		ShowWindow $Do_Upgrade_Quick_CK ${SW_SHOW}
	${else}
		ShowWindow $Label_Two ${SW_HIDE}
		ShowWindow $Do_Upgrade_Quick_CK ${SW_HIDE}
	${EndIf}
FunctionEnd

/** Do_The_Uninstall()
 *
 * Executes the uninstall program and waits for its return.  The user could
 * have:
 *    Finished the uninstall
 *    Canceled the uninstall because they want to stop any running Rexx programs
 *    Canceled the uninstll for some other reason
 *
 * In addition, the script may have aborted the uninstall for some unexplained
 * error.
 *
 * In all cases we quit the install.  We put up a message box to explain why we
 * are quitting in most cases, the only exception is if the user choose to quit
 * to stop any running Rexx programs.
 *
 * @note  If we are doing an upgrade install, then we need to install to the
 *        same location as the original install.  This could easily be different
 *        than what $INSTDIR currently is, so we set $INSTDIR to our uninstall
 *        location.  For an upgrade install, the portion of the installer that
 *        allows the user to pick the install location will be disabled.
 */
Function Do_The_Uninstall

  ; Use $3 for the arg to the uninstall program.
  ${If} $DoUpgrade == 'true'
    StrCpy $INSTDIR $RegVal_uninstallLocation
    StrCpy $3 "upgrade"

    ${If} $DoUpgradeQuick == 'true'
      StrCpy $3 "upgradeQuick"
    ${EndIf}
  ${EndIf}

  HideWindow
  ClearErrors

  /* the "_?=$RegVal_uninstallLocation" portion of the command sets the
   * uninstall dir to $R2 and *prevents* the uninstaller from running in the
   * temp dir, which is what we want.
   */
  ExecWait '$RegVal_uninstallString /U=$3 _?=$RegVal_uninstallLocation' $0

  IfErrors UninstallErrors
  ${If} $0 == 0
    ; No errors, do a sanity check and finish up.
    IfFileExists "$INSTDIR\${KEYFILE1}" UninstallErrors
    IfFileExists "$INSTDIR\${KEYFILE2}" UninstallErrors
    Delete "$RegVal_uninstallLocation\${UNINSTALLER}"
    RMDir "$RegVal_uninstallLocation"

    BringToFront
    Goto NotInstalled
  ${EndIf}

  ${If} $0 == 1
    ; The user canceled the uninstall ...
    MessageBox MB_OK|MB_ICONEXCLAMATION|MB_TOPMOST \
               "You have elected to cancel the uninstall of the previous version of \
               ${SHORTNAME}.  There are very few cases where installing ${LONGNAME} \
               without removing the previous version will work and this installation \
               will abort.$\n$\n\
               If you are determined to install ${SHORTNAME} without removing the \
               previous version, rerun the installation and select to not uninstall \
               the previous version.  Then select to force the installation." \
               /SD IDOK
    Goto DoAbort
  ${EndIf}

  ${If} $0 == 4
    ; The user wants to quit to stop rxapi.  Only set to 4 if the user cancels
    ; on the page where she is asked to stop rxapi.  On that page she is given
    ; the option to quit completely.
    Goto DoAbort
  ${EndIf}

  ${If} $0 == 5
    ; 5 is only set when there are locked files
    MessageBox MB_OK|MB_ICONEXCLAMATION|MB_TOPMOST \
               "The uninstall of the previous version of ${SHORTNAME} was terminated by \
               the uninstall script.  The most likely cause of this is that there are \
               ${SHORTNAME} programs still running, which prevents critical files from being \
               updated.$\n$\n\
               The installation will abort.$\n$\n\
               You must ensure all ${SHORTNAME} programs are ended.  Then restart the installation." \
               /SD IDOK

    Goto DoAbort
  ${EndIf}

  ; Return code is 2 or greater, but not 4 or 5.  2 is uninstall canceled by
  ; script, we treat anything greater than 2 in the same way.
  MessageBox MB_OK|MB_ICONEXCLAMATION|MB_TOPMOST \
             "The uninstall of the previous version of ${SHORTNAME} was terminated by \
             the uninstall script.  The most likely cause of this is that the rxapi \
             process is running and could not be stopped.$\n$\n\
             When the previous version of rxapi is not stopped, the new version \
             of ${SHORTNAME} can not be installed correctly.$\n$\n\
             The installation will abort.$\n$\n\
             You can:$\n$\n\
             1.) Contact the developers on the SourceForge project for help.$\n$\n\
             2.) Try stopping rxapi manually and rerunning the installation.  Use \
             the task manager to stop the rxapi process.$\n$\n\
             3.) Elect to not stop rxapi and to not remove the previous version.  To \
             do this, rerun the installation and click No when asked to uninstall \
             the previous version.  Then click Yes when asked if you want to \
             continue.  However, if you do this ${SHORTNAME} may not be installed \
             correctly." \
             /SD IDOK
  Goto DoAbort

  UninstallErrors:
    MessageBox MB_OK|MB_ICONEXCLAMATION|MB_TOPMOST \
               "There were unexpected errors uninstalling the previous version \
               of ${SHORTNAME}.  There are very few cases where installing ${LONGNAME} \
               without removing the previous version will work and this installation \
               will abort.  You should first try rerunning the installation.$\n$\n\
               If this is the second attempt at installation and you still get this \
               message, you can:$\n$\n\
               1.) Contact the developers on the SourceForge project for help.$\n$\n\
               2.) Try removing the previous version manually and rerun the installation.$\n$\n\
               3.) Elect to not remove the previous version.  To do this, rerun the installation \
               and click No when asked to uninstall the previous version.  Then click Yes when \
               asked if you want to continue.$\n$\n\
               In all cases, please report this problem to the ${SHORTNAME} project on SourceForge." \
               /SD IDOK
    Goto DoAbort

  DoAbort:
    Quit

  NotInstalled:
  ; The previous version is now uninstalled, so we set the variable to reflect that.
  StrCpy $PreviousVersionInstalled 'false'
FunctionEnd

/** Ok_Stop_RxAPI_page()  Custom page function.
 *
 * This is a custom page that is shown if rxapi is still running.  If rxapi.exe
 * is not running the page is skipped.  On the page, the user is asked for the
 * okay to stop rxapi and advised of possible consequences.  If the user says
 * no, the install will be aborted..
 */
Function Ok_Stop_RxAPI_page
  Call CheckIsRxapiRunning

  ${If} $RxapiIsRunning == 'false'
    Abort
  ${EndIf}

  !insertmacro MUI_HEADER_TEXT "The ${LONGNAME} rxapi process is currently running." \
                               "A new version of rxapi can not be installed while rxapi is running."
  nsDialogs::Create /NOUNLOAD 1018
  Pop $Dialog

  ${If} $Dialog == error
    Abort
  ${EndIf}

  ${NSD_CreateLabel} 0 0 100% 112u \
    "A previous version of the ${LONGNAME} rxapi process is currently running. \
    The new version of rxapi can not be installed while the previous version is running.$\n$\n\
    When the Stop rxapi check box is checked, the installation will stop rxapi before \
    proceeding.  If the check box is not checked, rxapi will not be stopped.$\n$\n\
    If rxapi is not stopped the install will be canceled.$\n$\n\
    If, and only if, there are Rexx programs running, stopping rxapi could \
    possibly cause data loss.$\n$\n\
    If you are worried about this, please uncheck the Stop rxapi check box.  When the \
    install ends, stop all running Rexx programs, and rerun the installation program."

  Pop $Label_One

  ${NSD_CreateCheckBox} 0 116u 100% 15u "Stop rxapi"
  Pop $StopRxAPI_CK
  ${NSD_SetState} $StopRxAPI_CK 1

  nsDialogs::Show

FunctionEnd

/** Ok_Stop_RxAPI_leave()  Call back function.
 *
 * Invoked when the user leaves the page that asks for permission to stop the
 * rxapi process.  We check if the user said okay or not.  If the user does not
 * say okay we quit the install.
 *
 * When the user does say okay, we stop rxapi and check that it is indeed
 * stopped.  If it is not stopped, we inform the user and also quit the install.
 */
Function Ok_Stop_RxAPI_leave

  ${NSD_GetState} $StopRxAPI_CK $StopRxAPI_CK_State

  ${If} $StopRxAPI_CK_State == 0
    Quit
  ${EndIf}

  Call StopRxapi
  Pop $R0
  ${If} $R0 == 'Ok'
    Goto NotRunning
  ${EndIf}

  ; rxapi was not stopped, the error code is now at top of stack
  Pop $R0

  MessageBox MB_OK|MB_ICONEXCLAMATION|MB_TOPMOST \
             "Can not determine conclusively that rxapi is stopped.  Since a new version of rxapi \
             can not be installed while rxapi is running, the installation will quit.$\n$\n\
             Please use the task manager to locate rxapi.exe and end that process, then restart the \
             installation.  If you are uncomfortable with using the task manager, contact the \
             ${SHORTNAME} developers on SourceForge for help.$\n$\n\
             If you report this problem, please note that the error code is $R0." /SD IDOK
    Quit

  NotRunning:

FunctionEnd

/** Components_Page_pre()  Call back function
 *
 * Invoked by the installer before the components page is created.  We do one
 * last check that there are no locked files.  If there are we quit.  This could
 * be frustrating for a user, but we know that things will fail if we proceed.
 *
 * If this is a QUICK upgrade install, we skip the page.
 */
Function Components_Page_pre

  StrCpy $CheckRxApiLock 'false'
  Call CheckLockedFiles
  ${If} $$UserRequestAbort == 'true'
    Quit
  ${EndIf}

  ${If} $DoUpgrade == 'true'
  ${andif} $DoUpgradeQuick == 'true'
    Abort
  ${EndIf}

FunctionEnd

/** Components_Page_show()  Call back function
 *
 * Invoked by the installer right before the components page is shown.
 *
 * If this is an upgrade install, we don't allow the user to quit from here on
 * out.  On this page we also don't let the user go back
 *
 * When it is not an upgrade install, nothing is done.
 */
Function Components_Page_show

  ${If} $DoUpgrade == 'true'
    ; Disable Back button
    GetDlgItem $0 $HWNDPARENT 3
    EnableWindow $0 0

    ; Disable the components list view control
    EnableWindow $mui.ComponentsPage.Components 0

    ; Change the descriptive text
    SendMessage $mui.ComponentsPage.Text ${WM_SETTEXT} 0 \
      "STR:These components of ${LONGNAME} ${VERSION} wil be installed.  The component list can not be \
      changed for an upgrade type of install.  Click Next to continue."

    Call PageDisableQuit
  ${EndIf}

FunctionEnd

/** Directory_Page_pre()  Call back function
 *
 * Invoked by the installer before the directory page is created.
 *
 * If this is a QUICK upgrade install, we skip the page.
 */
Function Directory_Page_pre

  ${If} $DoUpgrade == 'true'
  ${andif} $DoUpgradeQuick == 'true'
    Abort
  ${EndIf}

FunctionEnd

/** Directory_Page_show()  Call back function
 *
 * Invoked by the installer right before the directory page is shown.
 *
 * If this is an upgrade install, the install location can not be changed.  We
 * use function to show the user the install location, but not let them change
 * the location.
 *
 * When it is not an upgrade install, nothing is done.
 */
Function Directory_Page_show

  ${If} $DoUpgrade == 'true'
    SendMessage $mui.DirectoryPage.Text ${WM_SETTEXT} 0 \
      "STR:Setup will install ${LONGNAME} ${VERSION} in the following folder.  The location can not be \
      changed for an upgrade type of install.  Click Next to continue."

    EnableWindow $mui.DirectoryPage.Directory 0
    EnableWindow $mui.DirectoryPage.BrowseButton 0

    Call PageDisableQuit
  ${EndIf}

FunctionEnd

/** Finish_Page_pre()  Call back function
 *
 * Invoked by the installer before the finish page is created.
 *
 * If this is an upgrade install, the creation or not, of the desktop icon can
 * not be changed.  So we always create the icon here if we are going to.
 *
 * If this is a QUICK upgrade install, we abort here so that the finish page is
 * not shown at all
 *
 * At the time this is run, the registry values have been deleted.  The value in
 * RegVal_desktop_icon is the value in the registry when this installer was
 * started.  If there is an existing ooRexx, the ooRexx uninstaller is run and
 * it always deletes all the existing registry entries.  If we are doing an
 * upgrade and creating the icon we write a 1 for the registry value.  If we are
 * not creating the icon we write a 0 just to be tidy.  Leaving out the entry
 * altogether would be fine.  If we are not doing an upgrade, we do not do
 * anything here, the Finish page will be shown and the CreateDesktopIcon()
 * function will do the appropriate thing.
 */
Function Finish_Page_pre

  ${If} $DoUpgrade == 'true'
    ${If} $RegVal_desktop_icon == '1'
      CreateShortcut "$DESKTOP\Open Object Rexx Resources.lnk" "$SMPROGRAMS\${LONGNAME}\" "" "$INSTDIR\rexx.exe"
      Call OpenUninstallLog
      ${AddItem} "$DESKTOP\Open Object Rexx Resources.lnk"
      WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SHORTNAME}" "CreateDesktopIcon" 1
      Call CloseUninstallLog
    ${else}
      WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SHORTNAME}" "CreateDesktopIcon" 0
    ${EndIf}
    ${If} $DoUpgradeQuick == 'true'
      Abort
    ${EndIf}
  ${EndIf}

FunctionEnd

/** Finish_Page_show()  Call back function
 *
 * Invoked by the installer right before the finish page is shown.
 *
 * Note that if this is a quick upgrade type, we never get here.
 *
 * If this is an upgrade install, the create desktop icon value can not be
 * changed.  We use function to show the create desktop icon value by checking
 * or not checking the check box, but we disable the check box.  For the show
 * getting started with Windows ooRex checkbox, we assume on an upgrade install,
 * the user doesn't need this at all and we make the check box invisible.
 *
 * When it is not an upgrade install, nothing is done.
 */
Function Finish_Page_show

  ${If} $DoUpgrade == 'true'
    SendMessage $mui.FinishPage.Text ${WM_SETTEXT} 0 \
      "STR:${LONGNAME} ${VERSION} has been installed on your computer.  Whether a Desktop \
      Icon has been created or not is indicated by the state of the check box. This can not \
      be changed for an upgrade type of install.$\n$\n  Click Finish to close this Wizard."

    SendMessage $mui.FinishPage.Run ${BM_SETCHECK} ${BST_CHECKED} $RegVal_desktop_icon
    EnableWindow $mui.FinishPage.Run 0

    ShowWindow $mui.FinishPage.ShowReadme ${SW_HIDE}

    ; Show or not show the link?
    ShowWindow $mui.FinishPage.Link ${SW_HIDE}

  ${EndIf}

FunctionEnd

/** File_Associations_page()  Custom page function.
 *
 * Allows the user to specify whether they want to use Windows file associations
 * or not.
 *
 * The page is not shown when doing an upgrade type of install.
 */
Function File_Associations_page

  ${If} $DoUpgrade == 'true'
    Abort
  ${EndIf}

  !insertmacro MUI_HEADER_TEXT "Associate file extensions with the ooRexx executables." \
                               "Any, or all, of the ooRexx executables (rexx.exe, rexxhide.exe, or rexxpaws.exe) \
                               can be associated with a file extension."

  nsDialogs::Create 1018
  Pop $Dialog

  ${If} $Dialog == error
    Abort
  ${EndIf}

  ${NSD_OnBack} File_Associations_leave

  ${NSD_CreateLabel} 0 0 100% 120u \
    "Windows file associations define how Windows treats a file type on your system. \
    File associations control, among other things, what happens when a user double-clicks a \
    file, which icon appears for a file by default, and how the file appears when viewed \
    in Windows Explorer.$\n$\n\
    Associating a file extension with an ooRexx executable allows Rexx programs to be executed by \
    double clicking them in Windows Explorer, and to be run from the command line by just typing \
    their file name.  In addition, you can specify an editor for the file type.  This editor is \
    used when the Edit item of the context menu for the file is selected.$\n$\n\
    Check the check box to have the installer create file associations.  The following pages \
    will allow you to specify which associations are created.  Uncheck the check box if you \
    do not want any associations to be created."

  Pop $Label_One

  ${NSD_CreateCheckBox} 0 122u 100% 8u "Create Windows file associations"
  Pop $Use_File_Associations_CK
  ${NSD_SetState} $Use_File_Associations_CK $Use_File_Associations_CK_state

  nsDialogs::Show

FunctionEnd

/** File_Associations_leave()  Call back function.
 *
 * Invoked when the user clicks the Back or Next buttons on the File
 * Associations page.  Saves the state of the Use File Associations check box.
 */
Function File_Associations_leave

  ${NSD_GetState} $Use_File_Associations_CK $Use_File_Associations_CK_state

FunctionEnd

/** SendTo_Items_page()  Custom page function.
 *
 * Allows the user to create 'Send To' items for the Rexx executables.
 *
 * The page is skipped if we are doing a quick upgrade.
 */
Function SendTo_Items_page

  ${If} $DoUpgrade == 'true'
  ${andif} $DoUpgradeQuick == 'true'
    Abort
  ${EndIf}

  ${If} $DoUpgrade == 'true'
    !insertmacro MUI_HEADER_TEXT "The Send To items that will be created." \
                                 "Which Send To items will be created can not be changed during an upgrade \
                                 type of install."
  ${else}
    !insertmacro MUI_HEADER_TEXT "Create 'Send To' items for the Rexx executables." \
                                 "'Send To' items can be used instead of file associations, or in addition \
                                 to file associations."
  ${EndIf}

  nsDialogs::Create 1018
  Pop $Dialog

  ${If} $Dialog == error
    Abort
  ${EndIf}

  ${NSD_OnBack} SendTo_Items_leave

  ${NSD_CreateLabel} 0u 0u 100% 72u \
    "The 'Send To' context menu item for objects displayed in the Windows Explorer contains a list of \
    programs that the object can be 'sent to.'  Typically, the items in the list are executables that \
    can process the file or directory object sent to them.  'Sending' your Rexx program to one of the \
    Rexx executables will execute your program.$\n$\n\
    Rather than create a file association for rexxhide.exe and rexxpaws.exe you may wish to create a \
    'Send To' item for those executables.  Or create both a file association and 'Send To' items for \
    those executables.  Usually a file association is created for rexx.exe and not a 'Send To' item."

  Pop $Label_One

  ${NSD_CreateCheckBox}   0u   80u 100%  8u "Create 'Send To' Rexx item  (Typically this is not done.)"
  Pop $SendTo_rexx_CK

  ${NSD_CreateCheckBox}    0u 100u 100%  8u "Create 'Send To' Rexx Hide (rexxhide.exe) item"
  Pop $SendTo_rexxHide_CK

  ${NSD_CreateCheckBox}    0u 120u 100%  8u "Create 'Send To' Rexx Pause (rexxpaws.exe) item"
  Pop $SendTo_rexxPaws_CK

  ${NSD_SetState} $SendTo_rexx_CK $SendTo_rexx_CK_state
  ${NSD_SetState} $SendTo_rexxhide_CK $SendTo_rexxHide_CK_state
  ${NSD_SetState} $SendTo_rexxpaws_CK $SendTo_rexxPaws_CK_state

  ${If} $DoUpgrade == 'true'
    EnableWindow $Label_One 0
	  EnableWindow $SendTo_rexx_CK 0
	  EnableWindow $SendTo_rexxHide_CK 0
	  EnableWindow $SendTo_rexxPaws_CK 0
    Call PageDisableQuit
	${EndIf}

  nsDialogs::Show

FunctionEnd

/** SendTo_Items_leave()  Call back function.
 *
 * This function is called when the Send To Items page is left.  The state of
 * the dialog controls is saved.
 */
Function SendTo_Items_leave

  ${NSD_GetState} $SendTo_rexx_CK $SendTo_rexx_CK_state
  ${NSD_GetState} $SendTo_rexxHide_CK $SendTo_rexxHide_CK_state
  ${NSD_GetState} $SendTo_rexxPaws_CK $SendTo_rexxPaws_CK_state

FunctionEnd

/** Associate_rexx_page()  Custom page function.
 *
 * Presents the option to the user of creating a file association for rexx.exe
 *
 * The page is skipped if not using file associations, or if we are doing a
 * quick upgrade.
 */
Function Associate_rexx_page

  ${If} $Use_File_Associations_CK_state == ${BST_UNCHECKED}
    Abort
  ${EndIf}

  ${If} $DoUpgrade == 'true'
  ${andif} $DoUpgradeQuick == 'true'
    Abort
  ${EndIf}

  ${If} $DoUpgrade == 'true'
    !insertmacro MUI_HEADER_TEXT "The file extension for rexx.exe and Rexx program editor choices." \
                                 "These choices can not be changed during an upgrade type of install."
  ${else}
    !insertmacro MUI_HEADER_TEXT "Associate a file extension with rexx.exe." "Pick the editor to be used when the Edit \
                                 item of the context menu is selected."
  ${EndIf}

  nsDialogs::Create 1018
  Pop $Dialog

  ${If} $Dialog == error
    Abort
  ${EndIf}

  ${NSD_OnBack} Associate_rexx_leave

  ${NSD_CreateLabel} 0u 0u 100% 16u \
    "Select the editor to be used with your ooRexx file type(s).  This adds the Edit menu item to \
    the context menu of the file type.  The same editor is used for all file types."

  Pop $Label_One

  ; Editor line
  ${NSD_CreateLabel}     0u 20u 60u  8u "Full path to editor:"
  Pop $0  ; Discarded

  ${NSD_CreateText}      0u 30u 185u 12u $Rexx_editor_text
  Pop $Rexx_editor_EDIT

  ${NSD_CreateButton}   190u 28u  45u 16u "Browse..."
  Pop $Rexx_editor_PB

	System::Call shlwapi::SHAutoComplete(i$Rexx_editor_EDIT, i${SHACF_FILESYSTEM})


  ${NSD_CreateLabel} 0u 60u 100% 24u \
    "By default in ${LONGNAME} installations the Rexx interpreter, rexx.exe, is associated with the \
    ${DefRexxExt} extension using the file type name of ${DefRexxFType}.  However, you can change these values if \
    you care to."

  Pop $Label_Two

  ${NSD_CreateGroupBox} 0u 90u 100% 44u "File Association for rexx.exe"
  Pop $0  ; Discarded

  ${NSD_CreateCheckBox} 8u  104u 80% 8u "Create rexx.exe file association"
  Pop $Associate_rexx_CK

  ${NSD_SetState} $Associate_rexx_CK $Associate_rexx_CK_state

  ; Extension line
  ${NSD_CreateLabel}     16u  116u  75u  8u "Extension (no spaces):"
  Pop $0  ; Discarded

  ${NSD_CreateText}      91u  114u  36u 12u $Rexx_ext_text
  Pop $Rexx_ext_EDIT

  ; File type line
  ${NSD_CreateLabel}     137u 116u  90u  8u "File type name (no spaces):"
  Pop $0  ; Discarded

  ${NSD_CreateText}      228u 114u  46u 12u $Rexx_ftype_text
  Pop $Rexx_ftype_EDIT

  ${NSD_SetState} $Associate_rexx_CK $Associate_rexx_CK_state
  ${NSD_SetState} $SendTo_rexx_CK $SendTo_rexx_CK_state

  ${If} $Associate_rexx_CK_state == ${BST_UNCHECKED}
  ${orif} $DoUpgrade == 'true'
	  EnableWindow $Rexx_ext_EDIT 0
	  EnableWindow $Rexx_ftype_EDIT 0

    ${If} $DoUpgrade == 'true'
  	  EnableWindow $Rexx_editor_EDIT 0
  	  EnableWindow $Rexx_editor_PB 0
  	  EnableWindow $Associate_rexx_CK 0
      EnableWindow $Label_One 0
      EnableWindow $Label_Two 0
      Call PageDisableQuit
  	${EndIf}
	${EndIf}

  ${NSD_OnClick} $Associate_rexx_CK EnableRexxAssociation
  ${NSD_OnClick} $Rexx_editor_PB Get_rexx_editor_file

  nsDialogs::Show

FunctionEnd

/** Associate_rexx_leave()  Call back function.
 *
 * This function is called when the Rexx association page is left.  We check
 * that the text fields are 'sane' and return the user to the page if they
 * are not.  If the fields are good, the state of the dialog controls is saved.
 */
Function Associate_rexx_leave

  ${NSD_GetState} $Associate_rexx_CK $Associate_rexx_CK_state

  ${If} $Associate_rexx_CK_state == ${BST_CHECKED}
    ${NSD_GetText} $Rexx_ext_EDIT $0
    ${NSD_GetText} $Rexx_ftype_EDIT $1

    ; If either the extension field or the ftype field are blank, abort.
    ${If} $0 == ""
    ${orif} $1 == ""
      MessageBox MB_OK|MB_ICONEXCLAMATION \
        "Creating a file association requires that \
        both the file extension and the file type field \
        be filled in."

      ${If} $0 == ""
        SendMessage $Dialog ${WM_NEXTDLGCTL} $Rexx_ext_EDIT 1
      ${else}
        SendMessage $Dialog ${WM_NEXTDLGCTL} $Rexx_ftype_EDIT 1
      ${EndIf}
      Abort
    ${EndIf}

    ; Copy the first char of the ext field to $0 if not a '.', abort.
    StrCpy $2 $0 1
    ${If} $2 != "."
      MessageBox MB_OK|MB_ICONEXCLAMATION \
        "Please include the leading dot '.' of the file extension."
      SendMessage $Dialog ${WM_NEXTDLGCTL} $Rexx_ext_EDIT 1
      Abort
    ${EndIf}

    ; Check that the user did not include any spaces in either field. If so abort
    push $0
    call CheckForSpaces
    pop $2
    push $1
    call CheckForSpaces
    pop $3

    ${If} $2 > 0
    ${orif} $3 > 0
      MessageBox MB_OK|MB_ICONEXCLAMATION \
        "Neither the file extension field nor the file \
        type name field can contain a space."

      ${If} $2 > 0
        SendMessage $Dialog ${WM_NEXTDLGCTL} $Rexx_ext_EDIT 1
      ${else}
        SendMessage $Dialog ${WM_NEXTDLGCTL} $Rexx_ftype_EDIT 1
      ${EndIf}
      Abort
    ${EndIf}

  ${EndIf}


  ; Okay text fields are okay.  If editor field is blank, it is just not used.
  ${NSD_GetText} $Rexx_ext_EDIT $Rexx_ext_text
  ${NSD_GetText} $Rexx_ftype_EDIT $Rexx_ftype_text
  ${NSD_GetText} $Rexx_editor_EDIT $Rexx_editor_text

FunctionEnd

/** Get_rexx_editor_file()
 *
 * Puts up a file open dialog and allows the user to select a file.  If the
 * user does not cancel, the edit control is updated with the file selected.
 */
Function Get_rexx_editor_file
	Pop $Rexx_editor_PB
	${NSD_GetText} $Rexx_editor_EDIT $0

  nsDialogs::SelectFileDialog open $0 "*.exe"
  pop $0
  ${If} $0 != ""
  	${NSD_SetText} $Rexx_editor_EDIT $0
  ${EndIf}

FunctionEnd

/** EnableRexxAssociation()
 *
 * Called when the user clicks on the Create rexx.exe file association check
 * box.  Disables, or enables, the controls depending on if the check box is
 * checked or not.
 */
Function EnableRexxAssociation
	Pop $Associate_rexx_CK
	${NSD_GetState} $Associate_rexx_CK $0

	${If} $0 == 1
	  EnableWindow $Rexx_ext_EDIT 1
	  EnableWindow $Rexx_ftype_EDIT 1
	${Else}
	  EnableWindow $Rexx_ext_EDIT 0
	  EnableWindow $Rexx_ftype_EDIT 0
	${EndIf}
FunctionEnd

/** Associate_otherExes_page()  Custom page function.
 *
 * This is a custom page
 *
 *
 *
 */
Function Associate_otherExes_page

  ${If} $Use_File_Associations_CK_state == ${BST_UNCHECKED}
    Abort
  ${EndIf}

  ${If} $DoUpgrade == 'true'
  ${andif} $DoUpgradeQuick == 'true'
    Abort
  ${EndIf}

  ${If} $DoUpgrade == 'true'
    !insertmacro MUI_HEADER_TEXT "The file extension chocies for rexxhide.exe. and rexxpaws.exe" \
                                 "These choices can not be changed during an upgrade type of install."
  ${else}
    !insertmacro MUI_HEADER_TEXT "Associate a file extension with rexxhide.exe and / or rexxpaws.exe" \
                                 "rexxhide default file extension: $\"${DefRexxHideExt}$\" file type: $\"${DefRexxHideFType}$\"$\n\
                                 rexpaws default file extension: $\"${DefRexxPawsExt}$\" file type: $\"${DefRexxPawsFType}$\"."
  ${EndIf}

  nsDialogs::Create 1018
  Pop $Dialog

  ${If} $Dialog == error
    Abort
  ${EndIf}

  ${NSD_OnBack} Associate_otherExes_leave

  /* Controls for Rexx Hide */
  ${NSD_CreateLabel} 0u 0u 100% 8u \
    "rexxhide runs Rexx programs without creating a console window."

  Pop $Label_One

  ${NSD_CreateGroupBox} 0u 12u 100% 44u "File Association for rexxhide.exe"
  Pop $0  ; Discarded

  ${NSD_CreateCheckBox} 8u 24u 80% 8u "Create rexxhide.exe file association"
  Pop $Associate_rexxhide_CK

  ${NSD_SetState} $Associate_rexxhide_CK $Associate_rexxhide_CK_state

  ; Extension line
  ${NSD_CreateLabel}     16u  38u   75u  8u "Extension (no spaces):"
  Pop $0  ; Discarded

  ${NSD_CreateText}      91u  36u  36u 12u $RexxHide_ext_text
  Pop $RexxHide_ext_EDIT

  ; File type line
  ${NSD_CreateLabel}     137u 38u   90u  8u "File type name (no spaces):"
  Pop $0  ; Discarded

  ${NSD_CreateText}      228u 36u  46u 12u $RexxHide_ftype_text
  Pop $RexxHide_ftype_EDIT


  /* Controls for Rexx Paws */
  ${NSD_CreateLabel} 0u 70u 100% 16u \
    "rexxpaws runs a Rexx programs and 'pauses' until the user hits the Enter key, allowing any output to \
    be read before the console window closes."

  Pop $Label_Two

  ${NSD_CreateGroupBox} 0u 92u 100% 44u "File Association for rexxpaws.exe"
  Pop $0  ; Discarded

  ${NSD_CreateCheckBox} 8u 104u 80% 8u "Create rexxpaws.exe file association"
  Pop $Associate_rexxpaws_CK

  ${NSD_SetState} $Associate_rexxpaws_CK $Associate_rexxpaws_CK_state

  ; Extension line
  ${NSD_CreateLabel}     16u  118u  75u  8u "Extension (no spaces):"
  Pop $0  ; Discarded

  ${NSD_CreateText}      91u  116u  36u 12u $RexxPaws_ext_text
  Pop $RexxPaws_ext_EDIT

  ; File type line
  ${NSD_CreateLabel}     137u 118u  90u  8u "File type name (no spaces):"
  Pop $0  ; Discarded

  ${NSD_CreateText}      228u 116u  46u 12u $RexxPaws_ftype_text
  Pop $RexxPaws_ftype_EDIT

  ${If} $DoUpgrade == 'true'
    EnableWindow $Associate_rexxhide_CK 0
	  EnableWindow $RexxHide_ext_EDIT 0
	  EnableWindow $RexxHide_ftype_EDIT 0

  	EnableWindow $Associate_rexxpaws_CK 0
	  EnableWindow $RexxPaws_ext_EDIT 0
	  EnableWindow $RexxPaws_ftype_EDIT 0

    EnableWindow $Label_One 0
    EnableWindow $Label_Two 0

    Call PageDisableQuit
  ${else}
    ${If} $Associate_rexxhide_CK_state == ${BST_UNCHECKED}
  	  EnableWindow $RexxHide_ext_EDIT 0
  	  EnableWindow $RexxHide_ftype_EDIT 0
  	${EndIf}

    ${If} $Associate_rexxpaws_CK_state == ${BST_UNCHECKED}
  	  EnableWindow $RexxPaws_ext_EDIT 0
  	  EnableWindow $RexxPaws_ftype_EDIT 0
    ${EndIf}
  ${EndIf}

  ${NSD_OnClick} $Associate_rexxhide_CK EnableRexxHideAssociation
  ${NSD_OnClick} $Associate_rexxpaws_CK EnableRexxPawsAssociation

  nsDialogs::Show

FunctionEnd

/** Associate_otherExes_leave()  Call back function.
 *
 * This function is called when the RexxHide association page is left.  We check
 * that the text fields are 'sane' and return the user to the page if they
 * are not.  If the text field values are good, the state of the dialog contorls
 * is saved.
 */
Function Associate_otherExes_leave

  /* Check the Rexx Hide controls */
  ${NSD_GetState} $Associate_rexxhide_CK $Associate_rexxhide_CK_state

  ${If} $Associate_rexxhide_CK_state == ${BST_CHECKED}
    ${NSD_GetText} $RexxHide_ext_EDIT $0
    ${NSD_GetText} $RexxHide_ftype_EDIT $1

    ; If either the extension field or the ftype field are blank, abort.
    ${If} $0 == ""
    ${orif} $1 == ""
      MessageBox MB_OK|MB_ICONEXCLAMATION \
        "Creating a file association requires that \
        both the file extension and the file type field \
        be filled in."

      ${If} $0 == ""
        SendMessage $Dialog ${WM_NEXTDLGCTL} $RexxHide_ext_EDIT 1
      ${else}
        SendMessage $Dialog ${WM_NEXTDLGCTL} $RexxHide_ftype_EDIT 1
      ${EndIf}
      Abort
    ${EndIf}

    ; Copy the first char of the ext field to $0 if not a '.', abort.
    StrCpy $2 $0 1
    ${If} $2 != "."
      MessageBox MB_OK|MB_ICONEXCLAMATION \
        "Please include the leading dot '.' of the file extension."
      SendMessage $Dialog ${WM_NEXTDLGCTL} $RexxHide_ext_EDIT 1
      Abort
    ${EndIf}

    ; Check that the user did not include any spaces in either field. If so abort
    push $0
    call CheckForSpaces
    pop $2
    push $1
    call CheckForSpaces
    pop $3

    ${If} $2 > 0
    ${orif} $3 > 0
      MessageBox MB_OK|MB_ICONEXCLAMATION \
        "Neither the file extension field nor the file \
        type name field can contain a space."

      ${If} $2 > 0
        SendMessage $Dialog ${WM_NEXTDLGCTL} $RexxHide_ext_EDIT 1
      ${else}
        SendMessage $Dialog ${WM_NEXTDLGCTL} $RexxHide_ftype_EDIT 1
      ${EndIf}
      Abort
    ${EndIf}


  ${EndIf}

  /* Check the Rexx Paws controls */
  ${NSD_GetState} $Associate_rexxpaws_CK $Associate_rexxpaws_CK_state

  ${If} $Associate_rexxpaws_CK_state == ${BST_CHECKED}
    ${NSD_GetText} $RexxPaws_ext_EDIT $0
    ${NSD_GetText} $RexxPaws_ftype_EDIT $1

    ; If either the extension field or the ftype field are blank, abort.
    ${If} $0 == ""
    ${orif} $1 == ""
      MessageBox MB_OK|MB_ICONEXCLAMATION \
        "Creating a file association requires that \
        both the file extension and the file type field \
        be filled in."

      ${If} $0 == ""
        SendMessage $Dialog ${WM_NEXTDLGCTL} $RexxPaws_ext_EDIT 1
      ${else}
        SendMessage $Dialog ${WM_NEXTDLGCTL} $RexxPaws_ftype_EDIT 1
      ${EndIf}
      Abort
    ${EndIf}

    ; Copy the first char of the ext field to $0 if not a '.', abort.
    StrCpy $2 $0 1
    ${If} $2 != "."
      MessageBox MB_OK|MB_ICONEXCLAMATION \
        "Please include the leading dot '.' of the file extension."
      SendMessage $Dialog ${WM_NEXTDLGCTL} $RexxPaws_ext_EDIT 1
      Abort
    ${EndIf}

    ; Check that the user did not include any spaces in either field. If so abort
    push $0
    call CheckForSpaces
    pop $2
    push $1
    call CheckForSpaces
    pop $3

    ${If} $2 > 0
    ${orif} $3 > 0
      MessageBox MB_OK|MB_ICONEXCLAMATION \
        "Neither the file extension field nor the file \
        type name field can contain a space."

      ${If} $2 > 0
        SendMessage $Dialog ${WM_NEXTDLGCTL} $RexxPaws_ext_EDIT 1
      ${else}
        SendMessage $Dialog ${WM_NEXTDLGCTL} $RexxPaws_ftype_EDIT 1
      ${EndIf}
      Abort
    ${EndIf}

  ${EndIf}

  ; Okay text fields are okay.
  ${NSD_GetText} $RexxHide_ext_EDIT $RexxHide_ext_text
  ${NSD_GetText} $RexxHide_ftype_EDIT $RexxHide_ftype_text
  ${NSD_GetText} $RexxPaws_ext_EDIT $RexxPaws_ext_text
  ${NSD_GetText} $RexxPaws_ftype_EDIT $RexxPaws_ftype_text

FunctionEnd

/** EnableRexxHideAssociation()
 *
 * Called when the user clicks on the Create rexxhide.exe file association check
 * box.  Disables, or enables, the controls depending on if the check box is
 * checked or not.
 */
Function EnableRexxHideAssociation
	Pop $Associate_rexxhide_CK
	${NSD_GetState} $Associate_rexxhide_CK $0

	${If} $0 == 1
	  EnableWindow $RexxHide_ext_EDIT 1
	  EnableWindow $RexxHide_ftype_EDIT 1
	${Else}
	  EnableWindow $RexxHide_ext_EDIT 0
	  EnableWindow $RexxHide_ftype_EDIT 0
	${EndIf}
FunctionEnd

/** EnableRexxPawsAssociation()
 *
 * Called when the user clicks on the Create rexxpaws.exe file association check
 * box.  Disables, or enables, the controls depending on if the check box is
 * checked or not.
 */
Function EnableRexxPawsAssociation
	Pop $Associate_rexxpaws_CK
	${NSD_GetState} $Associate_rexxpaws_CK $0

	${If} $0 == 1
	  EnableWindow $RexxPaws_ext_EDIT 1
	  EnableWindow $RexxPaws_ftype_EDIT 1
	${Else}
	  EnableWindow $RexxPaws_ext_EDIT 0
	  EnableWindow $RexxPaws_ftype_EDIT 0
	${EndIf}
FunctionEnd

/** Confirm_page()  Custom page function.
 *
 * Gives the user one last chance to go back and change any settings.
 *
 * The page is skipped if we are doing an upgrade type of install.
 */
Function Confirm_page

  ${If} $DoUpgrade == 'true'
  ${andif} $DoUpgradeQuick == 'true'
    Abort
  ${EndIf}

  ${If} $DoUpgrade == 'true'
    !insertmacro MUI_HEADER_TEXT "${LONGNAME} is ready for installation." \
                                 "Installation options remain the same for an upgrade type of installation \
                                 of ${LONGNAME}."
  ${else}
    !insertmacro MUI_HEADER_TEXT "${LONGNAME} is ready for installation." \
                                 "All options for ${LONGNAME} have been collected."
  ${EndIf}

  nsDialogs::Create 1018
  Pop $Dialog

  ${If} $Dialog == error
    Abort
  ${EndIf}

  ${If} $DoUpgrade == 'true'
    ${NSD_CreateLabel} 0u 0u 100% 72u \
    "Click the Install button to begin installation.  Click the Back button if you \
     wish to review the installation options.  An upgrade type of installation can \
     not be canceled at this point."
  ${else}
    ${NSD_CreateLabel} 0u 0u 100% 72u \
    "All the parameters needed to install ${LONGNAME} on your system have been \
    gathered together.$\n$\n\
    Click the Install button to begin installation.  Click the Back button to \
    review or change any settings.  Click the Cancel button to abort the installation \
    altogether."
  ${EndIf}

  Pop $Label_One

  ${If} $DoUpgrade == 'true'
    Call PageDisableQuit
  ${EndIf}

  nsDialogs::Show

FunctionEnd

/** PageDisableQuit()
 *
 * Prevents the user from closing (quitting) the installer from the current
 * page.  The function could be generic, but at this point only works if we
 * are doing an upgrade install.
 */
Function PageDisableQuit

  ; Really this should only be called when DoUpgrade is true, but we'll use
  ; a little defensive programming.
  ${If} $DoUpgrade == 'true'
    ; Disable the close button on title bar.
    push $1
    System::Call "user32::GetSystemMenu(i $HWNDPARENT,i 0) i.s"
    pop $1
    System::Call "user32::EnableMenuItem(i $1,i 0xF060,i 1)"
    pop $1

    ; Disable Cancel button
    GetDlgItem $0 $HWNDPARENT 2
    EnableWindow $0 0

    ; Set focus to the Next button
    GetDlgItem $0 $HWNDPARENT 1
    SendMessage $HWNDPARENT ${WM_NEXTDLGCTL} $0 1
  ${EndIf}

FunctionEnd

/** .onMouseOverSection()  Call back function
 *
 * Invoked when the user puts the mouse over one of the componets that can be
 * installed.  This is what provides the description of each component.
 */
Function .onMouseOverSection

  !insertmacro MUI_DESCRIPTION_BEGIN
    !insertmacro MUI_DESCRIPTION_TEXT ${SecMain} "Installs the core components of ${LONGNAME} to the application folder."
    !insertmacro MUI_DESCRIPTION_TEXT ${SecDev} "Installs the files required to embed ${LONGNAME} into you C/C++ application."
    !insertmacro MUI_DESCRIPTION_TEXT ${SecDemo} "Install sample ${LONGNAME} programs."
    !insertmacro MUI_DESCRIPTION_TEXT ${SecDoc} "Install ${LONGNAME} documentation."
 !insertmacro MUI_DESCRIPTION_END

FunctionEnd

/** DoSendToItems()
 *
 * Create 'Send To' items depending on what the user specified.  This is only
 * called when we are not doing an upgrade type of install.
 *
 * Note that we do not add the shortcut files to the uninstall log.  Deleting
 * the files is done separately from the uninstall log usage because there is
 * no (easy) way to tell which file is being deleted when using the uninstall
 * log.
 */
Function DoSendToItems

  ; Save the user specified settings into the registry variables so the are
  ; written to the registry correctly.
  StrCpy $RegVal_sendTo_rexx $SendTo_rexx_CK_state
  StrCpy $RegVal_sendTo_rexxHide $SendTo_rexxHide_CK_state
  StrCpy $RegVal_sendTo_rexxPaws $SendTo_rexxPaws_CK_state

  SetOutPath $INSTDIR
  ${If} $SendTo_rexx_CK_state == ${BST_CHECKED}
    CreateShortCut "$SENDTO\ooRexx.lnk" "$INSTDIR\rexx.exe" "" "" "" SW_SHOWNORMAL "" "ooRexx"
    DetailPrint "Created Send To rexx.exe item"
  ${EndIf}

  ${If} $SendTo_rexxHide_CK_state == ${BST_CHECKED}
    CreateShortCut "$SENDTO\ooRexx with no console (rexxhide).lnk" "$INSTDIR\rexxhide.exe" "" "" "" SW_SHOWNORMAL "" "ooRexx with no console (rexxhide)"
    DetailPrint "Created Send To rexxhide.exe item"
  ${EndIf}

  ${If} $SendTo_rexxPaws_CK_state == ${BST_CHECKED}
    CreateShortCut "$SENDTO\ooRexx with pause (rexxpaws).lnk" "$INSTDIR\rexxpaws.exe" "" "" "" SW_SHOWNORMAL "" "ooRexx with pause (rexxpaws)"
    DetailPrint "Created Send To rexxpaws.exe item"
  ${EndIf}

FunctionEnd

/** DoFileAssociations()
 *
 * Does the file associations for ooRexx.  Only called when not doing an
 * upgrade.
 *
 * We do two things:
 *   Fill in the values stored in the uninstall section for ooRexx.  These
 *   values tell the uninstaller, when it runs, what it should delete from the
 *   registry.
 *
 *   Write out the actual file associations selected by the user to the
 *   registry.
 */
Function DoFileAssociations

  ; Set everything to blank, then fill in those values the user specified.
  StrCpy $RegVal_rexxAssociation ""
  StrCpy $RegVal_rexxEditor ""
  StrCpy $RegVal_rexxHideAssociation ""
  StrCpy $RegVal_rexxPawsAssociation ""

  ${If} $Use_File_Associations_CK_state == ${BST_UNCHECKED}
    DetailPrint "Do not use Windows file associations specified."
    Return
  ${EndIf}

  ${If} $Associate_rexx_CK_state == ${BST_CHECKED}
    StrCpy $AssociationProgramName 'rexx.exe'
    StrCpy $RegVal_rexxAssociation '$Rexx_ext_text $Rexx_ftype_text'
    StrCpy $RegVal_rexxEditor '$Rexx_editor_text'

    Call AssociateExtensionWithExe
  ${EndIf}

  ${If} $Associate_rexxhide_CK_state == ${BST_CHECKED}
    StrCpy $AssociationProgramName 'rexxhide.exe'
    StrCpy $RegVal_rexxHideAssociation '$RexxHide_ext_text $RexxHide_ftype_text'
    StrCpy $RegVal_rexxEditor '$Rexx_editor_text'

    Call AssociateExtensionWithExe
  ${EndIf}

  ${If} $Associate_rexxpaws_CK_state == ${BST_CHECKED}
    StrCpy $AssociationProgramName 'rexxpaws.exe'
    StrCpy $RegVal_rexxPawsAssociation '$RexxPaws_ext_text $RexxPaws_ftype_text'
    StrCpy $RegVal_rexxEditor '$Rexx_editor_text'

    Call AssociateExtensionWithExe
  ${EndIf}

  System::Call 'Shell32::SHChangeNotify(i ${SHCNE_ASSOCCHANGED}, i ${SHCNF_IDLIST}, i 0, i 0)'
FunctionEnd

/** DoEnvVariables()
 *
 * Sets up the variable environemnt variables.
 */
Function DoEnvVariables

    Push "REXX_HOME"
    Push $INSTDIR
    Push $IsAdminUser ; "true" or "false"
    Call WriteEnvStr

    ; Add the install directory to the PATH env variable, either system wide or
    ; user-specific
    Push $INSTDIR
    Push $IsAdminUser ; "true" or "false"
    Push "PATH"
    Call AddToPath

    ; Do the PATHEXT extensions
    Call AddToPathExt
FunctionEnd

/** AssociateExtensionWithExe()
 *
 * Associates a file extension and file type with one of the ooRexx executables,
 * rexx.exe, rexxhide.exe, or rexxpaws.  We are only called when we have
 * something to do.
 *
 * TODO - I added the section to install into the user customizable area some
 *        years ago.  Really what we should be doing, rather than this IsAdmin
 *        stuff is deciding if this is a machine-wide install (All Users) or
 *        a single-user install.  Then use SHCTX or SHELL_CONTEXT to just write
 *        once. SHCTX will use HKCR if it is an all users install and HKCU for
 *        a single user install.
 *
 */
Function AssociateExtensionWithExe

  ; We will put the file extension in $0, the ftype in $1, and the editor file
  ; name in $2
  ${If} $AssociationProgramName == 'rexx.exe'
    ${StrTok} $0 $RegVal_rexxAssociation " " "0" "0"
    ${StrTok} $1 $RegVal_rexxAssociation " " "1" "0"
    StrCpy $AssociationText "ooRexx Rexx Program"
    StrCpy $AssociationEditor '$RegVal_rexxEditor'
  ${elseif} $AssociationProgramName == 'rexxhide.exe'
    ${StrTok} $0 $RegVal_rexxHideAssociation " " "0" "0"
    ${StrTok} $1 $RegVal_rexxHideAssociation " " "1" "0"
    StrCpy $AssociationText "ooRexx Rexx GUI Program"
    StrCpy $AssociationEditor '$RegVal_rexxEditor'
  ${elseif} $AssociationProgramName == 'rexxpaws.exe'
    ${StrTok} $0 $RegVal_rexxPawsAssociation " " "0" "0"
    ${StrTok} $1 $RegVal_rexxPawsAssociation " " "1" "0"
    StrCpy $AssociationText "ooRexx Rexx pausing Program"
    StrCpy $AssociationEditor "$RegVal_rexxEditor"
  ${else}
    DetailPrint "Unrecoverable ERROR. The ftype association executable: $AssociationProgramName is not recognized."
    Goto DoneWithRexxExe
  ${EndIf}

  ${If} $0 == ''
  ${orif} $1 == ''
    DetailPrint "Unrecoverable ERROR.  Empty string in $AssociationProgramName association"
    DetailPrint "  Word one=<$0> word two=<$1>"
    Goto DoneWithRexxExe
  ${EndIf}

  ClearErrors
  ; Write key $0 (.rex for example) with default value of $1 (RexxScript for example.)
  WriteRegStr HKCR $0 "" $1
  IfErrors TryCurrentUser
  DetailPrint "Registered $0 extension as ftype $1 to open with $AssociationProgramName for all users"
  Goto WriteHKCRRegKeys

  TryCurrentUser:
  ; Failed to write to the registy, try the user customizable area.
  ClearErrors
  WriteRegStr HKCU $0 "" $1
  IfErrors 0
    DetailPrint "Could NOT associate $0 extension with $AssociationProgramName for either all users or the current user"
    Goto DonewithRexxExe

  DetailPrint "Registered $0 extension as ftype $1 to open with $AssociationProgramName for the current user."
  WriteRegStr HKCU "SOFTWARE\Classes\$1" "" $AssociationText
  WriteRegStr HKCU "SOFTWARE\Classes\$1\shell" "" "open"
  WriteRegStr HKCU "SOFTWARE\Classes\$1\DefaultIcon" "" "$INSTDIR\$AssociationProgramName,0"
  WriteRegStr HKCU "SOFTWARE\Classes\$1\shell\open" "" "Run"
  WriteRegStr HKCU "SOFTWARE\Classes\$1\shell\open\command" "" '"$INSTDIR\$AssociationProgramName" "%1" %*'

  ${If} $AssociationEditor != ""
    WriteRegStr HKCU "SOFTWARE\Classes\$1\shell\edit" "" "Edit"
    WriteRegStr HKCU "SOFTWARE\Classes\$1\shell\edit\command" "" '"$AssociationEditor" "%1"'
  ${EndIf}

  WriteRegStr HKCU "SOFTWARE\Classes\$1\shellex\DropHandler" "" "{60254CA5-953B-11CF-8C96-00AA00B8708C}"
  Goto DoneWithRexxExe

  WriteHKCRRegKeys:
  WriteRegStr HKCR "$1" "" $AssociationText
  WriteRegStr HKCR "$1\shell" "" "open"
  WriteRegStr HKCR "$1\DefaultIcon" "" "$INSTDIR\$AssociationProgramName,0"
  WriteRegStr HKCR "$1\shell\open" "" "Run"
  WriteRegStr HKCR "$1\shell\open\command" "" '"$INSTDIR\$AssociationProgramName" "%1" %*'

  ${If} $AssociationEditor != ""
    WriteRegStr HKCR "$1\shell\edit" "" "Edit"
    WriteRegStr HKCR "$1\shell\edit\command" "" '"$AssociationEditor" "%1"'
  ${EndIf}

  WriteRegStr HKCR "$1\shellex\DropHandler" "" "{60254CA5-953B-11CF-8C96-00AA00B8708C}"

  DoneWithRexxExe:
FunctionEnd

/** SetDefaultFileAssociation()
 *
 * Use to set the variable values for all the file association controls to the
 * default.
 */
Function SetDefaultFileAssociation
  StrCpy $Use_File_Associations_CK_state '${BST_CHECKED}'

  StrCpy $Associate_rexx_CK_state '${BST_CHECKED}'
  StrCpy $Rexx_ext_text ${DefRexxExt}
  StrCpy $Rexx_ftype_text ${DefRexxFType}
  StrCpy $Rexx_editor_text "$WINDIR\System32\NotePad.exe"

  StrCpy $Associate_rexxhide_CK_state '${BST_UNCHECKED}'
  StrCpy $RexxHide_ext_text ${DefRexxHideExt}
  StrCpy $RexxHide_ftype_text ${DefRexxHideFType}

  StrCpy $Associate_rexxpaws_CK_state '${BST_UNCHECKED}'
  StrCpy $RexxPaws_ext_text ${DefRexxPawsExt}
  StrCpy $RexxPaws_ftype_text ${DefRexxPawsFType}

FunctionEnd

/** SetBlankFileAssociation()
 *
 * Use to set the variable values for all the file association controls to the
 * the empty string.
 */
Function SetBlankFileAssociation
  StrCpy $Use_File_Associations_CK_state '${BST_UNCHECKED}'

  StrCpy $Associate_rexx_CK_state '${BST_UNCHECKED}'
  StrCpy $Rexx_ext_text ""
  StrCpy $Rexx_ftype_text ""
  StrCpy $Rexx_editor_text ""

  StrCpy $Associate_rexxhide_CK_state '${BST_UNCHECKED}'
  StrCpy $RexxHide_ext_text ""
  StrCpy $RexxHide_ftype_text ""

  StrCpy $Associate_rexxpaws_CK_state '${BST_UNCHECKED}'
  StrCpy $RexxPaws_ext_text ""
  StrCpy $RexxPaws_ftype_text ""
FunctionEnd

/** SetFileAssociationVars()
 *
 * Used to set the variable values for the file association dialog controls to
 * the proper value on start up of the installer.
 *
 * Note: we can not know at this time, if the user will elect to do an upgrade
 * type of install.  So the RegVal_* variables can not be changed.
 *
 * If there is no previous install and the reg values are blank, all the
 * variables are set to the defaults.  Likewise, if there is a previous version
 * installed, but the uninstaller version is not able to do an upgrade type of
 * install, we also set the variables to their defaults.
 *
 * Otherwise, the variables are set initially to what is in the registry.
 */
Function SetFileAssociationVars

    ${If} $PreviousVersionInstalled == 'false'
    ${andif} $RegVal_rexxAssociation == ''
      Call SetDefaultFileAssociation
    ${elseif} $UpgradeTypeAvailable == 'false'
      Call SetDefaultFileAssociation
    ${else}
      ${If} $RegVal_rexxAssociation == ''
      ${andif} $RegVal_rexxHideAssociation == ''
      ${andif} $RegVal_rexxPawsAssociation == ''
        Call SetBlankFileAssociation
      ${else}
        ; We will put the file extension in $0 and the ftype in $1

        StrCpy $Use_File_Associations_CK_state '${BST_CHECKED}'
        StrCpy $Rexx_editor_text "$RegVal_rexxEditor"

        ${If} $RegVal_rexxAssociation != ''
          ${StrTok} $0 $RegVal_rexxAssociation " " "0" "0"
          ${StrTok} $1 $RegVal_rexxAssociation " " "1" "0"

          StrCpy $Associate_rexx_CK_state '${BST_CHECKED}'
          StrCpy $Rexx_ext_text $0
          StrCpy $Rexx_ftype_text $1
        ${else}
          StrCpy $Associate_rexx_CK_state '${BST_UNCHECKED}'
        ${EndIf}

        ${If} $RegVal_rexxHideAssociation != ''
          ${StrTok} $0 $RegVal_rexxHideAssociation " " "0" "0"
          ${StrTok} $1 $RegVal_rexxHideAssociation " " "1" "0"

          StrCpy $Associate_rexxhide_CK_state '${BST_CHECKED}'
          StrCpy $RexxHide_ext_text $0
          StrCpy $RexxHide_ftype_text $1
        ${else}
          StrCpy $Associate_rexxhide_CK_state '${BST_UNCHECKED}'
        ${EndIf}

        ${If} $RegVal_rexxPawsAssociation != ''
          ${StrTok} $0 $RegVal_rexxPawsAssociation " " "0" "0"
          ${StrTok} $1 $RegVal_rexxPawsAssociation " " "1" "0"

          StrCpy $Associate_rexxpaws_CK_state '${BST_CHECKED}'
          StrCpy $RexxPaws_ext_text $0
          StrCpy $RexxPaws_ftype_text $1
        ${else}
          StrCpy $Associate_rexxpaws_CK_state '${BST_UNCHECKED}'
        ${EndIf}
      ${EndIf}
    ${EndIf}

FunctionEnd

/** SetSendToVars()
 *
 * Sets the values of the SendTo check box states on start up.  Either to the
 * defaults if there is no previous installation or a pre-4.1.0 installation.
 * Otherwise, the variables are set to what we read out of the registry.
 */
Function SetSendToVars

    ${If} $PreviousVersionInstalled == 'false'
    ${orif} $UpgradeTypeAvailable == 'false'
    ${orif} $RegVal_sendTo_rexx == ''
      StrCpy $SendTo_rexx_CK_state ${BST_UNCHECKED}
      StrCpy $SendTo_rexxHide_CK_state ${BST_CHECKED}
      StrCpy $SendTo_rexxPaws_CK_state ${BST_CHECKED}
    ${else}
      StrCpy $SendTo_rexx_CK_state $RegVal_sendTo_rexx
      StrCpy $SendTo_rexxHide_CK_state $RegVal_sendTo_rexxHide
      StrCpy $SendTo_rexxPaws_CK_state $RegVal_sendTo_rexxPaws
    ${EndIf}

FunctionEnd

/** test */

/** CreateDesktopShortCut()
 *
 * This callback function is executed if, on the finish page, the user checks
 * the Create Desktop Icon check box.  The short cut we create is a link to the
 * Open Object Rexx Start Menu folder.
 */
Function CreateDesktopShortcut

    CreateShortcut "$DESKTOP\Open Object Rexx Resources.lnk" "$SMPROGRAMS\${LONGNAME}\" "" "$INSTDIR\rexx.exe"

    Call OpenUninstallLog
    ${AddItem} "$DESKTOP\Open Object Rexx Resources.lnk"
    WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SHORTNAME}" "CreateDesktopIcon" 1
    Call CloseUninstallLog

FunctionEnd

/** CheckInstalledStatus()
 *
 * Helper function used to determine if there is a previous version of ooRexx
 * installed, and if so what level is the uninstaller at.
 */
Function CheckInstalledStatus

  StrCpy $PreviousVersionInstalled 'false'
  StrCpy $UpgradeTypeAvailable 'false'

  ${If} $RegVal_uninstallString != ""
    StrCpy $PreviousVersionInstalled 'true'

    ${If} $RegVal_uninstallLocation == ""
      ; No location in the registry, we'll use the installation directory.
      StrCpy $RegVal_uninstallLocation $INSTDIR
    ${EndIf}

    ${If} $RegVal_uninstallVersion != ""
      ${VersionCompare} $RegVal_uninstallVersion "4.1.0.0" $0

      ; Returned in $0: 0 == versions are equal, 1 == version is greater than 4.1.0.0, 2 == version is less than 4.1.0.0
      ${If} $0 < 2
        StrCpy $UpgradeTypeAvailable 'true'
      ${EndIf}
    ${EndIf}
  ${EndIf}

FunctionEnd


/** CheckLockedFiles()
 *
 * Helper function used to determine if files are locked.  This function is
 * called on init and right before we show the Components page.  The first time
 * rxapi may or may not be running.  The second time is after rxapi should have
 * been stopped.  If any of these files are locked, we know the install will be
 * inconsistent.  If the files are locked we give the user a chance to close
 * them and retry.
 */
Function CheckLockedFiles

  StrCpy $UserRequestAbort 'false'

check_lock_loop:

  StrCpy $KeyFileName '$RegVal_uninstallLocation\${KEYFILE1}'
  LockedList::IsFileLocked $KeyFileName
  Pop $R0
  ${If} $R0 == true
    goto rexxIsRunning
  ${EndIf}

  StrCpy $KeyFileName '$RegVal_uninstallLocation\${KEYFILE2}'
  LockedList::IsFileLocked $KeyFileName
  Pop $R0
  ${If} $R0 == true
    goto rexxIsRunning
  ${EndIf}

  ; Key file 3 is rxapi.exe.  We only check it when we think it should be
  ; stopped and we are about to do an install.
  ${If} $CheckRxApiLock == 'true'
    StrCpy $KeyFileName '$INSTDIR\${KEYFILE3}'
    LockedList::IsFileLocked $KeyFileName
    Pop $R0
    ${If} $R0 == true
      goto rexxIsRunning
    ${EndIf}
  ${EndIf}

  StrCpy $KeyFileName '$RegVal_uninstallLocation\rexxhide.exe'
  LockedList::IsFileLocked $KeyFileName
  Pop $R0
  ${If} $R0 == true
    goto rexxIsRunning
  ${EndIf}

  StrCpy $KeyFileName '$RegVal_uninstallLocation\rexxpaws.exe'
  LockedList::IsFileLocked $KeyFileName
  Pop $R0
  ${If} $R0 == true
    goto rexxIsRunning
  ${EndIf}

  StrCpy $KeyFileName '$RegVal_uninstallLocation\ooDialog.exe'
  LockedList::IsFileLocked $KeyFileName
  Pop $R0
  ${If} $R0 == true
    goto rexxIsRunning
  ${EndIf}

  StrCpy $KeyFileName '$RegVal_uninstallLocation\ooDialog.dll'
  LockedList::IsFileLocked $KeyFileName
  Pop $R0
  ${If} $R0 == true
    goto rexxIsRunning
  ${EndIf}

  goto done_out

  rexxIsRunning:
      MessageBox MB_RETRYCANCEL|MB_ICONEXCLAMATION|MB_TOPMOST \
        "WARNING.  The file:$\n$\n\
          $keyFileName$\n$\n\
        is locked and can not be updated by the installer.  This indicates \
        that not all Rexx programs have been halted.$\n$\n\
        Continuing with the install in this case is known to cause problems.$\n$\n\
        To Retry:$\n$\n\
        Ensure all Rexx programs and processes are halted and then push Retry.$\n$\n\
        To Quit the install and fix the problem:$\n$\n\
        Push Cancel.  Determine which Rexx programs are open and close \
        them.  Ensure no other Rexx programs or processes are open.  Then \
        retry the install." \
        /SD IDCANCEL IDRETRY check_lock_loop

        StrCpy $UserRequestAbort 'true'

done_out:

FunctionEnd


/** CheckBitnessMatch()
 *
 * Checks that the bitness of the ooRexx to be installed matches the bitness of
 * the ooRexx to be uninstalled.
 */
Function CheckBitnessMatch

  StrCpy $UserRequestAbort 'false'

  ${If} $RegVal_uninstallBitness != ""
    ${If} $RegVal_uninstallBitness != ${CPU}
      MessageBox MB_YESNO \
        "WARNING.  You are installing the ${CPU} version of ooRexx.  \
        The installed version of ooRexx is the $RegVal_uninstallBitness version.  \
        Running the uninstaller from within the installer in this case \
        is known to cause problems, and is not supported.$\n$\n\
        The previous version of ooRexx should be uninstalled separately.  To \
        do this, halt this installation.  Run the uninstall program using \
        the Control Panel, or the Start Menu item under the ${LONGNAME} \
        program group.  Then restart this installation program.$\n$\n\
        Do you wish to continue the installation knowing there may be \
        problems with the install?" \
        /SD IDNO IDYES done_return
        StrCpy $UserRequestAbort 'true'
        done_return:
    ${EndIf}
  ${EndIf}

FunctionEnd

/** CheckStrLen()
 *
 * Checks that this installer is built using the long string version of NSIS.
 */
Function CheckStrLen

  StrCpy $UserRequestAbort 'false'

  ; Max string length is 8192 in the long string build

  ${If} ${NSIS_MAX_STRLEN} < 8192
    MessageBox MB_YESNO \
      "WARNING.  The current installer was built using the short \
      string version of NSIS.  There are 2 problems with this:$\n$\n\
      1.)  This indicates this is not an official ooRexx installer.$\n\
      2.)  There is the possiblity that using this installer will \
      delete the PATH on this system.$\n$\n\
      It is not advised that this installer be used to install \
      ooRexx.  If you continue it is at your own risk.$\n$\n\
      Do you wish to continue despite the risk?" \
      /SD IDNO IDYES done_return
      StrCpy $UserRequestAbort 'true'
      done_return:
  ${EndIf}

FunctionEnd


/** CheckForSpaces()
 *
 * This function checks for spaces in a string.  It is taken from the NSIS
 * examples provided on the NSIS site.
 *
 * It should be used this way:
 *
 * push <str>
 * call CheckForSpaces
 * pop $R0
 *
 * $R0 will contain the number of spaces.  When using the LogicLib, a check like
 * this can be done
 *
 * ${If} $R0 > 0
 *   <do something>
 * ${EndIf}
 *
 */
Function CheckForSpaces
   Exch $R0
   Push $R1
   Push $R2
   Push $R3

   StrCpy $R1 -1
   StrCpy $R3 $R0
   StrCpy $R0 0
   loop:
     StrCpy $R2 $R3 1 $R1
     IntOp $R1 $R1 - 1
     StrCmp $R2 "" done
     StrCmp $R2 " " 0 loop
     IntOp $R0 $R0 + 1
   Goto loop
   done:

   Pop $R3
   Pop $R2
   Pop $R1
   Exch $R0
FunctionEnd

/** AddToPathExt()
 *
 * Adds the file extension(s) associated with the ooRexx executables to PATHEXT.
 *
 * We upper case the extension so that it matches what is commonly seen on
 * Windows.
 *
 * @notes - This could be done for a single-user install, but remember that
 *          the user specific PATHEXT *replaces* the system wide PATHEXT, so
 *          we would need to read the system wide value and add the extension
 *          to it and then write it to the user specific PATHEXT.
 */
Function AddToPathExt

  ${If} $IsAdminUser == "false"  ; TODO fix this
    Return
  ${EndIf}

  ${StrTok} $0 $RegVal_rexxAssociation " " "0" "0"
  ${StrCase} $1 $0 "U"
  DetailPrint "Adding the $1 extension to PATHEXT"
  Push $1
  Push $IsAdminUser      ; should only be "true" at this point
  Push "PATHEXT"
  Call AddToPath

  ${StrTok} $0 $RegVal_rexxHideAssociation " " "0" "0"
  ${StrCase} $1 $0 "U"
  DetailPrint "Adding the $1 extension to PATHEXT"
  Push $1
  Push $IsAdminUser      ; should only be "true" at this point
  Push "PATHEXT"
  Call AddToPath

  ${StrTok} $0 $RegVal_rexxPawsAssociation " " "0" "0"
  ${StrCase} $1 $0 "U"
  DetailPrint "Adding the $1 extension to PATHEXT"
  Push $1
  Push $IsAdminUser      ; should only be "true" at this point
  Push "PATHEXT"
  Call AddToPath

FunctionEnd

/** CheckIsRxapirunning()
 *
 * Determines if a rxapi.exe process is running.  On return the variable
 * RxapiIsRunning is set to 'true', 'false' or 'unknown N' where N is an error
 * return code.
 *
 */
Function CheckIsRxapiRunning
  ooRexxProcess::findProcess "rxapi.exe"
  Pop $R0
  DetailPrint "ooRexxProcess::findProcess rc: $R0"
  ${If} $R0 == '0'
    StrCpy $RxapiIsRunning 'true'
  ${elseif} $R0 == '1'
    StrCpy $RxapiIsRunning 'false'
  ${else}
    StrCpy $RxapiIsRunning 'unknown $R0'
  ${EndIf}
FunctionEnd

/** StopRxapi()
 *
 * Stop the rxapi.exe process.
 *
 * For 5.0 rxapi is no longer installed as a service, so we use killProcess
 * to stop rxapi.
 *
 * On return top of stack will contain 'Ok' for success or 'Error'.  If there
 * was an error top of stack minus 1 will contain the error code from
 * ooRexxProcess::killProcess.
 *
 * @remarks  There was a problem I was having with CheckisRxapiRunning saying
 *           rxapi was running when it actually was not.
 *
 *           Although rxapi is no longer installed as a service, we add a
 *           .3 sleep for good measure.
 */
Function StopRxapi

  ooRexxProcess::killProcess 'rxapi'
  Pop $R0
  Sleep 300

  Call CheckIsRxapiRunning
  ${If} $RxapiIsRunning == 'false'
    Push 'Ok'
    return
  ${EndIf}

  ; Still running, try one more time, although this is probably a waste of time.
  ; But, we will capture the error code for debugging.  Note that if the return
  ; from killProcess is 1, then the process was not found, so it is not running.
  ooRexxProcess::killProcess 'rxapi'
  Pop $R0
  ${If} $R0 == 0
  ${orif} $R0 == 1
    Push 'Ok'
  ${else}
    Push $R0
    Push 'Error'
  ${EndIf}
FunctionEnd

;===============================================================================
;  Uninstaller portion of oorexx.nsi.
;===============================================================================

;
; Note this:  If the install was done by a non-admin user, the .rex file association may have been written
;             to the HKEY_CURRENT_USER\SOFTWARE\Classes area.  You would think that we need to check for
;             that and specifically delete those keys.  However, testing shows that the current code always
;             removes those keys.  Tested on a number of machines with a number of different users.

;===============================================================================
;  Uninstaller Sections
;===============================================================================

;-------------------------------------------------------------------------------
; Uninstall section
Section "Uninstall"

  /*
   temporarily comment out orxscrpt stuff while it is disabled in the build.

   ; orxscrpt.dll needs to be degistered  NOTE WSH DLL name may have changed.
   !insertmacro Un
   InstallLib REGDLL NOTSHARED REBOOT_PROTECTED "$INSTDIR\orxscrpt.dll"
   ;
   ; In the old WSH code, entering the orxscrpt.dll started up the interpreter.
   ; This may no longer be the case.  If it is, rxapi will need to be stopped
   ; again.
   ooRExxProcess::killProc "rxapi.exe"
  */

  /* If we are doing an upgrade type of install, we leave everything as it was. */
  ${If} $DoUpgrade == 'false'

    ; One last check, see if rxapi.exe is locked.  We do this here and below
    ; because we want to quit, if we are going to, before anything is undone.
    StrCpy $CheckRxApiLock 'false'
    Call un.CheckLockedFiles
    ${If} $UserRequestAbort == 'true'
      setErrorLevel 5
      Quit
    ${EndIf}

    ; Get rid of the file associations.  Also removes the extension from
    ; PATHEXT.
    Call un.DeleteFileAssociations

    ; remove directory from PATH
    Push $INSTDIR
    Push $IsAdminUser ; pushes "true" or "false"
    Push "PATH"
    Call un.RemoveFromPath

    ; remove the REXX_HOME environment variable
    Push "REXX_HOME"
    Push $IsAdminUser ; "true" or "false"
    Call un.DeleteEnvStr
  ${EndIf}

  ; One last check, see if rxapi.exe is locked.
  ${If} $DoUpgrade == 'true'
    StrCpy $CheckRxApiLock 'false'
    Call un.CheckLockedFiles
    ${If} $UserRequestAbort == 'true'
      setErrorLevel 5
      Quit
    ${EndIf}
  ${EndIf}

  StrCpy $KeyFileName '$INSTDIR\${KEYFILE3}'

  LockedList::IsFileLocked $KeyFileName
  Pop $R0
  ${If} $R0 == true
      MessageBox MB_OK|MB_ICONSTOP \
      "Unexpected error the file:$\n$\n\
        $KeyFileName$\n$\n\
      is locked. The uninstall will abort.  Report \
      this error to the ${SHORTNAME} developers." \
      /SD IDOK
      SetErrorLevel 3
      Quit
  ${EndIf}

  ; Upgrade or not, we always remove the installation stuff.
  DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SHORTNAME}"
  ;DeleteRegKey HKLM "SOFTWARE\${LONGNAME}"  We don't write anything here, maybe we should?

  Call un.Delete_Installed_Files

SectionEnd

;===============================================================================
;  Uninstaller Functions
;===============================================================================

/** un.onInit()  Callback function.
 *
 *  Called by the uninstaller program before any pages are shown.  We use it to
 *  set up the execution variables.
 *
 */
Function un.onInit

  StrCpy $DoUpgrade 'false'
  StrCpy $DoUpgradeQuick 'false'

  ${GetOptions} "$CMDLINE" "/U="  $R0
  ${If} $R0 == 'upgrade'
    StrCpy $DoUpgrade 'true'
  ${elseif} $R0 == 'upgradeQuick'
    StrCpy $DoUpgrade 'true'
    StrCpy $DoUpgradeQuick 'true'
  ${EndIf}

  StrCpy $DeleteWholeTree 'false'

  ;StrCpy $DeleteWholeTree 'true'  ; TEMP TEMP TEMP always del tree while testing MM */

  ; UnInstall as All Users if an admin
  Call un.IsUserAdmin
  Pop $IsAdminUser
  ${If} $IsAdminUser == "true"
    SetShellVarContext all
  ${EndIf}

  StrCpy $CheckRxApiLock 'false'
  Call un.CheckLockedFiles
  ${If} $UserRequestAbort == 'true'
    setErrorLevel 5
    abort
  ${EndIf}

  ; Read in the file associations done by the installer.
  ReadRegStr $RegVal_rexxAssociation HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SHORTNAME}" "RexxAssociation"
  ReadRegStr $RegVal_rexxHideAssociation HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SHORTNAME}" "RexxHideAssociation"
  ReadRegStr $RegVal_rexxPawsAssociation HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SHORTNAME}" "RexxPawsAssociation"

  StrCpy $StopRxAPI_CK_State 1
  StrCpy $InStopRxapiPage 'false'
  Call un.CheckIsRxapiRunning

FunctionEnd


/** un.Ok_Stop_RxAPI_page()  Custom page function.
 *
 * This is a custom page that follows the Welcome page.  If rxapi.exe is not
 * running the page is skipped.  If rxapi.exe is running, the user is asked for
 * the okay to stop it.  If the user says no, we quit the uninstall.
 */
Function un.Ok_Stop_RxAPI_page
  ${If} $RxapiIsRunning == 'false'
    Abort
  ${EndIf}

  StrCpy $InStopRxapiPage 'true'

  !insertmacro MUI_HEADER_TEXT "The ooRexx rxapi process." "The ${LONGNAME} rxapi process is currently running"
  nsDialogs::Create /NOUNLOAD 1018
  Pop $Dialog

  ${If} $Dialog == error
    Abort
  ${EndIf}

  ${NSD_CreateLabel} 0 0 100% 104u \
    "${SHORTNAME} can not be completely uninstalled while rxapi is running.$\n$\n\
    When the Stop rxapi check box is checked, the uninstall will stop rxapi before \
    proceeding.  If the check box is not checked, rxapi will not be stopped.$\n$\n\
    If rxapi is not stopped the uninstall will be canceled.$\n$\n\
    If, and only if, there are Rexx programs running, stopping rxapi could \
    possibly cause data loss.$\n$\n\
    If you are worried about this, cancel the uninstall at this point by using the cancel \
    button or unchecking the Stop rxapi check box.  Then stop all running Rexx programs, \
    and rerun the uninstall program, (or the installation program.)"

  Pop $Label_One

  ${NSD_CreateCheckBox} 0 108u 100% 15u "Stop rxapi"
  Pop $StopRxAPI_CK
  ${NSD_SetState} $StopRxAPI_CK $StopRxAPI_CK_State

  GetFunctionAddress $0 un.CheckOkToStopRxapiBack
  nsDialogs::OnBack $0

  nsDialogs::Show

FunctionEnd

/** un.Ok_Stop_RxAPI_leave()  Custom Page Call back function.
 *
 * Invoked by the uninstaller when the user clicks Next on the Ok to stop rxapi
 * page.  We check if the user agreed to stopping rxapi.  If not we quit the
 * uninstaller.  Otherwise we stop rxapi.  If we can not stop rxapi, we also
 * quit the uninstaller.
 */
Function un.Ok_Stop_RxAPI_leave

  ${NSD_GetState} $StopRxAPI_CK $StopRxAPI_CK_State

  ${If} $StopRxAPI_CK_State == 0
    SetErrorLevel 4
    Quit
  ${EndIf}

  StrCpy $InStopRxapiPage 'false'

  Call un.StopRxapi
  Pop $R0
  ${If} $R0 == 'Ok'
    Return
  ${EndIf}

  ; rxapi was not stopped, the error code is now at top of stack
  Pop $R0

  MessageBox MB_OK|MB_ICONEXCLAMATION|MB_TOPMOST \
             "Can not determine conclusively that rxapi is stopped.  You may not have \
             sufficient privileges to uninstall ${SHORTNAME}.$\n$\n\
             The uninstall will quit.$\n$\n\
             If you believe you do have sufficient privileges to do the uninstall, \
             you can:$\n$\n\
             1.) Manually stop the rxapi process and restart the uninstall.  If rxapi \
             is installed as a service, stop the service.  Otherwise, use the task \
             manager to end the rxapi process.$\n$\n\
             2.) Ask the ${SHORTNAME} developers for help.  Please report this error code \
             to the ${SHORTNAME} developers: killProcess $R0$\n$\n"\
             /SD IDOK
  SetErrorLevel 2
  Quit

FunctionEnd

Function un.CheckOkToStopRxapiBack
  ${NSD_GetState} $StopRxAPI_CK $StopRxAPI_CK_State
  StrCpy $InStopRxapiPage 'false'
FunctionEnd


/** un.CheckLockedFiles()
 *
 * Helper function used to determine if files are locked.  This function is
 * called on init of the uninstaller.  rxapi may or may not be running, so we
 * don't check it.  If any of these files are locked, we know the install will
 * be inconsistent.  If the files are locked we give the user a chance to close
 * them and retry.
 */
Function un.CheckLockedFiles

  StrCpy $UserRequestAbort 'false'

check_lock_loop:

  StrCpy $KeyFileName '$INSTDIR\${KEYFILE1}'
  LockedList::IsFileLocked $KeyFileName
  Pop $R0
  ${If} $R0 == true
    goto rexxIsRunning
  ${EndIf}

  StrCpy $KeyFileName '$INSTDIR\${KEYFILE2}'
  LockedList::IsFileLocked $KeyFileName
  Pop $R0
  ${If} $R0 == true
    goto rexxIsRunning
  ${EndIf}

  ; Key file 3 is rxapi.exe.  We only check it when we think it should be
  ; stopped.
  ${If} $CheckRxApiLock == 'true'
    StrCpy $KeyFileName '$INSTDIR\${KEYFILE3}'
    LockedList::IsFileLocked $KeyFileName
    Pop $R0
    ${If} $R0 == true
      goto rexxIsRunning
    ${EndIf}
  ${EndIf}

  StrCpy $KeyFileName '$INSTDIR\rexxhide.exe'
  LockedList::IsFileLocked $KeyFileName
  Pop $R0
  ${If} $R0 == true
    goto rexxIsRunning
  ${EndIf}

  StrCpy $KeyFileName '$INSTDIR\rexxpaws.exe'
  LockedList::IsFileLocked $KeyFileName
  Pop $R0
  ${If} $R0 == true
    goto rexxIsRunning
  ${EndIf}

  StrCpy $KeyFileName '$INSTDIR\ooDialog.exe'
  LockedList::IsFileLocked $KeyFileName
  Pop $R0
  ${If} $R0 == true
    goto rexxIsRunning
  ${EndIf}

  StrCpy $KeyFileName '$INSTDIR\ooDialog.dll'
  LockedList::IsFileLocked $KeyFileName
  Pop $R0
  ${If} $R0 == true
    goto rexxIsRunning
  ${EndIf}

  goto done_out

  rexxIsRunning:
      MessageBox MB_RETRYCANCEL|MB_ICONEXCLAMATION|MB_TOPMOST \
        "WARNING.  The file:$\n$\n\
          $keyFileName$\n$\n\
        is locked and can not be removed by the uninstaller.  This indicates \
        that not all ${SHORTNAME} programs have been halted.$\n$\n\
        Continuing with the uninstall in this case is known to cause problems.$\n$\n\
        To Retry:$\n$\n\
        Ensure all ${SHORTNAME} programs and processes are halted and then push \
        Retry.$\n$\n\
        To Quit the uninstall and fix the problem:$\n$\n\
        Push Cancel.  Determine which ${SHORTNAME} programs are open and close \
        them.  Ensure no other ${SHORTNAME} programs or processes are open.  Then \
        retry the uninstall." \
        /SD IDCANCEL IDRETRY check_lock_loop

        StrCpy $UserRequestAbort 'true'

done_out:

FunctionEnd


/** un.Uninstall_By_Log_page()  Custom page function.
 *
 * This is a custom page that follows the page that checks if it is okay to
 * stop rxapi.  Here we check for the uninstall log.  We then give the user the
 * option of simply deleting the ooRexx directory tree (50 times faster on my
 * system) or using the log file to individually delete only the install files.
 *
 * If the uninstall log is missing, the user does not have the option of
 * deleting individual files and directories.
 */
Function un.Uninstall_By_Log_page

  StrCpy $LogFileExists 'false'
  IfFileExists "$INSTDIR\${UninstLog}" 0 +4
    StrCpy $LogFileExists 'true'

  ${If} $LogFileExists == 'false'
    !insertmacro MUI_HEADER_TEXT \
      "${UninstLog} NOT found." \
      "The option of only removing files installed by the prior ooRexx installer is not available."

    StrCpy $0 \
      "Because the ${UninstLog} file is missing, the uninstall process must remove all \
      files in the $INSTDIR directory tree.$\n$\n\
      WARNING: This will remove all folders and files in the $INSTDIR folder, including \
      any folders or files not placed there by the ooRexx installation.$\n$\n\
      If there are any personl folders or files in the $INSTDIR directory tree that need \
      to be saved, please cancel the uninstall, move the files, and restart the uninstall \
      program."
  ${else}
    !insertmacro MUI_HEADER_TEXT \
      "Choose the method for removing installed files." \
      "Delete only installed files or delete entire directory tree?"

    StrCpy $0 \
      "The uninstall program can use an install log to delete only the folders and files \
      placed in the $INSTDIR directory tree by the original installation program.$\n$\n\
      Optionally, the entire $INSTDIR directory tree can be deleted.$\n$\n\
      WARNING: Deleting the entire directory tree will remove all folders and files in the \
      $INSTDIR folder.  This will include any folders or files not placed there by the ooRexx \
      installation."

  ${EndIf}

  ; If the log file exists and we are doing an upgrade type of uninstall, then
  ; we don't show this page.  On the other hand, if we are doing an upgrade, but
  ; the install log is missing, we do show the page so that the user can cancel
  ; here.

  ${If} $DoUpgrade == 'true'
  ${andif} $LogFileExists == 'true'
    Abort
  ${EndIf}

  nsDialogs::Create /NOUNLOAD 1018
  Pop $Dialog

  ${If} $Dialog == error
    Abort
  ${EndIf}

  ${If} $LogFileExists == 'false'
    ${NSD_CreateLabel} 0 0 100% 80u $0
    Pop $Label_One

    ${NSD_CreateCheckBox} 0 84u 100% 8u "Delete entire directory tree"
    Pop $Delete_ooRexx_Tree_CK
    ${NSD_Check} $Delete_ooRexx_Tree_CK
    EnableWindow $Delete_ooRexx_Tree_CK 0
  ${else}
    ${NSD_CreateLabel} 0 0 100% 80u $0
    Pop $Label_One

    ${NSD_CreateLabel} 0 100u 100% 16u "To DELETE the entire $INSTDIR directory tree, check the check box."
    Pop $Label_Two

    ${NSD_CreateCheckBox} 0 120u 100% 8u "Delete entire directory tree"
    Pop $Delete_ooRexx_Tree_CK
  ${EndIf}

  ; Set focus to the page dialog rather than the installer dialog, set focus to
  ; the check box, and then show the page dialog
  SendMessage $Dialog ${WM_SETFOCUS} $HWNDPARENT 0
  SendMessage $Dialog ${WM_NEXTDLGCTL} $Delete_ooRexx_Tree_CK 1

  nsDialogs::Show

FunctionEnd

/** un.Uninstall_By_Log_leave()  Call back function.
 *
 * Invoked by the uninstaller when the user clicks Next on the uninstall using
 * the log page.
 */
Function un.Uninstall_By_Log_leave

  ${NSD_GetState} $Delete_ooRexx_Tree_CK $0

  ${If} $0 == 1
    StrCpy $DeleteWholeTree 'true'
  ${else}
    StrCpy $DeleteWholeTree 'false'
  ${EndIf}

FunctionEnd

/** un.Confirm_Page_pre()  Call back function.
 *
 * Invoked before the Confirm page, (the page that shows "uninstalling from,")
 * is created.  We use this to not show that page if we are doing a quick
 * upgrade install.
 *
 */
Function un.Confirm_Page_pre
  ${If} $DoUpgrade == 'true'
  ${andif} $DoUpgradeQuick == 'true'
    Abort
  ${EndIf}
FunctionEnd

/** un.onCancelButton()  Call back function
 *
 * Invoked by the uninstaller when the user clicks the cancel button.  We only
 * care if the user was on the ok to stop rxapi page.  If so, we set the error
 * level to 4 to indicate that, if the uninstall was invoked by the installer,
 * we should just quit.
 */
Function un.onCancelButton
  ${If} $InStopRxapiPage == 'true'
    SetErrorLevel 4
  ${EndIf}
FunctionEnd

/** un.Delete_Installed_Files()
 *
 * Deletes the installed files in the manner specified by the user.  Either by
 * using the log file to delete only files installed by the previous
 * installaltion or by simply deleting the whole installation directory.
 */
Function un.Delete_Installed_Files

  ${If} $DeleteWholeTree == 'true'
    DetailPrint "Uninstall files by deleting the $INSTDIR directory tree"
    RMDir /r "$INSTDIR"
    DetailPrint "Removing all Start Menu short cuts by removing the $SMPROGRAMS\${LONGNAME} folder"
    RMDir /r "$SMPROGRAMS\${LONGNAME}"
    Delete "$DESKTOP\Open Object Rexx Resources.lnk"

  ${else}
    DetailPrint "Uninstall files using the install log file"
    Push $R0
    Push $R1
    Push $R2
    SetFileAttributes "$INSTDIR\${UninstLog}" NORMAL
    FileOpen $UninstLog "$INSTDIR\${UninstLog}" r
    StrCpy $R1 0

    GetLineCount:
      ClearErrors
      FileRead $UninstLog $R0
      IntOp $R1 $R1 + 1
      IfErrors 0 GetLineCount

    LoopRead:
      FileSeek $UninstLog 0 SET
      StrCpy $R2 0
      FindLine:
      FileRead $UninstLog $R0
      IntOp $R2 $R2 + 1
      StrCmp $R1 $R2 0 FindLine

      StrCpy $R0 $R0 -2
      IfFileExists "$R0\*.*" 0 +3
        RMDir $R0  #is dir
      Goto +3
      IfFileExists $R0 0 +2
        Delete $R0 #is file

      IntOp $R1 $R1 - 1
      StrCmp $R1 0 LoopDone
      Goto LoopRead
    LoopDone:
    FileClose $UninstLog

    Delete "$INSTDIR\${UninstLog}"
    RMDir "$INSTDIR"
    Pop $R2
    Pop $R1
    Pop $R0
  ${EndIf}

  /*
   * Remove the send to entries unless we are doing an updgrade type. These
   * entries are not put into the uninstall log.  We simply deleted them if we
   * are not doing an upgrade and leave them alone if we are doing an upgrade.
   *
   * If they do not exist, deleting them does not harm, i.e., there is no
   * warning or error rasised.
   */
  ${If} $DoUpgrade == 'false'
    Delete "$SENDTO\ooRexx.lnk"
    Delete "$SENDTO\ooRexx with pause (rexxpaws).lnk"
    Delete "$SENDTO\ooRexx with no console (rexxhide).lnk"
    DetailPrint "Removed 'Send To' items (if any.)"
  ${EndIf}

FunctionEnd


/** un.DeleteFileAssociations()
 *
 * Deletes the file associations set by the installer.
 *
 * @note  Notice that we do the uninstaller differently from the installer.  In
 *        the installer, addToPathExt() determines which extensions to add to
 *        PATHEXT.  Here, un.DeleteFileAssociations decides which extensions to
 *        remove from the PATHEXT.
 *
 * TODO need to test this well. TODO need to determine if this is a per machine
 * install or a per user install!!!!
 */
Function un.DeleteFileAssociations

  ; We will put the file extension in $0 and the ftype in $1

  ${If} $RegVal_rexxAssociation != ''
    ${UnStrTok} $0 $RegVal_rexxAssociation " " "0" "0"
    ${UnStrTok} $1 $RegVal_rexxAssociation " " "1" "0"

    ; Only delete the association if we own it.  In other words, the ftype we
    ; read from the registry should match the ftype we saved in our uninstall
    ; strings.
    ReadRegStr $2 HKCR "$0" ""
    ${If} $1 == $2
      DeleteRegKey HKCR "$0"
      DeleteRegKey HKCR "$1"
      DetailPrint "Deleted file association for $0"

      push $0
      Call un.AddToPathExt
    ${EndIf}
  ${EndIf}

  ${If} $RegVal_rexxHideAssociation != ''
    ${UnStrTok} $0 $RegVal_rexxHideAssociation " " "0" "0"
    ${UnStrTok} $1 $RegVal_rexxHideAssociation " " "1" "0"

    ReadRegStr $2 HKCR "$0" ""
    ${If} $1 == $2
      DeleteRegKey HKCR "$0"
      DeleteRegKey HKCR "$1"
      DetailPrint "Deleted file association for $0"

      push $0
      Call un.AddToPathExt
    ${EndIf}
  ${EndIf}

  ${If} $RegVal_rexxPawsAssociation != ''
    ${UnStrTok} $0 $RegVal_rexxPawsAssociation " " "0" "0"
    ${UnStrTok} $1 $RegVal_rexxPawsAssociation " " "1" "0"

    ReadRegStr $2 HKCR "$0" ""
    ${If} $1 == $2
      DeleteRegKey HKCR "$0"
      DeleteRegKey HKCR "$1"
      DetailPrint "Deleted file association for $0"

      push $0
      Call un.AddToPathExt
    ${EndIf}
  ${EndIf}

  System::Call 'Shell32::SHChangeNotify(i ${SHCNE_ASSOCCHANGED}, i ${SHCNF_IDLIST}, i 0, i 0)'

FunctionEnd

/** un.AddToPathExt()
 *
 * Removes the specified file extension from PATHEXT.  The file extension is
 * pushed on the stack to send it here.
 *
 * @notes - This could be done for a single-user install, but remember that
 *          ... what? - need to think about how to do this for a single user,
 *          could easily hose the system for a user.  I.e., end up with no
 *          programs running from the command line.
 *
 * Usage:
 *   Push <ext>
 *
 * Here:
 *   Pop $R0 -> $R0 now contains the extension to un.add to PATHEXT.  I.e., the
 *              extension to remove.
 */
Function un.AddToPathExt

  Pop $R0

  ${If} $IsAdminUser == "false"
    Return
  ${EndIf}

  DetailPrint "Removing the $R0 extension from PATHEXT."
  Push $R0
  Push $IsAdminUser      ; should only be "true" at this point
  Push "PATHEXT"
  Call un.RemoveFromPath
FunctionEnd

/** un.CheckIsRxapiRunning()
 *
 * Determines if rxapi.exe is running.
 *
 * On return the top of the stack contains 'true', 'false', or 'unknoww <rc>'
 * where the <rc> is the error recturn code from ooRexxProcess::findProcess.
 */
Function un.CheckIsRxapiRunning

  ooRexxProcess::findProcess "rxapi.exe"
  Pop $R0
  DetailPrint "ooRexxProcess::findProcess rc: $R0"
  ${If} $R0 == '0'
    StrCpy $RxapiIsRunning 'true'
  ${elseif} $R0 == '1'
    StrCpy $RxapiIsRunning 'false'
  ${else}
    StrCpy $RxapiIsRunning 'unknown $R0'
  ${EndIf}
FunctionEnd

/** un.StopRxapi()
 *
 * Stop the rxapi.exe process.
 *
 * For 5.0 rxapi is no longer installed as a service, so we use killProcess
 * to stop rxapi.
 *
 * On return top of stack will contain 'Ok' for success or 'Error'.  If there
 * was an error top of stack minus 1 will contain the error code from
 * ooRexxProcess::killProcess.
 *
 * @remarks  There was a problem I was having with CheckisRxapiRunning saying
 *           rxapi was running when it actually was not.
 *
 *           Although rxapi is no longer installed as a service, we add a
 *           .3 sleep for good measure.
 */
Function un.StopRxapi

  ooRexxProcess::killProcess 'rxapi'
  Pop $R0
  Sleep 300

  Call un.CheckIsRxapiRunning
  ${If} $RxapiIsRunning == 'false'
    Push 'Ok'
    return
  ${EndIf}

  ; Still running, try one more time, although this is probably a waste of time.
  ; But, we will capture the error code for debugging.  Note that if the return
  ; from killProcess is 1, then the process was not found, so it is not running.
  ooRexxProcess::killProcess 'rxapi'
  Pop $R0
  ${If} $R0 == 0
  ${orif} $R0 == 1
    Push 'Ok'
  ${else}
    Push $R0
    Push 'Error'
  ${EndIf}
FunctionEnd

;eof
