postupdate_helper.nsh (5731B)
1 # This Source Code Form is subject to the terms of the Mozilla Public 2 # License, v. 2.0. If a copy of the MPL was not distributed with this 3 # file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 5 !include "LogicLib.nsh" 6 7 !define buildNumWin10 10240 ; First Win10 version 8 9 ; Depending on the installation type (as admin or not) we have different 10 ; default installation directories, one of which we push onto the stack as the 11 ; return value. 12 Function getDefaultInstallDir 13 Push $1 ; save $1 to restore it later 14 UserInfo::GetAccountType 15 Pop $1 16 ${If} $1 == "User" 17 ${GetLocalAppDataFolder} $1 18 StrCpy $1 "$1\${BrandFullName}\" 19 Push $1 20 ${Else} 21 !ifdef HAVE_64BIT_BUILD 22 Push "$PROGRAMFILES64\${BrandFullName}\" 23 !else 24 Push "$PROGRAMFILES32\${BrandFullName}\" 25 !endif 26 ${EndIf} 27 Exch 28 Pop $1 ; restore $1 29 FunctionEnd 30 31 ; This function expects the topmost element of the stack to be the path to be 32 ; normalized. It returns one of: 33 ; a) the resolved path with a maximum length of 1000 chars. 34 ; b) the string '[!] GetFullPathNameW: Insufficient buffer memory.' (error case) 35 ; c) the string '[!] GetFullPathNameW: Unknown error.' (should never happen) 36 ; 37 ; In all error cases (b, c) this function uses SetError to enable checks like: 38 ; ${If} ${Errors} 39 ; Pop $ErrorMessage 40 ; ${EndIf} 41 ; This means that after calling this function it always returns a string value 42 ; on the stack. 43 Function getNormalizedPath 44 Exch $0 ; Equivalent to: Push $0, Exch, Pop $0 45 Push $1 46 Push $2 47 48 ; MAX_PATH defines a 260-character limit, but GetFullPathNameW can handle 49 ; paths up to 32767 characters when using the "\\?\" prefix. Since NSIS 50 ; registers are limited to 1024 bytes, we allow path length up to 1000 chars 51 ; and leave 23 headroom for testing purposes. 52 System::Call 'kernel32::GetFullPathNameW(w r0, i 1000, w .r1, i0) i .r2' 53 # Check if return value in $0 is 0 (error) 54 ${If} $2 == 0 55 StrCpy $0 "[!] GetFullPathNameW: Unknown error." 56 SetErrors 57 ${OrIf} $2 >= 1000 58 StrCpy $0 "[!] GetFullPathNameW: Insufficient buffer memory." 59 SetErrors 60 ${Else} 61 StrCpy $0 $1 62 ${EndIf} 63 64 ; Restore the variables from the stack. 65 Pop $2 66 Pop $1 67 68 ; Return the result on the stack and restore $0 69 Exch $0 70 FunctionEnd 71 72 ; This function takes no arguments and returns the name of the legacy uninstall 73 ; key stored on the stack. 74 Function getLegacyUninstallKey 75 Push $0 76 77 ; $0 is used as the return value for this function. It is initially set to 78 ; the Uninstall key, which has been standard for decades. 79 StrCpy $0 "Software\Microsoft\Windows\CurrentVersion\Uninstall\${BrandFullNameInternal} ${AppVersion}" 80 ${WordFind} "${UpdateChannel}" "esr" "E#" $1 81 ${IfNot} ${Errors} 82 StrCpy $0 "$0 ESR" 83 ${EndIf} 84 StrCpy $0 "$0 (${ARCH} ${AB_CD})" 85 86 Exch $0 87 FunctionEnd 88 89 ; This function returns the uninstallation key used for installing applications 90 ; in their default directory on the stack. 91 Function getModernUninstallKey 92 Push "Software\Microsoft\Windows\CurrentVersion\Uninstall\${BrandFullNameInternal}" 93 FunctionEnd 94 95 ; This function checks for a registry key under HKEY_LOCAL_MACHINE with a 96 ; matching installation directory to $INSTDIR or an empty string if no matching 97 ; installation is found. 98 Function findUninstallKey 99 Push $0 100 Push $1 101 Push $2 102 103 ${GetLongPath} "$INSTDIR" $2 104 105 Call getLegacyUninstallKey 106 Pop $0 107 ReadRegStr $1 "HKLM" $0 "InstallLocation" 108 ${If} $1 != $2 109 Call getModernUninstallKey 110 Pop $0 111 ReadRegStr $1 "HKLM" $0 "InstallLocation" 112 ${If} $1 != $2 113 StrCpy $0 "" 114 ${EndIf} 115 ${EndIf} 116 117 Pop $2 118 Pop $1 119 Exch $0 120 FunctionEnd 121 122 ; This function expects the Windows build number as a parameter from the stack. 123 ; It Returns the appropriate uninstall registry key on the stack. 124 Function getUninstallKey 125 Exch $3 ; Equivalent to: Push $3, Exch, Pop $3 126 Push $0 127 Push $1 128 Push $2 129 130 Call getLegacyUninstallKey 131 Pop $0 132 133 ${If} $3 >= ${buildNumWin10} 134 ClearErrors 135 136 ; Determine the path to the user configured target directory. 137 Push "$INSTDIR\" 138 Call getNormalizedPath 139 Pop $2 ; contains the absolute path to the $INSTDIR (user definable) now. 140 141 ; Determine the absolute path of the default installation directory 142 Call getDefaultInstallDir ; pushes the default directory on the stack 143 Call getNormalizedPath 144 Pop $1 ; contains the absolute path to the default directory now. 145 146 ${IfNot} ${Errors} 147 ${AndIf} "$1" == "$2" 148 ; The default path and target path matched. 149 Call getModernUninstallKey 150 Pop $0 151 DetailPrint "Default installation detected." 152 ${EndIf} 153 ${EndIf} 154 155 StrCpy $3 $0 156 Pop $2 157 Pop $1 158 Pop $0 159 ; Return the result on the stack and restore $0 160 Exch $3 161 FunctionEnd 162 163 ; Looks at installation_telemetry.json to determine whether the installation 164 ; was installed by the stub installer or not. 165 ; 166 ; Expects the JSON file on the stack as a parameter; will return the 167 ; installation type from the JSON file, generally either "stub" or "full". 168 ; On failure, pushes "unknown". 169 Function GetInstallationType 170 Exch $1 ; directory 171 Push $0 ; temporary variable 172 173 nsJSON::Set /file /unicode "$1" 174 nsJSON::Get /type `installer_type` /end 175 176 Pop $0 177 ${If} $0 == "" 178 ; It's only ever written as UTF-16, but decode it as ANSI for redundancy. 179 nsJSON::Set /file "$1" 180 nsJSON::Get /type `installer_type` /end 181 Pop $0 ; type 182 ${EndIf} 183 184 ClearErrors 185 StrCpy $1 "unknown" 186 ${If} $0 == "string" 187 nsJSON::Get `installer_type` /end 188 ${IfNot} ${Errors} 189 ; get the actual installer type from the file 190 Pop $1 191 ${EndIf} 192 ${EndIf} 193 194 Exch 195 Pop $0 196 Exch $1 197 ClearErrors 198 FunctionEnd