{"id":108820,"date":"2023-09-25T07:00:00","date_gmt":"2023-09-25T14:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=108820"},"modified":"2023-09-25T08:48:17","modified_gmt":"2023-09-25T15:48:17","slug":"20230925-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20230925-00\/?p=108820","title":{"rendered":"GetQueueStatus and the queue state"},"content":{"rendered":"<p>Some time ago, we learned that the <code>Msg\u00adWait\u00adFor\u00adMultiple\u00adObjects<\/code> function <a title=\"MsgWaitForMultipleObjects and the queue state\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20050217-00\/?p=36423\"> waits only for <i>new<\/i> events to arrive<\/a>. In particular, this means that when <code>Msg\u00adWait\u00adFor\u00adMultiple\u00adObjects<\/code> tells you that an event has arrived, you need to process <i>all<\/i> of those events before looping back and calling <code>Msg\u00adWait\u00adFor\u00adMultiple\u00adObjects<\/code> again, because <code>Msg\u00adWait\u00adFor\u00adMultiple\u00adObjects<\/code> isn&#8217;t going to tell you about those old events.\u00b9<\/p>\n<p>It so happens that the <code>Get\u00adQueue\u00adStatus<\/code> function also manipulates the queue status. Each time you call <code>Get\u00adQueue\u00adStatus<\/code> to check a flag, that flag is marked as no longer &#8220;new&#8221; in the queue status, in the same way that <code>Msg\u00adWait\u00adFor\u00adMultiple\u00adObjects<\/code> marks the flag as no longer &#8220;new&#8221; when it wakes up due to a queue status change.<\/p>\n<p>This behavior of <code>Get\u00adQueue\u00adStatus<\/code> is <i>very surprising<\/i>, because you don&#8217;t expect a function called &#8220;Get&#8221; to have destructive side effects.<\/p>\n<p>The <code>Get\u00adQueue\u00adStatus<\/code> function returns the queue status in two forms, packed into a single 32-bit integer. The low-order 16 bits contain the <i>new<\/i> queue status bits (the queue status changes since the last time you asked about them), whereas the high-order 16 bits contain the <i>cumulative<\/i> queue status bits (all the status bits, both old and new). This is explained in the &#8220;Return value&#8221; section of the documentation, but it&#8217;s something that you may read without fully comprehending the consequences.<\/p>\n<p>Therefore, if you want to know if there is (say) any raw input available, either old or new, you need to write<\/p>\n<pre>if (HIWORD(GetQueueStatus(QS_RAWINPUT)) &amp; QS_RAWINPUT)\r\n<\/pre>\n<p>And if you want to drain the raw input, you should use a <code>while<\/code> loop to keep processing the raw input until the bit goes clear in the high word.<\/p>\n<p>The fact that <code>Get\u00adQueue\u00adStatus<\/code> is a destructive operation is one of those hidden gotchas of the window manager. This sort of atomic &#8220;test and clear&#8221; operation is common inside the window manager, so they exposed a function that let applications do it too, using the same name that the window manager used internally, so you might say that this function was named while wearing window manager colored glasses: The fact that this is a &#8220;test and clear&#8221; function is obvious if you work on the window manager, and completely surprising if you don&#8217;t.<\/p>\n<p>\u00b9 The <code>Msg\u00adWait\u00adFor\u00adMultiple\u00adObjects\u00adEx<\/code> function lets you pass the <code>MWMO_<wbr \/>INPUT\u00adAVAILABLE<\/code> flag to mean, &#8220;Also consider old events that haven&#8217;t yet been processed.&#8221;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>There&#8217;s stuff going on that&#8217;s hiding behind the innocuous-looking name.<\/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-108820","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>There&#8217;s stuff going on that&#8217;s hiding behind the innocuous-looking name.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/108820","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=108820"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/108820\/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=108820"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=108820"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=108820"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}