{"id":102593,"date":"2019-06-14T07:00:00","date_gmt":"2019-06-14T14:00:00","guid":{"rendered":"http:\/\/devblogs.microsoft.com\/oldnewthing\/?p=102593"},"modified":"2019-06-13T21:46:53","modified_gmt":"2019-06-14T04:46:53","slug":"20190614-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20190614-00\/?p=102593","title":{"rendered":"Why does SetFocus fail without telling me why?"},"content":{"rendered":"<p>One of my colleagues was debugging a program and discovered that a call to <code>Set\u00adFocus<\/code> returned <code>NULL<\/code>, which the documentation calls out as indicating an error condition. However, a follow-up call to <code>Get\u00adLast\u00adError()<\/code> returned 0, which means &#8220;Everything is just fine.&#8221;<\/p>\n<p>After much debugging, they figured it out: There was a <code>WH_<\/code><code>CBT<\/code> hook that was intercepting the <code>Set\u00adFocus<\/code> call and rejecting the focus change by returning <code>TRUE<\/code>.<\/p>\n<p>&#8220;It would have been nice to have received a useful error code like <code>ERROR_<\/code><code>YOU_<\/code><code>JUST_<\/code><code>GOT_<\/code><code>SCREWED_<\/code><code>BY_<\/code><code>A_<\/code><code>HOOK<\/code>.&#8221;<\/p>\n<p>You don&#8217;t get a useful error because the window manager doesn&#8217;t know that the hook is screwing with you. You called <code>Set\u00adFocus<\/code>. The window hook said, &#8220;Nope, don&#8217;t change focus. It&#8217;s all good. No worries.&#8221; The window manager says, &#8220;Okay, well, then I guess it&#8217;s all taken care of.&#8221;<\/p>\n<p>Hooks let you modify or even replace certain parts of the window manager. If you do that, then it&#8217;s on you to do so in a manner that will not confuse the rest of the system. If your hook wants to make <code>Set\u00adFocus<\/code> fail, and not set an error code, we&#8217;ll that&#8217;s your decision. The system is not going to call <code>Set\u00adLast\u00adError(<\/code><code>ERROR_<\/code><code>YOU_<\/code><code>JUST_<\/code><code>GOT_<\/code><code>SCREWED_<\/code><code>BY_<\/code><code>A_<\/code><code>HOOK)<\/code> because that might overwrite an error code set by the hook.<\/p>\n<p>In this specific example, the point of the <code>WH_<\/code><code>CBT<\/code> hook is to assist with computer-based training: The program installs a CBT hook, which can then do things like prevent the program from changing focus so that the window containing the training materials retains focus. The underlying assumption is that a CBT hook is going to mess around only with windows that it is already in cahoots with.<\/p>\n<p>&#8220;Oh, this is my print dialog. I&#8217;m going to prevent it from taking focus so that my instructions on how to use the printer stays on screen with focus. I&#8217;m also going to make changes to my print dialog function so it doesn&#8217;t freak out when it fails to get focus.&#8221;<\/p>\n<p>Whatever program installed this CBT hook didn&#8217;t limit their meddling to windows they already controlled. This means that their actions sowed confusion among other windows that weren&#8217;t part of their little game.<\/p>\n<p>I suspect no actual computer-based training was going on at all. The CBT hook was being used not for its stated purpose of computer-based training, but rather because it provided a way to alter the behavior of the window manager in very fundamental ways, and being able to make those alterations fit into the program&#8217;s world view somehow.<\/p>\n<p>Somebody who installs a hook can alter the behavior of the system, and it&#8217;s important that they do it right, so that their changes still maintain the contracts promised by the system. One of those being that when <code>Set\u00adFocus<\/code> fails, it tells you why.<\/p>\n<p><b>Related reading<\/b>: <a href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20141031-00\/?p=43723\"> The case of the file that won&#8217;t copy because of an Invalid Handle error message<\/a>.<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>If you&#8217;re going to replace part of the operating system, you have to replace the side effects, too.<\/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-102593","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>If you&#8217;re going to replace part of the operating system, you have to replace the side effects, too.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/102593","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=102593"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/102593\/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=102593"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=102593"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=102593"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}