Old 15th June 2015, 10:26   #41
th_mi
Member
 
Join Date: Sep 2005
Location: Sitting next to my desk
Posts: 56
Quote:
Originally Posted by LoRd_MuldeR View Post
(The new solution doesn't depend on some obscure GUID that's guaranteed to break with the next Windows version, but uses GetFileVersionInfo() directly on kernel32.dll. Yes, it's ugly, but it works. If, in the next Windows version - provided that there will be a next Windows version - they break GetFileVersionInfo() too or they ship a kernel32.dll with "wrong" version number in its resource section, I'll just throw my Windows PC out of the window)
I use this way to identify the OS Version since Win8/8.1. In case they asl obreak this way I'll do the Windows API way. Until today every Windows Version brings new API commands. A new version has a few new APIs, it is also a try to use LoadLibrary/GetProceAddress to find out what API exist on what OS...

But I agree it is getting more and more strange at all...

This signature is currently on vacation!
th_mi is offline   Reply With Quote
Old 16th June 2015, 11:30   #42
LoRd_MuldeR
Major Dude
 
LoRd_MuldeR's Avatar
 
Join Date: Sep 2005
Location: Somewhere over the Slaughterhouse
Posts: 797
Quote:
Originally Posted by Anders View Post
It is not a invalid result, it is just that your app is running in compatibility mode. If you include the GUID for Windows 10 today in 2015 then your app is supposed to work without changes on Windows 11 assuming you are not doing undocumented stuff. It is of course impossible to test on Windows 11 now so your app is just supposed to pretend that it is still on 10 which is why the API lies.
IMO, if my application uses only documented functions and only relies on documented behavior, there will be no need for any "compatibility mode" at all! It will continue to work perfectly fine in future Windows versions without "compatibility" hacks or workarounds – provided that M$ doesn't intentionally break the documented behavior, of course. There would be some use case for "compatibility mode", if a broken application relies on undocumented behavior (or even bugs) that existed in earlier Windows versions, but not in the current one. But in this case we should rather fix the broken application than implementing workarounds that only encourage people to rely on undocumented stuff.

Actually, the "enforced compatibility mode" has great potential to breaking things. If, e.g., my application relies on the correct documented behavior of GetVersionEx(), it will stop working in Windows 8.1. So, following the M$ method, I will need to "fix" my application by adding the required GUID. But on Windows 10 it will break, once again. And I will need to "fix" my application, once again. For every new Windows version I will have to "fix" my application – again and again! Without all the "compatibility" mess and if they do not mindlessly break existing documented behavior, the very same binary that was originally compiled for Windows XP could still be working perfectly fine in Windows 10.

BTW: If I want to accurately emulate the behavior of Windows N on Windows N+1, there is a solution known for decades - virtualization.

Quote:
Originally Posted by Anders View Post
Your are not really supposed to check the version number anyway, you are supposed to check if a feature exists before using it or whatever fallback mode you might have. Granted, it sucks for logs etc but MS has decided that compatibility for crappy programs is more important than keeping developers happy...
The operating system provides services to the application. So the job of the OS is to correctly implement these services. If and how the application makes use of these services - the OS doesn't need to care! I decide what I do with the version number in my program. Microsoft's job is to give me the correct number – not more, not less. If the application does something stupid, it's the problem of this application. And it can only be properly fixed inside that particular application. Microsoft's sphere of influence must end at the application boundary.

Really, you can't punish every application out there, just because a few applications do stupid things. If at all, the "compatibility" hacks must be optional (disabled by default!), so they can be enabled if and only if they are actually needed and/or helpful. Heck, if they think users are too dumb for enabling compat mode themselves, they could have implemented a Blacklist for known "broken" applications.

Quote:
Originally Posted by th_mi View Post
I use this way to identify the OS Version since Win8/8.1. In case they asl obreak this way I'll do the Windows API way. Until today every Windows Version brings new API commands. A new version has a few new APIs, it is also a try to use LoadLibrary/GetProceAddress to find out what API exist on what OS...
I have been experimenting with this method too. The problem here is: You can only distinguish Windows versions that already existed by the time when you program was compiled. You can not detect future versions, as you don't know which new API's they are going to add or which NT version the next Windows will have. From this point of view, your solution has the same limitation as the "GUID" workaround.

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 June 2015, 13:03   #43
Afrow UK
Moderator
 
Afrow UK's Avatar
 
Join Date: Nov 2002
Location: Surrey, England
Posts: 8,434
I'm still a little confused as to what the issue is here. If you need to detect that you are running Windows 10, add the GUID. Otherwise on Windows 10 as far as your app knows it is running on Windows 8.1. Why is this such a big issue?

I can see this being an issue for logging or reporting purposes but surely it's not difficult to add the GUID and send out an updated version of your app? That is the only case that there is an issue and it is a very minor one.

Also I'm not sure how this "punishes" the application by giving it the false version. As I've said before, the app will not support newer Windows 10 features until you add them anyway - at which point you can add the GUID...

Stu
Afrow UK is offline   Reply With Quote
Old 16th June 2015, 13:21   #44
DrO
 
Join Date: Sep 2003
Posts: 27,873
as for not working with newer OS features, most cases you need to update to support the newer OS so then adding the guid at that point is a non-issue imho.

tbh the argument that comes across is almost like "why should I have to keep updating things". and with the compatibility issues, MS can also insert a shim to correct / revert things if needed (often without you knowing about it in the first place) so that's a bit of a non-issue as well.

sure it's not great if the OS changes things but it's not just an issue specific to Windows and any developed system can 'break' things or change the rules (which am sure are not changed unless there's a reason to do so).

either way, I can why for some cases it's not great about this change, then again just magically expecting things to work like before is a bit naive and I don't mind the guid aspect as it's not like things with Windows haven't changed / been broken before and any change in OS means having to do some sort of update if you really need to know the OS version anyway (as how can you magically know in advance the name for the OS?).

if anything, a reliance on the OS version for identification is an old way of thinking about things (yes I know it'd be needed to gauge what OS a crash report comes from) but the more web-like way of querying for functionality than assuming it on the OS is better imho (and is something that has definitely been needed since XP such as for SP2 vs SP3 additions).
DrO is offline   Reply With Quote
Old 16th June 2015, 18:54   #45
LoRd_MuldeR
Major Dude
 
LoRd_MuldeR's Avatar
 
Join Date: Sep 2005
Location: Somewhere over the Slaughterhouse
Posts: 797
Quote:
Originally Posted by Afrow UK View Post
I'm still a little confused as to what the issue is here. If you need to detect that you are running Windows 10, add the GUID. Otherwise on Windows 10 as far as your app knows it is running on Windows 8.1. Why is this such a big issue?
If you are only interested to get the correct result on Windows versions that existed by the time when you compiled your program, the GUID method can work for you. It's an extra burden for the developer, but works. But as soon as you want to ensure that your program will still get correct result on future Windows versions – and I mean without having to modify/rebuild the program – the GUID method can not work.

Now you can say: "I don't care about future OS versions" or "getting the correct version isn't all that important for me". But for some people it is! Suppose I have shipped a program 6 months ago and today I get a bug report from a customer. If the log file says "Windows 8.1" this could mean he really is on "Windows 8.1", but it could also means he is on "Windows 10" (because the info in the log is wrong). Of course I need to know the exact system specification to try to replicate his problem! So I will have to ask him what OS he really uses. Now suppose he is located on the opposite side of the globe. Means I will have to wait (at least) until the next workday to get an answer. Thank you M$!

---

Also there is another very important point: Very often you are writing library code! This means you can not influence the Manifest of the program, which will contain your code, at all! And, in my experience, most program files don't contain any of these compatibility GUID's – programmers barely know that such thing exists. So, for library code, you have to assume that no particular GUID will be included in the program. Therefore, you won't even be able to distinguish those Windows versions that exited by the time you created your code !!!

Quote:
Also I'm not sure how this "punishes" the application by giving it the false version.
They have intentionally crippled the version getter API (make it report the wrong result), because they think a few programs used it to do something that Microsoft didn't "intend". Who do they think they are to tell programmers what they are supposed to do? Anyway, instead of just "blacklisting" the few programs that were effected by this "problem", they crippled the entire version API, for all applications.

Quote:
As I've said before, the app will not support newer Windows 10 features until you add them anyway - at which point you can add the GUID...
The program now needs to be modified in order to "support" Windows 10 (i.e. get the correct results under Windows 10), because M$ has intentionally broken the documented behavior of the Win32 API. And the program will have to be modified – again and again – for every new Windows version. If, on the other hand, they hadn't done this act of mental deficiency, any program compiled for Windows XP that only uses documented functions and only relies on documented behavior, would probably still work correctly on Windows 10 today.

---

I will not try to further convince you that it's important to have a reliable method to detect the exact OS version that we are running on – current and future. But I surely need this functionality. And it appears a lot of other people do too. So whoever finds the GetRealOSVersion and GetRealOSName functions useful may use them – now on Windows 10 too. The rest of the world can just happily ignore them

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

Last edited by LoRd_MuldeR; 16th June 2015 at 21:00.
LoRd_MuldeR is offline   Reply With Quote
Old 20th June 2015, 15:02   #46
Lenge
Member
 
Join Date: Oct 2007
Posts: 64
As already stated, I agree with LoRd_MuldeR on this topic in any and all possible ways. If I need to determine the exact real version that my app is running on a regular basis, I do so for a reason, and I need a way to do so that is not influenced by some compatibility hack that Microsoft created for certain OS versions.

So I am glad that that the GetRealOSVersion function exists, and I hope that it'll be updated if Microsoft should break their own documented APIs again.
Lenge is offline   Reply With Quote
Old 20th June 2015, 16:41   #47
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
So I am glad that that the GetRealOSVersion function exists, and I hope that it'll be updated if Microsoft should break their own documented APIs again.
As long as GetRealOSVersion needs to be updated for each new Windows version, it's not really better than the GUID workaround. Okay, GetRealOSVersion can work inside libraries too, which is impossible for the GUID method (by design). But the actual plan is to find something that will continue to work in future Windows version without modification. So far, Microsoft is leading 1:0, but we'll see

My Plugins: StdUtils | NSISList | CPUFeatures | ExecTimeout | KillProc
My source of inspiration: http://youtu.be/lCwY4_0W1YI
LoRd_MuldeR is offline   Reply With Quote
Old 22nd June 2015, 16:19   #48
Lenge
Member
 
Join Date: Oct 2007
Posts: 64
BTW: Now that GetRealOSVersion, GetRealOSName, and VerifyOSVersion work correctly again on all (yet-released) Windows versions (thanks again!), what is the current state of GetRealOSBuildNo and VerifyOSBuildNo? I guess that is not as easy to fix, right?
Lenge is offline   Reply With Quote
Old 22nd June 2015, 18:36   #49
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
BTW: Now that GetRealOSVersion, GetRealOSName, and VerifyOSVersion work correctly again on all (yet-released) Windows versions (thanks again!), what is the current state of GetRealOSBuildNo and VerifyOSBuildNo?
Internally, all these functions are just "wrappers" around the very same "core" function. And this "core" function reveals the real OS version by first retrieving the "fake" version via GetVersionEx() and then refining the result via an iterative algorithm based on VerifyVersionInfo(). And now it additionally compares the detected version with the file version of KERNEL32.DLL in order to "repair" the result on Windows 10 too. This all works the exactly same way for the "major" and "minor" NT versions as well as for the "build" number. It's simply different parts of the same intermediate result. However, I wonder what will happen when they exceed build #65535, because that's the highest number that can be represented as a 16-Bit value - and the part of the KERNEL32.DLL version that they use for the build number is only 16-Bit in size!

BTW: GetRealOSName naturally cannot give you the correct name of future Windows version, because this name is not even decided yet. Still it should return "unknown" instead of returning an invalid Windows version, like GetVersionEx() would do - and knowing that you are actually running on some unknown OS version (by the time your product was released) can already be a valuable information, I think.

My Plugins: StdUtils | NSISList | CPUFeatures | ExecTimeout | KillProc
My source of inspiration: http://youtu.be/lCwY4_0W1YI
LoRd_MuldeR is offline   Reply With Quote
Old 23rd June 2015, 17:28   #50
Lenge
Member
 
Join Date: Oct 2007
Posts: 64
Ok, thanks for the detailed information. This is exactly what I was looking for: So, on a future OS, I will still receive the correct major/minor version and build number regardless of any compatibility mode that might be in effect (at least until MS breaks things again). Of course the OS name cannot be known in advance, so "unknown" is a good choice.
Lenge is offline   Reply With Quote
Old 24th June 2015, 06:56   #51
Afrow UK
Moderator
 
Afrow UK's Avatar
 
Join Date: Nov 2002
Location: Surrey, England
Posts: 8,434
You could read version information from HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion (SetRegView 64) if that is sufficient as a last resort.

Edit: Or WMI of course...
wmic os get caption

Stu
Afrow UK is offline   Reply With Quote
Old 14th May 2016, 13:56   #52
LoRd_MuldeR
Major Dude
 
LoRd_MuldeR's Avatar
 
Join Date: Sep 2005
Location: Somewhere over the Slaughterhouse
Posts: 797
Here is a new version of StdUtils, which contains an improved GetRealOSVersion function:
https://github.com/lordmulder/stduti...eases/tag/1.10

This one no longer relies on investigating the file version of KERNEL32.DLL to detect Windows 10+. Does not rely on WMI (COM) or dubious Registry hacks either. Instead we call the "native" RtlGetVersion() function directly, instead of the "crippled" equivalent.

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 May 2016, 14:45   #53
Anders
Moderator
 
Anders's Avatar
 
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 5,163
FYI RtlGetVersion is affected by the compatibility tab so it might not report the real version.

IntOp $PostCount $PostCount + 1
Anders is offline   Reply With Quote
Old 14th May 2016, 17:02   #54
LoRd_MuldeR
Major Dude
 
LoRd_MuldeR's Avatar
 
Join Date: Sep 2005
Location: Somewhere over the Slaughterhouse
Posts: 797
Quote:
Originally Posted by Anders View Post
FYI RtlGetVersion is affected by the compatibility tab so it might not report the real version.
In my test, "compatibility mode" was unable to spoil the result. You can test with:
RealOSVersion.2016-05-14.zip

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 May 2016, 19:33   #55
Anders
Moderator
 
Anders's Avatar
 
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 5,163
If it is not affected, why do you bother looping with VerifyVersionInfo?

Anyway, I have seen RtlGetVersion on Vista SP2 return 5.1.2600 if you set compatibility to XP (don't remember if AcLayers was involved though).

On Windows 8 RtlGetVersion returns the correct value but then a hook overwrites parts of the result:
Quote:
call dword ptr [eax+54h] ds:002b:0056dfe4={ntdll!RtlGetVersion (77bf8b69)}
mov edi,eax
test edi,edi
js AcLayers!NS_WinXPSP3VersionLie::APIHook_RtlGetVersion+0x91 (5fc07c04)
cmp dword ptr [esi],11Ch
mov dword ptr [esi+4],5
mov dword ptr [esi+8],1
mov dword ptr [esi+0Ch],0A28h
mov dword ptr [esi+10h],2
and it got hooked because GetProcAddress is actually AcLayers!NS_WRPDllRegister::APIHook_GetProcAddress.



PHP Code:
System::Call '*(&l4,i,i,i,i,&w128,i,i)p.r0'
System::Call 'KERNEL32::LoadLibrary(t "NTDLL")p.s'
System::Call 'KERNEL32::GetProcAddress(ps, m "RtlGetVersion")p.r9'
IntFmt $"0x%p" $9
System
::Call 'KERNEL32::GetModuleHandleEx(i4,pr9,*p0r8)'
System::Call 'KERNEL32::GetModuleFileName(pr8,t.r7,i999)'
DetailPrint "RtlGetVersion=$9 is in $7"
System::Call '::$9(pr0)'
System::Call '*$0(i,i.r1,i.r2)'
System::Free $0
DetailPrint 
$1.$

IntOp $PostCount $PostCount + 1
Anders is offline   Reply With Quote
Old 15th May 2016, 18:38   #56
LoRd_MuldeR
Major Dude
 
LoRd_MuldeR's Avatar
 
Join Date: Sep 2005
Location: Somewhere over the Slaughterhouse
Posts: 797
Quote:
Originally Posted by Anders View Post
If it is not affected, why do you bother looping with VerifyVersionInfo?
Because it is still required under some circumstances.

Windows 10 without compat mode:
http://pastie.org/10838499

Windows 10 with Win9x compat mode:
http://pastie.org/10838500

Windows 10 with WinXP compat mode:
http://pastie.org/10838502

In the last case even RtlGetVersion() lies, but RtlVerifyVersionInfo can reveal the expected result.

RealOSVersion.2016-05-15.zip

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 May 2016, 13:04   #57
Anders
Moderator
 
Anders's Avatar
 
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 5,163
RtlVerifyVersionInfo probably helps because its internal call to RtlGetVersion is not hooked, this might change in the future of course because MS will discover that people are doing this. Our only hope is that it is a layering violation for NTDLL to call back up to the shim dll's so they might let this one slide, fingers crossed...

IntOp $PostCount $PostCount + 1
Anders is offline   Reply With Quote
Old 17th May 2016, 12:35   #58
th_mi
Member
 
Join Date: Sep 2005
Location: Sitting next to my desk
Posts: 56
Quote:
Originally Posted by Anders View Post
RtlVerifyVersionInfo probably helps because its internal call to RtlGetVersion is not hooked, this might change in the future of course because MS will discover that people are doing this.
No RtlGetVersion is not an "internal" function. It is a well documented part of the Windows Driver Support routines:
https://msdn.microsoft.com/en-us/lib...(v=vs.85).aspx
https://msdn.microsoft.com/en-us/lib...(v=vs.85).aspx

From what I remember this functions did not changed since eons. Currently I also do not expect this functions will be changed, Microsoft will surely not making the driver development more difficuilt. And since most drivers are capable to be used on more than one OS this functions are very essential for driver development.

This signature is currently on vacation!
th_mi is offline   Reply With Quote
Old 17th May 2016, 14:23   #59
Anders
Moderator
 
Anders's Avatar
 
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 5,163
Quote:
Originally Posted by th_mi View Post
No RtlGetVersion is not an "internal" function. It is a well documented part of the Windows Driver Support routines:
Where did I say that RtlGetVersion is an internal function? The RtlVerifyVersionInfo implementation calls RtlGetVersion to get the version info it uses when comparing the fields. Because this call happens inside ntdll it is not affected by the compatibility hooking that is forced on you when calling RtlGetVersion in your own code.

Quote:
Originally Posted by th_mi View Post
Microsoft will surely not making the driver development more difficuilt. And since most drivers are capable to be used on more than one OS this functions are very essential for driver development.
While some functions exist both in kernel and user mode they don't have to share the same implementation. It would be possible for ntdll!RtlGetVersion to lie without affecting drivers! RtlGetVersion is only documented for driver use, the user mode version is technically undocumented and could even go away in the future.

IntOp $PostCount $PostCount + 1
Anders is offline   Reply With Quote
Old 18th May 2016, 20:20   #60
Anders
Moderator
 
Anders's Avatar
 
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 5,163
And as a cruel joke, here I'm breaking your GetRealOSVersion detection:






@th_mi: Oh look, the user-mode implementation is not the same as the kernel implementation!
Attached Files
File Type: zip TrickRealVer.zip (61.4 KB, 124 views)

IntOp $PostCount $PostCount + 1
Anders is offline   Reply With Quote
Old 18th May 2016, 20:37   #61
LoRd_MuldeR
Major Dude
 
LoRd_MuldeR's Avatar
 
Join Date: Sep 2005
Location: Somewhere over the Slaughterhouse
Posts: 797
Quote:
Originally Posted by Anders View Post
Unless is this made-up, what exactly did trigger this? (looks like Windows 8)

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 May 2016, 22:06   #62
Anders
Moderator
 
Anders's Avatar
 
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 5,163
Quote:
Originally Posted by LoRd_MuldeR View Post
Unless is this made-up, what exactly did trigger this? (looks like Windows 8)
It is a real screenshot of the program I attached in my post and it is just a really basic NSIS script. The screenshot is from Windows 8 but you should get the same result on any Windows version >= Win2000 AFAIK. I did not modify your plug-in in any way but I did some hex editing on the NSIS stub. If you add a IMAGE_LOAD_CONFIG_DIRECTORY32 entry you should be able to change the service pack number as well...

IntOp $PostCount $PostCount + 1
Anders is offline   Reply With Quote
Old 10th October 2016, 23:13   #63
Lenge
Member
 
Join Date: Oct 2007
Posts: 64
Besides: Is StdUtils still able to extract the real OS version even if Microsoft now also fakes file version information?

See: http://forums.winamp.com/showpost.ph...38&postcount=7
Lenge is offline   Reply With Quote
Old 11th October 2016, 07:59   #64
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
Besides: Is StdUtils still able to extract the real OS version even if Microsoft now also fakes file version information?
Latest StdUtils version should be able, yes. Provided that you don't mess with the PE header

My Plugins: StdUtils | NSISList | CPUFeatures | ExecTimeout | KillProc
My source of inspiration: http://youtu.be/lCwY4_0W1YI
LoRd_MuldeR 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