Holy cow, I wrote a book!
this house on Mercer Island,
which happens to be
Asking price: A shade under $35 million.
Five bedrooms, nine bathrooms, over
22 thousand square feet,
two swimming pools,
space to park a 140-foot yacht,
and an interior so opulent you'd be afraid to touch anything.
If you were even allowed anywhere near it.
But the sagging economy has taken its toll on this house.
They were originally asking $40 million.
Best line from the article:
"But we decided we might want to simplify a little, and move to Medina."
For those who aren't familiar with Seattle-area geography,
Medina is the quiet little town which has the modest homes
of simple people
like Bill Gates.
If you are placed in the unfortunate position of having to debug
a user-mode crash from kernel mode,
one of the first things you have to do is get back to the exception
on the user-mode side so you can see what happened.
We saw earlier
how you can get symbols for operating system binaries to help you
suck the exception pointers out of a user-mode stack trace;
here's a corresponding tip for the kernel-mode side.
Your stack trace will look something like this:
ChildEBP RetAddr Args to Child
8fc86660 818844e3 83811e00 83811d78 83811e30 nt!KiSwapContext+0x26
8fc8669c 8184abd2 83811d78 00000000 83811d78 nt!KiSwapThread+0x3d2
8fc866fc 81a690b1 8fc86740 00000000 00000000 nt!KeWaitForSingleObject+0x414
8fc8681c 81a6a5aa 90a06108 83811d78 8fc86860 nt!DbgkpQueueMessage+0x283
8fc86844 819e3cbd 8fc86860 80000003 00000000 nt!DbgkpSendApiMessage+0x44
8fc86908 8183c542 8fc86cf0 00000001 00000000 nt!DbgkForwardException+0xd0
8fc86cd4 8184e51a 8fc86cf0 00000000 8fc86d44 nt!KiDispatchException+0x2ee
8fc86d3c 8184e4ce 063fedc8 75b9b7df badb0d00 nt!CommonDispatchException+0x4a
8fc86d44 75b9b7df badb0d00 00000000 00000000 nt!KiExceptionExit+0x186
063fedc8 75b963ea 4eedcfb0 4f370fb0 063ff0bc ABC!Control::Character::OnDestroy+0xbc
063ff020 747d3782 4f370fb0 5665cf68 063ff0bc ABC!Control::Character::MessageHandler+0x476
063ff034 747d3819 063ff0bc 063ff050 747d37f6 DEF!EventGizmo::FireEvent+0xf
063ff040 747d37f6 063ff0bc 0000000c 063ff0a8 DEF!Gizmo::CallStubEvent+0x1a
063ff050 747d3842 4f370fb0 063ff0bc c6db9237 DEF!Callback::CallOnEvent+0x19
063ff0a8 747d6ed0 4f370fb0 063ff0bc 00000001 DEF!Callback::Invoke+0x20
063ff0d0 747d7708 4f370fb0 00000001 4eedcfb0 DEF!Callback::FireDestroy+0x2a
063ff0f0 747d728a 3618af68 4eedcfb0 747d7429 DEF!ObjectManager::DestroyAllChildren+0x34
063ff0fc 747d7429 4a1bff78 4eedcfb0 747d6e9d DEF!ObjectManager::BeginDestroy+0x2e
063ff108 747d6e9d 4eedcfb0 747d7721 4a1bff78 DEF!ObjectManager::Destroy+0x1a
The third parameter to
KiDispatchException is the trap frame.
Most people who write about
KiDispatchException do so in the context of driver debugging,
but trap frames are also used during user-mode-to-kernel-mode transitions.
0: kd> .trap 8fc86d44
ErrCode = 00000004
eax=00000001 ebx=00000001 ecx=4e62e594 edx=00000000 esi=5665cf68 edi=5630eff8
eip=75b9b7df esp=063fedb4 ebp=063fedc8 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010246
001b:75b9b7df 8b01 mov eax,dword ptr [ecx] ds:0023:4e62e594=?????
And there you have it,
the original exception.
Although Microsoft employees are internally assigned a
cryptic email address by the IT department,
the email address used for mail to and from the outside world
is open to customization, to some degree.
For example, consider an imaginary employee named
Christopher might be assigned an email address like
or chriscol or
or possibly the Slavic-sounding
But Christopher has the option of choosing the external email address:
When he sends a message to somebody outside Microsoft,
the "From" line will show the external address,
and if somebody from outside Microsoft sends mail to the
it will get routed to Christopher.
When you choose your external name, you have a few options.
The most basic version consists of
your first and last name, separated with a dot:
You can include your middle name or initial,
to distinguish you from other people who have the same name:
There are other possibilities, like using your nickname or initials
instead of your legal name,
but that's the basic idea.
There is one final option: Don't have separate external
and internal email addresses; just use your internal email address
I had a brief conversation with somebody who, as it happened,
encountered a bug in the tool that lets you choose your
external email address.
This person wanted something fairly standard like
Robin.Williams∂microsoft.com but for reasons
not worth going into since they're not important to the story,
a bug in the system ended up assigning the external address
(Note: Not Robin's real name, so don't try sending to it.)
The IT department fixed the bug, but Robin decided to keep
the erroneously-assigned email address.
I'm somewhat jealous: It's not often that a database glitch
ends up giving you a cool email address.
how most parts of your entry in the company address book are
closely regulated, but the differentiator is left to the honor system.
Here are two and a half more examples of people who decided to
do something funny with their bonus text.
A message was sent to a mailing list I happen to be a member of,
and the sender's name was listed as
"John Doe (O|||||O)".
I told John that I though the (O|||||O) was hilarious,
and he wrote back,
"Also, call my phone and listen to how the autobot says my name."
I did, of course.
The text to speech synthesizer pronounced his name as
John Doe overtical bracket vertical bracket vertical bracketo.
PowerShell blogger extraordinaire,
uses as his differentiator a PowerShell prompt.
He shows up in the address book as "Lee Holmes (PS C:\> _)".
Oh, and wait, it's fancier than that.
The underscore blinks, albeit at a glacial rate:
Every so often, Lee removes the underscore from the differentiator
or adds it back.
And here's the half:
changed his name in the address book to
Robert Hensing (EL CONQUISTADOR)
(not to be confused with
This is only half of an example because I'm not going to tell you
why he chose "EL CONQUISTADOR" to go after his name.
I'll leave the story for him to tell (if he feels so inclined).
One of the things that happens when you arrive at Microsoft
is you are assigned an email account,
and the name of that account
becomes your identity.
The IT department has a set of rules which they follow to arrive at
your account name,
but you can petition for reconsideration
if the result of their algorithm produces something you don't like.
You have more flexibility with your display name.
you may commonly go by a
less formal version of your legal name,
or you may
go by your middle name
or you may choose to
adopt an English name
as your professional name.
But even though you have flexibility here,
you don't have total freedom.
I doubt that a request for my name to show up in the address book
would be approved.
There is a third component to your name, however,
that you do have much more freedom with.
The official name for it is the differentiator,
and it appears in parentheses after the rest of your name.
Here are some common uses for this bonus text:
Originally, the differentiator also was submitted for approval,
but the people who were responsible for approving them
must have gotten tired of wading through thousands of boring
requests for approval for this and other
categories of personnel record changes that used to require approval.
People are now simply trusted not to choose differentiators
that are offensive or misleading.
Some people have used this new freedom for humorous purposes.
One prominent member of the application compatibility team
has a non-English name that people often pronounce incorrectly.
For the sake of discussion, let's say his name is Lav.
At first, he signed his email
–Lav, rhymes with Dave
After a few months, based on a suggestion from a colleague
(who might have been me), he changed it to
–Lav, doesn't rhyme with "have"
At this point, things got silly pretty quickly.
A few months later, the signature changed to
–Lav, rhymes with orange
The last step was changing the differentiator after his name in the
If you look him up, he is listed as
"Lav Pivo (ORANGE)".
decided that going off topic in the comments to this Web site
was so much fun,
she didn't want to let the
So she created the
Off-Roading The Old New Thing
where people who get a thrill out of going off topic can
do so without running afoul of this Web site's Ground Rules.
Have fun, everybody!
It was possible to use generic thunks in 16-bit code to allow it to
call into 32-bit code.
Why can't we do the same thing to
allow 32-bit code to call 64-bit code?
It's the address space.
Both 16-bit and 32-bit Windows lived in a 32-bit linear address space.
The terms 16 and 32 refer to the size of the offset relative to the selector.
Okay, I suspect most people haven't had to deal with selectors
(and that's probably a good thing).
In 16-bit Windows,
addresses were specified in the form of
a selector (often mistakenly called a "segment")
and an offset.
For example, a typical address might be 0x0123:0x4567.
This means "The byte at offset 0x4567 relative to the selector 0x0123."
Each selector had a corresponding entry in one of the descriptor tables
which describes things like what type of selector it is
(can it be used to read data? write data? execute code?),
but what's important here is that it also contained a base address
and a limit.
For example, the entry for selector 0x0123 might say
"0x0123 is a read-only data selector which begins at linear address
0x00524200 and has a limit of 0x7FFF."
This means that the address 0x0123:n refers to
the byte whose linear address is 0x00524200 + n,
provided that n ≤ 0x7FFF.
With the introduction of the 80386, the maximum limit for a selector
was raised from 0xFFFF to 0xFFFFFFFF.
(Accessing the bytes past 0xFFFF required a 32-bit offset,
Now, if you were clever, you could say
"Well, let me create a selector and set its base to 0x00000000
and its limit to 0xFFFFFFFF.
With this selector, I can access the entire 32-bit linear address space.
There's no need to chop it up into 64KB chunks like I had to back in the
And then I can just declare that all addresses will be in this form
and nobody would have to bother specifying which selector to use since
it is implied."
And if you said this, then you invented the Win32 addressing scheme.
It's not that there are no selectors; it's just that there is effectively only
one selector, so there's no need to say it all the time.
Now let's look at the consequences of this for thunking.
First, notice that a full-sized 16-bit pointer and a 32-bit flat
pointer are the same size.
The value 0x0123:0x467 requires 32 bits, and wow,
so too does a 32-bit pointer.
This means that data structures containing pointers do not change
size between their 16-bit and 32-bit counterparts.
A very handy coincidence.
Next, notice that the 16-bit address space is still fully capable
of referring to every byte in the 32-bit address space, since they
are both windows into the same underlying linear address space.
It's just that the 16-bit address space can only see the underlying
linear address space in windows of 64KB,
whereas the 32-bit address space can see it all at once.
This means that any memory that 32-bit code can access
16-bit code can also access.
It's just more cumbersome from the 16-bit side since you have
to build a temporary address window.
Neither of these two observations holds true for 32-bit to 64-bit
The size of the pointer has changed, which means that converting a
32-bit structure to a 64-bit structure and vice versa changes the
size of the structure.
And the 64-bit address space is four billion times larger than the
32-bit address space.
If there is some memory in the 64-bit address space at offset
32-bit code will be unable to access it.
It's not like you can build a temporary address window,
because 32-bit flat code doesn't know about these temporary address windows;
they abandoned selectors, remember?
It's one thing when two people have two different words to describe
the same thing.
But if one party doesn't even have the capability of talking about
that thing, translating between the two will be quite difficult indeed.
P.S., like most things I state as "fact", this is just
PowerPoint is a fine presentation tool,
some people have elevated it to the level of a cult.
The most recent member of the PowerPoint cult
was a customer who decided to use PowerPoint in an email message.
No, I don't mean that the customer attached a bad PowerPoint presentation
to the email.
I mean that the customer's email was itself a
three-slide PowerPoint presentation.
What they actually did was create a three-slide presentation,
then take screenshots of each slide and
embed them in the email.
Well, not quite.
The screenshots were shrunk to save size.
Each page from the PowerPoint presentation contained about 50 words of text.
Which were very hard to read because the screenshots were shrunk.
The PowerPoint presentation itself was a shortened form of your
typical boring PowerPoint slide presentation.
The first slide was an introduction to the program they were using.
The second slide was a statement of the problem they were having.
The third slide was a call to action for Microsoft to assist in
determining why the program was having the problem.
Thank goodness it didn't have a concluding "Any questions?" slide.
I was looking at one of those
"my program is consuming 100% of the CPU and I don't know why"
and upon closer investigation, the proximate reason the
program was consuming 100% CPU was that one of the threads
was being bombarded with WM_TIMER messages
where the MSG.hWnd is NULL.
The program was dispatching them as fast as it could,
but the messages just kept on coming.
Curiously, the LPARAM for these messages was zero.
This should be enough information for you to figure out what is going on.
First, you should refresh your memory as to what a null window handle
in a WM_TIMER message means:
These are thread timers,
timers which are associated not with a window but with a thread.
You create a thread timer by calling the SetTimer
function and passing NULL as the window handle.
Thread timer messages arrive in the message queue,
and the DispatchMessage function
calls the timer procedure specified by the message LPARAM.
If the LPARAM of a thread timer message
is zero, then dispatching the message
consists merely of throwing it away.
(If there were a window handle, then the message would be delivered
to the window procedure,
but there isn't one, so there's nothing else that can be done.)
The program was spending all its time retrieving WM_TIMER
messages from its queue and throwing them away.
The real question is how all these thread timers ended up on the
thread when they don't do anything.
Who would create a timer that didn't do anything?
And who would create dozens of them?
One of the more common patterns for creating a window timer is to write
SetTimer(hwnd, idTimer, dwTimeout, NULL).
This creates a window timer whose identifier is idTimer.
Since the timer procedure is NULL, the WM_TIMER
message is dispatched to the window procedure,
which in turn will have a case WM_TIMER statement
followed by a
switch (wParam) to handle the timer message.
SetTimer(hwnd, idTimer, dwTimeout, NULL)
But what if hwnd is NULL,
say because you forgot to check the return value of a function
Well, then you just created a thread timer by mistake.
And if you make this mistake several times in a row,
you've just created several thread timers.
Now you might think that the code that created the thread timer
by mistake will also destroy the thread timer by mistake when it
finally gets around to calling
KillTimer(hwnd, idTimer) and passes
NULL for the hwnd.
But it doesn't.
One reason is that in many cases, it's the timer that turns itself off.
In other words, the KillTimer happens inside the
WM_TIMER message handler.
But if the WM_TIMER message
isn't associated with that window,
then that window procedure never gets a chance to turn off the timer.
Another reason is more insidious.
Recall that the idTimer parameter to the
SetTimer function is ignored when you create a
Since you can't predict what other thread timers may exist,
you can't know which timer identifiers are in use and which are free.
Instead, the SetTimer function creates a unique
thread timer identifier and returns it,
and it is that timer identifier you must use when destroying
the thread timer.
Of course, the code that accidentally created the thread timer
thought it was creating a window timer (which uses the timer
identifier you specify),
so it didn't bother saving the return value.
Result: Thread timer is created and becomes orphaned.
The machine I was asked to look at was running a stress scenario,
so it was entirely likely that a low memory condition caused
a function like CreateWindow to fail,
and the program most likely neglected to check the return value.
I never did hear back to find out if that indeed was the source
of the problem, but seeing as they didn't come back for more help,
I suspect I put them on the right track.
a short documentary on hoarders,
fascinating because I teeter on the brink of hoarding myself
and have to
Some days I am more successful than others.
Notice how coherently the subjects talk about their obsession.
They know it's pathological, but they can't stop themselves.
I was able to beat my hoarding of cardboard boxes
("Hey, it'd be a waste to toss these cardboard boxes
into the recycle bin; I could re-use it someday,
like maybe if I have to mail a package or something")
when a friend of mine was moving and needed cardboard boxes
to pack up his things.
I gladly handed over my stash of cardboard boxes, with
the instructions that when he was finished, the cardboard
boxes were his problem.
That solved two problems.
I was able to get rid of my cardboard boxes with a clear conscience,
and my friend got a bunch of moving boxes.