{"id":95175,"date":"2017-01-12T07:00:00","date_gmt":"2017-01-12T22:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/?p=95175"},"modified":"2019-03-13T01:04:24","modified_gmt":"2019-03-13T08:04:24","slug":"20170112-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20170112-00\/?p=95175","title":{"rendered":"How do I detect Windows 10 if I cannot GetProcAddress for the function IsWindows10OrGreater?"},"content":{"rendered":"<p>A customer wanted to use the handy functions provided in the <code>Version&shy;Helpers.h<\/code> header file, like <code>Is&shy;Windows&shy;10&shy;Or&shy;Greater<\/code>, while maintaining the same source code for both Windows 7 and Windows 10 targets. Their plan was to <code>Load&shy;Library<\/code> for <code>kernel32.dll<\/code>, and then <code>Get&shy;Proc&shy;Address<\/code> for <code>Is&shy;Windows&shy;10&shy;Or&shy;Greater<\/code>, but they found that the <code>Get&shy;Proc&shy;Address<\/code> call always failed, even on Windows 10. They looked in <code>kernelbase.dll<\/code> and <code>ntdll.dll<\/code>; no luck there either. How is it possible that Windows 10 doesn&#8217;t know whether it is Windows 10? <\/p>\n<p>The customer investigated further and found that when their test program called <code>Is&shy;Windows&shy;10&shy;Or&shy;Greater<\/code>, there was no call to <code>Load&shy;Library<\/code> at all! <\/p>\n<pre>\n0:000&gt; k\n# ChildEBP RetAddr  \n00 0133f9fc 00c01806 ntdll!VerSetConditionMask+0x14\n01 0133fc2c 00c01739 Test!IsWindowsVersionOrGreater+0xa6 \n02 0133fd0c 00c01a33 Test!IsWindows10OrGreater+0x29\n03 0133fe10 00c022be Test!main+0x23\n04 0133fe24 00c02120 Test!invoke_main+0x1e\n05 0133fe7c 00c01fbd Test!__scrt_common_main_seh+0x150\n06 0133fe84 00c022d8 Test!__scrt_common_main+0xd\n07 0133fe8c 77a962c4 Test!mainCRTStartup+0x8\n08 0133fea0 77bd0609 KERNEL32!BaseThreadInitThunk+0x24\n09 0133fee8 77bd05d4 ntdll!__RtlUserThreadStart+0x2f\n0a 0133fef8 00000000 ntdll!_RtlUserThreadStart+0x1b\n<\/pre>\n<p>The customer wanted to know how to call functions like <code>Is&shy;Windows&shy;10&shy;Or&shy;Greater<\/code> dynamically. <\/p>\n<p>The reason the customer cannot find the function <code>Is&shy;Windows&shy;10&shy;Or&shy;Greater<\/code> in <code>kernel32.dll<\/code> or any other DLL is simple: <a HREF=\"http:\/\/tvtropes.org\/pmwiki\/pmwiki.php\/main\/itwaswithyouallalong\">The function was inside you all along<\/a>. <\/p>\n<p>The functions in the <code>Version&shy;Helpers.h<\/code> header file are all inline functions. They are not exported anywhere. These functions do the grunt work of figuring out the operating system so you don&#8217;t have to write the version detection code yourself (and invariable <a HREF=\"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/20040213-00\/?p=40633\">mess up<\/a>) by building the appropriate query and calling <code>Verify&shy;Version&shy;Info<\/code>, which has been available since Windows 2000 (possibly longer). <\/p>\n<p>If you think about it, the answer must be like that, for how could <code>kernel32.dll<\/code> export all of these specific version-checking functions? The Windows 7 version of <code>kernel32.dll<\/code> would have to be clairvoyant and have exports for all of these functions like <code>Is&shy;Windows&shy;10&shy;Or&shy;Greater<\/code>, which would be quite a feat. Presumably the implementations would simply be hard-coded to return either <code>TRUE<\/code> or <code>FALSE<\/code>, as appropriate. (I guess you could imagine that each version of Windows exports only the functions for which it returns <code>TRUE<\/code>, and the absence of the function implies that the corresponding version is not installed.) <\/p>\n<p>So just go ahead and use the functions in <code>Version&shy;Helpers.h<\/code>. They will always work and give you an answer. (Well, unless you&#8217;re targeting systems earlier than Windows 2000, but if you&#8217;re doing that, then you probably aren&#8217;t too interested in version detection since your customer that is still running Windows NT 4.0 is unlikely ever to upgrade.) <\/p>\n<p><b>Bonus chatter<\/b>: Note that the operating system version check does raise its own question: &#8220;Why are you doing an operating system version check at all?&#8221; Because that sort of thing gives the application compatibility team the heebie-jeebies. We asked, but the customer never did answer that question. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Just like in a cheesy movie, the answer was inside you all along.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-95175","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Just like in a cheesy movie, the answer was inside you all along.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/95175","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=95175"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/95175\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=95175"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=95175"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=95175"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}