{"id":15333,"date":"2010-01-11T07:00:00","date_gmt":"2010-01-11T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2010\/01\/11\/why-arent-compatibility-workarounds-disabled-when-a-debugger-is-attached\/"},"modified":"2010-01-11T07:00:00","modified_gmt":"2010-01-11T07:00:00","slug":"why-arent-compatibility-workarounds-disabled-when-a-debugger-is-attached","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20100111-00\/?p=15333","title":{"rendered":"Why aren&#039;t compatibility workarounds disabled when a debugger is attached?"},"content":{"rendered":"<p>\nKen Hagan wonders\n<a HREF=\"http:\/\/blogs.msdn.com\/oldnewthing\/pages\/407234.aspx#751847\">\nwhy compatibility workarounds aren&#8217;t simply disabled when\na debugger is attached<\/a>.\n<\/p>\n<p>\nAs I noted earlier,\nmany compatibility workarounds are actually quicker than the code\nthat detects whether the workaround would be needed.\n<\/p>\n<pre>\nBOOL IsZoomed(HWND hwnd)\n{\n  return GetWindowLong(hwnd, GWL_STYLE) &amp; WS_MAXIMIZED;\n}\n<\/pre>\n<p>\nNow suppose you find a compatibility problem with some applications\nthat expect the <code>IsZoomed<\/code> function to return exactly\n<code>TRUE<\/code> or <code>FALSE<\/code>.\nYou then change the function to something like this:\n<\/p>\n<pre>\nBOOL IsZoomed(HWND hwnd)\n{\n  return (GetWindowLong(hwnd, GWL_STYLE) &amp; WS_MAXIMIZED) != 0;\n}\n<\/pre>\n<p>\nNow, we add code to enable the compatibility workaround only if\nthe application is on the list of known applications which need\nthis workaround:\n<\/p>\n<pre>\nBOOL IsZoomed(HWND hwnd)\n{\n  if (GetWindowLong(hwnd, GWL_STYLE) &amp; WS_MAXIMIZED) {\n      if (IsApplicationCompatibilityWorkaroundRequired(ISZOOMED_TRUEFALSE)) {\n          return TRUE;\n      } else {\n          return WS_MAXIMIZED;\n      }\n  } else {\n    return FALSE;\n  }\n}\n<\/pre>\n<p>\nWhat was a simple flag test now includes a check to see whether\nan application compatibility workaround is required.\nThese checks are not cheap, because the compatibility infrastructure\nneeds to look up the currently-running application in the compatibility\ndatabase, check that the version of the application that is running\nis the one the compatibility workaround is needed for\n(which could involve reading the file version resource or\nlooking for other identifying clues),\nand then returning either the compatible answer (<code>TRUE<\/code>)\nor the answer that resulted from the original simple one-line\nfunction.\n<\/p>\n<p>\nSo not only is the function slower\n(having to do a compatibility check),\nit also looks really stupid.\n<\/p>\n<p>\nOh wait, now we also have to stick in a debugger check:\n<\/p>\n<pre>\nBOOL IsZoomed(HWND hwnd)\n{\n  if (GetWindowLong(hwnd, GWL_STYLE) &amp; WS_MAXIMIZED) {\n      if (!IsDebuggerPresent() &amp;&amp;\n         IsApplicationCompatibilityWorkaroundRequired(ISZOOMED_TRUEFALSE)) {\n          return TRUE;\n      } else {\n          return WS_MAXIMIZED;\n      }\n  } else {\n    return FALSE;\n  }\n}\n<\/pre>\n<p>\nAnd then people complain that Windows is slow and bloated:\nA simple one-line function ballooned into ten lines.\n<\/p>\n<p>\nAnother reason why these compatibility workarounds are left\nintact when a debugger is running is that changing program\nbehavior based on whether a debugger is attached would prevent\napplication\nvendors from debugging one problem because all sorts of new problems\nsuddenly got injected.\n<\/p>\n<p>\nSuppose you support Program&nbsp;X, and you get a report of\na security vulnerability in your program.\nYou run the program under the debugger,\nand when you run the alleged exploit code,\nyou find that the program doesn&#8217;t behave the same as it does\nwhen the debugger is not attached.\nSome compatibility workaround that was active when your program\nis run normally is being suppressed, and the change in behavior\nchanges your program enough that the alleged security exploit\ndoesn&#8217;t behave quite the same.\n<\/p>\n<p>\nWhen run outside the debugger, the program crashes,\nbut when run under the debugger, the program displays a strange\nerror message but manages to keep from crashing.\nCongratulations, you introduced a Heisenbug.\n<\/p>\n<p>\nAnd then you say, &#8220;There&#8217;s something wrong with the debugger.\nIt must be a bug in Windows.&#8221;\n<\/p>\n<p>\n<b>Pre-emptive Yuhong Bao comment<\/b>:\nThe heap manager\n<a HREF=\"http:\/\/msdn.microsoft.com\/cc266414.aspx\">\nswitches to an alternate algorithm if it\ndetects a debugger<\/a>,\nand the\n<code>CloseHandle<\/code> function\n<a HREF=\"http:\/\/msdn.microsoft.com\/ms724211.aspx\">\nraises an exception if running under the debugger<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Ken Hagan wonders why compatibility workarounds aren&#8217;t simply disabled when a debugger is attached. As I noted earlier, many compatibility workarounds are actually quicker than the code that detects whether the workaround would be needed. BOOL IsZoomed(HWND hwnd) { return GetWindowLong(hwnd, GWL_STYLE) &amp; WS_MAXIMIZED; } Now suppose you find a compatibility problem with some applications [&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":[26],"class_list":["post-15333","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-other"],"acf":[],"blog_post_summary":"<p>Ken Hagan wonders why compatibility workarounds aren&#8217;t simply disabled when a debugger is attached. As I noted earlier, many compatibility workarounds are actually quicker than the code that detects whether the workaround would be needed. BOOL IsZoomed(HWND hwnd) { return GetWindowLong(hwnd, GWL_STYLE) &amp; WS_MAXIMIZED; } Now suppose you find a compatibility problem with some applications [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/15333","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=15333"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/15333\/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=15333"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=15333"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=15333"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}