<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	
  <title>The Old New Thing - Dreamcatcher Edition</title>
	<atom:link href="https://devblogs.microsoft.com/oldnewthing/feed/" rel="self" type="application/rss+xml" />
	<link>https://devblogs.microsoft.com/oldnewthing/</link>
	<description>Practical development throughout the evolution of Windows.</description>
	<lastBuildDate>Thu, 12 Nov 2026 19:57:42 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://devblogs.microsoft.com/oldnewthing/wp-content/uploads/sites/38/2021/03/Microsoft-Favicon.png</url>
	
  <title>The Old New Thing - Dreamcatcher Edition</title>
	<link>https://devblogs.microsoft.com/oldnewthing/</link>
	<width>32</width>
	<height>32</height>
</image> 
	
  <item>
    <title>How can I pass more than one parameter to co_await?</title>
    <link>https://devblogs.microsoft.com/oldnewthing/20261112-00/?p=112851/</link>
    <comments>https://devblogs.microsoft.com/oldnewthing/20261112-00/?p=112851/#respond</comments>
    <dc:creator><![CDATA[Raymond Chen]]></dc:creator>
    <pubDate>Thu, 12 Nov 2026 15:00:00 +0000</pubDate>
    <category><![CDATA[Old New Thing]]></category>
    <category><![CDATA[Code]]></category>
    <guid isPermaLink="false">https://devblogs.microsoft.com/oldnewthing/?p=112851</guid>
    <content:encoded><![CDATA[<p>Suppose you have an awaitable object, but you want the caller to pass a bonus parameter when they do a <code>co_await</code>. For example, you may want the caller to be able to pass a priority or a timeout or something else that modifies how the await occurs.</p>
<pre>struct Widget
{
    ⟦ ... other stuff ... ⟧

    bool await_ready() const { return ⟦ ... ⟧; }

    bool await_suspend(std::coroutine_handle&lt;&gt; handle)
    {
        int priority = ??? how do I get a priority ???;

        return internal_start(handle, priority);
    }

    auto await_resume() { return ⟦ ... ⟧; }
};

// This doesn't work
auto result = co_await (widget, priority);
</pre>
<p>So how do you pass two parameters to <code>co_await</code> so they can be used in <code>await_<wbr />suspend</code>?</p>
<p>It&#8217;s a trick question. You can&#8217;t. The <code>co_await</code> operator takes only one parameter.</p>
<p>So you&#8217;ll have to take all the things you want to use and put them into a single parameter.</p>
<p>Wrap the awaitable object and its parameters into a larger object, and then await the larger object.</p>
<p>First, let&#8217;s rename away the coroutine methods inside <code>Widget</code> since we aren&#8217;t awaiting it directly any more.</p>
<pre>struct Widget
{
    ⟦ ... other stuff ... ⟧

<span style="border: solid 1px currentcolor;">private:</span>
    bool <span style="border: solid 1px currentcolor;">inner_</span>await_ready() const { return ⟦ ... ⟧; }

    bool <span style="border: solid 1px currentcolor;">inner_</span>await_suspend(std::coroutine_handle&lt;&gt; handle)
    {
        int priority = ??? how do I get a priority ???;

        return internal_start(handle, priority);
    }

    auto <span style="border: solid 1px currentcolor;">inner_</span>await_resume() const { return ⟦ ... ⟧; }
};
</pre>
<p>Now we can add a priority parameter to the <code>inner_<wbr />await_<wbr />suspend</code>:</p>
<pre>struct Widget
{
    ⟦ ... other stuff ... ⟧

private:
    bool inner_await_ready() const { return ⟦ ... ⟧; }

    bool inner_await_suspend(std::coroutine_handle&lt;&gt; handle, <span style="border: solid 1px currentcolor;">int priority</span>)
    {
        return internal_start(handle, priority);
    }

    auto inner_await_resume() const { return ⟦ ... ⟧; }
};
</pre>
<p>And finally, we create a helper class (which is a friend of <code>Widget</code>) that wraps the original object and its priority into a single new awaitable object.</p>
<pre>struct Widget
{
    ⟦ ... other stuff ... ⟧

private:
    <span style="border: solid 1px currentcolor;">friend struct widget_with_priority;</span>

    ⟦ ... as before ... ⟧
};

<span style="border: solid 1px currentcolor; border-bottom: none;">struct widget_with_priority                                          </span>
<span style="border: 1px currentcolor; border-style: none solid;">{                                                                    </span>
<span style="border: 1px currentcolor; border-style: none solid;">    widget_with_priority(Widget const&amp; widget, int priority) :       </span>
<span style="border: 1px currentcolor; border-style: none solid;">        m_widget(widget), m_priority(priority) {}                    </span>
<span style="border: 1px currentcolor; border-style: none solid;"><!-- -->                                                                     </span>
<span style="border: 1px currentcolor; border-style: none solid;">    bool await_ready() const { return m_widget.inner_await_ready(); }</span>
<span style="border: 1px currentcolor; border-style: none solid;"><!-- -->                                                                     </span>
<span style="border: 1px currentcolor; border-style: none solid;">    auto await_suspend(std::coroutine_handle&lt;&gt; handle)               </span>
<span style="border: 1px currentcolor; border-style: none solid;">    {                                                                </span>
<span style="border: 1px currentcolor; border-style: none solid;">        return m_widget.inner_await_suspend(handle, m_priority);     </span>
<span style="border: 1px currentcolor; border-style: none solid;">    }                                                                </span>
<span style="border: 1px currentcolor; border-style: none solid;"><!-- -->                                                                     </span>
<span style="border: 1px currentcolor; border-style: none solid;">    auto await_ready() {                                             </span>
<span style="border: 1px currentcolor; border-style: none solid;">        return m_widget.await_ready();                               </span>
<span style="border: 1px currentcolor; border-style: none solid;">    }                                                                </span>
<span style="border: 1px currentcolor; border-style: none solid;"><!-- -->                                                                     </span>
<span style="border: 1px currentcolor; border-style: none solid;">    Widget const&amp; m_widget;                                          </span>
<span style="border: 1px currentcolor; border-style: none solid;">    int m_priority;                                                  </span>
<span style="border: solid 1px currentcolor; border-top: none;">};                                                                   </span>
</pre>
<p>You can now do</p>
<pre>co_await widget_with_priority(widget, priority);
</pre>
<p>This solves the problem but is rather unwieldy. We&#8217;ll address that next time.</p>
<p>The post <a href="https://devblogs.microsoft.com/oldnewthing/20261112-00/?p=112851/">How can I pass more than one parameter to &lt;CODE&gt;co_await&lt;/CODE&gt;?</a> appeared first on <a href="https://devblogs.microsoft.com/oldnewthing">The Old New Thing</a>.</p>
]]></content:encoded>
    <wfw:commentRss>https://devblogs.microsoft.com/oldnewthing/20261112-00/?p=112851/feed/</wfw:commentRss>
    <slash:comments>0</slash:comments>
    <image type="image/png" url="https://devblogs.microsoft.com/oldnewthing/wp-content/uploads/sites/38/2025/10/banner-oldnewthing-blue.webp"/>
  </item>
		
  <item>
    <title>I didn&#8217;t write a program with emoji, but I did use a control character</title>
    <link>https://devblogs.microsoft.com/oldnewthing/20261111-00/?p=112848/</link>
    <comments>https://devblogs.microsoft.com/oldnewthing/20261111-00/?p=112848/#comments</comments>
    <dc:creator><![CDATA[Raymond Chen]]></dc:creator>
    <pubDate>Wed, 11 Nov 2026 15:00:00 +0000</pubDate>
    <category><![CDATA[Old New Thing]]></category>
    <category><![CDATA[History]]></category>
    <guid isPermaLink="false">https://devblogs.microsoft.com/oldnewthing/?p=112848</guid>
    <content:encoded><![CDATA[<p><a href="https://martypc.blogspot.com/"> Adventures in PC Emulation</a> recently wrote about <a href="https://martypc.blogspot.com/2026/08/executable-emoji.html"> Executable Emoji</a>: Writing an MS-DOS program using machine code represented solely by Unicode emoji characters.</p>
<p>This reminded me that back in the day I did something similar, but much less impressive: I wrote a <tt>reboot.com</tt> program that could be generated from the command line via <tt>echo</tt>.</p>
<pre>echo <span style="border: solid 1px currentcolor; padding: 2px;"><kbd>Alt</kbd>+<kbd>Num2</kbd>,<kbd>Num0</kbd>,<kbd>Num5</kbd></span><span style="border: solid 1px currentcolor; border-left: none; padding: 2px;"><kbd>Ctrl</kbd>+<kbd>Y</kbd></span>&gt;reboot.com
</pre>
<p>The <kbd>Alt</kbd>+<kbd>Num2</kbd>,<kbd>Num0</kbd>,<kbd>Num5</kbd> means to press and hold the <kbd>Alt</kbd> while sequentially pressing and releasing <kbd>Num2</kbd>, <kbd>Num0</kbd>, <kbd>Num5</kbd> on the numeric keypad, and then releasing the <kbd>Alt</kbd> key. In the IBM PC 437 code page, this comes out looking like <span style="border: solid 1px currentcolor; padding: 1px;">═</span>, which is character 205, or hex <tt>0xCD</tt>.</p>
<p>The byte <tt>0xCD</tt> is the machine code for the <tt>int</tt> instruction, for issuing a software interrupt. And <kbd>Ctrl</kbd>+<kbd>Y</kbd> generates character 25, or hex <tt>0x19</tt>, which completes the instruction: <tt>int 19h</tt>.</p>
<p>Interrupt 19h was a sort-of not-very-good &#8220;reboot the system&#8221; interrupt. You can read about all the problems it has in <a href="https://www.ctyme.com/intr/rb-2270.htm"> Ralph Brown&#8217;s Interrupt List</a>.</p>
<blockquote class="q"><p>This interrupt reboots the system without clearing memory or restoring interrupt vectors. Because interrupt vectors are preserved, this interrupt usually causes a system hang if any TSRs have hooked vectors from 00h through 1Ch, particularly INT 08.</p></blockquote>
<p>Since this was not a very good way of rebooting the system, it was mostly just a parlor trick.</p>
<p>But at least I did it.</p>
<p>The post <a href="https://devblogs.microsoft.com/oldnewthing/20261111-00/?p=112848/">I didn&#8217;t write a program with emoji, but I did use a control character</a> appeared first on <a href="https://devblogs.microsoft.com/oldnewthing">The Old New Thing</a>.</p>
]]></content:encoded>
    <wfw:commentRss>https://devblogs.microsoft.com/oldnewthing/20261111-00/?p=112848/feed/</wfw:commentRss>
    <slash:comments>2</slash:comments>
    <image type="image/png" url="https://devblogs.microsoft.com/oldnewthing/wp-content/uploads/sites/38/2025/10/banner-oldnewthing-blue.webp"/>
  </item>
		
  <item>
    <title>Microsoft employee price list from 1987</title>
    <link>https://devblogs.microsoft.com/oldnewthing/20261110-00/?p=112843/</link>
    <comments>https://devblogs.microsoft.com/oldnewthing/20261110-00/?p=112843/#comments</comments>
    <dc:creator><![CDATA[Raymond Chen]]></dc:creator>
    <pubDate>Tue, 10 Nov 2026 15:00:00 +0000</pubDate>
    <category><![CDATA[Old New Thing]]></category>
    <category><![CDATA[History]]></category>
    <guid isPermaLink="false">https://devblogs.microsoft.com/oldnewthing/?p=112843</guid>
    <content:encoded><![CDATA[<p>I present for your amusement the Microsoft employee price list from 1987. Marvel at the Microsoft software catalog from nearly 40 years ago. Use your inflation calculators to figure out how much those prices translate into today&#8217;s dollars. (Note that these are the discounted employee prices, not the retail price.)</p>
<pre>                                                                         May 4, 1987

                                 <u>EMPLOYEE PRICE LIST</u>

 PART                            EMPLOYEE       PART                             EMPLOYEE
<u>NUMBER</u>       <u>DESCRIPTION</u>           <u>PRICE </u>       <u>NUMBER</u>       <u>DESCRIPTION</u>           <u>PRICE </u>

             <b>FORTRAN</b>                                    <b>MULTIPLAN</b>
005-014v400   MS-DOS               $30.00       023-014v203   MS-DOS 3.0           $15.00
005-023       SOFTCARD             $10.00       023-022       APPLE II (NATIVE)    $15.00
005-092v331   XENIX 286            $30.00       023-096v111   MACINTOSH            $15.00
005-096v220   MACINTOSH            $20.00       
                                                             <b>PROJECT</b>
             <b>A.L.D.S.</b>                           027-014v301   IBM                  $30.00
006-023       SOFTCARD             $20.00       026-214v300   COURSEWARE           $30.00
                                                
             <b>BASIC COMPILER</b>                                  <b>FLIGHT SIMULATOR</b>
007-014v536   MS-DOS               $15.00       030-096v102   MACINTOSH            $10.00
007-023       SOFTCARD             $25.00       030-099v213   IBM                  $10.00
007-096v100   MACINTOSH 1.0        $20.00       
007-114v300   QUICKBASIC           $ 5.00                    <b>FILE</b>
                                                033-096v105   MACINTOSH            $15.00
             <b>MUMATH/MUSIMP</b>               
009-014v412   MS-DOS               $20.00                    <b>WORD</b>
                                                034-049v300   NETWORK              $45.00
             <b>COBOL</b>                              034-049-034   NETWORK WORKSTATION  $20.00
011-014v210   MS-DOS               $25.00       034-096v301   MACINTOSH            $ TBA
011-023       SOFTCARD             $20.00       034-099v311   IBM                  $40.00
011-092       XENIX 286            $30.00       034-214v310   COURSEWARE 3.1 DOS   $35.00
                                                034-296v300   COURSEWARE 3.1 MAC   $25.00
             <b>BASIC INTERPRETER</b>           
014-014       MS-DOS               $20.00                    <b>CHART</b>
014-092v541   XENIX 286            $15.00       035-096v102   MACINTOSH 1.02       $15.00
014-096v300   MACINTOSH            $15.00       035-099v203   IBM                  $15.00
                                                035-214v200   COURSEWARE 2.0 DOS   $25.00
             <b>MACRO ASSEMBLER</b>             
016-014v400   MS-DOS               $20.00                    <b>MS-DOS</b>
                                                036-214v321   DOS/GW-BASIC         $15.00
             <b>SORT</b>                        
017-014       MS-DOS               $20.00                    <b>BUS MOUSE</b>
                                                037-299v602   IBM                  $40.00
             <b>LISP</b>                               037-399v600   Inport Mouse         $30.00
018-014v510   MS-DOS               $30.00       
                                                             <b>SERIAL MOUSE</b>
             <b>PASCAL COMPILER</b>                    039-199v602   IBM                  $45.00
020-014v332   MS-DOS               $30.00       
020-092v331   XENIX 286            $35.00                    <b>BUSINESS BASIC COMPILER</b>
                                                045-014       MS-DOS               $20.00
</pre>
<p>Page two:</p>
<pre>                                                                         May 4, 1897

 PART                            EMPLOYEE       PART                             EMPLOYEE
<u>NUMBER</u>       <u>DESCRIPTION</u>           <u>PRICE </u>       <u>NUMBER</u>       <u>DESCRIPTION</u>           <u>PRICE </u>

             <b>APPLESOFT COMPILER</b>
023-022       APPLE II             $15.00

             <b>C COMPILER</b>
048-014v400   MS-DOS               $35.00

             <b>WINDOWS</b>
050-050v104   IBM
               (retail version)    $10.00
050-150v103   WINDOWS TOOLKIT ISV
               (developers only)   $40.00
050-051v104   WINDOWS 3.5"         $10.00

             <b>MACH 10</b>
058-099       WITH WINDOWS        $185.00
058-199       BOARD ONLY          $130.00

             <b>EXCEL</b>
065-096v104   MACINTOSH            $20.00
065-196       "HANDS ON EXCEL"
                WORKBOOK           $20.00

             <b>ACCESS</b>
066-099v101   IBM                  $20.00

070-096v100  <b>MICROSOFT WORKS</b>       $20.00

             <b>LEARN M/P &amp; CHART</b>
082-096       MACINTOSH            $ 5.00

089-014v101  <b>LEARNING DOS</b>          $ 5.00

094-014      <b>COBOL TOOLS IBM</b>       $15.00

094-092      <b>COBOL XENIX TOOLS</b>     $15.00
</pre>
<p>There are other pages for books from Microsoft Press, which I didn&#8217;t bother to reproduce here.</p>
<p>A.L.D.S. is the Assembly Language Development System, a software development system for CP/M. <a href="https://ia801608.us.archive.org/8/items/msmumath/MS_muMATH-muSIMP80-Manual.pdf"> muMATH/muSIMP</a> was a lisp system disguised as a symbolic mathematics package. (muMath was the symbolic mathematics part; muSimp was the lisp part.)</p>
<p>I&#8217;ve talked about some of these products before:</p>
<ul>
<li>Flight Simulator is probably Microsoft&#8217;s oldest continuing product. There was <a title="That time a customer reported an error in the map used by Flight Simulator" href="https://devblogs.microsoft.com/oldnewthing/20170418-00/?p=95985"> that time a customer reported an error in the map</a>.</li>
<li>Access is a telecommunications program. <a title="Where did the name for Microsoft Access come from?" href="https://devblogs.microsoft.com/oldnewthing/20060413-09/?p=31543"> The name was later reused for a database program</a>.</li>
<li>FORTRAN was succeeded much later by Fortran PowerStation, <a title="We got around three" href="https://devblogs.microsoft.com/oldnewthing/20151124-00/?p=92151"> which was not a resounding success</a>.</li>
<li>The Mach 10 was not very successful either, but at least <a title="The worst-selling Microsoft software product of all time: OS/2 for the Mach 20" href="https://devblogs.microsoft.com/oldnewthing/20221226-00/?p=107615"> it did better than the Mach 20 for OS/2</a>!</li>
<li>The source code for the Applesoft Compiler <a title="The Applesoft Compiler (TASC): We have the source code, in a sense" href="https://devblogs.microsoft.com/oldnewthing/20220419-00/?p=106496"> became shrouded in mystery</a>. I have a follow-up to that story, but haven&#8217;t had time to research it and write it up.</li>
<li>The Microsoft Softcard was a <a title="The Microsoft SoftCard for the Apple II: Getting two processors to share the same memory" href="https://devblogs.microsoft.com/oldnewthing/20251104-00/?p=111758"> plug-in board that you added to your Apple II to turn it into a CP/M system</a>. It looks like a good number of programming languages were available in a Softcard edition.</li>
</ul>
<p>The post <a href="https://devblogs.microsoft.com/oldnewthing/20261110-00/?p=112843/">Microsoft employee price list from 1987</a> appeared first on <a href="https://devblogs.microsoft.com/oldnewthing">The Old New Thing</a>.</p>
]]></content:encoded>
    <wfw:commentRss>https://devblogs.microsoft.com/oldnewthing/20261110-00/?p=112843/feed/</wfw:commentRss>
    <slash:comments>16</slash:comments>
    <image type="image/png" url="https://devblogs.microsoft.com/oldnewthing/wp-content/uploads/sites/38/2025/10/banner-oldnewthing-blue.webp"/>
  </item>
		
  <item>
    <title>If the Windows Update hot patcher checks that the function hasn&#8217;t already been patched, does that mean you can&#8217;t install two hot-patches?</title>
    <link>https://devblogs.microsoft.com/oldnewthing/20261109-00/?p=112841/</link>
    <comments>https://devblogs.microsoft.com/oldnewthing/20261109-00/?p=112841/#comments</comments>
    <dc:creator><![CDATA[Raymond Chen]]></dc:creator>
    <pubDate>Mon, 09 Nov 2026 15:00:00 +0000</pubDate>
    <category><![CDATA[Old New Thing]]></category>
    <category><![CDATA[Other]]></category>
    <guid isPermaLink="false">https://devblogs.microsoft.com/oldnewthing/?p=112841</guid>
    <content:encoded><![CDATA[<p>In my earlier discussion of how Windows Update uses the hot-patching space (and <a title="If somebody tries to hot-patch an already-hot-patched function, how do they avoid conflicts?" href="https://devblogs.microsoft.com/oldnewthing/20261005-00/?p=112755"> how nobody else should be using it</a>), the question arose of what happens when Windows Update wants to hot-patch a binary that has already been hotpatched. Does this mean that you cannot apply hot patches two updates in a row?</p>
<p>Microsoft issues hot patches for two updates in a row. I linked to it in the original article, and here it is again: <a href="https://techcommunity.microsoft.com/blog/windows-itpro-blog/hotpatch-for-windows-client-now-available/4399808"> Hotpatch for Windows client now available</a>.</p>
<p>Notice in the diagram that Windows supports <i>two</i> hot-patch cycles before forcing a traditional update.</p>
<div id="p20261109_head" style="display: none;"> </div>
<table style="border-collapse: collapse; text-align: center;" border="0" cellspacing="0" cellpadding="3">
<tbody>
<tr>
<td style="padding-right: 1em;">Hot-patch<br />
track</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td style="border: solid 1px currentcolor;">Hot-patch<br />
update</td>
<td>→</td>
<td style="border: solid 1px currentcolor;">Hot-patch<br />
update</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td style="border: solid 1px currentcolor;">Hot-patch<br />
update</td>
<td>→</td>
<td style="border: solid 1px currentcolor;">Hot-patch<br />
update</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2197.png" alt="↗" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2198.png" alt="↘" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
<td>&nbsp;</td>
<td><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2197.png" alt="↗" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2198.png" alt="↘" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
<td>&nbsp;</td>
</tr>
<tr>
<td style="padding-right: 1em;">Traditional<br />
track</td>
<td style="border: solid 1px currentcolor;">Traditional<br />
update</td>
<td>→</td>
<td style="border: solid 1px currentcolor;">Traditional<br />
update</td>
<td>→</td>
<td style="border: solid 1px currentcolor;">Traditional<br />
update</td>
<td>→</td>
<td style="border: solid 1px currentcolor;">Traditional<br />
update</td>
<td>→</td>
<td style="border: solid 1px currentcolor;">Traditional<br />
update</td>
<td>→</td>
<td style="border: solid 1px currentcolor;">Traditional<br />
update</td>
<td>→</td>
<td style="border: solid 1px currentcolor;">Traditional<br />
update</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>Jan<br />
baseline</td>
<td>&nbsp;</td>
<td>Feb</td>
<td>&nbsp;</td>
<td>Mar</td>
<td>&nbsp;</td>
<td>Apr<br />
baseline</td>
<td>&nbsp;</td>
<td>May</td>
<td>&nbsp;</td>
<td>Jun</td>
<td>&nbsp;</td>
<td>Jul<br />
baseline</td>
</tr>
</tbody>
</table>
<p>The first month of each quarter issues a traditional update. Administrators who opted into the hot-patch track can install two months of hot patches, while everybody else continues to get traditional updates. At the start of the next quarter, everybody gets a traditional update again, and the cycle continues.</p>
<p>Okay, so how can Windows Update apply a hot-patch on top of another hot-patch?</p>
<p>Why can&#8217;t you tickle yourself?</p>
<p>Your brain knows that you&#8217;re the one doing the tickling, so it suppresses the tickle response.</p>
<p>And Windows Update knows that it&#8217;s patching something that it already patched, so it knows what it did to apply the hot-patch, and therefore it knows what code was originally there before it performed the hot-patch. I think all it has to do to patch a patch is update the far jump target in the trampoline to point to the new hot-patch function.</p>
<p>I suspect that the limit of two stacked hot-patches avoids an unbounded accumulation of internal data structures that are used to keep track of all the hot-patches, and to ensure we don&#8217;t run out of patch space in the binary itself.</p>
<p>
<script>
window.addEventListener("load", function() {
  var fullFF = getComputedStyle(document.body).fontFamily;
  var simpleFF = fullFF.replace(/ Emoji/g, "");
  // break up "style" to prevent wordpress from injecting random junk
  document.getElementById("p20261109_head").innerHTML =
`<s` + `tyle>
body { font-family: ${simpleFF}; }
.emoji { font-family: ${fullFF}; }
.entry-content th { padding: 1px; } /* stylesheet workaround */
.entry-content td { padding: 1px; } /* stylesheet workaround */
</s` + `tyle>`;
}); // wacky comment to prevent wordpress from injecting random junk
</script></p>
<p>The post <a href="https://devblogs.microsoft.com/oldnewthing/20261109-00/?p=112841/">If the Windows Update hot patcher checks that the function hasn&#8217;t already been patched, does that mean you can&#8217;t install two hot-patches?</a> appeared first on <a href="https://devblogs.microsoft.com/oldnewthing">The Old New Thing</a>.</p>
]]></content:encoded>
    <wfw:commentRss>https://devblogs.microsoft.com/oldnewthing/20261109-00/?p=112841/feed/</wfw:commentRss>
    <slash:comments>2</slash:comments>
    <image type="image/png" url="https://devblogs.microsoft.com/oldnewthing/wp-content/uploads/sites/38/2025/10/banner-oldnewthing-blue.webp"/>
  </item>
		
  <item>
    <title>Why are we all worked up about atomicity when applying hot-patches if we can just suspend all the threads?</title>
    <link>https://devblogs.microsoft.com/oldnewthing/20261106-00/?p=112838/</link>
    <comments>https://devblogs.microsoft.com/oldnewthing/20261106-00/?p=112838/#respond</comments>
    <dc:creator><![CDATA[Raymond Chen]]></dc:creator>
    <pubDate>Fri, 06 Nov 2026 15:00:00 +0000</pubDate>
    <category><![CDATA[Old New Thing]]></category>
    <category><![CDATA[Code]]></category>
    <guid isPermaLink="false">https://devblogs.microsoft.com/oldnewthing/?p=112838</guid>
    <content:encoded><![CDATA[<p>I noted that one of the concerns of the Windows hot-patching system is that the patch can be activated atomically. But why does it need to be atomic? Can&#8217;t just suspend all the threads of the process (except for the one doing the patching)? That way, nobody else can be executing a half-installed patch.</p>
<p>For processors with variable-length instructions (<a title="The x86 architecture is the weirdo" href="https://devblogs.microsoft.com/oldnewthing/20040914-00/?p=37873">looking at you, x86</a>), the patched instruction cannot be shorter than its replacement. This applies even if you can suspend all the threads of the process, because you might suspend a thread just as it&#8217;s about to execute bytes from what would be the second of half of the replacement instruction.</p>
<table style="border-collapse: collapse;" border="0" cellspacing="0" cellpadding="3">
<tbody>
<tr>
<td style="text-align: right;" colspan="3">instruction<br />
pointer</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td style="text-align: center;">↓</td>
</tr>
<tr>
<td>original</td>
<td style="border: solid 1px currentcolor;"><tt>XX</tt></td>
<td style="border: solid 1px currentcolor;"><tt>YY</tt></td>
</tr>
<tr>
<td style="height: 1ex;" colspan="3"> </td>
</tr>
<tr>
<td>patch</td>
<td style="border: solid 1px currentcolor;" colspan="2"><tt>AA BB</tt></td>
</tr>
</tbody>
</table>
<p>If you were unlucky and froze the thread after it executed the <code>XX</code> instruction and was about to execute the <code>YY</code> instruction, and then replaced both bytes with a two-byte instruction <code>AA BB</code>, then when the thread resumes, it will execute <code>BB</code> as if it were the start of a new instruction.</p>
<p>Okay fine, so <a title="Why don’t Windows functions begin with a pointless MOV EDI,EDI instruction on x86-64?" href="https://devblogs.microsoft.com/oldnewthing/20221109-00/?p=107373"> we&#8217;ll make sure that the original instruction is at least as big as the replacement instruction</a>, so that a frozen thread is never caught in the middle of the replacement instruction. But assuming we do that, can&#8217;t we just suspend all the threads, and then patch at will without having to worry about atomicity?</p>
<p>While it&#8217;s true that you suspended all the threads in the process, that doesn&#8217;t prevent new threads from being created in the process by a function like <code>Create­Remote­Thread</code>. The caller of <code>Create­Remote­Thread</code> can specify whether the new thread is suspended or not, and if it chooses non-suspended (or if it chose suspended and then decided to resume it), you now have a live thread running in the process while you are busy trying to patch it.</p>
<p>Atomicity is important so that you don&#8217;t accidentally patch code while an injected thread happens to be running it.</p>
<p><b>Bonus chatter</b>: Now, atomicity is still not bulletproof, because even if you manage to suspend all the threads, and prevent new ones from being injected, you still have the case where somebody calls <code>Write­Process­Memory</code> to modify the bytes of the process while everything in it is suspended.</p>
<p>And we saw earlier that <a title="Is WriteProcessMemory faster than shared memory for transferring data between two processes?" href="https://devblogs.microsoft.com/oldnewthing/20251119-00/?p=111800"> <code>Write­Process­Memory</code> is not atomic</a>, so it&#8217;s possible that a two-byte <code>Write­Process­Memory</code> writes the first byte, and then you do your atomic update of both bytes, and then the <code>Write­Process­Memory</code> finishes by writing the second byte, leaving a mishmash of your patch and the rogue one.</p>
<p>On the other hand, anybody who was using <code>Write­Process­Memory</code> to do code patching was already broken because of this lack of atomicity, so we are not introducing a new problem.</p>
<p>Furthermore, since the hot-patching space is reserved for Windows Update, an outsider that uses <code>Write­Process­Memory</code> to apply a hot-patch from another process is already breaking the rules. At this point Windows Update says, &#8220;Look, I can&#8217;t protect myself from this, and you&#8217;re in double-unsupported territory by the time we got here, so whatever happens is your problem.&#8221;</p>
<p>The post <a href="https://devblogs.microsoft.com/oldnewthing/20261106-00/?p=112838/">Why are we all worked up about atomicity when applying hot-patches if we can just suspend all the threads?</a> appeared first on <a href="https://devblogs.microsoft.com/oldnewthing">The Old New Thing</a>.</p>
]]></content:encoded>
    <wfw:commentRss>https://devblogs.microsoft.com/oldnewthing/20261106-00/?p=112838/feed/</wfw:commentRss>
    <slash:comments>0</slash:comments>
    <image type="image/png" url="https://devblogs.microsoft.com/oldnewthing/wp-content/uploads/sites/38/2025/10/banner-oldnewthing-blue.webp"/>
  </item>
		
  <item>
    <title>You shouldn&#8217;t change the style of a Win32 static control after it has been created</title>
    <link>https://devblogs.microsoft.com/oldnewthing/20261105-00/?p=112835/</link>
    <comments>https://devblogs.microsoft.com/oldnewthing/20261105-00/?p=112835/#comments</comments>
    <dc:creator><![CDATA[Raymond Chen]]></dc:creator>
    <pubDate>Thu, 05 Nov 2026 15:00:00 +0000</pubDate>
    <category><![CDATA[Old New Thing]]></category>
    <category><![CDATA[Code]]></category>
    <guid isPermaLink="false">https://devblogs.microsoft.com/oldnewthing/?p=112835</guid>
    <content:encoded><![CDATA[<p>Win32 classic static controls come with a bunch of possible styles to describe what it renders and how. Maybe it&#8217;s text. Maybe it&#8217;s an image. Maybe it&#8217;s just a solid color.</p>
<p>What happens if you create the control with one style and then change the style later?</p>
<p>Don&#8217;t do that.</p>
<p>The Win32 classic static control was originally written in the early 1980s for Windows 1.0, and back then, people didn&#8217;t play funny games like changing a static control from text to bitmap. They barely had enough memory to add two numbers together!</p>
<p>The Win32 static control decides what it is when it is created, and it doesn&#8217;t listen to the <code>WM_<wbr />STYLE­CHANGED</code> message to learn that somebody told it to change its clothes. Mostly because the <code>WM_<wbr />STYLE­CHANGED</code> message wouldn&#8217;t exist for another decade. It assumes that the style doesn&#8217;t change for the lifetime of the control.</p>
<p>If you change the style on the fly, say, from image to text, what happens is that the control starts up and realizes that it&#8217;s an image, so it loads the image. And then when it is destroyed, it checks what it is, and hopefully it still says &#8220;You&#8217;re an image,&#8221; so it frees the image. But if you secretly changed it to &#8220;You&#8217;re text&#8221;, it says &#8220;Well, in that case, I don&#8217;t have to free an image,&#8221; and the image gets leaked.</p>
<p>This behavior has remained unchanged in the static control for backward compatibility. There are almost certainly programs that &#8220;know&#8221; about this behavior when they change an image static control to a text static control, so they &#8220;fix&#8221; the problem by deleting the leaked image. If the leak were fixed in the static control, this would result in a double-delete bug.</p>
<p>So just stay away from the electrified wire. If you need to change the style of a static control, destroy it and create a new one with the new style, or create two static controls (say, one image and one text) and hide one and show the other depending on which one you need.</p>
<p>The post <a href="https://devblogs.microsoft.com/oldnewthing/20261105-00/?p=112835/">You shouldn&#8217;t change the style of a Win32 static control after it has been created</a> appeared first on <a href="https://devblogs.microsoft.com/oldnewthing">The Old New Thing</a>.</p>
]]></content:encoded>
    <wfw:commentRss>https://devblogs.microsoft.com/oldnewthing/20261105-00/?p=112835/feed/</wfw:commentRss>
    <slash:comments>4</slash:comments>
    <image type="image/png" url="https://devblogs.microsoft.com/oldnewthing/wp-content/uploads/sites/38/2025/10/banner-oldnewthing-blue.webp"/>
  </item>
		
  <item>
    <title>There are things with ranks, but it&#8217;s not always clear what the ranks mean</title>
    <link>https://devblogs.microsoft.com/oldnewthing/20261104-00/?p=112830/</link>
    <comments>https://devblogs.microsoft.com/oldnewthing/20261104-00/?p=112830/#comments</comments>
    <dc:creator><![CDATA[Raymond Chen]]></dc:creator>
    <pubDate>Wed, 04 Nov 2026 15:00:00 +0000</pubDate>
    <category><![CDATA[Old New Thing]]></category>
    <category><![CDATA[Code]]></category>
    <guid isPermaLink="false">https://devblogs.microsoft.com/oldnewthing/?p=112830</guid>
    <content:encoded><![CDATA[<p>There are a number of features in Windows that establish an order by a thing called a &#8220;rank&#8221;. Unfortunately, the documentation for them doesn&#8217;t always tell you what rank actually means. Does a higher rank take priority over a lower rank?</p>
<p>I started with SQL Server. In the documentation page <a title="Limit search results with RANK" href="https://learn.microsoft.com/en-us/sql/relational-databases/search/limit-search-results-with-rank?view=sql-server-ver17#:~:text=with%20a%20lower%20value,lower%20relevance"> Limit search results with RANK</a>, it opens by telling you that higher ranks mean better matches, or at least that lower ranks mean worse matches, which is basically the same thing:</p>
<blockquote class="q"><p>The CONTAINSTABLE and FREETEXTTABLE functions return a column named RANK that contains ordinal values from 0 through 1,000 (rank values). These values rank the rows according to how well they match the selection criteria. The rank values indicate only a relative order of relevance of the rows in the result set, <span style="border: solid 1px currentcolor;">with a lower value indicating lower relevance</span>. The actual values are unimportant and typically differ each time the query runs.</p></blockquote>
<p>It says that lower ranks are poorer-quality matches, so this implies that higher quality matches have higher ranks.</p>
<p>This &#8220;higher is better&#8221; is made more explicitly on the the RANK of a query result is a value that increases as the match quality improves: <a title="Query with Full-Text Search" href="https://learn.microsoft.com/en-us/sql/relational-databases/search/query-with-full-text-search?view=sql-server-ver17#:~:text=The%20higher%20the%20rank,full%2dtext%20query."> Query with Full-Text Search</a> page:</p>
<blockquote class="q"><p>The higher the rank value of the text or document in a row, the more relevant the row is for the given full-text query.</p></blockquote>
<p>Okay, so that&#8217;s SQL Server. Good job, SQL Server.</p>
<p>The Windows Package Graph also has the concept of rank. And here the documentation is less helpful.</p>
<p>The <i>rank</i> parameter to the <code>Add­Package­Dependency</code> function <a href="https://learn.microsoft.com/en-us/windows/win32/api/appmodel/nf-appmodel-addpackagedependency#:~:text=The%20rank%20to%20use,the%20remarks."> is documented as</a></p>
<blockquote class="q"><p>The rank to use to add the resolved package to the caller&#8217;s package graph. For more information, see the remarks.</p></blockquote>
<p>If you go down to the remarks, <a href="https://learn.microsoft.com/en-us/windows/win32/api/appmodel/nf-appmodel-addpackagedependency#:~:text=If%20multiple%20packages%20are%20present,options%20parameter."> the only mention of rank</a> is</p>
<blockquote class="q"><p>If multiple packages are present in the package graph with the same rank as the call to <b>Add­Package­Dependency</b>, the resolved package is (by default) added after others of the same rank. To add a package before others of the same rank, specify <code>Add­Package­Dependency­Options_<wbr />Prepend­If­Rank­Collision</code> for the options parameter.</p></blockquote>
<p>That&#8217;s nice, but it doesn&#8217;t tell me whether packages are searched from low rank to high, or from high rank to low. All I know is that if I want to be considered ahead of others of the <i>same</i> rank, I should pass this special flag; otherwise by default I am considered <i>after</i> others of the same rank. But it doesn&#8217;t say whether I am considered ahead of or after other packages with <i>different</i> ranks.</p>
<p>There is a &#8220;For more information&#8221; that takes me to the <a href="https://learn.microsoft.com/en-us/windows/apps/desktop/modernize/framework-packages/use-the-dynamic-dependency-api#:~:text=and%20the%20desired%20rank,graph."> Using the Dynamic Dependency API</a> page, but the only mention of rank is</p>
<blockquote class="q"><p>When you call this API, you must pass in the dependency ID that was returned when you created the install-time reference, and the desired rank to use for the MSIX package in the process&#8217;s package graph.</p></blockquote>
<p>So it tells me that I have to pass a rank, but it doesn&#8217;t tell me what the rank <i>means</i>.</p>
<p>Okay, maybe I can get a clue from another API in the Windows App SDK: <a href="https://learn.microsoft.com/en-us/windows/windows-app-sdk/api/winrt/microsoft.windows.widgets.providers.widgetinfo.rank?view=windows-app-sdk-2.0#:~:text=An%20integer%20specifying%20the%20relative%20rank,lower%20values."> The <code>Rank</code> property on the <code>WidgetInfo</code> class. Let&#8217;s see what that says. </a></p>
<blockquote class="q"><p>An integer specifying the relative rank of the widget. Smaller values are ranked higher than lower values.</p></blockquote>
<p>Okay, so I learn that ranks are relative rather than absolute values. But that second sentence makes no sense: It says that smaller values are treated differently from lower values. Huh? What&#8217;s the difference between a &#8220;smaller value&#8221; and a &#8220;lower value&#8221;? And what does &#8220;higher&#8221; rank mean anyway?</p>
<p>Unfortunately, the <a href="https://github.com/microsoft/WindowsAppSDK-Samples/tree/main/Samples/Widgets"> Widget sample</a> doesn&#8217;t use the <code>Rank</code> property, so I still don&#8217;t know.</p>
<p>This is just another example of the principle that &#8220;The person who understands the feature the best is often the person least qualified to explain it.&#8221; They know what the rank is. They&#8217;ve been working with ranks for months. To them, ranks are so obvious and intuitive that they don&#8217;t need an explanation.</p>
<p><b>Bonus chatter</b>: I contacted a colleague who works on the package graph, who explained to me how it works and also lamented how the information provided to the documentation team somehow got garbled along the way. (And put fixing it onto the backlog.)</p>
<p>The missing sentence is</p>
<blockquote class="q"><p>Packages are searched in ascending rank.</p></blockquote>
<p>In other words, at least for the package graph, lower ranks have precedence over higher ranks.</p>
<p>A process&#8217;s package graph is an ordered list of packages and is initially empty.</p>
<p>If the process has declared dependencies, then all of those packages are added to the package graph with rank zero, in the order described by <a href="https://github.com/microsoft/WindowsAppSDK/blob/main/specs/dynamicdependencies/DynamicDependencies.md#7-static-package-dependency-resolution-algorithm"> static package dependency resolution algorithm</a>.</p>
<p>Once that initial package graph is established, you can manually modify the graph by calling <code>Add­Package­Dependency</code> and <code>Remove­Package­Dependency</code>. When you add a package to the package graph, it is inserted into the graph after all the packages with lower rank and before all the packages with higher rank. By default, it also goes after all the packages with the same rank, but you can override this with <code>Add­Package­Dependency­Options_<wbr />Prepend­If­Rank­Collision</code>, which will put it in front of all the packages with the same rank.</p>
<p>In the package graph, the rank is a signed integer, so you can use a negative rank to go in front of the static package dependencies.</p>
<p><b>Bonus bonus chatter</b>: In the world of filter drivers, the applicable term is <i>altitude</i>, and the meaning <a href="https://learn.microsoft.com/en-us/windows-hardware/drivers/ifs/load-order-groups-and-altitudes-for-minifilter-drivers#:~:text=The%20altitude%20is%20an%20infinite,higher%20numerical%20value."> is quite clearly spelled out</a>:</p>
<blockquote class="q"><p>The altitude is an infinite-precision string interpreted as a decimal number. A filter driver that has a low numerical altitude is loaded into the I/O stack below a filter driver that has a higher numerical value.</p></blockquote>
<p>The post <a href="https://devblogs.microsoft.com/oldnewthing/20261104-00/?p=112830/">There are things with ranks, but it&#8217;s not always clear what the ranks mean</a> appeared first on <a href="https://devblogs.microsoft.com/oldnewthing">The Old New Thing</a>.</p>
]]></content:encoded>
    <wfw:commentRss>https://devblogs.microsoft.com/oldnewthing/20261104-00/?p=112830/feed/</wfw:commentRss>
    <slash:comments>3</slash:comments>
    <image type="image/png" url="https://devblogs.microsoft.com/oldnewthing/wp-content/uploads/sites/38/2025/10/banner-oldnewthing-blue.webp"/>
  </item>
		
  <item>
    <title>How do you implement a random-access database when you don&#8217;t have random-access external storage?</title>
    <link>https://devblogs.microsoft.com/oldnewthing/20261103-00/?p=112825/</link>
    <comments>https://devblogs.microsoft.com/oldnewthing/20261103-00/?p=112825/#comments</comments>
    <dc:creator><![CDATA[Raymond Chen]]></dc:creator>
    <pubDate>Tue, 03 Nov 2026 15:00:00 +0000</pubDate>
    <category><![CDATA[Old New Thing]]></category>
    <category><![CDATA[History]]></category>
    <guid isPermaLink="false">https://devblogs.microsoft.com/oldnewthing/?p=112825</guid>
    <content:encoded><![CDATA[<p><a title="10 REM&quot;_(C2SLFF4" href="https://beej.us/blog/data/mystery-comment/"> The mystery comment</a> investigated by <a href="https://beej.us/blog/"> Beej&#8217;s Bit Bucket</a> reminded me of a similar trick in an Apple ][ telephone directory program.</p>
<p>The base Apple ][ was sold without a floppy drive. The only supported external storage device in the base unit was a cassette I/O port. Yet there was a database program for digitizing your phone list.¹ How did it do database stuff when the only I/O was a cassette drive? It could not programmatically start or stop the tape, or programmatically rewind or advance it.</p>
<p>If you took a listing of the program (which was written in BASIC), it began with a comment block saying not to edit any lines before line 1000. And then you saw your own telephone directory stored in <code>DATA</code> statements.² Followed by a bunch of dummy <code>DATA</code> statements. And then the program began.</p>
<p>Wait, how did your telephone directory show up as <code>DATA</code> statements? The BASIC <code>DATA</code> statement was a place for the program developer to store tables of precalculated read-only data, to be consumed by the <code>READ</code> statement at runtime. They shipped the program to you without your telephone directory in it, and yet somehow your telephone data ended up in the program.</p>
<p>That&#8217;s because the program used its own <code>DATA</code> statements as the memory for a database.</p>
<p>When it wanted to read from the database, it read the data via the usual <code>READ</code> command. And when it wanted to write to the database, it used self-modifying code to <code>POKE</code> the information back into its own <code>DATA</code> statements.</p>
<p>When you told the program that you wanted to save your changes, it told you to turn on the cassette player, and then it invoked the <code>SAVE</code> command to save the program to cassette. And since the program modified itself to contain your telephone data, saving the program also saved your data that was embedded inside it.</p>
<p>When you wanted to use your telephone directory, you loaded the program from cassette and ran it.</p>
<p>Now, the Apple ][ did have routines in the monitor ROM to save a block of memory to cassette, so it could have saved the database to tape in a more traditional manner. But that would have meant that when you wanted to use your telephone directory, you first had to load the program from cassette and run it, and then you had to set up the cassette a second time to load the database. Saving the entire program meant that the two load operations (loading the program and loading the data) were combined into a single cassette pass.</p>
<p>¹ This was back in the early days when the sales pitch for personal computers included &#8220;Organize your recipes!&#8221; and &#8220;Digitize your telephone directory!&#8221; Things that nobody ever actually did. (I don&#8217;t know how many people used it for personal finance, but it was definitely <a title="VisiCalc: Information from its creators, Dan Bricklin and Bob Frankston" href="http://www.bricklin.com/visicalc.htm"> very popular for <i>business</i> finance</a>.)</p>
<p>² At least, I think it was <code>DATA</code> statements. Maybe it was comments. But the same principle applies.</p>
<p>The post <a href="https://devblogs.microsoft.com/oldnewthing/20261103-00/?p=112825/">How do you implement a random-access database when you don&#8217;t have random-access external storage?</a> appeared first on <a href="https://devblogs.microsoft.com/oldnewthing">The Old New Thing</a>.</p>
]]></content:encoded>
    <wfw:commentRss>https://devblogs.microsoft.com/oldnewthing/20261103-00/?p=112825/feed/</wfw:commentRss>
    <slash:comments>9</slash:comments>
    <image type="image/png" url="https://devblogs.microsoft.com/oldnewthing/wp-content/uploads/sites/38/2025/10/banner-oldnewthing-blue.webp"/>
  </item>
		
  <item>
    <title>Sneaking into the auditorium for the Windows 2000 launch rehearsal</title>
    <link>https://devblogs.microsoft.com/oldnewthing/20261102-00/?p=112818/</link>
    <comments>https://devblogs.microsoft.com/oldnewthing/20261102-00/?p=112818/#comments</comments>
    <dc:creator><![CDATA[Raymond Chen]]></dc:creator>
    <pubDate>Mon, 02 Nov 2026 15:00:00 +0000</pubDate>
    <category><![CDATA[Old New Thing]]></category>
    <category><![CDATA[History]]></category>
    <guid isPermaLink="false">https://devblogs.microsoft.com/oldnewthing/?p=112818</guid>
    <content:encoded><![CDATA[<p>The Windows 2000 launch in San Francisco was accompanied by an expo, and a large number of Windows 2000 team members were dispatched to run the various booths and stations, give informal presentations on the new features of Windows 2000, and answer technical questions from the various attendees. And from among the people who were sent to the expo, a smaller group was selected to attend the launch event itself in person.</p>
<p><b>Related reading</b>: <a title="A ticket to the Windows 95 launch" href="https://devblogs.microsoft.com/oldnewthing/20050824-12/?p=34453"> A ticket to the Windows 95 launch</a>.</p>
<p>After a few of us arrived early at the Civic Auditorium for the launch event, we had to entertain ourselves until the doors opened. There was some speculation as to who the celebrity host would be, since it hadn&#8217;t been announced. One of my colleagues tried to sneak into what looked like a VIP tent.¹ I, on the other hand, went exploring.</p>
<p>I found an unlocked door that took me into the empty upper level of the main auditorium.</p>
<p>I took a seat and tried not to be noticed.</p>
<p>The stage was set up with a 10-meter tall mock laptop, screens to the left and right of the stage for projecting slides, prerecorded videos, or to get a better look at on-stage close-ups, gray curtains unobtrusively hung to shield from view what would turn out to be various surprises throughout the event, and various other desks, demo areas, and even an airplane cabin set.²</p>
<p>While I sat and took in the complexity of the stage, there was an announcement that they would be rehearsing the opening in one minute. The lights dimmed in preparation. The lid of the giant laptop closed <i>very slowly</i>.</p>
<p>About ten minutes after the announcement, the rehearsal actually began.</p>
<p>The laptop lid opened, and on the laptop screen, it looked like someone was signing into Windows 2000, and then the mouse clicked the Start button. This led to a video montage, and when the montage was over, a voice announced, &#8220;Ladies and Gentlemen, please welcome Patrick Stewart!&#8221;</p>
<p>Oh my goodness, Patrick Stewart is going to be the presenter for the Windows 2000 launch!</p>
<p>Mere seconds later, onto the stage bounded&#8230; a crew member wearing a headset pretending to be Patrick Stewart so that the camera and lighting crew could make sure they were properly positioned.</p>
<p>Okay, that&#8217;s the end of the rehearsal. The lights come back on, and the auditorium once again buzzes with the sound of equipment being moved and people discussing things.</p>
<p>I left the auditorium and went back to join the crowd of people waiting to get in. I didn&#8217;t tell them who the host was.</p>
<p>The event itself seemed to go off pretty much as planned. With the real Patrick Stewart.</p>
<p>Patrick Stewart had such a commanding presence. If he had come out on stage and announced, &#8220;It is the dawn of a new era: The era of lime Jell-O&#8221;, people would say, &#8220;Yeah, lime Jell-O, I need to upgrade to lime Jell-O.&#8221; But instead of trying to spark a new dessert trend, he talked about Windows 2000, reading words from a teleprompter that he almost certainly didn&#8217;t understand, but he made them sound great.</p>
<p>¹ My colleague eventually returned with a Commemorative Edition boxed copy of Windows 2000.</p>
<p>² The airplane cabin was used for a sketch that demonstrated mobile business computing. The demoer took their laptop on a plane trip, where they happened to sit next to a character named William Wentworth, portrayed by actor John O&#8217;Hurley, president of William Wentworth Worldwide. (He gave his email address as <tt>www@www.com</tt>.) The sketch demonstrated infrared file sharing and other mobile scenarios. Remember infrared file sharing? Of course you don&#8217;t.</p>
<p>The post <a href="https://devblogs.microsoft.com/oldnewthing/20261102-00/?p=112818/">Sneaking into the auditorium for the Windows 2000 launch rehearsal</a> appeared first on <a href="https://devblogs.microsoft.com/oldnewthing">The Old New Thing</a>.</p>
]]></content:encoded>
    <wfw:commentRss>https://devblogs.microsoft.com/oldnewthing/20261102-00/?p=112818/feed/</wfw:commentRss>
    <slash:comments>12</slash:comments>
    <image type="image/png" url="https://devblogs.microsoft.com/oldnewthing/wp-content/uploads/sites/38/2025/10/banner-oldnewthing-blue.webp"/>
  </item>
		
  <item>
    <title>The Microsoft building that was reportedly haunted</title>
    <link>https://devblogs.microsoft.com/oldnewthing/20261030-00/?p=112815/</link>
    <comments>https://devblogs.microsoft.com/oldnewthing/20261030-00/?p=112815/#comments</comments>
    <dc:creator><![CDATA[Raymond Chen]]></dc:creator>
    <pubDate>Fri, 30 Oct 2026 14:00:00 +0000</pubDate>
    <category><![CDATA[Old New Thing]]></category>
    <category><![CDATA[History]]></category>
    <guid isPermaLink="false">https://devblogs.microsoft.com/oldnewthing/?p=112815</guid>
    <content:encoded><![CDATA[<p>Earlier this year, Microsoft sold what was known as Building 22, an office building just up the hill from what is now the Overlake Village Station stop on the light rail 2 line.¹ The build was demolished in late June, bring an end to a creepy piece of Microsoft history.</p>
<p>Building 22 began its life in 1982, when construction began on what was then known as the Koll Center Overlake business park. The building was owned and operated by The Koll Company, a commercial real estate company, and was scheduled to be completed in the middle of 1983.</p>
<p>In February 1991, Microsoft purchased the building from Koll, and by July it was occupied by the International Product Group.</p>
<p>During its time as a Microsoft office, Building 22 was believed by many to be haunted. The descriptions ranged from &#8220;it was creepy to say the least&#8221; to &#8220;the ghosts were quite benign&#8221; to &#8220;those ghosts were no joke&#8221;. Evidence included a phenomenon nicknamed &#8220;sick building syndrome&#8221; that made many people ill, elevator doors opening randomly, unexplained whistling or rattling sounds from the windows, occasional ghost spottings in the hallway, and at least one time that a car&#8217;s parking brake failed, causing the empty car to roll down the hill and collide with another car. Did a ghost release the brake? Who knows?</p>
<p>At the time, there was a Group Health hospital complex next door.² Somehow, the story got around that Building 22 had previously served as the morgue³ for the hospital, and I suspect that the ghost stories and the morgue theory developed in tandem. However, research by Microsoft&#8217;s own archives team could not find significant evidence that the building was ever a morgue, despite people insisting with certainty that their office was exactly where the morgue used to be.</p>
<p>Haunted or not, the new owners of the building intend to build apartments on the property. Were the ghosts sold with the building? Will the new apartment be haunted? We&#8217;ll let the future residents decide.</p>
<p><b>Bonus chatter</b>: An <a title="Defrag Tools #100 - Episode 100!!! - Campus Tour" href="https://web.archive.org/web/20201130175119/https://channel9.msdn.com/Shows/Defrag-Tools/Defrag-Tools-100-Episode-100-Campus-Tour"> old Channel 9 video</a> introduces us to Building 22, ghost included.</p>
<p><b>Bonus bonus chatter</b>: Another morbid reputation that Building 22 had was that it where teams were &#8220;sent to die&#8221;, meaning that they were transferred to the building as a final stop before the team was disbanded.</p>
<p>Some people nicknamed Building 22 &#8220;Hotel California&#8221; or &#8220;the black hole&#8221; because once you were assigned there, it was almost impossible to get out. You might get moved to another building, but somehow you ended up back in 22. One person who managed to escape quipped, &#8220;The longest two years of my career were the six months I spent there.&#8221;</p>
<p>Part of what contributed to the dreary reputation of Building 22 was that due to the steep slope of the terrain, half of the bottom floor was underground. One person who had an office on the bottom floor said that it was comfortably cool in the summer, but freezing cold in the winter.</p>
<p>Another quirk of the building was that there was bridge from the uphill side directly into the second floor. People on the first floor whose offices were in the shadow of the bridge nicknamed themselves &#8220;trolls&#8221;.</p>
<p>¹ Not to be confused with &#8220;The Village at Overlake Station&#8221;, a residential complex about four blocks from Overlake Village Station.</p>
<p>² The property was sold in 2009 and is now the Esterra Park development.</p>
<p>³ An alternate rumor was that the building used to be the psychiatric ward for the hospital, and the room above the atrium was allegedly the <a href="https://en.wikipedia.org/wiki/Padded_cell"> padded room</a> for people at risk of hurting themselves. Some people reported hearing screams from the padded room area.</p>
<p>The post <a href="https://devblogs.microsoft.com/oldnewthing/20261030-00/?p=112815/">The Microsoft building that was reportedly haunted</a> appeared first on <a href="https://devblogs.microsoft.com/oldnewthing">The Old New Thing</a>.</p>
]]></content:encoded>
    <wfw:commentRss>https://devblogs.microsoft.com/oldnewthing/20261030-00/?p=112815/feed/</wfw:commentRss>
    <slash:comments>1</slash:comments>
    <image type="image/png" url="https://devblogs.microsoft.com/oldnewthing/wp-content/uploads/sites/38/2025/10/banner-oldnewthing-blue.webp"/>
  </item>
	</channel>
</rss>
