Archive: Windows XP Home vs Windows XP Pro


Windows XP Home vs Windows XP Pro
How do I detect if the OS is XP Pro vs XP Home. If it is Home, I plan on rejecting the installer, throwing an error and if its pro, to allow it. i got a script that detects 95,98,etc, but i like to know pro/home of xp.

thanks


You must do some calls with the system plugin,
first determine if the os is xp (with code you already have, or by calling GetVersion or GetVersionEx)
then if the os is xp (>= 5.1) then call GetVersionEx again, but this time with the OSVERSIONINFOEX struct, then check the wSuiteMask member for the VER_SUITE_PERSONAL bit

You could also use this class if you want to create a plugin instead of using the system plugin

ref:
http://msdn.microsoft.com/library/de...tversionex.asp
http://msdn.microsoft.com/library/de...infoex_str.asp


pardon my ignorance, but i am still quite new to NSIS. How do I do this? this is what i use right now.


GetWindowsVersion
;
; Based on Yazno's function, http://yazno.***********/powerpimpit/
; Updated by Joost Verburg
;
; Returns on top of stack
;
; Windows Version (95, 98, ME, NT x.x, 2000, XP, 2003)
; or
; '' (Unknown Windows Version)
;
; Usage:
; Call GetWindowsVersion
; Pop $R0
; ; at this point $R0 is "NT 4.0" or whatnot

Function GetWindowsVersion

Push $R0
Push $R1

ClearErrors

ReadRegStr $R0 HKLM \
"SOFTWARE\Microsoft\Windows NT\CurrentVersion" CurrentVersion

IfErrors 0 lbl_winnt

; we are not NT
ReadRegStr $R0 HKLM \
"SOFTWARE\Microsoft\Windows\CurrentVersion" VersionNumber

StrCpy $R1 $R0 1
StrCmp $R1 '4' 0 lbl_error

StrCpy $R1 $R0 3

StrCmp $R1 '4.0' lbl_win32_95
StrCmp $R1 '4.9' lbl_win32_ME lbl_win32_98

lbl_win32_95:
StrCpy $R0 '95'
MessageBox MB_OK|MB_ICONSTOP "Windows 95 is not supported by the software. $\n$\nPlease call 1-800- for additional support options." IDOK
Quit
Goto lbl_done

lbl_win32_98:
StrCpy $R0 '98'
MessageBox MB_OK|MB_ICONSTOP "Windows 98 is not supported by the software. $\n$\nPlease call 1-800-) for additional support options." IDOK
Quit
Goto lbl_done

lbl_win32_ME:
StrCpy $R0 'ME'
MessageBox MB_OK|MB_ICONSTOP "Windows Millennium Edition is not supported by the software. $\n$\nPlease call 1-800- for additional support options." IDOK
Quit
Goto lbl_done

lbl_winnt:

StrCpy $R1 $R0 1

StrCmp $R1 '3' lbl_winnt_x
StrCmp $R1 '4' lbl_winnt_x

StrCpy $R1 $R0 3

StrCmp $R1 '5.0' lbl_winnt_2000
StrCmp $R1 '5.1' lbl_winnt_XP
StrCmp $R1 '5.2' lbl_winnt_2003 lbl_error

lbl_winnt_x:
StrCpy $R0 "NT $R0" 6
MessageBox MB_OK|MB_ICONSTOP "Windows NT is not supported by the software. $\n$\nPlease call 1-800- for additional support options." IDOK
Quit
Goto lbl_done

lbl_winnt_2000:
Strcpy $R0 '2000'
Goto lbl_done

lbl_winnt_XP:
Strcpy $R0 'XP'
;; TODO: Detect Home and Professional Editions, abort on home
;; MessageBox MB_OK|MB_ICONSTOP "Windows XP Home Edition is not supported by the software. $\n$\nPlease switch to Windows XP Professional or call for additional support options."
;; Quit
Goto lbl_done

lbl_winnt_2003:
Strcpy $R0 '2003'
Goto lbl_done

lbl_error:
Strcpy $R0 ''
lbl_done:

Pop $R1
Exch $R0

FunctionEnd


thanks

I know i make use of System::Call Kernel32::getversionex but i dont get how i get the suite out of it, nor do i get the call itself using the system plugin. please clarify, sorry for asking such a silly question, but i dont get it


In the german press was an interesting article of how to convert a home edition to a pro edition. The article said the following Registry Key determines the kind of edition:

HKLM\SYSTEM\ControlSet001\Control\ProductOptions\ProductSuite

If the Value is "Personal" than it's the home otherwise its the pro edition.


Wunderbar, tausend dank!


Nice find.
You can then change the NSIS GetWindowsVersion function.

Change:

   lbl_winnt_XP:
Strcpy $R0 'XP'
Goto lbl_done

To:
   lbl_winnt_XP:
ReadRegStr $R0 HKLM "SYSTEM\ControlSet001\Control\ProductOptions" ProductSuite
StrCmp $R0 'personal' 0 +3
Strcpy $R0 'XP Home'
Goto lbl_done
Strcpy $R0 'XP Pro'
Goto lbl_done


-Stu

i dont have XP Home here in the office, but i imagine the StrCmp is NOT case sensitive? if it is, i think it should be 'Personal' but i am not sure.


Nope, it's case insensitive.

-Stu


Ok...Doesnt work because of this it is a reg_multi_sz

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\ProductOptions]
"ProductType"="WinNT"
"ProductSuite"=hex(7):50,00,65,00,72,00,73,00,6f,00,6e,00,61,00,6c,00,00,00,00,\
00
any ideas?


lbl_winnt_XP:
ReadRegStr $R5 HKLM "SYSTEM\ControlSet001\Control\ProductOptions" ProductSuite
MessageBox MB_OK "Suite: $R5" IDOK
; StrCmp $R5 'Personal' home_error lbl_done

I think ReadRegDWORD will work instead.

-Stu


I dont have home in the office so i cant check it here, but i dont think that would work. I found this on the wiki http://nsis.sourceforge.net/wiki/REG_MULTI_SZ_Reader but its quite complex and it has a lot of functionality i dont need. i just need the string returned so i can do a strcmp.

thanks


Haven't tested this, but it should work.


!define HKEY_CLASSES_ROOT 0x80000000
!define HKEY_CURRENT_USER 0x80000001
!define HKEY_LOCAL_MACHINE 0x80000002
!define HKEY_USERS 0x80000003
!define HKEY_PERFORMANCE_DATA 0x80000004
!define HKEY_PERFORMANCE_TEXT 0x80000050
!define HKEY_PERFORMANCE_NLSTEXT 0x80000060
!define HKEY_CURRENT_CONFIG 0x80000005
!define HKEY_DYN_DATA 0x80000006

!define KEY_QUERY_VALUE 0x0001
!define KEY_ENUMERATE_SUB_KEYS 0x0008

!define REG_NONE 0
!define REG_SZ 1
!define REG_EXPAND_SZ 2
!define REG_BINARY 3
!define REG_DWORD 4
!define REG_DWORD_LITTLE_ENDIAN 4
!define REG_DWORD_BIG_ENDIAN 5
!define REG_LINK 6
!define REG_MULTI_SZ 7

!define RegOpenKeyEx "Advapi32::RegOpenKeyExA(i, t, i, i, i) i"
!define RegQueryValueEx "Advapi32::RegQueryValueExA(i, t, i, i, i, i) i"
!define RegCloseKey "Advapi32::RegCloseKeyA(i) i"

!define ReadRegMultiSz "!insertmacro ReadRegMultiSz"

!macro ReadRegMultiSz VAR ROOT_KEY SUB_KEY VALUE
Push "${ROOT_KEY}"
Push "${SUB_KEY}"
Push "${VALUE}"
Call ReadRegMultiSz
Pop "${Var}"
!macroend

Function ReadRegMultiSz
Exch $R0
Exch
Exch $R1
Exch 2
Exch $R2
Exch 2
Push $0
Push $1
Push $2
Push $3
StrCpy $0 ""
StrCpy $1 ""
StrCpy $2 ""
StrCpy $3 ""
SetPluginUnload alwaysoff
System::Call "*(i) i (0) .r0"
System::Call "*(i) i (0) .r1"
System::Call "*(i) i (0) .r2"
System::Call "${RegOpenKeyEx}($R2, '$R1', \
0, ${KEY_QUERY_VALUE}|${KEY_ENUMERATE_SUB_KEYS}, r0) .r3"

StrCmp $3 0 goon
DetailPrint "Can't open registry key! ($3)"
Goto done
goon:

System::Call "*$0(&i4 .r4)"
System::Call "${RegQueryValueEx}(r4, '$R0', 0, r1, 0, r2) .r3"

StrCmp $3 0 read
DetailPrint "Can't query registry value! ($3)"
Goto done

read:

System::Call "*$1(&i4 .r3)"

StrCmp $3 ${REG_MULTI_SZ} multisz
DetailPrint "Registry value no SZ_MULTI_SZ! ($3)"
Goto done

multisz:

System::Call "*$2(&i4 .r3)"

StrCmp $3 0 0 multiszalloc
DetailPrint "Registry value empty! ($3)"
Goto done

multiszalloc:

System::Free $1
System::Alloc $3
Pop $1

StrCmp $1 0 0 multiszget
DetailPrint "Can't allocate enough memory! ($3)"
Goto done

multiszget:

System::Call "${RegQueryValueEx}(r4, '${VALUE}', 0, 0, r1, r2) .r3"

StrCmp $3 0 multiszprocess
DetailPrint "Can't query registry value! ($3)[2]"
Goto done

multiszprocess:

StrCpy $4 $1

loop:

System::Call "*$4(&t${NSIS_MAX_STRLEN} .r3)"
StrCmp $3 "" done
StrLen $5 $3
IntOp $4 $4 + $5
IntOp $4 $4 + 1
Goto loop

done:

System::Free $2
System::Free $1

StrCmp $0 0 noClose
System::Call "${RegCloseKey}(r0)"

noClose:

SetPluginUnload manual
System::Free $0
StrCpy $R0 $3

Pop $3
Pop $2
Pop $1
Pop $0
Pop $R2
Pop $R1
Exch $R0
FunctionEnd


You might want to put it all in a seperate .nsh file and !include it.

Usage:
${ReadRegMultiSz} $R0 HKLM "Software\Blah" "BlahBlah"

You should try ReadRegStr and only if that fails, call this function (e.g. IfErrors is set - make sure to use ClearErrors before hand).

-Stu

hmm we're getting warmer

1 warning:
unknown variable/constant "{VALUE}" detected, ignoring (registry.nsh:100)

;;;line 100 below label
multiszget:

System::Call "${RegQueryValueEx}(r4, '${VALUE}', 0, 0, r1, r2) .r3"

this is how i called it, maybe thats why

lbl_winnt_XP:
${ReadRegMultiSz} $R5 HKLM "SYSTEM\ControlSet001\Control\ProductOptions" "ProductSuite"
StrCmp $R5 'Personal' home_error lbl_done


Sorry, missed a replacement.
In the code above, ${VALUE} should be $R0

-Stu


I apologise for not getting back sooner, I was unable to get to a test computer with home edition (apparently ms wont allow you to change the null sring to Personal if i use professional (odd as it should be the other way around).

However, my installer still allowed me to install on a home install. everything else works fine except for home. i reckon this shouldnt be a problem as i can just leave it as is.

in an earlier post in this thread someone mentions using the system call to kernel32, maybe thats the best way, as it uses a function that does just that instead? but i dont know how to make use of that function, esp in my function i currently use.


how to diff b/w win2003 and win2003R2.....question related to the originalpost
how to diff b/w win2003 and win2003R2