{"id":105979,"date":"2021-11-29T07:00:00","date_gmt":"2021-11-29T15:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=105979"},"modified":"2021-11-29T05:43:52","modified_gmt":"2021-11-29T13:43:52","slug":"20211129-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20211129-00\/?p=105979","title":{"rendered":"How did Windows 3.1&#8217;s virtual machine manager get the information to show in the text-mode <KBD>Alt<\/KBD>+<KBD>Tab<\/KBD> switcher?"},"content":{"rendered":"<p>When I told <a title=\"The life story of the SwitchToThisWindow function\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20111107-00\/?p=9183\"> the life story of the <code>Switch\u00adTo\u00adThis\u00adWindow<\/code> function<\/a>, some people were curious about how the virtual machine manager knew about the current windows and their z-order, so that it could show them in the fake text-mode <kbd>Alt<\/kbd>+<kbd>Tab<\/kbd> switcher.<\/p>\n<p>The virtual machine manager has a friend, namely the Windows program that provided the graphical user interface for the virtual machine, named <code>WINOLDAP<\/code>. It got that name because it is the program which provides the Windows user interface for old (MS-DOS) applications. If the MS-DOS virtual machine is running windowed, then this program&#8217;s main window draws a graphical depiction of the contents of the virtual machine&#8217;s screen. If the MS-DOS virtual machine is running full-screen, then this program&#8217;s main window doesn&#8217;t need to draw anything, but it is still there, ready to help out the virtual machine manager.<\/p>\n<p>If you press the <kbd>Alt<\/kbd>+<kbd>Tab<\/kbd> hotkey while in a full-screen MS-DOS virtual machine, the virtual machine manager receives the hotkey and tries to emulate the graphical <kbd>Alt<\/kbd>+<kbd>Tab<\/kbd> user interface.<\/p>\n<p>The text-mode <kbd>Alt<\/kbd>+<kbd>Tab<\/kbd> code asks the virtual machine scheduler to switch execution context to the Windows virtual machine, and then call it back once this has occurred.<\/p>\n<p>In 16-bit Windows, the <code>Post\u00adMessage<\/code> function is special in that it is one of the few Windows function that could be called from a hardware interrupt handler. The callback function (now running in the context of the Windows virtual machine) saves the current virtual machine context, and then creates a new execution context that calls the <code>Post\u00adMessage<\/code> function, which from the virtual machine client&#8217;s point of view looks like a hardware interrupt in the sense that the function is being called out of the blue, from an unknown context. After the call to <code>Post\u00adMessage<\/code> function returns, the callback function restores the original context and allows execution to continue normally.<\/p>\n<p>The message is posted to the <code>WINOLDAP<\/code> window, and when it receives the message, it gathers information about the next window in the <kbd>Alt<\/kbd>+<kbd>Tab<\/kbd> list, as well as information about the user&#8217;s color preferences. It then issues a kernel call into the text-mode <kbd>Alt<\/kbd>+<kbd>Tab<\/kbd> code, passing this information along.<\/p>\n<p>The text-mode <kbd>Alt<\/kbd>+<kbd>Tab<\/kbd> code uses the color information to render a text-mode version of the <kbd>Alt<\/kbd>+<kbd>Tab<\/kbd> user interface, showing the name of the window being proposed as the switch destination.<\/p>\n<div style=\"font-family: monospace; background-color: #aaaaaa; line-height: 100%; font-weight: bold; text-align: center; height: 24em; width: 40em;\">\n<div style=\"background-color: #0000aa; color: #ffffff;\">Program Manager<\/div>\n<\/div>\n<p>If the user completes the <kbd>Alt<\/kbd>+<kbd>Tab<\/kbd> sequence, and the destination is a full-screen MS-DOS virtual machine, then the text-mode <kbd>Alt<\/kbd>+<kbd>Tab<\/kbd> switcher performs a direct virtual machine switch to the target. Performing the switch directly avoids bouncing through the Windows desktop. It then returns control back to <code>WINOLDAP<\/code> with a return value that means &#8220;You&#8217;re all done, do nothing more.&#8221;<\/p>\n<p>If the destination is not a full-screen MS-DOS virtual machine, then the text-mode <kbd>Alt<\/kbd>+<kbd>Tab<\/kbd> code returns control back to <code>WINOLDAP<\/code> with a return value that means &#8220;Switch to this window and return,&#8221; and in response, <code>WINOLDAP<\/code> calls the <code>Switch\u00adTo\u00adThis\u00adWindow<\/code> function to tell the window manager to switch to the window in the style of <kbd>Alt<\/kbd>+<kbd>Tab<\/kbd>.<\/p>\n<p>If the user continues the <kbd>Alt<\/kbd>+<kbd>Tab<\/kbd> sequence, either by tabbing forward or holding the <kbd>Shift<\/kbd> key to tab backward, then the text-mode <kbd>Alt<\/kbd>+<kbd>Tab<\/kbd> code returns control back to <code>WINOLDAP<\/code> with a return value that means &#8220;Get information about the next\/previous window in the <kbd>Alt<\/kbd>+<kbd>Tab<\/kbd> order and call me back.&#8221;<\/p>\n<p>The communication between the text-mode <kbd>Alt<\/kbd>+<kbd>Tab<\/kbd> code and <code>WINOLDAP<\/code> basically takes the form of a captive thread, where the <code>WINOLDAP<\/code> function issues a kernel call which doesn&#8217;t return until the user decides what they want to do next with the <kbd>Alt<\/kbd>+<kbd>Tab<\/kbd> sequence.<\/p>\n<p>It&#8217;s a rather complicated dance (all written in assembly language, which was the fashion at the time) to accomplish something that looks so simple and obvious to the end user.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Getting by with a little help from a friend.<\/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-105979","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-history"],"acf":[],"blog_post_summary":"<p>Getting by with a little help from a friend.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/105979","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=105979"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/105979\/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=105979"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=105979"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=105979"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}