Old 12th March 2014, 18:00   #1
Lenge
Member
 
Join Date: Oct 2007
Posts: 64
Windows version detection reloaded

In generalization of the Windows 8.1 detection issues, I have examined the WinVer.nsh and StdUtils.GetRealOSVersion functions under various compatibility mode settings. Some results:
  • On a WinXP-32-SP3 host, the "Windows NT 4.0 (Service Pack 5)" compatibility mode makes WinVer.nsh detect Windows NT 4.0 with Service Pack 3 (instead of 5).
  • On a Win7-64-SP1 host, the same compatibility mode makes WinVer.nsh detect Windows NT 4.0 with Service Pack 5 (as expected).
  • On a Win7-64-SP1 host, the "Windows Server 2003" and "Windows Server 2008" compatibility modes make WinVer.nsh detect non-server versions (WinXP and Vista).
Not sure if these are shortcomings of the respective compatibility modes, the GetVersionEx API, or anything specific to WinVer.nsh. But it obviously fails to reliably detect the exact Windows version it is intended to see by the compatibility mode setting.

StdUtils.GetRealOSVersion aims to detect the "real" Windows version, regardless of any compatibility mode setting or any potentially missing OS support GUIDs in the application manifest. In my tests, the function mostly delivers on that promise, with the following exceptions:
  • On both WinXP-32-SP3 and Win7-64-SP1 hosts, the "Windows 95" and "Windows 98 / Windows Me" compatibility modes make StdUtils.GetRealOSVersion deliver "error" strings instead of the real Windows version.
  • StdUtils currently delivers "real" major and minor version numbers, but neither the "real" build number nor the "real" Service Pack number.
@Mulder: Any chance of according enhancements to StdUtils?
Lenge is offline   Reply With Quote
Old 13th March 2014, 23:29   #2
Anders
Moderator
 
Anders's Avatar
 
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 5,321
Windows 8 does not list server versions!

You can try this:
Quote:
System::Call '*(i284,i,i,i,i,&w128,i0,i0)p.r0'
System::Call 'kernel32::GetVersionExW(pr0)i.r9'
System::Call '*$0(i,i.r1,i.r2,i.r3,i,&w128,&i2.r4,&i2,&i2.r5,&i1.r6)'
DetailPrint $9=$1,$2,$3|SP=$4|SuiteMask=$5|Product=$6

IntOp $PostCount $PostCount + 1
Anders is offline   Reply With Quote
Old 14th March 2014, 02:46   #3
LoRd_MuldeR
Major Dude
 
LoRd_MuldeR's Avatar
 
Join Date: Sep 2005
Location: Somewhere over the Slaughterhouse
Posts: 797
Quote:
Originally Posted by Lenge View Post
[*]On both WinXP-32-SP3 and Win7-64-SP1 hosts, the "Windows 95" and "Windows 98 / Windows Me" compatibility modes make StdUtils.GetRealOSVersion deliver "error" strings instead of the real Windows version.[*]StdUtils currently delivers "real" major and minor version numbers, but neither the "real" build number nor the "real" Service Pack number.[/LIST]@Mulder: Any chance of according enhancements to StdUtils?
GetRealOSVersion() was written primarily to get the real Windows version on Windows 8.1+. It's more a side-effect that it also works around compatibility mode. Therefore it will only work when a Windows NT based system is found - Windows 9x didn't even have the required API's. The "Windows 9x" compatibility mode probably makes GetVersionEx() to report a Non-NT system - so the current code won't go on and fail right away. But I will have to analyze that more closely. As long as VerifyVersionInfo() still behaves correctly with "Windows 9x" compatibility mode enabled, a workaround should be possible. Also I think checks for the service pack version could be added, if required.

My Plugins: StdUtils | NSISList | CPUFeatures | ExecTimeout | KillProc
My source of inspiration: http://youtu.be/lCwY4_0W1YI
LoRd_MuldeR is offline   Reply With Quote
Old 14th March 2014, 08:24   #4
Lenge
Member
 
Join Date: Oct 2007
Posts: 64
Quote:
Originally Posted by LoRd_MuldeR View Post
As long as VerifyVersionInfo() still behaves correctly with "Windows 9x" compatibility mode enabled, a workaround should be possible. Also I think checks for the service pack version could be added, if required.
That would be great; thanks for your effort on such a useful plugin!
Lenge is offline   Reply With Quote
Old 14th March 2014, 17:02   #5
LoRd_MuldeR
Major Dude
 
LoRd_MuldeR's Avatar
 
Join Date: Sep 2005
Location: Somewhere over the Slaughterhouse
Posts: 797
Here is a test version with "Win9x compat mode" workaround:
http://sourceforge.net/projects/muld...4.zip/download

My Plugins: StdUtils | NSISList | CPUFeatures | ExecTimeout | KillProc
My source of inspiration: http://youtu.be/lCwY4_0W1YI
LoRd_MuldeR is offline   Reply With Quote
Old 15th March 2014, 14:03   #6
Lenge
Member
 
Join Date: Oct 2007
Posts: 64
Quote:
Originally Posted by LoRd_MuldeR View Post
Here is a test version with "Win9x compat mode" workaround:
http://sourceforge.net/projects/muld...4.zip/download
Thanks! I can confirm that this version now also works in the "Windows 95" and "Windows 98 / Windows Me" compatibility modes on a WinXP-32-SP3 host! (It'll take a while until I'll be able to also check the Win7-64-SP1 host.)

Would be great if you'd find a way to also verify the "real" service pack numbers and build numbers.
Lenge is offline   Reply With Quote
Old 15th March 2014, 14:12   #7
Lenge
Member
 
Join Date: Oct 2007
Posts: 64
Quote:
Originally Posted by Anders View Post
Windows 8 does not list server versions!
Win7-64 does. There are compatibility modes called "Windows Server 2003" and "Windows Server 2008". However, these modes make WinVer.nsh detect Windows XP and Vista instead of the server versions.

Quote:
Originally Posted by Anders View Post
You can try this: (...)
The second line - System::Call 'kernel32::GetVersionExW(pr0)i.r9' - seems to instantaneously quit the installer exe on my WinXP-32-SP3 host. The effect is fully reproducible, so I cannot try further. Am I doing something wrong or do I need a 64-bit host to try this approach?
Lenge is offline   Reply With Quote
Old 15th March 2014, 14:20   #8
Anders
Moderator
 
Anders's Avatar
 
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 5,321
Quote:
Originally Posted by Lenge View Post
The second line - System::Call 'kernel32::GetVersionExW(pr0)i.r9' - seems to instantaneously quit the installer exe on my WinXP-32-SP3 host. The effect is fully reproducible, so I cannot try further. Am I doing something wrong or do I need a 64-bit host to try this approach?
No, but you need to use NSIS 3. Change all the p's to i's for 2.4x. Anyway, when I tested it but setting it to a server manually it just reported the product as NT workstation so there might be a bug in Windows there.

IntOp $PostCount $PostCount + 1
Anders is offline   Reply With Quote
Old 16th March 2014, 12:54   #9
LoRd_MuldeR
Major Dude
 
LoRd_MuldeR's Avatar
 
Join Date: Sep 2005
Location: Somewhere over the Slaughterhouse
Posts: 797
I noticed there is a "major" and "minor" service pack number:
code:
WORD wServicePackMajor;
WORD wServicePackMinor;



Does anybody know whether the "minor" number has ever been actually used for something?

My Plugins: StdUtils | NSISList | CPUFeatures | ExecTimeout | KillProc
My source of inspiration: http://youtu.be/lCwY4_0W1YI

Last edited by LoRd_MuldeR; 16th March 2014 at 14:06.
LoRd_MuldeR is offline   Reply With Quote
Old 16th March 2014, 14:03   #10
LoRd_MuldeR
Major Dude
 
LoRd_MuldeR's Avatar
 
Join Date: Sep 2005
Location: Somewhere over the Slaughterhouse
Posts: 797
Here is a new test version that has Service Pack detection enabled:
http://sourceforge.net/projects/muld...6.zip/download

Only the "major" service pack version is returned currently, but I think that is sufficient.

My Plugins: StdUtils | NSISList | CPUFeatures | ExecTimeout | KillProc
My source of inspiration: http://youtu.be/lCwY4_0W1YI
LoRd_MuldeR is offline   Reply With Quote
Old 16th March 2014, 17:04   #11
Anders
Moderator
 
Anders's Avatar
 
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 5,321
I don't think the service pack minor has ever been used so that is probably safe...

IntOp $PostCount $PostCount + 1
Anders is offline   Reply With Quote
Old 17th March 2014, 17:28   #12
Lenge
Member
 
Join Date: Oct 2007
Posts: 64
Quote:
Originally Posted by LoRd_MuldeR View Post
Here is a new test version that has Service Pack detection enabled: [...]
Great, thanks! Any chances for also checking the Windows build number?
Quote:
Originally Posted by LoRd_MuldeR View Post
Only the "major" service pack version is returned currently, but I think that is sufficient.
The additional "minor" Service Pack number has been around for a long time (Windows 2000 or so), but I am not aware of any release that actually used the "minor" number.
Lenge is offline   Reply With Quote
Old 17th March 2014, 20:39   #13
LoRd_MuldeR
Major Dude
 
LoRd_MuldeR's Avatar
 
Join Date: Sep 2005
Location: Somewhere over the Slaughterhouse
Posts: 797
I probably could add the build number too. But what do you need the build number for?

To my understanding, each Windows NT version (and for some NT version also each Service Pack) has a corresponding build number. So the build number doesn't rally give you any additional benefit over knowing the NT version plus the Service Pack version, right?

Also, using the VerifyVersionInfo "trick" will probably be much more inefficient with such large values, as used for the build numbers...

My Plugins: StdUtils | NSISList | CPUFeatures | ExecTimeout | KillProc
My source of inspiration: http://youtu.be/lCwY4_0W1YI
LoRd_MuldeR is offline   Reply With Quote
Old 17th March 2014, 21:18   #14
Anders
Moderator
 
Anders's Avatar
 
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 5,321
Win95 and NT 4 are both 4.0 but then you can check for NT vs 9x, the only place it matters is for 98 vs 98 SE. Starting with Vista the service pack is part of the build number as well...

IntOp $PostCount $PostCount + 1
Anders is offline   Reply With Quote
Old 17th March 2014, 21:39   #15
LoRd_MuldeR
Major Dude
 
LoRd_MuldeR's Avatar
 
Join Date: Sep 2005
Location: Somewhere over the Slaughterhouse
Posts: 797
GetRealOSVersion() will fail, if a pre-NT system is detected, because it's technically impossible to run StdUtils.dll on systems prior to Windows NT. That's because some of the API's it uses, like VerifyVersionInfo(), were not even available on Win 9x.

Consequently I think the build number doesn't give any additional info over the Windows NT version plus the Service Pack number.

(I can still add detection of the build number, for purely informational purpose)

My Plugins: StdUtils | NSISList | CPUFeatures | ExecTimeout | KillProc
My source of inspiration: http://youtu.be/lCwY4_0W1YI
LoRd_MuldeR is offline   Reply With Quote
Old 18th March 2014, 02:36   #16
Lenge
Member
 
Join Date: Oct 2007
Posts: 64
Quote:
Originally Posted by LoRd_MuldeR View Post
I probably could add the build number too. But what do you need the build number for?
Please do so, at least for the VerifyOSVersion function. My current usage is verifying the version info reported by WinVer.nsh against the "real" OS version. At the moment WinVerGetMajor, WinVerGetMinor and WinVerGetServicePackLevel can be verified using StdUtils.VerifyOSVersion, but WinVerGetBuild cannot.

Quote:
Originally Posted by LoRd_MuldeR View Post
Also, using the VerifyVersionInfo "trick" will probably be much more inefficient with such large values, as used for the build numbers...
Probably true, at least for GetRealOSVersion. But I was more thinking of adding the build number to VerifyOSVersion, which should hopefully be more straightforward.
Lenge is offline   Reply With Quote
Old 18th March 2014, 23:12   #17
LoRd_MuldeR
Major Dude
 
LoRd_MuldeR's Avatar
 
Join Date: Sep 2005
Location: Somewhere over the Slaughterhouse
Posts: 797
Okay, I have implemented a halfway efficient way to detect the real Windows build number.

New test version here:
http://sourceforge.net/projects/muld...9.zip/download

My Plugins: StdUtils | NSISList | CPUFeatures | ExecTimeout | KillProc
My source of inspiration: http://youtu.be/lCwY4_0W1YI
LoRd_MuldeR is offline   Reply With Quote
Old 19th March 2014, 01:11   #18
Lenge
Member
 
Join Date: Oct 2007
Posts: 64
Quote:
Originally Posted by LoRd_MuldeR View Post
Okay, I have implemented a halfway efficient way to detect the real Windows build number. New test version here: [...]
According to my first set of test runs, it seems to work both reliably and acceptably fast. You rock!
Lenge is offline   Reply With Quote
Reply
Go Back   Winamp & Shoutcast Forums > Developer Center > NSIS Discussion

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump