WinVer.nsh 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509
  1. ; ---------------------
  2. ; WinVer.nsh
  3. ; ---------------------
  4. ;
  5. ; LogicLib extensions for handling Windows versions and service packs.
  6. ;
  7. ; IsNT checks if the installer is running on Windows NT family (NT4, 2000, XP, etc.)
  8. ;
  9. ; ${If} ${IsNT}
  10. ; DetailPrint "Running on NT. Installing Unicode enabled application."
  11. ; ${Else}
  12. ; DetailPrint "Not running on NT. Installing ANSI application."
  13. ; ${EndIf}
  14. ;
  15. ; IsServerOS checks if the installer is running on a server version of Windows (NT4, 2003, 2008, etc.)
  16. ;
  17. ; AtLeastWin<version> checks if the installer is running on Windows version at least as specified.
  18. ; IsWin<version> checks if the installer is running on Windows version exactly as specified.
  19. ; AtMostWin<version> checks if the installer is running on Windows version at most as specified.
  20. ;
  21. ; <version> can be replaced with the following values:
  22. ;
  23. ; 95
  24. ; 98
  25. ; ME
  26. ;
  27. ; NT4
  28. ; 2000
  29. ; XP
  30. ; 2003
  31. ; Vista
  32. ; 2008
  33. ; 7
  34. ; 2008R2
  35. ; 8
  36. ; 2012
  37. ; 8.1
  38. ; 2012R2
  39. ; 10
  40. ;
  41. ; Note: Windows 8.1 and later will be detected as Windows 8 unless ManifestSupportedOS is set correctly!
  42. ;
  43. ; AtLeastServicePack checks if the installer is running on Windows service pack version at least as specified.
  44. ; IsServicePack checks if the installer is running on Windows service pack version exactly as specified.
  45. ; AtMostServicePack checks if the installer is running on Windows service version pack at most as specified.
  46. ;
  47. ; Usage examples:
  48. ;
  49. ; ${If} ${IsNT}
  50. ; DetailPrint "Running on NT family."
  51. ; DetailPrint "Surely not running on 95, 98 or ME."
  52. ; ${AndIf} ${AtLeastWinNT4}
  53. ; DetailPrint "Running on NT4 or better. Could even be 2003."
  54. ; ${EndIf}
  55. ;
  56. ; ${If} ${AtLeastWinXP}
  57. ; DetailPrint "Running on XP or better."
  58. ; ${EndIf}
  59. ;
  60. ; ${If} ${IsWin2000}
  61. ; DetailPrint "Running on 2000."
  62. ; ${EndIf}
  63. ;
  64. ; ${If} ${IsWin2000}
  65. ; ${AndIf} ${AtLeastServicePack} 3
  66. ; ${OrIf} ${AtLeastWinXP}
  67. ; DetailPrint "Running Win2000 SP3 or above"
  68. ; ${EndIf}
  69. ;
  70. ; ${If} ${AtMostWinXP}
  71. ; DetailPrint "Running on XP or older. Surely not running on Vista. Maybe 98, or even 95."
  72. ; ${EndIf}
  73. ;
  74. ; Warning:
  75. ;
  76. ; Windows 95 and NT both use the same version number. To avoid getting NT4 misidentified
  77. ; as Windows 95 and vice-versa or 98 as a version higher than NT4, always use IsNT to
  78. ; check if running on the NT family.
  79. ;
  80. ; ${If} ${AtLeastWin95}
  81. ; ${And} ${AtMostWinME}
  82. ; DetailPrint "Running 95, 98 or ME."
  83. ; DetailPrint "Actually, maybe it's NT4?"
  84. ; ${If} ${IsNT}
  85. ; DetailPrint "Yes, it's NT4! oops..."
  86. ; ${Else}
  87. ; DetailPrint "Nope, not NT4. phew..."
  88. ; ${EndIf}
  89. ; ${EndIf}
  90. ;
  91. ;
  92. ; Other useful extensions are:
  93. ;
  94. ; * IsWin2003R2
  95. ; * IsStarterEdition
  96. ; * OSHasMediaCenter
  97. ; * OSHasTabletSupport
  98. ;
  99. !verbose push
  100. !verbose 3
  101. !ifndef ___WINVER__NSH___
  102. !define ___WINVER__NSH___
  103. !include LogicLib.nsh
  104. !include Util.nsh
  105. # masks for our variables
  106. !define _WINVER_VERXBIT 0x00000001
  107. !define _WINVER_MASKVMAJ 0x7F000000
  108. !define _WINVER_MASKVMIN 0x00FF0000
  109. !define _WINVER_NTBIT 0x80000000
  110. !define _WINVER_NTMASK 0x7FFFFFFF
  111. !define _WINVER_NTSRVBIT 0x40000000
  112. !define _WINVER_MASKVBLD 0x0000FFFF
  113. !define _WINVER_MASKSP 0x000F0000
  114. # possible variable values for different versions
  115. !define WINVER_95_NT 0x04000000 ;4.00.0950
  116. !define WINVER_95 0x04000000 ;4.00.0950
  117. !define WINVER_98_NT 0x040a0000 ;4.10.1998
  118. !define WINVER_98 0x040a0000 ;4.10.1998
  119. ;define WINVER_98SE 0x040a0000 ;4.10.2222
  120. !define WINVER_ME_NT 0x045a0000 ;4.90.3000
  121. !define WINVER_ME 0x045a0000 ;4.90.3000
  122. ;define WINVER_NT3.51 ;3.51.1057
  123. !define WINVER_NT4_NT 0x84000000 ;4.00.1381
  124. !define WINVER_NT4 0x04000000 ;4.00.1381
  125. !define WINVER_2000_NT 0x85000000 ;5.00.2195
  126. !define WINVER_2000 0x05000000 ;5.00.2195
  127. !define WINVER_XP_NT 0x85010000 ;5.01.2600
  128. !define WINVER_XP 0x05010000 ;5.01.2600
  129. ;define WINVER_XP64 ;5.02.3790
  130. !define WINVER_2003_NT 0x85020000 ;5.02.3790
  131. !define WINVER_2003 0x05020000 ;5.02.3790
  132. !define WINVER_VISTA_NT 0x86000000 ;6.00.6000
  133. !define WINVER_VISTA 0x06000000 ;6.00.6000
  134. !define WINVER_2008_NT 0x86000001 ;6.00.6001
  135. !define WINVER_2008 0x06000001 ;6.00.6001
  136. !define WINVER_7_NT 0x86010000 ;6.01.7600
  137. !define WINVER_7 0x06010000 ;6.01.7600
  138. !define WINVER_2008R2_NT 0x86010001 ;6.01.7600
  139. !define WINVER_2008R2 0x06010001 ;6.01.7600
  140. !define WINVER_8_NT 0x86020000 ;6.02.9200
  141. !define WINVER_8 0x06020000 ;6.02.9200
  142. !define WINVER_2012_NT 0x86020001 ;6.02.9200
  143. !define WINVER_2012 0x06020001 ;6.02.9200
  144. !define WINVER_8.1_NT 0x86030000 ;6.03.9600
  145. !define WINVER_8.1 0x06030000 ;6.03.9600
  146. !define WINVER_2012R2_NT 0x86030001 ;6.03.9600
  147. !define WINVER_2012R2 0x06030001 ;6.03.9600
  148. !define WINVER_10_NT 0x8A000000 ;10.0.10240
  149. !define WINVER_10 0x0A000000 ;10.0.10240
  150. # use this to make all nt > 9x
  151. !ifdef WINVER_NT4_OVER_W95
  152. !define /redef /math WINVER_NT4 ${WINVER_NT4} | ${_WINVER_VERXBIT}
  153. !endif
  154. # some definitions from header files
  155. !define OSVERSIONINFOW_SIZE 276
  156. !define OSVERSIONINFOEXW_SIZE 284
  157. !define OSVERSIONINFOA_SIZE 148
  158. !define OSVERSIONINFOEXA_SIZE 156
  159. !define /ifndef VER_PLATFORM_WIN32_NT 2
  160. !define /ifndef VER_NT_WORKSTATION 1
  161. !define SM_TABLETPC 86
  162. !define SM_MEDIACENTER 87
  163. !define SM_STARTER 88
  164. !define SM_SERVERR2 89
  165. # variable declaration
  166. !macro __WinVer_DeclareVars
  167. !ifndef __WINVER_VARS_DECLARED
  168. !define __WINVER_VARS_DECLARED
  169. Var /GLOBAL __WINVERV
  170. Var /GLOBAL __WINVERSP
  171. !endif
  172. !macroend
  173. # lazy initialization macro
  174. !ifmacrondef __WinVer_Call_GetVersionEx
  175. !macro __WinVer_Call_GetVersionEx STRUCT_SIZE
  176. System::Call '*$0(i ${STRUCT_SIZE})'
  177. System::Call kernel32::GetVersionEx(pr0)i.r3
  178. !macroend
  179. !endif
  180. !macro __WinVer_InitVars
  181. # variables
  182. !insertmacro __WinVer_DeclareVars
  183. # only calculate version once
  184. StrCmp $__WINVERV "" _winver_noveryet
  185. Return
  186. _winver_noveryet:
  187. # push used registers on the stack
  188. Push $0
  189. Push $1 ;maj
  190. Push $2 ;min
  191. Push $3 ;bld
  192. Push $R0 ;temp
  193. # a plugin call will lock the Unicode mode, it is now safe to set the struct size
  194. !ifdef NSIS_UNICODE
  195. !define /redef OSVERSIONINFO_SIZE ${OSVERSIONINFOW_SIZE}
  196. !define /redef OSVERSIONINFOEX_SIZE ${OSVERSIONINFOEXW_SIZE}
  197. !else
  198. !define /redef OSVERSIONINFO_SIZE ${OSVERSIONINFOA_SIZE}
  199. !define /redef OSVERSIONINFOEX_SIZE ${OSVERSIONINFOEXA_SIZE}
  200. !endif
  201. # allocate memory
  202. System::Call '*(&i${OSVERSIONINFOEX_SIZE})p.r0'
  203. # use OSVERSIONINFOEX
  204. !insertmacro __WinVer_Call_GetVersionEx ${OSVERSIONINFOEX_SIZE}
  205. IntCmp $3 0 "" _winver_ex _winver_ex
  206. # OSVERSIONINFOEX not allowed (Win9x or NT4 w/SP < 6), use OSVERSIONINFO
  207. !insertmacro __WinVer_Call_GetVersionEx ${OSVERSIONINFO_SIZE}
  208. _winver_ex:
  209. # get results from struct
  210. System::Call '*$0(i.s,i.r1,i.r2,i.r3,i.s,&t128.s,&i2.s,&i2,&i2,&i1.s,&i1)'
  211. # free struct
  212. System::Free $0
  213. # win9x has major and minor info in high word of dwBuildNumber - remove it
  214. IntOp $3 $3 & 0xFFFF
  215. # get dwOSVersionInfoSize
  216. Pop $R0
  217. # get dwPlatformId
  218. Pop $0
  219. # NT?
  220. IntCmp $0 ${VER_PLATFORM_WIN32_NT} "" _winver_notnt _winver_notnt
  221. IntOp $__WINVERSP $__WINVERSP | ${_WINVER_NTBIT}
  222. IntOp $__WINVERV $__WINVERV | ${_WINVER_NTBIT}
  223. _winver_notnt:
  224. # get service pack information
  225. IntCmp $0 ${VER_PLATFORM_WIN32_NT} _winver_nt "" _winver_nt # win9x
  226. # get szCSDVersion
  227. Pop $0
  228. # copy second char
  229. StrCpy $0 $0 1 1
  230. # discard invalid wServicePackMajor and wProductType
  231. Pop $R0
  232. Pop $R0
  233. # switch
  234. StrCmp $0 'A' "" +3
  235. StrCpy $0 1
  236. Goto _winver_sp_done
  237. StrCmp $0 'B' "" +3
  238. StrCpy $0 2
  239. Goto _winver_sp_done
  240. StrCmp $0 'C' "" +3
  241. StrCpy $0 3
  242. Goto _winver_sp_done
  243. StrCpy $0 0
  244. Goto _winver_sp_done
  245. _winver_nt: # nt
  246. IntCmp $R0 ${OSVERSIONINFOEX_SIZE} "" _winver_sp_noex _winver_sp_noex
  247. # discard szCSDVersion
  248. Pop $0
  249. # get wProductType
  250. Exch
  251. Pop $0
  252. # is server?
  253. IntCmp $0 ${VER_NT_WORKSTATION} _winver_noserver
  254. IntOp $__WINVERSP $__WINVERSP | ${_WINVER_NTSRVBIT}
  255. _winver_noserver:
  256. # get wServicePackMajor
  257. Pop $0
  258. # done with sp
  259. Goto _winver_sp_done
  260. _winver_sp_noex: # OSVERSIONINFO, not OSVERSIONINFOEX
  261. #### TODO
  262. ## For IsServerOS to support < NT4SP6, we need to check the registry
  263. ## here to see if we are a server and/or DC
  264. # get szCSDVersion
  265. Pop $0
  266. # discard invalid wServicePackMajor and wProductType
  267. Pop $R0
  268. Pop $R0
  269. # get service pack number from text
  270. StrCpy $R0 $0 13
  271. StrCmp $R0 "Service Pack " "" +3
  272. StrCpy $0 $0 "" 13 # cut "Service Pack "
  273. Goto +2
  274. StrCpy $0 0 # no service pack
  275. !ifdef WINVER_NT4_OVER_W95
  276. IntOp $__WINVERV $__WINVERV | ${_WINVER_VERXBIT}
  277. !endif
  278. _winver_sp_done:
  279. # store service pack
  280. IntOp $0 $0 << 16
  281. IntOp $__WINVERSP $__WINVERSP | $0
  282. ### now for the version
  283. # is server?
  284. IntOp $0 $__WINVERSP & ${_WINVER_NTSRVBIT}
  285. # windows xp x64?
  286. IntCmp $0 0 "" _winver_not_xp_x64 _winver_not_xp_x64 # not server
  287. IntCmp $1 5 "" _winver_not_xp_x64 _winver_not_xp_x64 # maj 5
  288. IntCmp $2 2 "" _winver_not_xp_x64 _winver_not_xp_x64 # min 2
  289. # change XP x64 from 5.2 to 5.1 so it's still XP
  290. StrCpy $2 1
  291. _winver_not_xp_x64:
  292. # server 2008?
  293. IntCmp $0 0 _winver_not_ntserver # server
  294. IntCmp 6 $1 "" "" _winver_not_ntserver # maj 6
  295. # extra bit so Server 2008 comes after Vista SP1 that has the same minor version, same for Win7 vs 2008R2
  296. IntOp $__WINVERV $__WINVERV | ${_WINVER_VERXBIT}
  297. _winver_not_ntserver:
  298. # pack version
  299. IntOp $1 $1 << 24 # VerMajor
  300. IntOp $__WINVERV $__WINVERV | $1
  301. IntOp $0 $2 << 16
  302. IntOp $__WINVERV $__WINVERV | $0 # VerMinor
  303. IntOp $__WINVERSP $__WINVERSP | $3 # VerBuild
  304. # restore registers
  305. Pop $R0
  306. Pop $3
  307. Pop $2
  308. Pop $1
  309. Pop $0
  310. !macroend
  311. # version comparison LogicLib macros
  312. !macro _WinVerAtLeast _a _b _t _f
  313. !insertmacro _LOGICLIB_TEMP
  314. ${CallArtificialFunction} __WinVer_InitVars
  315. IntOp $_LOGICLIB_TEMP $__WINVERV & ${_WINVER_NTMASK}
  316. !insertmacro _>= $_LOGICLIB_TEMP `${_b}` `${_t}` `${_f}`
  317. !macroend
  318. !macro _WinVerIs _a _b _t _f
  319. ${CallArtificialFunction} __WinVer_InitVars
  320. !insertmacro _= $__WINVERV `${_b}` `${_t}` `${_f}`
  321. !macroend
  322. !macro _WinVerAtMost _a _b _t _f
  323. !insertmacro _LOGICLIB_TEMP
  324. ${CallArtificialFunction} __WinVer_InitVars
  325. IntOp $_LOGICLIB_TEMP $__WINVERV & ${_WINVER_NTMASK}
  326. !insertmacro _<= $_LOGICLIB_TEMP `${_b}` `${_t}` `${_f}`
  327. !macroend
  328. !macro __WinVer_DefineOSTest Test OS Suffix
  329. !define ${Test}Win${OS} `"" WinVer${Test} ${WINVER_${OS}${Suffix}}`
  330. !macroend
  331. !macro __WinVer_DefineOSTests Test Suffix
  332. !insertmacro __WinVer_DefineOSTest ${Test} 95 '${Suffix}'
  333. !insertmacro __WinVer_DefineOSTest ${Test} 98 '${Suffix}'
  334. !insertmacro __WinVer_DefineOSTest ${Test} ME '${Suffix}'
  335. !insertmacro __WinVer_DefineOSTest ${Test} NT4 '${Suffix}'
  336. !insertmacro __WinVer_DefineOSTest ${Test} 2000 '${Suffix}'
  337. !insertmacro __WinVer_DefineOSTest ${Test} XP '${Suffix}'
  338. !insertmacro __WinVer_DefineOSTest ${Test} 2003 '${Suffix}'
  339. !insertmacro __WinVer_DefineOSTest ${Test} VISTA '${Suffix}'
  340. !insertmacro __WinVer_DefineOSTest ${Test} 2008 '${Suffix}'
  341. !insertmacro __WinVer_DefineOSTest ${Test} 7 '${Suffix}'
  342. !insertmacro __WinVer_DefineOSTest ${Test} 2008R2 '${Suffix}'
  343. !insertmacro __WinVer_DefineOSTest ${Test} 8 '${Suffix}'
  344. !insertmacro __WinVer_DefineOSTest ${Test} 2012 '${Suffix}'
  345. !insertmacro __WinVer_DefineOSTest ${Test} 8.1 '${Suffix}'
  346. !insertmacro __WinVer_DefineOSTest ${Test} 2012R2 '${Suffix}'
  347. !insertmacro __WinVer_DefineOSTest ${Test} 10 '${Suffix}'
  348. !macroend
  349. !insertmacro __WinVer_DefineOSTests AtLeast ""
  350. !insertmacro __WinVer_DefineOSTests Is _NT
  351. !insertmacro __WinVer_DefineOSTests AtMost ""
  352. # version feature LogicLib macros
  353. !macro _IsNT _a _b _t _f
  354. !insertmacro _LOGICLIB_TEMP
  355. ${CallArtificialFunction} __WinVer_InitVars
  356. IntOp $_LOGICLIB_TEMP $__WINVERSP & ${_WINVER_NTBIT}
  357. !insertmacro _!= $_LOGICLIB_TEMP 0 `${_t}` `${_f}`
  358. !macroend
  359. !define IsNT `"" IsNT ""`
  360. !macro _IsServerOS _a _b _t _f
  361. !insertmacro _LOGICLIB_TEMP
  362. ${CallArtificialFunction} __WinVer_InitVars
  363. IntOp $_LOGICLIB_TEMP $__WINVERSP & ${_WINVER_NTSRVBIT}
  364. !insertmacro _!= $_LOGICLIB_TEMP 0 `${_t}` `${_f}`
  365. !macroend
  366. !define IsServerOS `"" IsServerOS ""`
  367. # service pack macros
  368. !macro _WinVer_GetServicePackLevel OUTVAR
  369. ${CallArtificialFunction} __WinVer_InitVars
  370. IntOp ${OUTVAR} $__WINVERSP & ${_WINVER_MASKSP}
  371. IntOp ${OUTVAR} ${OUTVAR} >> 16
  372. !macroend
  373. !define WinVerGetServicePackLevel '!insertmacro _WinVer_GetServicePackLevel '
  374. !macro _AtLeastServicePack _a _b _t _f
  375. !insertmacro _LOGICLIB_TEMP
  376. ${WinVerGetServicePackLevel} $_LOGICLIB_TEMP
  377. !insertmacro _>= $_LOGICLIB_TEMP `${_b}` `${_t}` `${_f}`
  378. !macroend
  379. !define AtLeastServicePack `"" AtLeastServicePack`
  380. !macro _AtMostServicePack _a _b _t _f
  381. !insertmacro _LOGICLIB_TEMP
  382. ${WinVerGetServicePackLevel} $_LOGICLIB_TEMP
  383. !insertmacro _<= $_LOGICLIB_TEMP `${_b}` `${_t}` `${_f}`
  384. !macroend
  385. !define AtMostServicePack `"" AtMostServicePack`
  386. !macro _IsServicePack _a _b _t _f
  387. !insertmacro _LOGICLIB_TEMP
  388. ${WinVerGetServicePackLevel} $_LOGICLIB_TEMP
  389. !insertmacro _= $_LOGICLIB_TEMP `${_b}` `${_t}` `${_f}`
  390. !macroend
  391. !define IsServicePack `"" IsServicePack`
  392. # special feature LogicLib macros
  393. !macro _WinVer_SysMetricCheck m _b _t _f
  394. !insertmacro _LOGICLIB_TEMP
  395. System::Call user32::GetSystemMetrics(i${m})i.s
  396. pop $_LOGICLIB_TEMP
  397. !insertmacro _!= $_LOGICLIB_TEMP 0 `${_t}` `${_f}`
  398. !macroend
  399. !define IsWin2003R2 `${SM_SERVERR2} WinVer_SysMetricCheck ""`
  400. !define IsStarterEdition `${SM_STARTER} WinVer_SysMetricCheck ""`
  401. !define OSHasMediaCenter `${SM_MEDIACENTER} WinVer_SysMetricCheck ""`
  402. !define OSHasTabletSupport `${SM_TABLETPC} WinVer_SysMetricCheck ""`
  403. # version retrieval macros
  404. !macro __WinVer_GetVer var rshift mask outvar
  405. ${CallArtificialFunction} __WinVer_InitVars
  406. !if "${mask}" != ""
  407. IntOp ${outvar} ${var} & ${mask}
  408. !if "${rshift}" != ""
  409. IntOp ${outvar} ${outvar} >> ${rshift}
  410. !endif
  411. !else
  412. IntOp ${outvar} ${var} >> ${rshift}
  413. !endif
  414. !macroend
  415. !define WinVerGetMajor '!insertmacro __WinVer_GetVer $__WINVERV 24 ${_WINVER_MASKVMAJ}'
  416. !define WinVerGetMinor '!insertmacro __WinVer_GetVer $__WINVERV 16 ${_WINVER_MASKVMIN}'
  417. !define WinVerGetBuild '!insertmacro __WinVer_GetVer $__WINVERSP "" ${_WINVER_MASKVBLD}'
  418. # done
  419. !endif # !___WINVER__NSH___
  420. !verbose pop