Holy cow, I wrote a book!
One of the minor Valentine's Day
traditions at Microsoft is the charity fundraiser
based on identifying targets and embarrassing them
in front of all their colleagues.
In exchange for a charitable donation
American Heart Association (get it?)
an a cappella group will travel to an office or conference
room of your designation (conference room is much better, of course)
and sing a sappy song to your Valentine.
(Singing Valentines are also common on college campuses.)
This can get tricky when the victim's
spouse/boyfriend/girlfriend/whatever you want to call it
doesn't work at Microsoft,
because said potential prankster
(1) needs to know about this tradition in the first place,
and (2) needs to know some other Microsoft employee who
can arrange the prank on their behalf.
accused armed robber who is using political asylum as his defense
has been re-apprehended and
will not fight being returned to the United States.
I guess he needs to
update the "About Me" section of his blog.
I haven't experienced this problem, but I know of people who have.
They'll put their laptop into suspend or standby mode, and after a few
seconds, the laptop will spontaneously wake itself up.
Someone gave me this tip
that might (might) help you figure out what is wrong.
Open a command prompt and run the command
powercfg -devicequery wake_from_any
This lists all the hardware devices that are capable of waking up
the computer from standby.
But the operating system typically ignores most of them.
To see the ones that are not being ignored, run the command
powercfg -devicequery wake_armed
This second list is typically much shorter.
On my computer, it listed just the keyboard, the mouse, and the modem.
(The modem? I never use that thing!)
You can disable each of these devices one by one until you find the
one that is waking up the computer.
powercfg -devicedisablewake "device name"
(How is this different from unchecking
Allow this device to wake the computer
from the device properties in Device Manager?
Once you find the one that is causing problems, you can re-enable
powercfg -deviceenablewake "device name"
I would start by disabling wake-up for the keyboard and mouse.
Maybe the optical mouse is detecting tiny vibrations in your room.
Or the device might simply be "chatty",
generating activity even though you aren't touching it.
This may not solve your problem, but at least's something you can try.
I've never actually tried it myself, so who knows whether it works.
Exercise: Count how many disclaimers there are in this article,
and predict how many people will ignore them.
I didn't get a chance to thank you after the concert,
but I did want to express my appreciation for the running
commentary you provided during the performance of last week's
concert of Debussy, Schönberg and Brahms.
Most people wait until the break between pieces,
some may even dare to exchange information in whispers during the performance,
but you were smart.
You realized that whispered information is barely audible
to anyone more than a seat away,
so you spoke in a normal voice,
allowing audience members like me to hear your insightful commentary.
Here's an example of your astute observational skills:
Person 1: "The conductor is quite animated."
It seems that whenever there is a technology conference,
there's a decent chance that somebody will
ask me via email or a comment
whether I'm going.
The default answer to Are you going to this conference?
You may find it hard to believe,
but going to conferences around the world
is not part of my job.
My job is to sit in front of a computer and
read ema^W^Wwork on code.
I'm not a marketing person or a program manager who
goes around promoting some feature or service.
I'm the person back in Redmond actually implementing it.
The answer to
"Why isn't Raymond at TechEd?"
"Hm, let's see.
Spend a few vacation days and a few thousand dollars of my own money
on travel, accommodations, and registration for a conference I will
derive no benefit from?
For some reason, that's not my idea of a fun time."
In other words, if you want me to attend your conference,
you have to invite me.
That's what the folks at
XV Semana Informática do Instituto Superior Técnico
I'll be there on March 11th to tell stories about Windows history.
I don't have a specific list of stories set up yet, so if you want
to suggest something, you can post a comment and I'll see if I can
work it in.
I've got 90 minutes to fill, so that's going to be a lot of stories.
I'm usually game for burning some vacation days if the conference is
held somewhere interesting, because I can tack on a little vacation
after the conference is over.
(It also means that this Web site will be on autopilot from
March 10th to the 20th because I'll be out of the country
and unlikely to log on just to moderate comments.)
The conference organizers have reassured me that I will not have to
give my talk in Portuguese.
You can save having to foot my travel and lodging expenses if you
hold your conference in Seattle.
Then again, I'm not actually an invited speaker or anything
so I won't be able to get into the conference center.
I'm just showing up at
tonight's blogger geek dinner offsite.
Pre-emptive snarky comment: "Blogger" and "geek" are redundant.
Commenter Adam Russell asks
why Ctrl+ScrollLock cancels dialogs.
Because Ctrl+ScrollLock is the same as Ctrl+Break,
and Ctrl+Break cancels dialogs.
Okay, that answer actually raises two more questions.
First, why is Ctrl+ScrollLock the same as Ctrl+Break?
This is a consequence of the backward compatibility designed
into the Enhanced Keyboard layout which is in widespread use today.
If you go back and look at the original
PC/XT keyboard layout,
you'll see that many of the keys we're familiar with today
simply didn't exist back then,
and one key (PrtSc) existed in a very different form.
Let's start with PrtSc.
Observe that it was originally a shifted key, atop the asterisk.
PC/AT keyboard layout,
the PrtSc/* key migrated into the numeric keypad,
and with the introduction of the
enhanced keyboard layout,
the two functions PrtSc and multiplication were split into
two separate keys.
The asterisk stayed with the numeric keypad,
while the PrtSc function moved to the top row as a function key
(sharing a key with the SysRq key).
Okay, that's all nice, but what about Ctrl+ScrollLock and
Well, in the original PC/XT keyboard layout, there was no
The key sequence for Break was Ctrl+ScrollLock.
(And for completeness, the key sequence for Pause was
Even though the enhanced keyboard moved
the Pause and Break functions to their own key,
pressing the Pause key internally generated scan codes
that simulated a press of Ctrl+NumLock.
In other words, when you pressed Pause, the keyboard hardware
actually tells the computer,
"The user pressed the Ctrl key and then pressed the NumLock key."
Similarly, when you pressed Ctrl+Break, the keyboard hardware
tells the computer,
"The user pressed the Ctrl key and then pressed the ScrollLock key."
Therefore, Ctrl+ScrollLock acts like Ctrl+Break because at the hardware
level, they are the same thing.
That the two functions exist on separate keys is just a fake-out
by the keyboard hardware.
Okay, so now that we understand why Ctrl+ScrollLock is the same
as Ctrl+Break, the next question is why Ctrl+Break cancels a dialog box.
If you look at the list of virtual key codes in winuser.h,
you'll find lots of virtual keys that don't exist on the PC keyboard:
function keys VK_F13 through VK_F24,
and the long-forgotten VK_PA1.
What are all these things?
In the beginning, Windows and MS-DOS ran on more than just the IBM PC.
I know for certain that it also ran on the NEC PC-98,
and there were probably other architectures that were either explicitly
supported or for which support was planned or reserved.
The designers of the original Windows keyboard input driver model wanted to
cover all of the likely bases and included support for keys beyond the
basic 84-key PC/XT keyboard,
keys that could be found on then-popular keyboard layouts such as the
VT-100 and even the 3270.
I don't know which keyboard had a Cancel key,
but presumably one did, or at least the people who designed the
input driver model wanted to be prepared for the possibility of one
Given that you had a Cancel key,
it seemed natural for the dialog manager to support it by
treating a press of the Cancel key as the same as clicking the
Cancel button on a dialog.
Recall that the HINSTANCE identified a set of variables.
This causes a bit of a problem if your program has multiple data
segments; in other words, multiple sets of variables.
In such a program,
the code would load the data segment of whatever variable it needed
each time it needed to access a variable from a different segment.
This was no problem at all for a DLL,
since 16-bit DLLs were single-instance.
Go ahead, load your selectors whenever you want.
Since there's only one copy of each data segment,
you can just use them in your code and let the loader fix them up.
No matter which processes calls your DLL, you're still good.
But if you are doing this in a program,
you run into trouble once the user runs a second copy of the
All you get is an HINSTANCE
to pass to MakeProcInstance
(or to infer from your stack selector).
In other words, you get one set of variables.
If your program uses multiple sets of variables,
you don't have a way to access those other variables,
and the operating system has no way of telling you where
Now, a sufficiently clever compiler could work around this
failure of mathematics.
It could store the selectors of the extra data segments
into the data segment specified by the HINSTANCE.
When the program needed to access a variable from another
data segment, it could access them by loading the appropriate
selector from the stack segment register
(since SS == DS).
I don't know whether anybody actually bothered to write
a compiler that did this.
Not that writing one today will win you any accolades
since nobody writes 16-bit Windows programs any more.
It's one of those things that may have been a neat idea back
in its day but today will just get you quizzical looks.
Think of it as the computer version of inventing a
higher-capacity eight-track cartridge.
Crazy Asian Drinks,
a Web site devoted to the beverage preferences of people
from the eastern part of Asia.
Now, the text is really funny (which is important),
but I would like to come to the defense of
grass jelly drink.
First of all, when I was growing up, grass jelly wasn't a drink.
It was a dessert.
It came in a block, and you diced it up into pieces
about one cubic centimeter in size—not the microscopic flecks
that you end up in the beveragicized version.
You put a few spoonfuls of it in a bowl and stirred in some
sugar water and crushed ice.
Of course, you had to crush the ice yourself by hand, because that's
the way it was done; it built up the anticipation.
(You had to crush it uphill both ways.)
When you assembled the dessert, you ate it with a spoon.
This grass jelly drink is just a pale imitation of the original.
It's like if somebody mocked Jell-O gelatin because it was
served to them pureed in a shot glass.
Happy New Year, everybody.)
MakeProcInstance doesn't do anything.
#define MakeProcInstance(lpProc,hInstance) (lpProc)
What's the point of a macro that doesn't do anything?
It did something back in 16-bit Windows.
Recall that in 16-bit Windows, the HINSTANCE
was the mechanism for identifying a data segment;
i.e., a bunch of memory that represents the set of variables
in use by a module.
If you had two copies of Notepad running, there was one copy of
the code but two sets of variables (one for each copy).
It is the second set of variables that establishes the second
copy of Notepad.
When you set up a callback function, such as a window procedure,
the callback function needs to know which set of variables it's
being called for.
For example, if one copy of Notepad calls
EnumFonts and passes a callback function,
the function needs to know which copy of Notepad it is running in
so that it can access the correct set of variables.
That's what the MakeProcInstance function was for.
The parameters to MakeProcInstance are a function pointer
and an instance handle.
the MakeProcInstance function generated code on the fly
which set the data segment register equal to the
instance handle and then jumped to the original function pointer.
The return value of MakeProcInstance is a pointer to that
dynamically-generated code fragment
(known as a thunk),
and you used that code fragment as the function pointer whenever
you needed another function to call you back.
That way, when your function was called, its variables were properly
When you no longer needed the code fragment,
you freed it with the FreeProcInstance function.
Those who have worked with ATL have seen this sort of code fragment
generation already in the CStdCallThunk class.
The operation is entirely analogous with MakeProcInstance.
You initialize the CStdCallThunk with a function pointer
and a this parameter, and it generates code on the fly
which converts a static function into a C++ member function
by setting the this pointer before calling the function
you used to initialize the thunk.
The creation of these code fragments on 16-bit Windows had to be
done by the kernel because the 8086 processor did not have
a memory management unit.
There was no indirection through a translation table;
all addresses were physical.
As a result, if the memory manager had to move memory around,
it also had to know where all the references to the moved memory
were kept so it can update the pointers.
If a data segment moved, the kernel had to go fix up all the
MakeProcInstance thunks so that they used the new
instance handle instead of the old one.
who discovered that all this
MakeProcInstance work was unnecessary.
If the callback function resided in a DLL,
then the function could hard-code its instance handle
and just load it at the start of the function;
this technique ultimately became known as __loadds.
Since DLLs were single-instance, the DLL already knew
which set of variables it was supposed to use since there
was only one set of DLL variables to begin with!
(Of course, the hard-coded value had to be recorded as a fix-up
since the instance handle is determined at run time.
Plus the kernel needed to know which values to update if the instance
handle changed values.)
On the other hand, if the callback function resided in an executable,
then it could obtain its instance handle from the stack selector;
this technique ultimately became known as __export.
Each program ran on a single stack (no multi-threading here),
and the stack, data segment, and local heap all resided in the same
selector by convention.
And in a strange bit of coming full circle which I discovered as I wrote
up this reminiscence,
Michael Geary's copy of
the original readme for his FixDS program that brought this technique
to the public contains an introduction which links back to me...
In the summer of 2006,
a Japanese-inspired maid café opened in Toronto.
Known as the iMaid Cafe,
it offers Chinese food served by young Chinese women
in French maid costumes, while Japanese pop music plays in the background.
Owner Aaron Wang explains the concept to Canadian television.