{"id":5533,"date":"2013-01-17T07:00:00","date_gmt":"2013-01-17T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2013\/01\/17\/a-brief-history-of-the-getenvironmentstrings-functions\/"},"modified":"2013-01-17T07:00:00","modified_gmt":"2013-01-17T07:00:00","slug":"a-brief-history-of-the-getenvironmentstrings-functions","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20130117-00\/?p=5533\/","title":{"rendered":"A brief history of the GetEnvironmentStrings functions"},"content":{"rendered":"<p><P>\nThe\n<A HREF=\"http:\/\/msdn.microsoft.com\/library\/ms683187.aspx\">\n<CODE>Get&shy;Environment&shy;Strings<\/CODE> function<\/A>\nhas a long and troubled history.\n<\/P>\n<P>\nThe first bit of confusion is that the day it was introduced\nin Windows&nbsp;NT&nbsp;3.1, it was exported funny.\nThe UNICODE version was exported under the name\n<CODE>Get&shy;Environment&shy;StringsW<\/CODE>,\nbut the ANSI version was exported under the name\n<CODE>Get&shy;Environment&shy;Strings<\/CODE>\nwithout the usual <CODE>A<\/CODE> suffix.\n<\/P>\n<P>\nA mistake we have been living with for over two decades.\n<\/P>\n<P>\nThis is why the <CODE>winbase.h<\/CODE> header file\ncontains these confusing lines:\n<\/P>\n<PRE>\nWINBASEAPI\nLPCH\nWINAPI\nGetEnvironmentStrings(\n    VOID\n    );<\/p>\n<p>WINBASEAPI\nLPWCH\nWINAPI\nGetEnvironmentStringsW(\n    VOID\n    );<\/p>\n<p>#ifdef UNICODE\n#define GetEnvironmentStrings  GetEnvironmentStringsW\n#else\n#define GetEnvironmentStringsA  GetEnvironmentStrings\n#endif \/\/ !UNICODE\n<\/PRE>\n<P>\nIt&#8217;s trying to clean up a mess that was created long ago,\nand it only partly succeeds.\nThis is why your IDE may get confused when you try to call\nthe\n<CODE>Get&shy;Environment&shy;Strings<\/CODE> function\nand send you to the wrong definition.\nIt&#8217;s having trouble untangling the macros whose job is to\ntry to untangle the original mistake.\n<\/P>\n<P>\nThe kernel folks tried to clean this up as quickly as they could,\nby exporting new functions with the names\n<CODE>Get&shy;Environment&shy;StringsW<\/CODE> and\n<CODE>Get&shy;Environment&shy;StringsA<\/CODE>,\nlike they should have been in the first place,\nbut for compatibility purposes, they still have to export the weird\nunsuffixed\n<CODE>Get&shy;Environment&shy;Strings<\/CODE> function.\nAnd then to avoid all the &#8220;gotcha!&#8221;s from people\nlooking for proof of nefarious intent,\nthey kept the mistake in the public header files\nto make their actions visible to all.\n<\/P>\n<P>\nThough personally, I would have tidied things up differently:\n<\/P>\n<PRE>\nWINBASEAPI\nLPCH\nWINAPI\nGetEnvironmentStrings(\n    VOID\n    );<\/p>\n<p>WINBASEAPI\nLPCH\nWINAPI\nGetEnvironmentStringsA(\n    VOID\n    );<\/p>\n<p>WINBASEAPI\nLPWCH\nWINAPI\nGetEnvironmentStringsW(\n    VOID\n    );<\/p>\n<p>#ifdef UNICODE\n#define GetEnvironmentStrings  GetEnvironmentStringsW\n#else\n#define GetEnvironmentStrings  GetEnvironmentStringsA\n#endif \/\/ !UNICODE\n<\/PRE>\n<P>\nI would have left the declaration of the mistaken\n<CODE>Get&shy;Environment&shy;Strings<\/CODE> function\nin the header file, but redirected the symbolic name\nto the preferred suffixed version.\n<\/P>\n<P>\nBut then again, maybe my version would have confused IDEs\neven more than the current mechanism does.\n<\/P>\n<P>\nThe other unfortunate note in the history of the\n<CODE>Get&shy;Environment&shy;Strings<\/CODE> function\nis the odd way it handled the Unicode environment.\nBack in the old days,\nthe <CODE>Get&shy;Environment&shy;Strings<\/CODE> function\n<A HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2008\/09\/25\/8965129.aspx\">\nreturned a raw pointer to the environment block<\/A>.\nThe result was that if some other code modified the environment,\nyour pointer became invalid,\nand there was nothing you could do about it.\nAs I noted, the function was subsequently changed so that\nboth the ANSI and Unicode versions return <I>snapshots<\/I>\nof the environment strings,\nso that the environment strings you received wouldn&#8217;t get\nspontaneously corrupted by another thread.\n<\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>The Get&shy;Environment&shy;Strings function has a long and troubled history. The first bit of confusion is that the day it was introduced in Windows&nbsp;NT&nbsp;3.1, it was exported funny. The UNICODE version was exported under the name Get&shy;Environment&shy;StringsW, but the ANSI version was exported under the name Get&shy;Environment&shy;Strings without the usual A suffix. A mistake we have [&hellip;]<\/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":[2],"class_list":["post-5533","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-history"],"acf":[],"blog_post_summary":"<p>The Get&shy;Environment&shy;Strings function has a long and troubled history. The first bit of confusion is that the day it was introduced in Windows&nbsp;NT&nbsp;3.1, it was exported funny. The UNICODE version was exported under the name Get&shy;Environment&shy;StringsW, but the ANSI version was exported under the name Get&shy;Environment&shy;Strings without the usual A suffix. A mistake we have [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/5533","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=5533"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/5533\/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=5533"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=5533"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=5533"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}