<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>The Old New Thing</title><link>http://blogs.msdn.com/b/oldnewthing/</link><description>not actually to establish a blogging point where individuals can enrich their learns on facilitating and leveraging .NET-related activities most effectively</description><dc:language>en-US</dc:language><generator>Telligent Evolution Platform Developer Build (Build: 5.6.50428.7875)</generator><item><title>The extern "C" specifier disables C++ mangling, but that doesn't mean it disables mangling</title><link>http://blogs.msdn.com/b/oldnewthing/archive/2012/05/25/10310148.aspx</link><pubDate>Fri, 25 May 2012 14:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10310148</guid><dc:creator>Raymond Chen - MSFT</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/oldnewthing/rsscomments.aspx?WeblogPostID=10310148</wfw:commentRss><comments>http://blogs.msdn.com/b/oldnewthing/archive/2012/05/25/10310148.aspx#comments</comments><description>&lt;P&gt;
The
&lt;A HREF="http://msdn.microsoft.com/en-us/library/3y1sfaz2.aspx"&gt;
MSDN documentation on dllexport&lt;/A&gt;
contains the following enigmatic paragraph,
or at least did at the time I wrote this article:
&lt;/P&gt;
&lt;BLOCKQUOTE CLASS=q&gt;
&lt;B&gt;dllexport&lt;/B&gt; of a C++ function will expose the function
with C++ name mangling.
If C++ name mangling is not desired,
either use a .def file (EXPORTS keyword)
or declare the function as extern "C".
&lt;/BLOCKQUOTE&gt;
&lt;P&gt;
I've seen this sentence misinterpreted as follows:
&lt;/P&gt;
&lt;BLOCKQUOTE CLASS=q&gt;
&lt;B&gt;dllexport&lt;/B&gt; of a C++ function will expose the function
with C++ name mangling.
&lt;U&gt;To disable name mangling&lt;/U&gt;
either use a .def file (EXPORTS keyword)
or declare the function as extern "C".
&lt;/BLOCKQUOTE&gt;
&lt;P&gt;
This is an understandable misinterpretation, but it is still a
misinterpretation.
&lt;/P&gt;
&lt;P&gt;
The root cause of the misinterpretation is that
the author of this documentation was wearing
&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2011/05/12/10163578.aspx"&gt;
C++-colored glasses&lt;/A&gt;.
In the author's mind,
there are only two interesting cases:
&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;C++ name mangling, where all the cool people are, and
&lt;LI&gt;everything else, for all the lamers.
&lt;/OL&gt;
&lt;P&gt;
Here is a precise formulation of the paragraph:
&lt;/P&gt;
&lt;BLOCKQUOTE CLASS=q&gt;
&lt;B&gt;dllexport&lt;/B&gt; of a C++ function will expose the function
with C++ name mangling.
If C++ name mangling is not desired,
either use a .def file (EXPORTS keyword),
&lt;U&gt;which will expose the name without mangling&lt;/U&gt;,
or declare the function as extern "C",
&lt;U&gt;which will expose the name with
&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2004/01/08/48616.aspx"&gt;
C mangling&lt;/A&gt;&lt;/U&gt;.
&lt;/BLOCKQUOTE&gt;
&lt;P&gt;
Here's a version of the paragraph
that tries to take away the C++-colored glasses.
&lt;/P&gt;
&lt;BLOCKQUOTE CLASS=q&gt;
&lt;B&gt;dllexport&lt;/B&gt; exposes the function as it is decorated by the compiler.
For example,
if the function is a C++ function, it will be exposed with C++ name
mangling.
If the function is a C function, or has been declared as
&lt;CODE&gt;extern "C"&lt;/CODE&gt;,
it will be exposed with C name mangling.
To expose the function under its unmangled name (or to expose it
via an alternate name), use
use a .def file (EXPORTS keyword).
&lt;/BLOCKQUOTE&gt;
&lt;P&gt;
&lt;B&gt;Behind the scenes&lt;/B&gt;:
To forestall nitpickers, I had to go back to my copy of the C++
standard to make sure I filled in the blank in
"The &lt;CODE&gt;extern "C"&lt;/CODE&gt; _________" correctly.
Officially, &lt;CODE&gt;extern "C"&lt;/CODE&gt; is a &lt;I&gt;storage class specifier&lt;/I&gt;.
&lt;/P&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10310148" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/oldnewthing/archive/tags/Code/">Code</category></item><item><title>How do I prevent unchecked checkboxes in my listview control from disappearing?</title><link>http://blogs.msdn.com/b/oldnewthing/archive/2012/05/24/10309682.aspx</link><pubDate>Thu, 24 May 2012 14:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10309682</guid><dc:creator>Raymond Chen - MSFT</dc:creator><slash:comments>21</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/oldnewthing/rsscomments.aspx?WeblogPostID=10309682</wfw:commentRss><comments>http://blogs.msdn.com/b/oldnewthing/archive/2012/05/24/10309682.aspx#comments</comments><description>&lt;P&gt;
A customer asked,
"I have a listview control in report view with the
&lt;CODE&gt;LVS_&lt;WBR&gt;EX_&lt;WBR&gt;CHECK&amp;shy;BOXES&lt;/CODE&gt; extended style.
I noticed that unchecked checkboxes are not visible until I hover
over the corresponding item.
Is it possible to get the checkboxes to be visible all the time?"
&lt;/P&gt;
&lt;P&gt;
I was kind of puzzled by this question because the default
behavior of the list view control is to show the checkboxes all the time.
I could have sat down and written a test program to prove it,
but that would have taken too much time, and it wouldn't have
advanced the story any.
(The customer would merely have written back,
"Well, that's not what I'm seeing.")
&lt;/P&gt;
&lt;P&gt;
This appeared to be a case of a customer providing incomplete
information, forcing me to invoke my psychic powers to fill them in.
&lt;/P&gt;
&lt;P&gt;
"My psychic powers tell me that you have also set the
&lt;CODE&gt;LVS_&lt;WBR&gt;EX_&lt;WBR&gt;AUTO&amp;shy;CHECK&amp;shy;SELECT&lt;/CODE&gt; extended
style.
When
&lt;CODE&gt;LVS_&lt;WBR&gt;EX_&lt;WBR&gt;AUTO&amp;shy;CHECK&amp;shy;SELECT&lt;/CODE&gt; is set,
then unchecked checkboxes are hidden."
&lt;/P&gt;
&lt;P&gt;
Remember, when you ask a question about a component and you have
done any customization to that component, please remember to
mention that when you ask your question.
Otherwise nobody will be able to reproduce your problem,
because they will assume you left everything at the defaults.
&lt;/P&gt;
&lt;P&gt;
It's like calling the Ikea customer service line, saying
"My Ikea
&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2004/01/29/64390.aspx"&gt;
Frustr&amp;auml;t&lt;/A&gt; rolling cabinet doesn't roll properly on my
hardwood floor when I put more than about 25 pounds of stuff on it."
The person on the phone looks up the specifications for the
rolling cabinet and sees that that is well within the design limits.
"I paid for you guys to assemble and install it, so it can't be
an assembly or installation error."
The person on the other end scratches their head for a while.
And then you mention,
"Oh, but I didn't like the color of the wheels, so I replaced
them with some other wheels I bought at Home Depot."
&lt;/P&gt;
&lt;P&gt;
Oh, yeah, thanks for not mentioning that.
&lt;/P&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10309682" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/oldnewthing/archive/tags/Code/">Code</category></item><item><title>GUIDs are designed to be unique, not random</title><link>http://blogs.msdn.com/b/oldnewthing/archive/2012/05/23/10309199.aspx</link><pubDate>Wed, 23 May 2012 14:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10309199</guid><dc:creator>Raymond Chen - MSFT</dc:creator><slash:comments>39</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/oldnewthing/rsscomments.aspx?WeblogPostID=10309199</wfw:commentRss><comments>http://blogs.msdn.com/b/oldnewthing/archive/2012/05/23/10309199.aspx#comments</comments><description>&lt;P&gt;
A customer liaison asked,
"My customer is looking for information on the GUID generation algorithm.
They need to select &lt;I&gt;N&lt;/I&gt;&amp;nbsp;items randomly
from a pool of&amp;nbsp;&lt;I&gt;M&lt;/I&gt; (jury selection),
and their proposed algorithm is to assign each item a GUID,
then sort the items by GUID and take the first&amp;nbsp;&lt;I&gt;N&lt;/I&gt;."
(I've seen similar questions regarding using GUIDs for
things like passwords or other situations where the
programmer is looking for a way to generate a value
that cannot be predicted.)&lt;/P&gt;
&lt;P&gt;
The GUID generation algorithm was designed for uniqueness.
It was not designed for randomness or for unpredictability.
Indeed, if you look at
&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2008/06/27/8659071.aspx"&gt;
an earlier discussion&lt;/A&gt;,
you can see that so-called Algorithm&amp;nbsp;1
is &lt;I&gt;non-random&lt;/I&gt; and &lt;I&gt;totally predictable&lt;/I&gt;.
If you use an Algorithm&amp;nbsp;1 GUID generator to
assign GUIDs to candidates, you'll find that
the GUIDs are assigned in numerically ascending order
(because the timestamp increases).
The customer's proposed algorithm would
most likely
end up
choosing for jury duty the first&amp;nbsp;&lt;I&gt;N&lt;/I&gt;
people entered into the system
after a 32-bit timer rollover.
Definitely not random.
&lt;/P&gt;
&lt;P&gt;
Similarly, the person who wanted to use a GUID
for password generation would find that the passwords
are &lt;I&gt;totally predictable&lt;/I&gt;
if you know what time the GUID was generated
and which computer generated the GUID
(which you can get by looking at the final six bytes
from some other password-GUID).
Totally-predictable passwords are probably not a good idea.
&lt;/P&gt;
&lt;P&gt;
Even the Version&amp;nbsp;4 GUID algorithm
(which basically says "set the version to 4
and fill everything else with
random or pseudo-random numbers")
is not guaranteed to be unpredictable,
because the algorithm does not specify the quality
of the random number generator.
&lt;A HREF="http://en.wikipedia.org/wiki/Globally_unique_identifier"&gt;
The Wikipedia article for GUID contains primary research which suggests&lt;/A&gt;
that future and previous GUIDs can be predicted based on knowledge
of the random number generator state,
since the generator is not cryptographically strong.
&lt;/P&gt;
&lt;P&gt;
If you want a random number generator, then
&lt;I&gt;use a random number generator&lt;/I&gt;.
&lt;/P&gt;
&lt;P&gt;
&lt;B&gt;Bonus reading&lt;/B&gt;:
Eric Lippert's GUID Guide,
&lt;A HREF="http://blogs.msdn.com/b/ericlippert/archive/2012/04/24/guid-guide-part-one.aspx"&gt;
part 1&lt;/A&gt;,
&lt;A HREF="http://blogs.msdn.com/b/ericlippert/archive/2012/04/30/guid-guide-part-two.aspx"&gt;
part 2&lt;/A&gt;,
and
&lt;A HREF="http://blogs.msdn.com/b/ericlippert/archive/2012/05/07/guid-guide-part-three.aspx"&gt;
part 3&lt;/A&gt;.
&lt;/P&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10309199" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/oldnewthing/archive/tags/Code/">Code</category></item><item><title>Why is the Close button in the upper right corner?</title><link>http://blogs.msdn.com/b/oldnewthing/archive/2012/05/22/10308528.aspx</link><pubDate>Tue, 22 May 2012 14:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10308528</guid><dc:creator>Raymond Chen - MSFT</dc:creator><slash:comments>45</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/oldnewthing/rsscomments.aspx?WeblogPostID=10308528</wfw:commentRss><comments>http://blogs.msdn.com/b/oldnewthing/archive/2012/05/22/10308528.aspx#comments</comments><description>Chris wants to know
&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2010/07/20/10040074.aspx#10040418"&gt;
how the close button ended up to the right of the minimize and
maximize/restore buttons&lt;/A&gt;.
"In OS/2, it is on the left, which left the two other buttons in place."
&lt;/P&gt;
&lt;P&gt;
I don't know why the Close button went to the upper right
instead of going to the left of the other buttons,
but I'm going to guess.
(That's what I do around here most of the time anyway;
I just don't usually call it out.)
&lt;/P&gt;
&lt;P&gt;
Two words:
&lt;A HREF="http://en.wikipedia.org/wiki/Fitts's_law"&gt;
Fitts's Law&lt;/A&gt;.
&lt;/P&gt;
&lt;P&gt;
The corners of the screen are very valuable,
because users can target them with very little effort.
You just slam the mouse in the direction you want,
and the cursor goes into the corner.
And since closing a window is a much more common operation
than minimizing, maximizing, and restoring it,
it seems a natural choice to give the close button the
preferred location.
&lt;/P&gt;
&lt;P&gt;
Besides, maximizing and restoring a window
already have very large targets,
namely the entire caption.
You can double-click the caption to maximize,
and double-click again to restore.
The restore even gets you a little bit of Fitt's Law
action
because the top of the screen makes the height of the
caption bar effectively infinite.
&lt;/P&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10308528" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/oldnewthing/archive/tags/History/">History</category></item><item><title>What was the registry like in 16-bit Windows?</title><link>http://blogs.msdn.com/b/oldnewthing/archive/2012/05/21/10307822.aspx</link><pubDate>Mon, 21 May 2012 14:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10307822</guid><dc:creator>Raymond Chen - MSFT</dc:creator><slash:comments>21</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/oldnewthing/rsscomments.aspx?WeblogPostID=10307822</wfw:commentRss><comments>http://blogs.msdn.com/b/oldnewthing/archive/2012/05/21/10307822.aspx#comments</comments><description>&lt;P&gt;
Commenter Niels
wonders
&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2008/01/17/7137438.aspx"&gt;
when and how the registry was introduced to 16-bit Windows&lt;/A&gt;
and how much of it carried over to Windows&amp;nbsp;95.
&lt;/P&gt;
&lt;P&gt;
The 16-bit registry was
&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2008/01/17/7137438.aspx"&gt;
extremely simple&lt;/A&gt;.
There were just keys, no values.
The only
&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2003/08/08/54618.aspx"&gt;
hive&lt;/A&gt;
was &lt;CODE&gt;HKEY_&lt;WBR&gt;CLASSES_&lt;WBR&gt;ROOT&lt;/CODE&gt;.
All it was used for was COM objects and file associations.
The registry was stored in the &lt;CODE&gt;REG.DAT&lt;/CODE&gt; file,
and its maximum size was
64&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2009/06/11/9725386.aspx"
&gt;KB&lt;/A&gt;.
&lt;/P&gt;
&lt;P&gt;
It is my recollection that the registry was introduced in Windows&amp;nbsp;3.1,
but Niels says it's not in a plain vanilla install,
so I guess my memory is faulty.
&lt;/P&gt;
&lt;P&gt;
None of the 16-bit registry code was carried over to Windows&amp;nbsp;95.
Windows&amp;nbsp;95 extended the registry into kernel mode,
added support for values and non-string data types,
increased the maximum registry size (though if some people are to be
believed, not by enough),
and added a bunch of other hives, like
added the &lt;CODE&gt;HKEY_&lt;WBR&gt;CURRENT_&lt;WBR&gt;USER&lt;/CODE&gt;,
&lt;CODE&gt;HKEY_&lt;WBR&gt;LOCAL_&lt;WBR&gt;MACHINE&lt;/CODE&gt;,
and
the &lt;CODE&gt;HKEY_&lt;WBR&gt;DYN_&lt;WBR&gt;DATA&lt;/CODE&gt;,
The old 16-bit registry code was woefully inadequate for
all these new requirements
(especially the kernel mode part),
so it was all thrown out and a brand new registry written.
&lt;/P&gt;
&lt;P&gt;
In the early days of the Windows&amp;nbsp;95 registry,
the in-memory
&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2007/06/04/3069949.aspx"&gt;
signature value&lt;/A&gt;
to identify the data structures which represent an open registry key
were four bytes which corresponded to
the ASCII values for the initials of the two programmers
who wrote it.
&lt;/P&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10307822" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/oldnewthing/archive/tags/History/">History</category></item><item><title>How to view the stack of threads that were terminated as part of process teardown from user mode</title><link>http://blogs.msdn.com/b/oldnewthing/archive/2012/05/18/10306501.aspx</link><pubDate>Fri, 18 May 2012 14:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10306501</guid><dc:creator>Raymond Chen - MSFT</dc:creator><slash:comments>25</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/oldnewthing/rsscomments.aspx?WeblogPostID=10306501</wfw:commentRss><comments>http://blogs.msdn.com/b/oldnewthing/archive/2012/05/18/10306501.aspx#comments</comments><description>&lt;P&gt;
Last time we saw
&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2012/05/17/10306078.aspx"&gt;
how to view the stack of threads that were terminated
as part of process teardown from the kernel debugger&lt;/A&gt;.
You can do the same thing from a user-mode debugger,
and it's actually a bit easier there.
(The user-mode debugger I'm using is the one that comes with the
&lt;A HREF="http://msdn.microsoft.com/en-us/windows/hardware/gg463009"&gt;
Debugging Tools for Windows&lt;/A&gt;,
the debugging engine that goes by a number of different front-ends,
such as &lt;CODE&gt;ntsd&lt;/CODE&gt;, &lt;CODE&gt;cdb&lt;/CODE&gt;, and &lt;CODE&gt;windbg&lt;/CODE&gt;.)
&lt;/P&gt;
&lt;P&gt;
A direct translation of the kernel-mode technique from last
time would involve using the
&lt;CODE&gt;!vadump&lt;/CODE&gt; command and picking through for the
memory blocks with candidate size and attributes.
But there's an easier way.
&lt;/P&gt;
&lt;BLOCKQUOTE CLASS=m&gt;
Now would be a good point for me to remind you that
this information is
&lt;B&gt;for debugging purposes only&lt;/B&gt;.
The structures and offsets are all implementation details
which can change from release to release.
&lt;/BLOCKQUOTE&gt;
&lt;P&gt;
Recall that the TEB begins with some pointers which
bound the stack, and the seventh pointer is a self-pointer.
What's even more useful is the thirteenth pointer
(offset 0x30 for 32-bit TEBs, offset 0x60 for 64-bit TEBs),
because that is where the
&lt;A HREF="http://msdn.microsoft.com/en-us/library/ff564670.aspx"&gt;
PEB&lt;/A&gt; is stored.
&lt;/P&gt;
&lt;P&gt;
Each process has a single global PEB, so all the TEBs will have
the same PEB value at offset 0x30/0x60.
And you can figure out the address of the current process's
PEB either by using the !peb command or by simply looking
at the TEB you already have.
&lt;/P&gt;
&lt;PRE&gt;
0:000&amp;gt; dd fs:30 l1
0053:00000030  &lt;U&gt;7efde000&lt;/U&gt;
&lt;/PRE&gt;
&lt;P&gt;
Now you can search through memory looking for that value.
If you see any hits at offset 0x30/0x60, then that's a candidate TEB.
&lt;/P&gt;
&lt;P&gt;
The debugger normally limits memory scans to 256MB.
&lt;/P&gt;
&lt;PRE&gt;
0:001&amp;gt; s 00000000 L 80000000 00 e0 fd 7e
                           ^ Range error in 's 00000000 l 80000000 00 e0 fd 7e'
&lt;/PRE&gt;
&lt;P&gt;
Therefore, you have to issue the search eight times (for 32-bit processes)
to cover the 2GB user-mode address space.
&lt;/P&gt;
&lt;PRE&gt;
0:001&amp;gt; s 00000000 L 10000000 00 e0 fd 7e
0009e01c  00 e0 fd 7e 00 d0 fd 7e-44 e0 09 00 7b ef 17 77  ...~...~D...{..w
0009fdc0  00 e0 fd 7e 44 00 00 00-f0 ee 3a 00 10 ef 3a 00  ...~D.....:...:.
0009fe34  00 e0 fd 7e 78 fe 09 00-02 9f 18 77 00 e0 fd 7e  ...~x......w...~
0:001&amp;gt; s 10000000 L 10000000 00 e0 fd 7e
0:001&amp;gt; s 20000000 L 10000000 00 e0 fd 7e
0:001&amp;gt; s 30000000 L 10000000 00 e0 fd 7e
0:001&amp;gt; s 40000000 L 10000000 00 e0 fd 7e
0:001&amp;gt; s 50000000 L 10000000 00 e0 fd 7e
0:001&amp;gt; s 60000000 L 10000000 00 e0 fd 7e
0:001&amp;gt; s 70000000 L 10000000 00 e0 fd 7e
7486af70  00 e0 fd 7e 00 00 00 00-b8 00 16 77 28 00 16 77  ...~.......w(..w
7efda030  00 e0 fd 7e 00 00 00 00-00 00 00 00 00 00 00 00  ...~............
7efdd030  00 e0 fd 7e 00 00 00 00-00 00 00 00 00 00 00 00  ...~............
&lt;/PRE&gt;
&lt;P&gt;
Alternatively, you can use the "length sanity check override"
by inserting a question mark after the L:
&lt;/P&gt;
&lt;PRE&gt;
0:001&amp;gt; s 00000000 L?80000000 00 e0 fd 7e
0009e01c  00 e0 fd 7e 00 d0 fd 7e-44 e0 09 00 7b ef 17 77  ...~...~D...{..w
0009fdc0  00 e0 fd 7e 44 00 00 00-f0 ee 3a 00 10 ef 3a 00  ...~D.....:...:.
0009fe34  00 e0 fd 7e 78 fe 09 00-02 9f 18 77 00 e0 fd 7e  ...~x......w...~
7486af70  00 e0 fd 7e 00 00 00 00-b8 00 16 77 28 00 16 77  ...~.......w(..w
7efda030  00 e0 fd 7e 00 00 00 00-00 00 00 00 00 00 00 00  ...~............
7efdd030  00 e0 fd 7e 00 00 00 00-00 00 00 00 00 00 00 00  ...~............
&lt;/PRE&gt;
&lt;P&gt;
From the above output, we see that we can quickly reject all but
the last two entries because the offset within the page is not
the magic value 0x30.
(This is a 32-bit process.)
Hooray, two debugger commands reduce the search space to just
two pages!
&lt;/P&gt;
&lt;P&gt;
At this point, you can continue with the debugging technique from last
time, looking at each candidate TEB to see if there's a valid stack in there.
&lt;/P&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10306501" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/oldnewthing/archive/tags/Other/">Other</category></item><item><title>Charles Petzold is back with another edition of Programming Windows</title><link>http://blogs.msdn.com/b/oldnewthing/archive/2012/05/17/10306079.aspx</link><pubDate>Thu, 17 May 2012 14:00:01 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10306079</guid><dc:creator>Raymond Chen - MSFT</dc:creator><slash:comments>32</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/oldnewthing/rsscomments.aspx?WeblogPostID=10306079</wfw:commentRss><comments>http://blogs.msdn.com/b/oldnewthing/archive/2012/05/17/10306079.aspx#comments</comments><description>&lt;P&gt;
Back in the day (and perhaps still true today),
&lt;A HREF="http://www.charlespetzold.com/"&gt;Charles Petzold&lt;/A&gt;'s
&lt;I&gt;Programming Windows&lt;/I&gt; was
the definitive source for learning to program Windows.
The book is so old that even I used it to learn Windows programming,
back when everything was 16-bit and uphill both ways.
The most recent edition is
&lt;A HREF="http://www.amazon.com/exec/obidos/ISBN=157231995X?tag=tholneth-20"&gt;
&lt;I&gt;Programming Windows, 5th Edition&lt;/I&gt;&lt;/A&gt;,
which was published way back in 1998.
What has he been doing since then?
My guess would have been
"sitting on a beach in Hawai&amp;#x02BB;i,"
but apparently he's been writing books on
&lt;A HREF="http://www.amazon.com/exec/obidos/ASIN/0735613702?tag=tholneth-20"&gt;
C#&lt;/A&gt;
and
&lt;A HREF="http://www.amazon.com/exec/obidos/ASIN/0735621535?tag=tholneth-20"&gt;
Windows Forms&lt;/A&gt;
and
&lt;A HREF="http://www.amazon.com/exec/obidos/ASIN/0735619573?tag=tholneth-20"&gt;
WPF&lt;/A&gt;
and
&lt;A HREF="http://msdn.microsoft.com/en-us/magazine/ff798276.aspx"&gt;
Silverlight&lt;/A&gt;.
Hey, I could still be right:
Maybe he writes the books while sitting on a beach in Hawai&amp;#x02BB;i.
&lt;/P&gt;
&lt;P&gt;
It appears that Windows&amp;nbsp;8 has brought Mr. Petzold
back to the topic of Windows progarmming,
and despite his earlier claims that
&lt;A HREF="http://www.charlespetzold.com/faq.html"&gt;
he has no plans to write a sixth edition of
&lt;I&gt;Programming Windows&lt;/I&gt;&lt;/A&gt;,
it turns out that
&lt;A HREF="http://www.charlespetzold.com/blog/2012/05/Programming-Windows-6th-Edition-Preview-Ebook-Coming.html"&gt;
he's writing a sixth edition of
&lt;I&gt;Programming Windows&lt;/I&gt;&lt;/A&gt; specifically for Windows&amp;nbsp;8.
(Perhaps he could subtitle his book
&lt;I&gt;The New Old Thing&lt;/I&gt;.)
&lt;/P&gt;
&lt;P&gt;
Here's where it gets interesting.
&lt;/P&gt;
&lt;P&gt;
Before the book officially releases (target date November 15),
there will be two pre-release versions in eBook form,
one based on the Consumer Preview of Windows&amp;nbsp;8
and one based on the Release Preview.
&lt;/P&gt;
&lt;P&gt;
Now it gets &lt;I&gt;really&lt;/I&gt; interesting:
If you order the Consumer Preview eBook,
it comes with free upgrades to the Release Preview eBook
as well as the final eBook.
(If you order the Release Preview eBook, then it comes
with a free upgrade to the final eBook.)
&lt;/P&gt;
&lt;P&gt;
Can it get even more interesting than that? You bet!
Because the price of getting in on the action increases
the longer you wait.
Act now, and you can get the
Consumer Preview eBook (and all the free upgrades that come with it)
for just $10.
Wait a few weeks, and it'll cost you $20.
Wait another few months, and it'll cost you $30;
after another few weeks the price goes up to $40,
and if you are a lazy bum and wait until the final eBook
to be released, it'll cost you $50.
&lt;/P&gt;
&lt;P&gt;
But in order to take advantage of this offer,
you have to
&lt;A HREF="http://blogs.msdn.com/b/microsoft_press/archive/2012/04/21/mark-your-calendars-programming-windows-sixth-edition-is-coming.aspx"&gt;
&lt;B&gt;follow the instructions on this blog entry from Microsoft Press&lt;/B&gt;&lt;/A&gt;
(and read the mandatory legal mumbo-jumbo,
because the lawyers always get their say).
&lt;/P&gt;
&lt;P&gt;
&lt;B&gt;Bonus chatter&lt;/B&gt;:
One publisher asked me if
I wanted to write a book on programming Windows&amp;nbsp;8,
but I told them that I was too busy
&lt;A HREF="http://technet.microsoft.com/en-us/magazine/hh921911.aspx"&gt;
shipping&lt;/A&gt;
Windows&amp;nbsp;8
to have any extra time to write a book about it.
And it's a good thing I turned them down,
because imagine if I decided to write the book
and found that Charles Petzold was coming out of retirement
to write his own book.
My book would have done even worse than
&lt;A HREF="http://blogs.msdn.com/oldnewthing/archive/2006/12/07/1233002.aspx"&gt;
my first book&lt;/A&gt;,
which didn't even have any competition!
&lt;/P&gt;
&lt;P&gt;
&lt;B&gt;Bonus disclaimer&lt;/B&gt;:
Charles Petzold did not pay me to write this,
nor did he offer me a cut of his royalties
for shilling his book.
But that doesn't mean I won't accept it!
(Are you listening, Charles?)
&lt;/P&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10306079" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/oldnewthing/archive/tags/Other/">Other</category></item><item><title>How to view the stack of threads that were terminated as part of process teardown from the kernel debugger</title><link>http://blogs.msdn.com/b/oldnewthing/archive/2012/05/17/10306078.aspx</link><pubDate>Thu, 17 May 2012 14:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10306078</guid><dc:creator>Raymond Chen - MSFT</dc:creator><slash:comments>6</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/oldnewthing/rsscomments.aspx?WeblogPostID=10306078</wfw:commentRss><comments>http://blogs.msdn.com/b/oldnewthing/archive/2012/05/17/10306078.aspx#comments</comments><description>&lt;P&gt;
As we saw some time ago,
&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2007/05/03/2383346.aspx"&gt;
process shutdown is a multi-phase affair&lt;/A&gt;.
After you call &lt;CODE&gt;ExitProcess&lt;/CODE&gt;,
all the threads are forcibly terminated.
After that's done, each DLL is sent a &lt;CODE&gt;DLL_PROCESS_DETACH&lt;/CODE&gt;
notification.
You may be debugging
a problem with &lt;CODE&gt;DLL_PROCESS_DETACH&lt;/CODE&gt; handling
that suggests that some of those threads were not cleaned up properly.
For example, you might assert that a reference count is zero,
and you find during process shutdown that this assertion sometimes fires.
Maybe you terminated a thread before it got a chance to release
its reference?
How can you test this theory if the thread is already gone?
&lt;/P&gt;
&lt;P&gt;
It so happens that when all the threads are terminated during the
early phase of process shutdown,
the kernel is a bit lazy and doesn't free their stacks.
It figures, hey, the entire process is going away soon,
so the stack memory is going to be cleaned up as part of process
termination.
(It's sort of the kernel equivalent of
&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2012/01/05/10253268.aspx"&gt;
not bothering to sweep the floor
of a building that's about to be demolished&lt;/A&gt;.)
You can use this to your advantage by &lt;I&gt;grovelling the stacks
that were left behind&lt;/I&gt;.
&lt;/P&gt;
&lt;P&gt;
Hey, this is why you get called in to debug the hard stuff, right?
&lt;/P&gt;
&lt;BLOCKQUOTE CLASS=m&gt;
Before continuing, I need to emphasize that this information is
&lt;B&gt;for debugging purposes only&lt;/B&gt;.
The structures and offsets are all implementation details
which can change from release to release.
&lt;/BLOCKQUOTE&gt;
&lt;P&gt;
The first step is to identify where all the stacks are.
The direct approach is difficult because the stacks can be all
different sizes, so it's not easy to pick them out of a line-up.
But one thing does come in a consistent size: The
&lt;A HREF="http://msdn.microsoft.com/en-us/library/ff565433.aspx"&gt;
TEB&lt;/A&gt;.
&lt;/P&gt;
&lt;P&gt;
From the kernel debugger, use the &lt;CODE&gt;!process&lt;/CODE&gt; command
to dump the process you are interested in,
and from the header information, extract the &lt;CODE&gt;VadRoot&lt;/CODE&gt;.
&lt;/P&gt;
&lt;PRE&gt;
1: kd&amp;gt; !process -1
PROCESS 8731bd40  SessionId: 1  Cid: 0748    Peb: 7ffda000  ParentCid: 0620
    DirBase: 4247b000  ObjectTable: 96f66de0  HandleCount: 104.
    Image: oopsie.exe
    &lt;FONT COLOR=red&gt;&lt;U&gt;VadRoot 893de570&lt;/U&gt;&lt;/FONT&gt; Vads 124 Clone 0 Private 518. Modified 643. Locked 0.
    DeviceMap 995628c0
&lt;/PRE&gt;
&lt;P&gt;
Dump this VAD root with the &lt;CODE&gt;!vad&lt;/CODE&gt; command,
and pay attention only to the entries which say
&lt;CODE&gt;1 Private READWRITE&lt;/CODE&gt;.
&lt;/P&gt;
&lt;PRE&gt;
1: kd&amp;gt; !vad &lt;U&gt;893de570&lt;/U&gt;
VAD     level      start      end    commit
... ignore everything except "1 Private READWRITE" ...
8730a5f0 ( 6)         50       50         1 Private      READWRITE
9ab0cb40 ( 5)         60       7f         1 Private      READWRITE
893978b0 ( 6)         80       9f         1 Private      READWRITE
87302d30 ( 5)        110      110         1 Private      READWRITE
889693f8 ( 6)        120      121         1 Private      READWRITE
872f3fb8 ( 6)        170      170         1 Private      READWRITE
87089a80 ( 6)        1a0      1a0         1 Private      READWRITE
8cbf1cb0 ( 5)        1c0      1df         1 Private      READWRITE
88c079d0 ( 6)        1e0      1e0         1 Private      READWRITE
9abc33e0 ( 6)        410      48f         1 Private      READWRITE
873173b0 ( 7)        970      970         1 Private      READWRITE
8ca1c158 ( 7)      7ffd5    7ffd5         1 Private      READWRITE
88c02a78 ( 6)      7ffd6    7ffd6         1 Private      READWRITE
872f9298 ( 5)      7ffd7    7ffd7         1 Private      READWRITE
8750d210 ( 7)      7ffd8    7ffd8         1 Private      READWRITE
87075ce8 ( 6)      7ffda    7ffda         1 Private      READWRITE
87215da0 ( 4)      7ffdc    7ffdc         1 Private      READWRITE
872f2200 ( 6)      7ffdd    7ffdd         1 Private      READWRITE
8730a670 ( 5)      7ffdf    7ffdf         1 Private      READWRITE
&lt;/PRE&gt;
&lt;P&gt;
(If you are debugging from user mode, then you can use
&lt;CODE&gt;!vadump&lt;/CODE&gt; but the output format is different.)
&lt;/P&gt;
&lt;P&gt;
Each of these is a candidate TEB.
In practice, TEBs tend to be allocated at the high end of memory,
so the ones with a low &lt;CODE&gt;start&lt;/CODE&gt; value are probably
red herrings.
Therefore, you should investigate these candidates in reverse order.
&lt;/P&gt;
&lt;P&gt;
For each candidate, take the &lt;CODE&gt;start&lt;/CODE&gt; address and append
three zeroes.
(Each page on x86 is 4KB, which conveniently maps to 1000 in hex.)
Dump the first seven
pointers of the TEB with the &lt;CODE&gt;dp xxxxx000 L7&lt;/CODE&gt;
command.
&lt;/P&gt;
&lt;PRE&gt;
1: kd&amp;gt; dp 7ffdf000 L7
7ffdf000  0016fbb0 00170000 0016b000 00000000
7ffdf010  00001e00 00000000 7ffdf000 &amp;larr; hit
&lt;/PRE&gt;
&lt;P&gt;
If the TEB is valid, then the seventh pointer points back
to the start of the TEB.
In a valid TEB,
the second and third values are the
stack limits; in this case, the candidate stack lives between
&lt;CODE&gt;0016b000&lt;/CODE&gt; and &lt;CODE&gt;00170000&lt;/CODE&gt;.
(As a double-check, you can verify that the upper limit of the
stack, &lt;CODE&gt;00170000&lt;/CODE&gt; in this case, matches up with
the end of a VAD allocation in the &lt;CODE&gt;!vad&lt;/CODE&gt; output above.)
&lt;/P&gt;
&lt;P&gt;
Now that you know where the stack is, you can &lt;CODE&gt;dps&lt;/CODE&gt; it
and
&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2011/03/09/10138401.aspx"&gt;
look for EBP frames&lt;/A&gt;.
(I usually start about two to four pages below the upper limit of the stack.)
Test out each candidate EBP frame with the &lt;CODE&gt;k=&lt;/CODE&gt; command
until you find one that seems to be solid.
Record this candidate stack trace in a text file for further study.
&lt;/P&gt;
&lt;P&gt;
Repeat for each candidate TEB, and you will eventually reconstruct
what each thread in the process was doing at the moment it was
terminated.
If you're really lucky, you might even see the code that incremented
the reference count
but was terminated before it could release it.
&lt;/P&gt;
&lt;P&gt;
The above discussion also applies to debugging 64-bit processes.
However, instead of looking for
&lt;CODE&gt;1 Private READWRITE&lt;/CODE&gt; pages, you want to look for
&lt;CODE&gt;2 Private READWRITE&lt;/CODE&gt; pages.
As an additional wrinkle, if you are debugging ia64, then converting
a page frame to a linear address is sadly not as simple as appending
three zeroes.
Pages on ia64 are 8KB, not 4KB, so you need to shift the value left
by 25 bits: Add three zeroes and then multiply by two.
&lt;/P&gt;
&lt;P&gt;
And finally, if you are debugging a 32-bit process on x64,
then you want to look for &lt;CODE&gt;3 Private READWRITE&lt;/CODE&gt; pages,
but add 2 before appending the three zeroes.
That's because the TEB for a 32-bit process on x64 is really two
TEBs glued together: A 64-bit TEB followed by a 32-bit TEB.
&lt;/P&gt;
&lt;P&gt;
&lt;B&gt;Note&lt;/B&gt;:
I did not come up with this debugging technique on my own.
I learned it from an even greater debugging genius.
&lt;/P&gt;
&lt;P&gt;
&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2012/05/18/10306501.aspx"&gt;
Next time&lt;/A&gt;, we'll look at debugging this issue from a user-mode
debugger.
&lt;/P&gt;
&lt;P&gt;
&lt;B&gt;Trivia&lt;/B&gt;:
The informal term for these terminated-but-not-yet-completely-destroyed
threads is &lt;I&gt;ghost threads&lt;/I&gt;.
The term was coined by the Exchange support team,
because they often have to study server failures
that require them to do this type of investigation,
and they needed a cute name for it.
&lt;/P&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10306078" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/oldnewthing/archive/tags/Other/">Other</category></item><item><title>Sure, we do that: Context menu edition</title><link>http://blogs.msdn.com/b/oldnewthing/archive/2012/05/16/10305605.aspx</link><pubDate>Wed, 16 May 2012 14:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10305605</guid><dc:creator>Raymond Chen - MSFT</dc:creator><slash:comments>17</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/oldnewthing/rsscomments.aspx?WeblogPostID=10305605</wfw:commentRss><comments>http://blogs.msdn.com/b/oldnewthing/archive/2012/05/16/10305605.aspx#comments</comments><description>&lt;P&gt;
A customer
&lt;A HREF="http://blogs.msdn.com/b/aaron_margosis/archive/2004/06/23/163229.aspx#1370794"&gt;
reported a problem that occurred only when they
installed a particular application&lt;/A&gt;.
If they uninstalled it, then the problem went away.
After installing the application, the "Run As" context menu
option stopped working.
The customer didn't provide any other details,
but we were able to make an educated guess as to what was going on.
&lt;/P&gt;
&lt;P&gt;
A common programming error in context menu extensions occurs in
extensions which add only one menu item.
These extensions ignore the parameters to the
&lt;CODE&gt;IContextMenu::InvokeCommand&lt;/CODE&gt; and simply assume that
the only reason the method can be called is if the user selected
their menu item.
After all, if you have only one invokable item, there's no need
to figure out which one the user selected, because you have only
one to begin with!
&lt;/P&gt;
&lt;P&gt;
The problem is that a context menu extension can be invoked
not because the user selected an item under its control
but because a verb is
&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2004/11/26/270710.aspx"&gt;
being invoked programmatically&lt;/A&gt;,
and each handler is being asked,
"Do you know how to do this?"
&lt;/P&gt;
&lt;P&gt;
The result is that the context menu host calls the extension to say,
"If you know how to do &lt;CODE&gt;runas&lt;/CODE&gt;, then please do so,"
and the the extension says
"&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2004/02/11/71307.aspx"
&gt;Sure, we do that&lt;/A&gt;" and starts doing its thing.
If you are unlucky and the grabby extension is asked the question
before the actual &lt;CODE&gt;runas&lt;/CODE&gt; extension,
the &lt;CODE&gt;runas&lt;/CODE&gt; command winds up being hijacked by the grabby
extension.
&lt;/P&gt;
&lt;P&gt;
(This is the same mistake that causes
&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2004/02/02/66160.aspx"&gt;
the Copy To and Move To commands to behave strangely if you add
them to the context menu&lt;/A&gt;:
They assume that the only reason they are invoked is that the user
invoked their command, because they weren't designed to be hosted
by context menus to begin with!
They were designed to go into the toolbar, and the toolbar hosting
code never invoked commands by name.
It's like taking a ladder and using it as a bridge between two tall
buildings.
Sure, you can now cross from one building to another,
but you also run a serious risk of falling to your death.)
&lt;/P&gt;
&lt;P&gt;
A variation on the initial problem is
"I found that after installing a particular program, I can't
run anything from the Start menu."
I know of at least two programs which install
context menu extensions which steal the "open" command
on executables.
&lt;/P&gt;
&lt;P&gt;
This problem is sufficiently prevalent that there is a
&lt;A HREF="http://social.technet.microsoft.com/Forums/en-US/w7itproui/thread/6a138e65-2834-41ac-bd40-c2344e20b824#209450a5-e1d2-4f3d-bd0f-076e9d7de315"&gt;
special compatibility flag that can be set on a shell extension&lt;/A&gt;
to say,
"This is a grabby shell extension that steals commands.
Never ask it if it supports anything, because it will
always say yes!"
&lt;/P&gt;
&lt;P&gt;
Notice that the "MoveTo CopyTo Context Menu" is on the list,
which I find interesting because MoveTo/CopyTo was never meant
to go on the context menu in the first place.
Going back to our analogy, it'd be as if the ladder company
issued a safety bulletin to warn people of problems
that can occur if you use it as a bridge between two tall buildings!
&lt;/P&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10305605" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/oldnewthing/archive/tags/Tips_2F00_Support/">Tips/Support</category></item><item><title>Microspeak: The parking lot</title><link>http://blogs.msdn.com/b/oldnewthing/archive/2012/05/15/10305119.aspx</link><pubDate>Tue, 15 May 2012 14:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10305119</guid><dc:creator>Raymond Chen - MSFT</dc:creator><slash:comments>18</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/oldnewthing/rsscomments.aspx?WeblogPostID=10305119</wfw:commentRss><comments>http://blogs.msdn.com/b/oldnewthing/archive/2012/05/15/10305119.aspx#comments</comments><description>&lt;P&gt;
Mike Dunn wonders
&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2010/07/20/10040074.aspx#10040753"&gt;
what the Microspeak term &lt;I&gt;parking lot&lt;/I&gt; means&lt;/A&gt;.
&lt;/P&gt;
&lt;P&gt;
I'm not familiar with this term either,
and the first document I turned up during my search was
a PowerPoint presentation that said
"Avoid using Microsoft jargon terms, such as &lt;I&gt;parking lot&lt;/I&gt;
and
&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2011/08/02/10191834.aspx"&gt;
&lt;I&gt;dogfood&lt;/I&gt;&lt;/A&gt;."
&lt;/P&gt;
&lt;P&gt;
Yeah, that wasn't much help.
&lt;/P&gt;
&lt;P&gt;
From what I can gather,
the term &lt;I&gt;parking lot&lt;/I&gt; started out as a term used during
brainstorming sessions.
You've got a bunch of people in a conference room tossing out all
sorts of ideas.
The traditional way of organizing the ideas is to write each one
on a Post-It&amp;reg; note and stick it on the whiteboard.
As more and more notes appear,
you start to organize them by grouping together similar ideas.
&lt;/P&gt;
&lt;P&gt;
Every so often, you'll run into an idea that, while good,
isn't really relevant to the problem you're trying to solve.
You don't want to throw it away, so instead, you designate
a corner of the whiteboard to be the place to "park" those ideas
for later consideration.
That corner of the whiteboard is nicknamed the
&lt;I&gt;parking lot&lt;/I&gt;.
&lt;/P&gt;
&lt;P&gt;
The term &lt;I&gt;parking lot&lt;/I&gt; then began to be applied to
the document that collected all of these "parked" ideas,
so they could be circulated to a more appropriate audience.
&lt;/P&gt;
&lt;P&gt;
The term then expanded to refer to any document
which served as the official repository of assorted suggestions
for future work or discussion.
(Known to some people simply as
&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2010/05/31/10017567.aspx"&gt;
&lt;I&gt;The List&lt;/I&gt;&lt;/A&gt;.)
For example, there is a SharePoint List titled
&lt;I&gt;Active Issues&lt;/I&gt; and the subtitle
&lt;I&gt;parking lot for discussion topics in weekly XYZ meeting&lt;/I&gt;.
Each item on the list is assigned to a particular person and
assigned a priority.
&lt;/P&gt;
&lt;P&gt;
I can't find any citations for &lt;I&gt;parking lot&lt;/I&gt; being used
as a way to say something like "we'll talk about this after
the meeting is over,"
but I can see how it could be related to the sense of
&lt;I&gt;parking lot&lt;/I&gt; I was able to turn up:
The parking lot is the list of things that aren't really
relevant to the topic at hand but which are still worth discussing.
We just won't discuss them here.
&lt;/P&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10305119" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/oldnewthing/archive/tags/Other/">Other</category><category domain="http://blogs.msdn.com/b/oldnewthing/archive/tags/Microspeak/">Microspeak</category></item><item><title>What is the historical reason for MulDiv(1, -0x80000000, -0x80000000) returning 2?</title><link>http://blogs.msdn.com/b/oldnewthing/archive/2012/05/14/10304701.aspx</link><pubDate>Mon, 14 May 2012 14:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10304701</guid><dc:creator>Raymond Chen - MSFT</dc:creator><slash:comments>47</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/oldnewthing/rsscomments.aspx?WeblogPostID=10304701</wfw:commentRss><comments>http://blogs.msdn.com/b/oldnewthing/archive/2012/05/14/10304701.aspx#comments</comments><description>&lt;P&gt;
Commenter rs asks,
"&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2010/07/20/10040074.aspx#10040424"
&gt;Why does Windows (historically) return 2 for
&lt;CODE&gt;MulDiv(1, -0x80000000, -0x80000000)&lt;/CODE&gt; while Wine returns zero?&lt;/A&gt;"
&lt;/P&gt;
&lt;P&gt;
The &lt;CODE&gt;MulDiv&lt;/CODE&gt; function multiplies the first two parameters
and divides by the third. Therefore, the mathematically correct
answer for 
&lt;CODE&gt;MulDiv(1, &lt;NOBR&gt;-0x80000000,&lt;/NOBR&gt;
&lt;NOBR&gt;-0x80000000)&lt;/NOBR&gt;&lt;/CODE&gt; is 1,
because
&lt;I&gt;a&lt;/I&gt;&amp;nbsp;&amp;times;
&lt;I&gt;b&lt;/I&gt;&amp;nbsp;&amp;divide;
&lt;I&gt;b&lt;/I&gt;&amp;nbsp;=&amp;nbsp;&lt;I&gt;a&lt;/I&gt; for all nonzero&amp;nbsp;&lt;I&gt;b&lt;/I&gt;.
&lt;/P&gt;
&lt;P&gt;
So both Windows and Wine get it wrong.
I don't know why Wine gets it wrong, but I dug through the
archives to figure out what happened to Windows.
&lt;/P&gt;
&lt;P&gt;
First, some background.
What's the point of the &lt;CODE&gt;MulDiv&lt;/CODE&gt; function anyway?
&lt;/P&gt;
&lt;P&gt;
Back in the days of 16-bit Windows,
floating point was very expensive.
Most people did not have math coprocessors,
so floating point was performed via software emulation.
And the software emulation was slow.
First, you issued a floating point operation on the assumption
that you had a float point coprocessor.
If you didn't, then a &lt;I&gt;coprocessor not available&lt;/I&gt;
exception was raised.
This exception handler had a lot of work to do.
&lt;/P&gt;
&lt;P&gt;
It decoded the instruction that caused
the exception and then emulated the operation.
For example, if the bytes at the point of the exception were
&lt;CODE&gt;d9 45 08&lt;/CODE&gt;, the exception handler would have to
figure out that the instruction was &lt;CODE&gt;fld dword ptr ds:[di][8]&lt;/CODE&gt;.
It then had to simulate the operation of that instruction.
In this case, it would
retrieve the caller's &lt;CODE&gt;di&lt;/CODE&gt; register,
add 8 to that value,
load four bytes from that address
(relative to the caller's &lt;CODE&gt;ds&lt;/CODE&gt; register),
expand them from 32-bit floating point to 80-bit floating point,
and push them onto a pretend floating point stack.
Then it advanced the instruction pointer three bytes and
resumed execution.
&lt;/P&gt;
&lt;P&gt;
This took an instruction that with a coprocessor would take
around 40 cycles (already slow) and ballooned its total execution
time to a few hundred, probably thousand cycles.
(I didn't bother counting. Those who are offended by this
horrific laziness on my part can apply for a refund.)
&lt;/P&gt;
&lt;P&gt;
It was in this sort of floating point-hostile environment that
Windows was originally developed.
As a result,
Windows has historically avoided using floating point and preferred
to use integers.
And one of the things you often have to do with integers is
scale them by some ratio.
For example, a horizontal dialog unit is &amp;frac14; of the average
character width, and a vertical dialog unit is 1/8 of the average
character height.
If you have a value of, say, 15 horizontal dlu, the corresponding
number of pixels is
15 &amp;times; average character width &amp;divide; 4.
This multiply-then-divide operation is quite common, and that's
the model that the &lt;CODE&gt;MulDiv&lt;/CODE&gt; function is designed to
help out with.
&lt;/P&gt;
&lt;P&gt;
In particular, &lt;CODE&gt;MulDiv&lt;/CODE&gt; took care of three
things that a simple
&lt;I&gt;a&lt;/I&gt;&amp;nbsp;&amp;times;
&lt;I&gt;b&lt;/I&gt;&amp;nbsp;&amp;divide;
&lt;I&gt;c&lt;/I&gt; didn't.
(And remember, we're in 16-bit Windows, so &lt;I&gt;a&lt;/I&gt;,
&lt;I&gt;b&lt;/I&gt;&amp;nbsp;and&amp;nbsp;&lt;I&gt;c&lt;/I&gt; are all 16-bit signed values.)
&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;The intermediate product &lt;I&gt;a&lt;/I&gt;&amp;nbsp;&amp;times;&amp;nbsp;&lt;I&gt;b&lt;/I&gt; was
    computed as a 32-bit value, thereby avoiding overflow.
&lt;LI&gt;The result was &lt;I&gt;rounded&lt;/I&gt; to the nearest integer instead
    of truncated toward zero
&lt;LI&gt;If &lt;I&gt;c&lt;/I&gt;&amp;nbsp;=&amp;nbsp;0 or if the result did not fit
    in a signed 16-bit integer, it returned &lt;I&gt;INT_MAX&lt;/I&gt;
    or &lt;I&gt;INT_MIN&lt;/I&gt; as appropriate.
&lt;/UL&gt;
&lt;P&gt;
The &lt;CODE&gt;MulDiv&lt;/CODE&gt; function was written in assembly language,
as was most of GDI at the time.
Oh right, the &lt;CODE&gt;MulDiv&lt;/CODE&gt; function was exported by GDI
in 16-bit Windows.
Why?
Probably because they were the people who needed the function first,
so they ended up writing it.
&lt;/P&gt;
&lt;P&gt;
Anyway, after I studied the assembly language for the function,
I found the bug.
A &lt;CODE&gt;shr&lt;/CODE&gt; instruction was accidentally coded as &lt;CODE&gt;sar&lt;/CODE&gt;.
The problem manifests itself only for the denominator
&lt;A HREF="http://blogs.msdn.com/b/ericlippert/archive/2011/01/24/spot-the-defect-bad-comparisons-part-two.aspx"&gt;
&lt;CODE&gt;&amp;minus;0x8000&lt;/CODE&gt;&lt;/A&gt;, because that's the only one whose
absolute value has the high bit set.
&lt;/P&gt;
&lt;P&gt;
The purpose of the &lt;CODE&gt;sar&lt;/CODE&gt; instruction was to divide the
denominator by two, so it can get the appropriate rounding behavior
when there is a remainder.
Reverse-compiling back into C, the function goes like this:
&lt;/P&gt;
&lt;PRE&gt;
int16 MulDiv(int16 a, int16 b, int16 c)
{
 int16 sign = a ^ b ^ c; // sign of result

 // make everything positive; we will apply sign at the end
 if (a &amp;lt; 0) a = -a;
 if (b &amp;lt; 0) b = -b;
 if (c &amp;lt; 0) c = -c;

 //  add half the denominator to get rounding behavior
 uint32 prod = UInt16x16To32(a, b) + c / 2;
 if (HIWORD(prod) &amp;gt;= c) goto overflow;
 int16 result = UInt32Div16To16(prod, c);
 if (result &amp;lt; 0) goto overflow;
 if (sign &amp;lt; 0) result = -result;
 return result;

overflow:
 return sign &amp;lt; 0 ? INT_MIN : INT_MAX;
}
&lt;/PRE&gt;
&lt;P&gt;
Given that I've already told you where the bug is,
it should be pretty easy to spot in the code above.
&lt;/P&gt;
&lt;P&gt;
Anyway, when this assembly language function was ported
to Win32, it was ported as, well, an assembly language function.
And the port was so successful,
it even preserved (probably by accident) the sign extension bug.
&lt;/P&gt;
&lt;P&gt;
Mind you, it's a bug with amazing seniority.
&lt;/P&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10304701" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/oldnewthing/archive/tags/History/">History</category></item><item><title>Warum deine Mutter Deutsch spricht</title><link>http://blogs.msdn.com/b/oldnewthing/archive/2012/05/11/10304033.aspx</link><pubDate>Fri, 11 May 2012 14:00:01 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10304033</guid><dc:creator>Raymond Chen - MSFT</dc:creator><slash:comments>18</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/oldnewthing/rsscomments.aspx?WeblogPostID=10304033</wfw:commentRss><comments>http://blogs.msdn.com/b/oldnewthing/archive/2012/05/11/10304033.aspx#comments</comments><description>&lt;P&gt;
This upcoming Sunday is
Mother's Day in the United States.
In recognition of the holiday last year,
a local church displayed the following message on its message board:
"God couldn't be / everywhere / so God made mothers / German speaking."
&lt;/P&gt;
&lt;P&gt;
This explains why your mother speaks German.
&lt;/P&gt;
&lt;P&gt;
POIDH
&lt;/P&gt;
&lt;P&gt;
&lt;IMG SRC="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-29-05/0702.20120511.POIDH.jpg"
    WIDTH=351 HEIGHT=263&gt;
&lt;/P&gt;
&lt;P&gt;
The church in question has an evening German-language service,
and the advertisement for that service juxtaposed against the
Jewish proverb produced an unexpected result.
&lt;/P&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10304033" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/oldnewthing/archive/tags/Non_2D00_Computer/">Non-Computer</category></item><item><title>When you crash on a mov ebx, eax instruction, there aren't too many obvious explanations, so just try what you can</title><link>http://blogs.msdn.com/b/oldnewthing/archive/2012/05/11/10304032.aspx</link><pubDate>Fri, 11 May 2012 14:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10304032</guid><dc:creator>Raymond Chen - MSFT</dc:creator><slash:comments>20</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/oldnewthing/rsscomments.aspx?WeblogPostID=10304032</wfw:commentRss><comments>http://blogs.msdn.com/b/oldnewthing/archive/2012/05/11/10304032.aspx#comments</comments><description>&lt;P&gt;
A computer running some tests encountered a mysterious crash:
&lt;/P&gt;
&lt;PRE&gt;
eax=ffffffff ebx=00000000 ecx=038ef548 edx=17b060b4 esi=00000000 edi=038ef6f0
eip=14ae1b77 esp=038ef56c ebp=038ef574 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010202
FOO!CFrameWnd::GetAssociatedWidget+0x47:
14ae1b77 8bd8            mov     ebx,eax 
&lt;/PRE&gt;
&lt;P&gt;
A colleague of mine quickly diagnosed the proximate cause.
&lt;/P&gt;
&lt;BLOCKQUOTE CLASS=q&gt;
&lt;P&gt;
*Something* marked the code page PAGE_READWRITE,
instead of PAGE_EXECUTE_READ.
I suspect a bug in a driver.
FOO is just a victim here.
&lt;/P&gt;
&lt;PRE&gt;
0:002&amp;gt; !vprot 14ae1b77 
BaseAddress:       14ae1000
AllocationBase:    14ae0000
AllocationProtect: 00000080  PAGE_EXECUTE_WRITECOPY
RegionSize:        00001000
State:             00001000  MEM_COMMIT
Protect:           00000004  PAGE_READWRITE
Type:              01000000  MEM_IMAGE
&lt;/PRE&gt;
&lt;/BLOCKQUOTE&gt;
&lt;P&gt;
This diagnosis was met with astonishment.
"Wow!
What made you think to check the protection on the code page?"
&lt;/P&gt;
&lt;P&gt;
Well, let's see.
We're crashing on a &lt;CODE&gt;mov ebx, eax&lt;/CODE&gt; instruction.
This does not access memory;
it's a register-to-register operation.
There's no way a
properly functioning CPU
can raise an exception on this instruction.
&lt;/P&gt;
&lt;P&gt;
At this point, what possibilities remain?
&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;NX, which prevents the CPU from executing data.
&lt;LI&gt;
    &lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2005/04/12/407562.aspx"&gt;
    Overclocking&lt;/A&gt;, which will cause all sorts of "impossible" things.
&lt;LI&gt;
    &lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2006/04/21/580608.aspx"&gt;
    A root kit&lt;/A&gt;.
&lt;/UL&gt;
&lt;P&gt;
(Note that the second and third options involve rejecting the assumption
that the CPU is behaving properly.)
&lt;/P&gt;
&lt;P&gt;
These are in increasing order of paranoia,
so you naturally
&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2011/02/10/10127054.aspx"&gt;
start with the least paranoid possibility&lt;/A&gt;.
&lt;/P&gt;
&lt;P&gt;
Then, of course, there's the non-psychic solution:
Ask the debugger for the exception record.
&lt;/P&gt;
&lt;PRE&gt;
EXCEPTION_RECORD:  ffffffff -- (.exr 0xffffffffffffffff)
ExceptionAddress: 14ae1b77 (FOO!CFrameWnd::GetAssociatedWidget+0x00000047)
   ExceptionCode: c0000005 (Access violation)
  ExceptionFlags: 00000000
NumberParameters: 2
   Parameter[0]: 00000008
   Parameter[1]: 14ae1b77
&lt;FONT COLOR=blue&gt;Attempt to execute non-executable address&lt;/FONT&gt; 14ae1b77
&lt;/PRE&gt;
&lt;P&gt;
That last line pretty much hands it to you on a silver platter.
&lt;/P&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10304032" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/oldnewthing/archive/tags/Code/">Code</category></item><item><title>Cheap amusement: Searching for spelling errors in the registry</title><link>http://blogs.msdn.com/b/oldnewthing/archive/2012/05/10/10303506.aspx</link><pubDate>Thu, 10 May 2012 14:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10303506</guid><dc:creator>Raymond Chen - MSFT</dc:creator><slash:comments>34</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/oldnewthing/rsscomments.aspx?WeblogPostID=10303506</wfw:commentRss><comments>http://blogs.msdn.com/b/oldnewthing/archive/2012/05/10/10303506.aspx#comments</comments><description>&lt;P&gt;
One source of cheap amusement is searching for spelling errors
in the registry.
For example, one program tried to register a new file extension,
or at least they tried,
except that they spelled &lt;CODE&gt;Extension&lt;/CODE&gt; wrong.
&lt;/P&gt;
&lt;P&gt;
And they wonder why that feature never worked.
&lt;/P&gt;
&lt;P&gt;
My discovery was that my registry contained the mysterious key
&lt;CODE&gt;HKEY_&lt;WBR&gt;CURRENT_&lt;WBR&gt;USER\S&lt;/CODE&gt;.
After some debugging, I finally found the culprit.
There was a program on my computer that did the equivalent of this:
&lt;/P&gt;
&lt;PRE&gt;
RegCreateKeyA(HKEY_CURRENT_USER, (PCSTR)L"Software\\...", &amp;amp;hk);
&lt;/PRE&gt;
&lt;P&gt;
One of my colleagues remarked,
"With enough force, any peg will fit in any hole."
&lt;/P&gt;
&lt;P&gt;
I suspect that the code was not that aggressively wrong.
It was probably something
&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2012/03/28/10288227.aspx"&gt;
more subtle&lt;/A&gt;.
&lt;/P&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10303506" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/oldnewthing/archive/tags/Other/">Other</category></item><item><title>How do I hide a window without blocking on it?</title><link>http://blogs.msdn.com/b/oldnewthing/archive/2012/05/09/10302679.aspx</link><pubDate>Wed, 09 May 2012 14:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10302679</guid><dc:creator>Raymond Chen - MSFT</dc:creator><slash:comments>35</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/oldnewthing/rsscomments.aspx?WeblogPostID=10302679</wfw:commentRss><comments>http://blogs.msdn.com/b/oldnewthing/archive/2012/05/09/10302679.aspx#comments</comments><description>&lt;P&gt;
A customer was working on improving their application startup
performance.
They found that if their application was launched immediately
after a fresh boot,
the act of dismissing their splash screen was taking over 5%
of their boot time.
Their code removed the splash screen by calling
&lt;CODE&gt;Show&amp;shy;Window(hwndSplash, SW_HIDE)&lt;/CODE&gt;.
They suspect that the splash screen thread has, for some reason,
stopped responding to messages,
and while an investigation into that avenue was undertaken,
a parallel investigation into reducing the cost of hiding the
splash screen was also begun.
&lt;/P&gt;
&lt;P&gt;
One of the things they tried was to remove the
&lt;CODE&gt;WS_&lt;WBR&gt;EX_&lt;WBR&gt;TOOL&amp;shy;WINDOW&lt;/CODE&gt; style
and call &lt;CODE&gt;ITaskbarList::DeleteTab(hwndSplash)&lt;/CODE&gt;
but they found that it wasn't helping.
&lt;/P&gt;
&lt;P&gt;
The reason it wasn't helping is that
&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2011/02/21/10131989.aspx"&gt;
editing the window
style generates &lt;CODE&gt;WM_&lt;WBR&gt;STYLE&amp;shy;CHANGING&lt;/CODE&gt;/&lt;WBR
&gt;&lt;CODE&gt;WM_&lt;WBR&gt;STYLE&amp;shy;CHANGED&lt;/CODE&gt; messages to the
target window&lt;/A&gt;,
and now you're back where you started.
&lt;/P&gt;
&lt;P&gt;
A better way is to use
&lt;CODE&gt;Show&amp;shy;Window&amp;shy;Async(hwndSplash, SW_HIDE)&lt;/CODE&gt;.
The &lt;CODE&gt;-Async&lt;/CODE&gt; version of the
&lt;CODE&gt;Show&amp;shy;Window&lt;/CODE&gt; function is the
&lt;CODE&gt;Send&amp;shy;Notify&amp;shy;Message&lt;/CODE&gt;
version of &lt;CODE&gt;Show&amp;shy;Window&lt;/CODE&gt;:
If the window belongs to another thread group,
then it schedules the operation but does not wait for it to complete.
&lt;/P&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10302679" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/oldnewthing/archive/tags/Code/">Code</category></item><item><title>Why can't I use the file sharing wizard if I exclude inheritable permissions from a folder's parent?</title><link>http://blogs.msdn.com/b/oldnewthing/archive/2012/05/08/10301998.aspx</link><pubDate>Tue, 08 May 2012 14:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10301998</guid><dc:creator>Raymond Chen - MSFT</dc:creator><slash:comments>34</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/oldnewthing/rsscomments.aspx?WeblogPostID=10301998</wfw:commentRss><comments>http://blogs.msdn.com/b/oldnewthing/archive/2012/05/08/10301998.aspx#comments</comments><description>&lt;P&gt;
In Windows Vista and Windows Server 2008,
if you go to a the advanced security settings for a directory
and uncheck "include inheritable permissions from this
object's parent",
then go back to the Sharing tab,
you'll find that the "Share" button is disabled.
Why is this?
We don't see this behavior on Windows&amp;nbsp;7 or
Windows Server 2008&amp;nbsp;R2.
&lt;/P&gt;
&lt;P&gt;
(Yes, a customer actually noticed and asked the question.)
&lt;/P&gt;
&lt;P&gt;
The sharing wizard in
Windows Vista and Windows Server 2008 does not support
folders with the &lt;CODE&gt;SE_&lt;WBR&gt;DACL_&lt;WBR&gt;PROTECTED&lt;/CODE&gt;
security descriptor control bit
because it isn't sure that it can restore the ACL afterward.
&lt;/P&gt;
&lt;P&gt;
And as the customer noted, this restriction was lifted in
Windows&amp;nbsp;7 and Windows Server 2008&amp;nbsp;R2.
&lt;/P&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10301998" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/oldnewthing/archive/tags/Tips_2F00_Support/">Tips/Support</category></item><item><title>Why are the Windows 7 system notification icons colorless?</title><link>http://blogs.msdn.com/b/oldnewthing/archive/2012/05/07/10301625.aspx</link><pubDate>Mon, 07 May 2012 14:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10301625</guid><dc:creator>Raymond Chen - MSFT</dc:creator><slash:comments>41</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/oldnewthing/rsscomments.aspx?WeblogPostID=10301625</wfw:commentRss><comments>http://blogs.msdn.com/b/oldnewthing/archive/2012/05/07/10301625.aspx#comments</comments><description>&lt;P&gt;
Mike wondered
&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2010/07/20/10040074.aspx#10040329"&gt;
why the system notification icons went colorless in Windows&amp;nbsp;7&lt;/A&gt;
and why they went back to regular tooltips instead of the custom
tooltips.
&lt;/P&gt;
&lt;P&gt;
I don't know either, so I asked
&lt;A HREF="http://blogs.msdn.com/b/larryosterman/"&gt;
Larry Osterman&lt;/A&gt;,
who was in charge of the Volume icon.
&lt;/P&gt;
&lt;P&gt;
And he didn't know either.
He was merely given new icons by the design team.
&lt;/P&gt;
&lt;P&gt;
But that doesn't stop me from guessing.
(Which is what I do most of the time here,
I just don't explicitly say that I'm guessing.)
&lt;/P&gt;
&lt;P&gt;
My guess is that the design team looked at the new Windows&amp;nbsp;7
taskbar and noticed that all the system-provided pieces
were subdued and unobtrusive, with two exceptions:
The Start button itself and the notification icons.
The Start button kept its bright colors because, well, it's the
Start button.
But the notification icons?
They are peripheral elements; why do they stand out on an otherwise
neutral-looking taskbar?
Isn't that just drawing the user's attention to something that
doesn't deserve attention?
&lt;/P&gt;
&lt;P&gt;
So boom, make them monochromatic to fit with the
other taskbar elements.
The clock is monochromatic.
The Show Desktop button is monochromatic.
The taskbar itself is monochromatic.
Hooray, aesthetic unity is restored.
&lt;/P&gt;
&lt;P&gt;
As for the return to standard tooltips,
that's easy:
&lt;A HREF="http://msdn.microsoft.com/en-us/library/aa511448.aspx#richtooltips"&gt;
The custom tooltip was
a violation of the user interface guidelines&lt;/A&gt;.
&lt;/P&gt;
&lt;P&gt;
The old Windows Vista custom tooltip did not provide any useful
information beyond the standard tooltip,
so you paid the cost of developing and maintaining a custom tooltip
for very little benefit.
In the volume tooltip's case, the developers were spending effort
fixing little bugs here and there (for example, there were painting
glitches under certain accessibility conditions),
effort that was detracting from other work that could be done,
and switching to the standard tooltip made all the problems go away.
&lt;/P&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10301625" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/oldnewthing/archive/tags/History/">History</category></item><item><title>How does the MultiByteToWideChar function treat invalid characters?</title><link>http://blogs.msdn.com/b/oldnewthing/archive/2012/05/04/10300670.aspx</link><pubDate>Fri, 04 May 2012 14:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10300670</guid><dc:creator>Raymond Chen - MSFT</dc:creator><slash:comments>9</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/oldnewthing/rsscomments.aspx?WeblogPostID=10300670</wfw:commentRss><comments>http://blogs.msdn.com/b/oldnewthing/archive/2012/05/04/10300670.aspx#comments</comments><description>&lt;P&gt;
The &lt;CODE&gt;MB_&lt;WBR&gt;ERR_&lt;WBR&gt;INVALID_&lt;WBR&gt;CHARS&lt;/CODE&gt; flag
controls how the
&lt;CODE&gt;Multi&amp;shy;Byte&amp;shy;To&amp;shy;Wide&amp;shy;Char&lt;/CODE&gt;
function treats invalid characters.
Some people claim that the following sentences in the documentation
are contradictory:
&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;"Starting with Windows Vista, the function does not drop
    illegal code points if the application does not set the flag."
&lt;LI&gt;"Windows XP: If this flag is not set,
    the function silently drops illegal code points."
&lt;LI&gt;"The function fails if
    &lt;CODE&gt;MB_&lt;WBR&gt;ERR_&lt;WBR&gt;INVALID_&lt;WBR&gt;CHARS&lt;/CODE&gt; is set
    and an invalid character is encountered in the source string."
&lt;/UL&gt;
&lt;P&gt;
Actually, the three sentences are talking about different cases.
The first two talk about what happens if you omit the flag;
the third talks about what happens if you include the flag.
&lt;/P&gt;
&lt;P&gt;
Since people seem to like tables, here's a description of
the &lt;CODE&gt;MB_&lt;WBR&gt;ERR_&lt;WBR&gt;INVALID_&lt;WBR&gt;CHARS&lt;/CODE&gt; flag
in tabular form:
&lt;/P&gt;
&lt;TABLE BORDER=1 BORDERCOLOR=black
    STYLE="border-collapse: collapse; border: solid .75pt black"&gt;
&lt;TR&gt;
    &lt;TH&gt;&lt;CODE&gt;MB_&lt;WBR&gt;ERR_&lt;WBR&gt;INVALID_&lt;WBR&gt;CHARS&lt;/CODE&gt; set?&lt;/TH&gt;
    &lt;TH&gt;Operating system&lt;/TH&gt;
    &lt;TH&gt;Treatment of invalid character&lt;/TH&gt;
&lt;/TR&gt;
&lt;TR&gt;
    &lt;TD&gt;Yes&lt;/TD&gt;
    &lt;TD&gt;Any&lt;/TD&gt;
    &lt;TD&gt;Function fails&lt;/TD&gt;
&lt;/TR&gt;
&lt;TR&gt;
    &lt;TD ROWSPAN=2&gt;No&lt;/TD&gt;
    &lt;TD&gt;XP and earlier&lt;/TD&gt;
    &lt;TD&gt;Character is dropped&lt;/TD&gt;
&lt;/TR&gt;
&lt;TR&gt;
    &lt;TD&gt;Vista and later&lt;/TD&gt;
    &lt;TD&gt;Character is not dropped&lt;/TD&gt;
&lt;/TR&gt;
&lt;/TABLE&gt;
&lt;P&gt;
Here's a sample program that illustrates the possibilities:
&lt;/P&gt;
&lt;PRE&gt;
#include &amp;lt;windows.h&amp;gt;
#include &amp;lt;ole2.h&amp;gt;
#include &amp;lt;windowsx.h&amp;gt;
#include &amp;lt;commctrl.h&amp;gt;
#include &amp;lt;strsafe.h&amp;gt;
#include &amp;lt;uxtheme.h&amp;gt;

void MB2WCTest(DWORD flags)
{
 WCHAR szOut[256];
 int cch = MultiByteToWideChar(CP_UTF8, flags,
                               "\xC0\x41\x42", 3, szOut, 256);
 printf("Called with flags %d\n", flags);
 printf("Return value is %d\n", cch);
 for (int i = 0; i &amp;lt; cch; i++) {
  printf("value[%d] = %d\n", i, szOut[i]);
 }
 printf("-----\n");
}

int __cdecl main(int argc, char **argv)
{
 MB2WCTest(0);
 MB2WCTest(MB_ERR_INVALID_CHARS);
 return 0;
}
&lt;/PRE&gt;
&lt;P&gt;
If you run this on Windows&amp;nbsp;XP, you get
&lt;/P&gt;
&lt;PRE&gt;
Called with flags 0
Return value is 2
Value[0] = 65
Value[1] = 66
-----
Called with flags 8
Return value is 0
-----
&lt;/PRE&gt;
&lt;P&gt;
This demonstrates that passing the
&lt;CODE&gt;MB_&lt;WBR&gt;ERR_&lt;WBR&gt;INVALID_&lt;WBR&gt;CHARS&lt;/CODE&gt; flag
causes the function to fail,
and omitting it causes
the invalid character \xC0 to be dropped.
&lt;/P&gt;
&lt;P&gt;
If you run this on Windows&amp;nbsp;Vista, you get
&lt;/P&gt;
&lt;PRE&gt;
Called with flags 0
Return value is 3
Value[0] = 65533
Value[1] = 65
Value[2] = 66
-----
Called with flags 8
Return value is 0
-----
&lt;/PRE&gt;
&lt;P&gt;
This demonstrates again that passing the
&lt;CODE&gt;MB_&lt;WBR&gt;ERR_&lt;WBR&gt;INVALID_&lt;WBR&gt;CHARS&lt;/CODE&gt; flag
causes the function to fail,
but this time, if you omit the flag,
the invalid character \xC0 is converted to U+FFFD,
which is
&lt;A HREF="http://en.wikipedia.org/wiki/Specials (Unicode block)#Replacement_character"&gt;
REPLACEMENT CHARACTER&lt;/A&gt;.
(Note that it does not appear to be documented precisely
&lt;I&gt;what&lt;/I&gt; happens to invalid characters, aside from the fact
that they are not dropped.
Perhaps code pages other than &lt;CODE&gt;CP_UTF8&lt;/CODE&gt; convert
them to some other default character.)
&lt;/P&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10300670" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/oldnewthing/archive/tags/Code/">Code</category></item><item><title>How does Explorer calculate the folder size information in the folder tooltip?</title><link>http://blogs.msdn.com/b/oldnewthing/archive/2012/05/03/10300180.aspx</link><pubDate>Thu, 03 May 2012 14:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10300180</guid><dc:creator>Raymond Chen - MSFT</dc:creator><slash:comments>22</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/oldnewthing/rsscomments.aspx?WeblogPostID=10300180</wfw:commentRss><comments>http://blogs.msdn.com/b/oldnewthing/archive/2012/05/03/10300180.aspx#comments</comments><description>&lt;P&gt;
This information is accurate as of Windows&amp;nbsp;7;
the algorithm may change for future versions of Windows.
The information is being provided for the edification of computer
network administrators, who are curious about random stuff like this
since it can affect their network load.
&lt;/P&gt;
&lt;P&gt;
When you hover over a folder, Explorer shows an infotip (a special
type of tooltip) which contains information about the directory,
and the information that concerns network administrators is the
"Size".
How does Explorer calculate the size?
&lt;/P&gt;
&lt;P&gt;
Explorer calculates the size by performing a na&amp;iuml;ve recursive listing
of the directory and adding up the sizes of all the files it finds.
If the enumeration takes longer than three seconds, then Explorer
gives up after three seconds and reports the size as "larger than X"
where X was the size it managed to calculate so far.
&lt;/P&gt;
&lt;P&gt;
If you don't want Explorer to do this calculation, you can disable
it from the &lt;I&gt;Folder Options&lt;/I&gt; control panel
by unchecking the box labeled
&lt;I&gt;Display file size information in folder tips&lt;/I&gt;.
&lt;/P&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10300180" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/oldnewthing/archive/tags/Tips_2F00_Support/">Tips/Support</category></item><item><title>Why is there sometimes a long delay between pressing a hotkey for a shortcut and opening the shortcut?</title><link>http://blogs.msdn.com/b/oldnewthing/archive/2012/05/02/10299709.aspx</link><pubDate>Wed, 02 May 2012 14:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10299709</guid><dc:creator>Raymond Chen - MSFT</dc:creator><slash:comments>51</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/oldnewthing/rsscomments.aspx?WeblogPostID=10299709</wfw:commentRss><comments>http://blogs.msdn.com/b/oldnewthing/archive/2012/05/02/10299709.aspx#comments</comments><description>&lt;P&gt;
Via a customer liaison, we received a problem report
from a customer.
&lt;/P&gt;
&lt;BLOCKQUOTE CLASS=q&gt;
&lt;P&gt;
The customer
is facing issues with delayed desponses to opening a .lnk file
by pressing its keyboard shortcut hotkey.
This delay does not appear when the shortcut is double-clicked.
&lt;/P&gt;
&lt;P&gt;
For example, the customer has created a shortcut to Notepad
and assigned it the shortcut &lt;KBD&gt;Ctrl&lt;/KBD&gt;+&lt;KBD&gt;Alt&lt;/KBD&gt;+&lt;KBD&gt;X&lt;/KBD&gt;.
Pressing the keyboard combination sometimes takes 5 or 6 seconds
for Notepad to open.
As noted above, double-clicking on the shortcut causes Notepad
to open without delay.
&lt;/P&gt;
&lt;P&gt;
This issue is not consistently reproducible,
but it appears to be independent of the shortcut file itself.
Any shortcut with a hotkey exhibits this problem.
&lt;/P&gt;
&lt;P&gt;
All the shortcuts in question are on the desktop.
&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;P&gt;
The short answer is
"There is a program running on your machine that occasionally
stops responding to messages.
If you press a shortcut hotkey during those moments,
you will experience this problem.
Identify the program that stops responding to messages and
fix it."
&lt;/P&gt;
&lt;P&gt;
Okay,
that sort of cuts to the chase, but the interesting part is the
journey, not the destination.
&lt;/P&gt;
&lt;P&gt;
First, observe that if you associate a hotkey with a shortcut
to say Notepad,
and you press the hotkey twice, you do &lt;I&gt;not&lt;/I&gt; get two copies
of Notepad.
The first time you press the hotkey, Notepad launches, but the second
time you press the hotkey, focus is put on the &lt;I&gt;existing&lt;/I&gt;
copy of Notepad.
This is one of those things that's so natural you may not even
realize that it's happening.
&lt;/P&gt;
&lt;P&gt;
When you press the hotkey assigned to a shortcut,
Explorer receives the hotkey and needs to decide what to do about it.
Before it can launch the shortcut,
it needs to see if the shortcut target already has a window open,
in which case it should just switch to that window.
&lt;/P&gt;
&lt;P&gt;
Finding out whether a window has a hotkey is done by sending the window
the &lt;CODE&gt;WM_GETHOTKEY&lt;/CODE&gt; message.
When you press a hotkey that is assigned to a shortcut,
Explorer goes to all the windows already on the screen and asks each one,
"Hey, what's your hotkey?"
If any window says,
"My hotkey is &lt;KBD&gt;Ctrl&lt;/KBD&gt;+&lt;KBD&gt;Alt&lt;/KBD&gt;+&lt;KBD&gt;X&lt;/KBD&gt;,"
then Explorer says,
"Oh, sorry to step on your toes.
The user pressed your hotkey,
so here, go ahead and take focus."
&lt;/P&gt;
&lt;P&gt;
If no window cops to having
&lt;KBD&gt;Ctrl&lt;/KBD&gt;+&lt;KBD&gt;Alt&lt;/KBD&gt;+&lt;KBD&gt;X&lt;/KBD&gt; as its hotkey,
Explorer says,
"Okay, well, then I guess I have to make one."
It launches Notepad and tells it,
"Oh, and your hotkey is &lt;KBD&gt;Ctrl&lt;/KBD&gt;+&lt;KBD&gt;Alt&lt;/KBD&gt;+&lt;KBD&gt;X&lt;/KBD&gt;."
&lt;/P&gt;
&lt;P&gt;
If there is a window that is not responding to messages,
then when Explorer asks it,
"Hey, what's your hotkey?",
the window just sits there and doesn't answer.
After about three seconds, Explorer gives up.
"Yeesh, I was just asking a question.
Don't have to give me the silent treatment."
&lt;/P&gt;
&lt;P&gt;
And that petulant window is the source of the
3-second delay.
It takes Explorer 3 seconds before it finally gives up and says,
"Forget it.
Even if that was somebody's hotkey, they're being a jerk,
so I'm just going to pretend they didn't have a hotkey.
Let me open a new window instead and just deal with the hotkey conflict."
&lt;/P&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10299709" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/oldnewthing/archive/tags/Other/">Other</category></item><item><title>What happened to the Summary information created on Windows 2000 and Windows XP?</title><link>http://blogs.msdn.com/b/oldnewthing/archive/2012/05/01/10299322.aspx</link><pubDate>Tue, 01 May 2012 14:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10299322</guid><dc:creator>Raymond Chen - MSFT</dc:creator><slash:comments>32</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/oldnewthing/rsscomments.aspx?WeblogPostID=10299322</wfw:commentRss><comments>http://blogs.msdn.com/b/oldnewthing/archive/2012/05/01/10299322.aspx#comments</comments><description>&lt;P&gt;
In Windows&amp;nbsp;2000 and Windows&amp;nbsp;XP,
you could add Summary information on the
Details property page to files of all types.
Text files, image files, some crazy file your grandmother sent you
in a file format you don't know how to open.
If Windows supports storing the Summary information in the file itself
(for example, in EXIF tags or in
&lt;A HREF="http://msdn.microsoft.com/en-us/library/aa380050(v=VS.85).aspx"&gt;
Structure Storage properties&lt;/A&gt;),
then the information gets stored there.
Otherwise, Windows stashes the information in an alternate data stream.
Windows Vista dropped support for storing Summary information in
alternate data streams.
What happened?
&lt;/P&gt;
&lt;P&gt;
Support for storing Summary information in an alternate data stream
was dropped in Windows Vista
because alternate data streams were found to be too fragile.
If you back up the file to a CD-ROM or email it to a friend
or copy it to a thumb drive or upload it to a Web site
or store it in a ZIP file,
the alternate data stream ends up lost.
It was determined that it was better simple not to allow users
to create data that was so easy to destroy accidentally.
&lt;/P&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10299322" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/oldnewthing/archive/tags/Tips_2F00_Support/">Tips/Support</category></item><item><title>When you don't speak a language, don't sound like you speak the language</title><link>http://blogs.msdn.com/b/oldnewthing/archive/2012/04/30/10298920.aspx</link><pubDate>Mon, 30 Apr 2012 14:00:01 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10298920</guid><dc:creator>Raymond Chen - MSFT</dc:creator><slash:comments>35</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/oldnewthing/rsscomments.aspx?WeblogPostID=10298920</wfw:commentRss><comments>http://blogs.msdn.com/b/oldnewthing/archive/2012/04/30/10298920.aspx#comments</comments><description>&lt;P&gt;
I appreciate the help from
&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2010/09/17/10063630.aspx#10064288"&gt;
Christoph&lt;/A&gt;
and
&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2010/09/17/10063630.aspx#10064309"&gt;
Voo&lt;/A&gt;
in refining my German.
But that reminds me of a story about a friend of a friend.
&lt;/P&gt;
&lt;P&gt;
She was in Japan to visit some friends.
Although she speaks English and Mandarin fluently,
she doesn't know any Japanese,
so her friends taught her how to say
"Sorry, I don't speak Japanese."
She managed to say this sentence quite well
despite learning it purely phonetically.
&lt;/P&gt;
&lt;P&gt;
One day they were walking down the street as a group,
and a gentleman approached and asked her for directions.
She responded with the only sentence she knew:
"Sorry, I don't speak Japanese."
&lt;/P&gt;
&lt;P&gt;
The gentleman was offended by this response and began
scolding her for her rudeness.
"Look, if you don't want to talk to me, just say so.
Don't pretend like you don't speak Japanese."
Since he was scolding her in Japanese,
all she could do was stand there bewildered while this guy
yelled at her.
&lt;/P&gt;
&lt;P&gt;
Fortunately, her friends intervened and explained to the gentleman,
"No really, she doesn't speak any Japanese.
We just taught her that one sentence."
&lt;/P&gt;
&lt;P&gt;
The lesson I took from this story was that
when you don't speak a language,
it's important to sound like you don't speak the language.
In a way,
it's a good thing that my German is a little bit off.
That way, the person I'm talking with knows that my German is not all
that great.
&lt;/P&gt;
&lt;P&gt;
&lt;B&gt;Examples&lt;/B&gt;:
During a trip to Germany, I discovered that when I asked a simple
question, people would answer in rapid-fire German,
&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2007/05/23/2802894.aspx"&gt;
overflowing my internal parsing buffer&lt;/A&gt;.
During my trip to Sweden,
I applied the lesson from this article,
and found that people switched to simpler Swedish and spoke more slowly.
As a result,
I had little difficulty understanding what people were saying to me.
(Of course, it didn't help me
understand what they were saying to each other.)
&lt;/P&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10298920" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/oldnewthing/archive/tags/Non_2D00_Computer/">Non-Computer</category></item><item><title>What were the tests that WinG did to evaluate video cards?</title><link>http://blogs.msdn.com/b/oldnewthing/archive/2012/04/30/10298919.aspx</link><pubDate>Mon, 30 Apr 2012 14:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10298919</guid><dc:creator>Raymond Chen - MSFT</dc:creator><slash:comments>46</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/oldnewthing/rsscomments.aspx?WeblogPostID=10298919</wfw:commentRss><comments>http://blogs.msdn.com/b/oldnewthing/archive/2012/04/30/10298919.aspx#comments</comments><description>&lt;P&gt;
&lt;A HREF="http://www.georg-rottensteiner.de/"&gt;
Georg Rottensteiner&lt;/A&gt;
was curious about
&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2010/07/20/10040074.aspx#10040769"&gt;
the weird things that WinG performed on installation to
evaluate video cards&lt;/A&gt;.
"What did it do actually and what for?"
&lt;/P&gt;
&lt;P&gt;
I don't actually know,
since I was not involved in the WinG project,
but I remember chatting with one of the developers
who was working on video card benchmarks.
&lt;/P&gt;
&lt;P&gt;
He says that video card benchmarks are really hard to develop,
not just because video cards are complicated,
but also because video drivers
&lt;I&gt;cheat like a Mississippi riverboat card sharp
on a boat full of blind tourists&lt;/I&gt;.
&lt;/P&gt;
&lt;P&gt;
He discovered all sorts of crazy shenanigans.
Like a video driver which compares the string you
ask it to display with the text
"The quick brown fox jumps over the lazy dog."
If the string matches exactly, then it returns without
drawing anything three quarters of the time.
The reason:
Benchmarks often use that sample string to evaluate
text rendering performance.
The driver vendors realized that
&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2003/10/10/55256.aspx"&gt;
the fastest code is code that doesn't run&lt;/A&gt;,
so by ignoring three quarters of the "draw this string" requests,
they could improve their text rendering performance numbers fourfold.
&lt;/P&gt;
&lt;P&gt;
That was the only one of the sneaky tricks I remember
from that conversation.
(I didn't realize there was going to be a quiz 17 years later
or I'd have taken notes.)
Another example of benchmark cheating was a driver which
&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2004/03/05/84469.aspx"&gt;
checked if the program name was TUNNEL.EXE&lt;/A&gt;
and if so, enabled a collection of benchmark-specific optimizations.
&lt;/P&gt;
&lt;P&gt;
Anyway, I suspect that the weird things that the WinG installer
did were specifically chosen to be things that no video card
driver had figured out a way to cheat, at least at the time he
wrote the test.
I wouldn't be surprised if fifteen seconds after WinG was released,
video driver vendors started studying it to see how they could cheat
the WinG benchmark...
&lt;/P&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10298919" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/oldnewthing/archive/tags/History/">History</category></item><item><title>A process shutdown puzzle, Episode 2</title><link>http://blogs.msdn.com/b/oldnewthing/archive/2012/04/27/10298256.aspx</link><pubDate>Fri, 27 Apr 2012 14:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10298256</guid><dc:creator>Raymond Chen - MSFT</dc:creator><slash:comments>25</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/oldnewthing/rsscomments.aspx?WeblogPostID=10298256</wfw:commentRss><comments>http://blogs.msdn.com/b/oldnewthing/archive/2012/04/27/10298256.aspx#comments</comments><description>&lt;P&gt;
A customer reported that their program would very sporadically
crash in the function
&lt;A HREF="http://msdn.microsoft.com/en-us/library/ms682036(VS.85).aspx"&gt;
&lt;CODE&gt;Close&amp;shy;Thread&amp;shy;pool&amp;shy;Cleanup&amp;shy;Group&amp;shy;Members&lt;/CODE&gt;&lt;/A&gt;.
The customer was kind enough to provide a stack trace at the point
of the crash:
&lt;/P&gt;
&lt;PRE&gt;
ntdll!RtlUnhandledExceptionFilter2+0x31e
KERNELBASE!UnhandledExceptionFilter+0x175
ntdll!RtlUserThreadStart$filt$0+0x3f
ntdll!__C_specific_handler+0x8f
ntdll!RtlpExecuteHandlerForException+0xd
ntdll!RtlDispatchException+0x3a6
ntdll!RtlRaiseException+0x223
ntdll!TppRaiseInvalidParameter+0x48
ntdll!TpReleaseCleanupGroupMembers+0x246
litware!CThreadPool::UnInitialize+0x22
litware!_CRT_INIT+0xbf
litware!__DllMainCRTStartup+0x18b
ntdll!LdrpCallInitRoutine+0x3f
ntdll!LdrShutdownProcess+0x205
ntdll!RtlExitUserProcess+0x90
kernel32!ExitProcessImplementation+0xa
contoso!wmain+0x193
contoso!__wmainCRTStartup+0x13d
kernel32!BaseThreadInitThunk+0xd
ntdll!RtlUserThreadStart+0x1d
&lt;/PRE&gt;
&lt;P&gt;
The customer wondered,
"Could the problem be that my cleanup group does not have
a callback?
MSDN seems to suggest that this is okay."
&lt;/P&gt;
&lt;P&gt;
The exception being thrown is
&lt;CODE&gt;STATUS_&lt;WBR&gt;INVALID_&lt;WBR&gt;PARAMETER&lt;/CODE&gt;,
but that doesn't really say much.
&lt;/P&gt;
&lt;P&gt;
But that's okay, because the smoking gun isn't the exception
being raised.
It's in the stack.
&lt;/P&gt;
&lt;P&gt;
Do you see it?
&lt;/P&gt;
&lt;P&gt;
The code is calling
&lt;CODE&gt;Close&amp;shy;Thread&amp;shy;pool&amp;shy;Cleanup&amp;shy;Group&amp;shy;Members&lt;/CODE&gt;
from inside &lt;CODE&gt;DllMain&lt;/CODE&gt;
while handling the
&lt;CODE&gt;DLL_&lt;WBR&gt;PROCESS_&lt;WBR&gt;DETACH&lt;/CODE&gt; notification.
Looking further up the stack, you can see this was triggered by
a call to &lt;CODE&gt;ExitProcess&lt;/CODE&gt;,
and now all the stuff you know about
&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2007/05/03/2383346.aspx"&gt;
how processes exit&lt;/A&gt;
kicks in.
&lt;/P&gt;
&lt;P&gt;
For example, that the first thing that happens is that all threads
are forcibly terminated.
&lt;/P&gt;
&lt;P&gt;
That's your next clue.
&lt;/P&gt;
&lt;P&gt;
Observe that the customer's DLL is trying to communicate with the
thread pool during process termination.
But wait, all the threads have already been terminated.
It's trying to communicate with a nonexistent thread pool.
&lt;/P&gt;
&lt;P&gt;
The thread pool realizes,
"Hey, like I've already been destroyed.
I can't do what you ask because there is no thread pool any more.
You want me to block until all currently executing callback
functions finish,
but those callback functions will never finish (if they even exist at all)
&lt;I&gt;because the threads hosting their thread pool got destroyed&lt;/I&gt;.
Not that I can tell whether they are executing or not,
because I am already destroyed.
The only options are to hang or crash.
I think I'll crash."
&lt;/P&gt;
&lt;P&gt;
The customer needs to restructure the program so that it either
cleans up its thread pool work before the
&lt;CODE&gt;ExitProcess&lt;/CODE&gt;,
or it can simply skip all thread pool operations when the reason for
the &lt;CODE&gt;DLL_&lt;WBR&gt;PROCESS_&lt;WBR&gt;DETACH&lt;/CODE&gt; is process termination.
&lt;/P&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10298256" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/oldnewthing/archive/tags/Code/">Code</category></item><item><title>Shortcut properties are in the shortcut, so if they can read the shortcut, they can read the properties</title><link>http://blogs.msdn.com/b/oldnewthing/archive/2012/04/26/10297830.aspx</link><pubDate>Thu, 26 Apr 2012 14:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10297830</guid><dc:creator>Raymond Chen - MSFT</dc:creator><slash:comments>33</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/oldnewthing/rsscomments.aspx?WeblogPostID=10297830</wfw:commentRss><comments>http://blogs.msdn.com/b/oldnewthing/archive/2012/04/26/10297830.aspx#comments</comments><description>&lt;P&gt;
A customer wanted to know if "there was a way to hide the
properties of a shortcut."
&lt;/P&gt;
&lt;P&gt;
We asked for an explanation of the problem they were trying to solve,
so we could understand what their question meant.
The customer liaison explained:
&lt;/P&gt;
&lt;BLOCKQUOTE CLASS=q&gt;
The customer is insisting on this, even though I think it's really
the wrong approach.
They want to put a password into the parameters of a shortcut,
but they don't want their employees to see the password when
they right-click the shortcut and select Properties.
We're trying to convince them of better ways of doing this,
but right now they want to see if they can solve it by
marking the field as "hidden" somehow.
&lt;/BLOCKQUOTE&gt;
&lt;P&gt;
If the password is anywhere in the shortcut file,
the employees can dig it out.
After all, the shell needs to dig it out,
and since the shell runs with the user's privileges,
in order for the shell to see it, the user must be able to see it.
In other words, you can't hide anything in a shortcut
because the user can just open the shortcut in Notepad and
see all your "hidden" data.
Or they can go to Task Manager and ask to see the command line.
Or they can connect a debugger to Explorer and set a breakpoint on
the &lt;CODE&gt;Create&amp;shy;Process&lt;/CODE&gt; function.
&lt;/P&gt;
&lt;P&gt;
It's like saying,
"I want my employees to be able to bake cakes,
but I don't want them to have access to an oven.
To block access to the oven, I put a combination lock on the oven
controls.
On the other hand, I want to write a cake recipe that lets the
employees bake cakes in the oven.
Therefore, the recipe says
&lt;I&gt;Step 5: Go to the oven and press 1234&lt;/I&gt;.
But now the employee can just read the recipe and find out
the combination to the oven!
Is there a way I can write a cake recipe that lets them bake a cake
without revealing the oven combination?"
&lt;/P&gt;
&lt;P&gt;
The recipe executes with the privileges of the employee.
If you want the employee to be able to bake a cake by following
the recipe,
then they need to be able to perform the steps in the recipe,
and that means being able to go to the oven and press 1234.
&lt;/P&gt;
&lt;P&gt;
The oven analogy does provide some ideas on how you can solve
the problem.
For example,
if you simply don't want employees to be able to
email the oven combination to their friends with the subject line
&lt;I&gt;Here's the combination to the oven!&lt;/I&gt;,
then change the way access to the oven is managed.
Instead of putting a combination lock on the oven,
put an employee ID card scanner on the oven
that enables the oven controls if the employee has oven privileges.
&lt;/P&gt;
&lt;P&gt;
For the original problem, this means changing your database so
that instead of
&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2010/11/23/10095215.aspx"&gt;
using a single password to control access and trusting each client
to use it wisely&lt;/A&gt;,
it uses the security identity of the client to control access.
(I'm assuming that the password on the command line is a database password.)
&lt;/P&gt;
&lt;P&gt;
On the other hand, if your goal is to prevent employees from
using the oven to do anything other than
&lt;I&gt;bake at 350&amp;deg;F for one hour&lt;/I&gt;,
you can change the employee ID card scanner so that it checks
the employee for cake-baking privileges,
and if so, sets the oven to bake for 350&amp;deg;F for one hour
and locks the controls (except perhaps for a &lt;I&gt;cancel&lt;/I&gt; button).
If you have multiple recipes&amp;mdash;say, cakes and cookies&amp;mdash;the
ID card scanner checks which recipes
the employees are allowed to use and lets them choose which preset
they want to activate.
&lt;/P&gt;
&lt;P&gt;
For the original problem, this means changing your database so that
the user identity selects which operations are permitted on the database.
Some users have permission to see only records for active clients,
whereas others have permission to see all records,
and still others have modify permission.
&lt;/P&gt;
&lt;P&gt;
If your goal is to prevent employees from doing anything other than
&lt;I&gt;baking cakes according to this specific recipe&lt;/I&gt;,
then you need to move even more actions "behind the counter",
because you have no way of knowing that "that pan full of batter"
was created according to your walnut cake recipe,
or whether it's some unauthorized recipe with
extra cinnamon.
If you don't trust your employees to follow recipes,
then you need to take the recipe out of their hands.
The instructions are now &lt;I&gt;Step 1: Order a walnut cake from the cafeteria&lt;/I&gt;.
&lt;/P&gt;
&lt;P&gt;
For the original problem, this means changing your database so
that instead of letting the employee access records directly,
the employee submits the action to the database
("change client 23 address to 123 Main Street"),
and the database verifies that the employee has
"change a client address" permission, and if so, performs the record update.
&lt;/P&gt;
&lt;P&gt;
Of course, if you want to ignore all the security guidance
and "just hide the password in the shortcut file,
why won't you answer my question?",
you can just put the password somewhere
other than the shortcut file.
You could, say, have the shortcut run a batch file,
and the batch file has the password.
&lt;/P&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10297830" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/oldnewthing/archive/tags/Other/">Other</category></item></channel></rss>
