MultiUser.nsh 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505
  1. /*
  2. MultiUser.nsh
  3. Installer configuration for multi-user Windows environments
  4. Copyright 2008-2023 Joost Verburg
  5. */
  6. !ifndef MULTIUSER_INCLUDED
  7. !define MULTIUSER_INCLUDED 20210216
  8. !verbose push 3
  9. ;Standard NSIS header files
  10. !ifdef MULTIUSER_MUI
  11. !include MUI2.nsh
  12. !endif
  13. !include LogicLib.nsh
  14. !include WinVer.nsh
  15. !include FileFunc.nsh
  16. !if ${NSIS_PTR_SIZE} > 4
  17. !define /IfNDef MULTIUSER_MINWIN 0x501
  18. !else
  19. !define /IfNDef MULTIUSER_MINWIN 0x400
  20. !endif
  21. ;Variables
  22. Var MultiUser.Privileges
  23. Var MultiUser.InstallMode
  24. ;Command line installation mode setting
  25. !ifdef MULTIUSER_INSTALLMODE_COMMANDLINE
  26. !include StrFunc.nsh
  27. ${Using:StrFunc} StrStr
  28. !ifndef MULTIUSER_NOUNINSTALL
  29. ${Using:StrFunc} UnStrStr
  30. !endif
  31. Var MultiUser.Parameters
  32. Var MultiUser.Result
  33. !endif
  34. ;Installation folder stored in registry
  35. !ifdef MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_KEY & MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_VALUENAME
  36. Var MultiUser.InstDir
  37. !endif
  38. !ifdef MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_KEY & MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_VALUENAME
  39. Var MultiUser.DefaultKeyValue
  40. !endif
  41. ;Windows Vista UAC setting
  42. !if "${MULTIUSER_EXECUTIONLEVEL}" == Admin
  43. RequestExecutionLevel admin
  44. !define MULTIUSER_EXECUTIONLEVEL_ALLUSERS
  45. !else if "${MULTIUSER_EXECUTIONLEVEL}" == Power
  46. RequestExecutionLevel admin
  47. !define MULTIUSER_EXECUTIONLEVEL_ALLUSERS
  48. !else if "${MULTIUSER_EXECUTIONLEVEL}" == Highest
  49. RequestExecutionLevel highest
  50. !define MULTIUSER_EXECUTIONLEVEL_ALLUSERS
  51. !else
  52. RequestExecutionLevel user
  53. !ifndef MULTIUSER_EXECUTIONLEVEL
  54. !warning "MULTIUSER_EXECUTIONLEVEL not set!"
  55. !endif
  56. !endif
  57. /*
  58. Install modes
  59. */
  60. !macro MULTIUSER_INSTALLMODE_ALLUSERS UNINSTALLER_PREFIX UNINSTALLER_FUNCPREFIX
  61. ;Install mode initialization - per-machine
  62. ${ifnot} ${IsNT}
  63. ${orif} $MultiUser.Privileges == "Admin"
  64. ${orif} $MultiUser.Privileges == "Power"
  65. StrCpy $MultiUser.InstallMode AllUsers
  66. SetShellVarContext all
  67. !if "${UNINSTALLER_PREFIX}" != UN
  68. ;Set default installation location for installer
  69. !ifdef MULTIUSER_INSTALLMODE_INSTDIR
  70. !ifdef MULTIUSER_USE_PROGRAMFILES64
  71. StrCpy $INSTDIR "$PROGRAMFILES64\${MULTIUSER_INSTALLMODE_INSTDIR}"
  72. !else
  73. StrCpy $INSTDIR "$PROGRAMFILES\${MULTIUSER_INSTALLMODE_INSTDIR}"
  74. !endif
  75. !endif
  76. !endif
  77. !ifdef MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_KEY & MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_VALUENAME
  78. ReadRegStr $MultiUser.InstDir HKLM "${MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_KEY}" "${MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_VALUENAME}"
  79. ${if} $MultiUser.InstDir != ""
  80. StrCpy $INSTDIR $MultiUser.InstDir
  81. ${endif}
  82. !endif
  83. !ifdef MULTIUSER_INSTALLMODE_${UNINSTALLER_PREFIX}FUNCTION
  84. Call "${MULTIUSER_INSTALLMODE_${UNINSTALLER_PREFIX}FUNCTION}"
  85. !endif
  86. ${endif}
  87. !macroend
  88. !macro MULTIUSER_INSTALLMODE_CURRENTUSER UNINSTALLER_PREFIX UNINSTALLER_FUNCPREFIX
  89. ;Install mode initialization - per-user
  90. !if ${MULTIUSER_MINWIN} < 0x500
  91. ${if} ${IsNT}
  92. !endif
  93. StrCpy $MultiUser.InstallMode CurrentUser
  94. SetShellVarContext current
  95. !if "${UNINSTALLER_PREFIX}" != UN
  96. ;Set default installation location for installer
  97. !ifdef MULTIUSER_INSTALLMODE_INSTDIR
  98. !if ${MULTIUSER_MINWIN} < 0x490
  99. ${if} ${AtLeastWin2000}
  100. !endif
  101. GetKnownFolderPath $INSTDIR {5CD7AEE2-2219-4A67-B85D-6C9CE15660CB} ; FOLDERID_UserProgramFiles
  102. StrCmp $INSTDIR "" 0 +2
  103. StrCpy $INSTDIR "$LocalAppData\Programs" ; Fallback directory
  104. StrCpy $INSTDIR "$INSTDIR\${MULTIUSER_INSTALLMODE_INSTDIR}"
  105. !if ${MULTIUSER_MINWIN} < 0x490
  106. ${else}
  107. StrCpy $INSTDIR "$PROGRAMFILES\${MULTIUSER_INSTALLMODE_INSTDIR}"
  108. ${endif}
  109. !endif
  110. !endif
  111. !endif
  112. !ifdef MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_KEY & MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_VALUENAME
  113. ReadRegStr $MultiUser.InstDir HKCU "${MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_KEY}" "${MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_VALUENAME}"
  114. ${if} $MultiUser.InstDir != ""
  115. StrCpy $INSTDIR $MultiUser.InstDir
  116. ${endif}
  117. !endif
  118. !ifdef MULTIUSER_INSTALLMODE_${UNINSTALLER_PREFIX}FUNCTION
  119. Call "${MULTIUSER_INSTALLMODE_${UNINSTALLER_PREFIX}FUNCTION}"
  120. !endif
  121. !if ${MULTIUSER_MINWIN} < 0x500
  122. ${endif}
  123. !endif
  124. !macroend
  125. Function MultiUser.InstallMode.AllUsers
  126. !insertmacro MULTIUSER_INSTALLMODE_ALLUSERS "" ""
  127. FunctionEnd
  128. Function MultiUser.InstallMode.CurrentUser
  129. !insertmacro MULTIUSER_INSTALLMODE_CURRENTUSER "" ""
  130. FunctionEnd
  131. !ifndef MULTIUSER_NOUNINSTALL
  132. Function un.MultiUser.InstallMode.AllUsers
  133. !insertmacro MULTIUSER_INSTALLMODE_ALLUSERS UN .un
  134. FunctionEnd
  135. Function un.MultiUser.InstallMode.CurrentUser
  136. !insertmacro MULTIUSER_INSTALLMODE_CURRENTUSER UN .un
  137. FunctionEnd
  138. !endif
  139. /*
  140. Installer/uninstaller initialization
  141. */
  142. !macro MULTIUSER_INIT_QUIT UNINSTALLER_FUNCPREFIX
  143. !ifdef MULTIUSER_INIT_${UNINSTALLER_FUNCPREFIX}FUNCTIONQUIT
  144. Call "${MULTIUSER_INIT_${UNINSTALLER_FUNCPREFIX}FUNCTIONQUIT}"
  145. !else
  146. Quit
  147. !endif
  148. !macroend
  149. !macro MULTIUSER_INIT_TEXTS UNINSTALLER_PREFIX
  150. !if "${UNINSTALLER_PREFIX}" == ""
  151. !define /ReDef MULTIUSER_TMPSTR_CAPTION "$(^SetupCaption)"
  152. !else
  153. !define /ReDef MULTIUSER_TMPSTR_CAPTION "$(^Name)"
  154. !endif
  155. !define /IfNDef MULTIUSER_INIT_TEXT_ADMINREQUIRED "${MULTIUSER_TMPSTR_CAPTION} requires administrator privileges."
  156. !define /IfNDef MULTIUSER_INIT_TEXT_POWERREQUIRED "${MULTIUSER_TMPSTR_CAPTION} requires at least Power User privileges."
  157. !define /IfNDef MULTIUSER_INIT_TEXT_ALLUSERSNOTPOSSIBLE "Your user account does not have sufficient privileges to install $(^Name) for all users of this computer."
  158. !undef MULTIUSER_TMPSTR_CAPTION
  159. !macroend
  160. !macro MULTIUSER_INIT_CHECKS UNINSTALLER_PREFIX UNINSTALLER_FUNCPREFIX
  161. ;Installer initialization - check privileges and set install mode
  162. !insertmacro MULTIUSER_INIT_TEXTS "${UNINSTALLER_PREFIX}"
  163. UserInfo::GetAccountType
  164. Pop $MultiUser.Privileges
  165. !if ${MULTIUSER_MINWIN} < 0x500
  166. ${if} ${IsNT}
  167. !endif
  168. ;Check privileges
  169. !if "${MULTIUSER_EXECUTIONLEVEL}" == Admin
  170. ${if} $MultiUser.Privileges != "Admin"
  171. MessageBox MB_OK|MB_ICONSTOP "${MULTIUSER_INIT_TEXT_ADMINREQUIRED}"
  172. !insertmacro MULTIUSER_INIT_QUIT "${UNINSTALLER_FUNCPREFIX}"
  173. ${endif}
  174. !else if "${MULTIUSER_EXECUTIONLEVEL}" == Power
  175. ${if} $MultiUser.Privileges != "Power"
  176. ${andif} $MultiUser.Privileges != "Admin"
  177. ${if} ${AtMostWinXP}
  178. MessageBox MB_OK|MB_ICONSTOP "${MULTIUSER_INIT_TEXT_POWERREQUIRED}"
  179. ${else}
  180. MessageBox MB_OK|MB_ICONSTOP "${MULTIUSER_INIT_TEXT_ADMINREQUIRED}"
  181. ${endif}
  182. !insertmacro MULTIUSER_INIT_QUIT "${UNINSTALLER_FUNCPREFIX}"
  183. ${endif}
  184. !endif
  185. !ifdef MULTIUSER_EXECUTIONLEVEL_ALLUSERS
  186. ;Default to per-machine installation if possible
  187. ${if} $MultiUser.Privileges == "Admin"
  188. ${orif} $MultiUser.Privileges == "Power"
  189. !ifndef MULTIUSER_INSTALLMODE_DEFAULT_CURRENTUSER
  190. Call ${UNINSTALLER_FUNCPREFIX}MultiUser.InstallMode.AllUsers
  191. !else
  192. Call ${UNINSTALLER_FUNCPREFIX}MultiUser.InstallMode.CurrentUser
  193. !endif
  194. !ifdef MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_KEY & MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_VALUENAME
  195. ;Set installation mode to setting from a previous installation
  196. !ifndef MULTIUSER_INSTALLMODE_DEFAULT_CURRENTUSER
  197. ReadRegStr $MultiUser.DefaultKeyValue HKLM "${MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_KEY}" "${MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_VALUENAME}"
  198. ${if} $MultiUser.DefaultKeyValue == ""
  199. ReadRegStr $MultiUser.DefaultKeyValue HKCU "${MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_KEY}" "${MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_VALUENAME}"
  200. ${if} $MultiUser.DefaultKeyValue != ""
  201. Call ${UNINSTALLER_FUNCPREFIX}MultiUser.InstallMode.CurrentUser
  202. ${endif}
  203. ${endif}
  204. !else
  205. ReadRegStr $MultiUser.DefaultKeyValue HKCU "${MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_KEY}" "${MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_VALUENAME}"
  206. ${if} $MultiUser.DefaultKeyValue == ""
  207. ReadRegStr $MultiUser.DefaultKeyValue HKLM "${MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_KEY}" "${MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_VALUENAME}"
  208. ${if} $MultiUser.DefaultKeyValue != ""
  209. Call ${UNINSTALLER_FUNCPREFIX}MultiUser.InstallMode.AllUsers
  210. ${endif}
  211. ${endif}
  212. !endif
  213. !endif
  214. ${else}
  215. Call ${UNINSTALLER_FUNCPREFIX}MultiUser.InstallMode.CurrentUser
  216. ${endif}
  217. !else
  218. Call ${UNINSTALLER_FUNCPREFIX}MultiUser.InstallMode.CurrentUser
  219. !endif
  220. !ifdef MULTIUSER_INSTALLMODE_COMMANDLINE
  221. ;Check for install mode setting on command line
  222. ${${UNINSTALLER_FUNCPREFIX}GetParameters} $MultiUser.Parameters
  223. ${${UNINSTALLER_PREFIX}StrStr} $MultiUser.Result $MultiUser.Parameters "/CurrentUser"
  224. ${if} $MultiUser.Result != ""
  225. Call ${UNINSTALLER_FUNCPREFIX}MultiUser.InstallMode.CurrentUser
  226. ${endif}
  227. ${${UNINSTALLER_PREFIX}StrStr} $MultiUser.Result $MultiUser.Parameters "/AllUsers"
  228. ${if} $MultiUser.Result != ""
  229. ${if} $MultiUser.Privileges == "Admin"
  230. ${orif} $MultiUser.Privileges == "Power"
  231. Call ${UNINSTALLER_FUNCPREFIX}MultiUser.InstallMode.AllUsers
  232. ${else}
  233. MessageBox MB_OK|MB_ICONSTOP "${MULTIUSER_INIT_TEXT_ALLUSERSNOTPOSSIBLE}"
  234. !insertmacro MULTIUSER_INIT_QUIT "${UNINSTALLER_FUNCPREFIX}"
  235. ${endif}
  236. ${endif}
  237. !endif
  238. !if ${MULTIUSER_MINWIN} < 0x500
  239. ${else}
  240. ;Not running Windows NT, per-user installation not supported
  241. Call ${UNINSTALLER_FUNCPREFIX}MultiUser.InstallMode.AllUsers
  242. ${endif}
  243. !endif
  244. !macroend
  245. !macro MULTIUSER_INIT
  246. !verbose push 3
  247. !ifdef __UNINSTALL__
  248. !insertmacro MULTIUSER_UNINIT
  249. !else
  250. !insertmacro MULTIUSER_INIT_CHECKS "" ""
  251. !endif
  252. !verbose pop
  253. !macroend
  254. !ifndef MULTIUSER_NOUNINSTALL
  255. !macro MULTIUSER_UNINIT
  256. !verbose push 3
  257. !insertmacro MULTIUSER_INIT_CHECKS Un un.
  258. !verbose pop
  259. !macroend
  260. !endif
  261. /*
  262. Mode selection page
  263. */
  264. !macro MULTIUSER_PAGE_FUNCTION_CUSTOM TYPE
  265. !ifmacrodef MUI_PAGE_FUNCTION_CUSTOM
  266. !insertmacro MUI_PAGE_FUNCTION_CUSTOM "${TYPE}"
  267. !endif
  268. !ifdef MULTIUSER_PAGE_CUSTOMFUNCTION_${TYPE}
  269. Call "${MULTIUSER_PAGE_CUSTOMFUNCTION_${TYPE}}"
  270. !undef MULTIUSER_PAGE_CUSTOMFUNCTION_${TYPE}
  271. !endif
  272. !macroend
  273. !macro MULTIUSER_INSTALLMODEPAGE_INTERFACE
  274. !ifndef MULTIUSER_INSTALLMODEPAGE_INTERFACE
  275. !define MULTIUSER_INSTALLMODEPAGE_INTERFACE
  276. Var MultiUser.InstallModePage
  277. Var MultiUser.InstallModePage.Text
  278. Var MultiUser.InstallModePage.AllUsers
  279. Var MultiUser.InstallModePage.CurrentUser
  280. !endif
  281. !macroend
  282. !macro MULTIUSER_PAGEDECLARATION_INSTALLMODE UNPREFIX UNIQUEID
  283. !define /ReDef MULTIUSER_${UNPREFIX}INSTALLMODEPAGE "" ; Unlock strings in the language file(s)
  284. !insertmacro MULTIUSER_INSTALLMODEPAGE_INTERFACE
  285. !define /IfNDef MULTIUSER_INSTALLMODEPAGE_TEXT_TOP "$(MULTIUSER_INNERTEXT_INSTALLMODE_TOP)"
  286. !define /IfNDef MULTIUSER_INSTALLMODEPAGE_TEXT_ALLUSERS "$(MULTIUSER_INNERTEXT_INSTALLMODE_ALLUSERS)"
  287. !define /IfNDef MULTIUSER_INSTALLMODEPAGE_TEXT_CURRENTUSER "$(MULTIUSER_INNERTEXT_INSTALLMODE_CURRENTUSER)"
  288. PageEx custom
  289. PageCallbacks MultiUser.InstallModePre_${UNIQUEID} MultiUser.InstallModeLeave_${UNIQUEID}
  290. !define /IfNDef MULTIUSER_INSTALLMODEPAGE_CAPTION " "
  291. Caption "${MULTIUSER_INSTALLMODEPAGE_CAPTION}"
  292. PageExEnd
  293. !insertmacro MULTIUSER_FUNCTION_INSTALLMODEPAGE MultiUser.InstallModePre_${UNIQUEID} MultiUser.InstallModeLeave_${UNIQUEID}
  294. !undef MULTIUSER_INSTALLMODEPAGE_TEXT_TOP
  295. !undef MULTIUSER_INSTALLMODEPAGE_TEXT_ALLUSERS
  296. !undef MULTIUSER_INSTALLMODEPAGE_TEXT_CURRENTUSER
  297. !macroend
  298. !macro MULTIUSER_PAGE_INSTALLMODE
  299. !verbose push 3
  300. !ifndef MULTIUSER_EXECUTIONLEVEL_ALLUSERS
  301. !error "A mixed-mode installation requires MULTIUSER_EXECUTIONLEVEL to be set to Admin, Power or Highest."
  302. !endif
  303. !ifmacrodef MUI_PAGE_INIT
  304. !insertmacro MUI_PAGE_INIT
  305. !endif
  306. !insertmacro MULTIUSER_PAGEDECLARATION_INSTALLMODE "" ${__COUNTER__}
  307. !verbose pop
  308. !macroend
  309. !macro MULTIUSER_FUNCTION_INSTALLMODEPAGE PRE LEAVE
  310. !include nsDialogs.nsh
  311. Function "${PRE}"
  312. !if ${MULTIUSER_MINWIN} < 0x500
  313. ${ifnot} ${IsNT}
  314. Abort
  315. ${endif}
  316. !endif
  317. ${if} $MultiUser.Privileges != "Power"
  318. ${andif} $MultiUser.Privileges != "Admin"
  319. Abort
  320. ${endif}
  321. !insertmacro MULTIUSER_PAGE_FUNCTION_CUSTOM PRE
  322. !ifmacrodef MUI_HEADER_TEXT_PAGE
  323. !insertmacro MUI_HEADER_TEXT_PAGE $(MULTIUSER_TEXT_INSTALLMODE_TITLE) $(MULTIUSER_TEXT_INSTALLMODE_SUBTITLE)
  324. !endif
  325. nsDialogs::Create 1018
  326. Pop $MultiUser.InstallModePage
  327. ${NSD_CreateLabel} 0 2u 100% 42u "${MULTIUSER_INSTALLMODEPAGE_TEXT_TOP}"
  328. Pop $MultiUser.InstallModePage.Text
  329. ${NSD_CreateRadioButton} 15u 50u -15u 10u "${MULTIUSER_INSTALLMODEPAGE_TEXT_ALLUSERS}"
  330. Pop $MultiUser.InstallModePage.AllUsers
  331. !ifdef MULTIUSER_INSTALLMODEPAGE_SHOWUSERNAME
  332. !ifdef NOSYSTEMCALLS
  333. ReadEnvStr $0 USERNAME
  334. !else
  335. System::Call 'ADVAPI32::GetUserName(t""r0,*i${NSIS_MAX_STRLEN})'
  336. !endif
  337. StrCmp $0 "" +2
  338. StrCpy $0 " ($0)"
  339. ${NSD_CreateRadioButton} 15u 70u -15u 10u "${MULTIUSER_INSTALLMODEPAGE_TEXT_CURRENTUSER}$0"
  340. !else
  341. ${NSD_CreateRadioButton} 15u 70u -15u 10u "${MULTIUSER_INSTALLMODEPAGE_TEXT_CURRENTUSER}"
  342. !endif
  343. Pop $MultiUser.InstallModePage.CurrentUser
  344. ${if} $MultiUser.InstallMode == "AllUsers"
  345. SendMessage $MultiUser.InstallModePage.AllUsers ${BM_SETCHECK} ${BST_CHECKED} 0
  346. ${else}
  347. SendMessage $MultiUser.InstallModePage.CurrentUser ${BM_SETCHECK} ${BST_CHECKED} 0
  348. ${endif}
  349. !insertmacro MULTIUSER_PAGE_FUNCTION_CUSTOM SHOW
  350. nsDialogs::Show
  351. !insertmacro MULTIUSER_PAGE_FUNCTION_CUSTOM DESTROYED
  352. FunctionEnd
  353. Function "${LEAVE}"
  354. SendMessage $MultiUser.InstallModePage.AllUsers ${BM_GETCHECK} 0 0 $0
  355. ${if} $0 = ${BST_CHECKED}
  356. Call MultiUser.InstallMode.AllUsers
  357. ${else}
  358. Call MultiUser.InstallMode.CurrentUser
  359. ${endif}
  360. !insertmacro MULTIUSER_PAGE_FUNCTION_CUSTOM LEAVE
  361. FunctionEnd
  362. !macroend
  363. !verbose pop
  364. !endif