Holy cow, I wrote a book!
If you read the fine print of the
you'll see that on Windows NT 3.51 and earlier and on Windows 95,
the return value only matches the sign of the result of the increment
Why is that?
The 80386 instruction set supports interlocked increment and
decrement, but the result of the increment/decrement operation
is not returned. Only the flags are updated by the operation.
As a result, the only information you get back from the CPU about
the result of the operation is whether it was zero, positive, or
negative. (Okay, you also get some obscure information like whether
there were an even or odd number of 1 bits in the result, but that's
hardly useful nowadays.)
Since those operating systems supported the 80386 processor,
their implementations of the InterlockedIncrement and
InterlockedDecrement functions were limited by the capabilities
of the processor.
The 80486 introduced
the XADD instruction
which returns the original value of the operand.
With this additional information, it now becomes possible to
return the result of the operation exactly.
Windows NT 4 dropped support for the 80386 processor, requiring
a minimum of an 80486, so it could take advantage of this instruction.
Windows 98 still had to support the 80386, so it couldn't.
So how did Windows 98 manage to implement an operation that was not
supported by the CPU?
Windows 98 detected whether you had a CPU that supported the new XADD
instruction. If not, then it used an alternate
mechanism which was mind-bogglingly slow:
It called a driver whenever you wanted to increment or decrement
a variable. The driver would then emulate the XADD instruction by
disabling interrupts and performing the operation in locked memory.
Since Windows 98 was a uniprocessor operating system, it didn't
have to worry about a second processor changing the memory at the
same time; all it needed to ensure was that the single processor
didn't get interrupted while it was performing the "atomic" operation.
If you haven't read it yet, check out
voluminous discourse on various aspects of the history of Word.
It packs more history into one entry than I do all year.
And that was a sequel!
You can read the first half, too.
In fact, the good stuff keeps on coming.
just read it all.
When you broadcast a message
remember that the message you broadcast must have global meaning.
I discussed earlier what the various message ranges mean.
Notice that only the system-defined range (0..WM_USER-1) and
the registered message range (MAXINTATOM .. MAXWORD) have global
meaning. The other two ranges have class-specifc or
In other words, you can't broadcast a message in the WM_USER range
since that message has a different meaning for each window class.
Similarly, a message in the WM_APP range has a different meaning
for each application.
We ran into this problem in Windows 95.
There were programs that decided to broadcast
private messages like WM_USER+0x0100,
intending them to be delivered to
other instances of that program.
Of course, when those messages reached some other windows,
they interpreted WM_USER+0x0100 as some other private message
and either acted funny or crashed.
On the other hand, the programs really wanted the message to
reach the windows of other copies of itself, so we couldn't
just block the broadcast of the programs would stop working.
Progams were relying on the system not trying to stop them from
crashing other programs!
The solution was to split the difference.
If you broadcast a message that was not safe to broadcast,
Windows 95 would send it only to old-style programs.
New-style programs (marked as version 4.0 or higher) would not
receive the messages.
That way, old programs continued to affect each other as they
always did, but new programs followed the new rules.
Moral of the story:
When you broadcast a message, make sure it's one that every
receiving window will be able to handle.
I was going to write about why C# doesn't have "const",
already discussed this in
A Question of Const, so now I don't have to.
(And another example of synchronicity:
After I wrote up this item and tossed it into the queue,
Eric Gunnerson took up the topic as well.
Windows lets you hibernate the entire machine, but why can't
it hibernate just one process? Record the state of the process
and then resume it later.
Because there is state in the system that is not part of the process.
For example, suppose your program has taken a mutex, and then it
gets process-hibernated. Oops, now that mutex is abandoned
and is now up for grabs. If that mutex was protecting some
state, then when the process is resumed from hibernation,
it thinks it still owns the mutex and the state should therefore
be safe from tampering, only to find that it doesn't
own the mutex any more and its state is corrupted.
Imagine all the code that does something like this:
// assume hmtx is a mutex handle that
// protects some shared object G
// do stuff with G
// do more stuff with G on the assumption that
// G hasn't changed.
Nobody expects that the mutex could secretly get released
during the "..." (which is what would happen if the process
got hibernated). That goes against everything mutexes stand for!
Consider, as another example, the case where you have a file
that was opened for exclusive access. The program will
happily run on the assumption that nobody can modify
the file except that program. But if you process-hibernate
it, then some other process can now open the file (the exclusive owner
is no longer around), tamper with it, then resume the original program.
The original program on resumption will see a tampered-with file and
may crash or (worse) be tricked into a security vulnerability.
One alternative would be to keep all objects that belong to
a process-hibernated program still open. Then you would have
the problem of a file that can't be deleted because it is
being held open by a program that isn't even running!
(And indeed, for the resumption to be successful across a reboot,
the file would have to be re-opened upon reboot. So now you have
a file that can't be deleted even after a reboot because it's
being held open by a program that isn't running. Think of the
amazing denial-of-service you could launch against somebody:
Create and hold open a 20GB file, then hibernate the process
and then delete the hibernation file.
Ha-ha, you just created a permanently undeletable 20GB file.)
Now what if the hibernated program had created windows.
Should the window handles still be valid while the program
is hibernated? What happens if you send it a message?
If the window handles should not remain valid, then what happens
to broadcast messages? Are they "saved somewhere" to be replayed
when the program is resumed? (And what if the broadcast message
was something like "I am about to remove this USB hard drive,
here is your last chance to flush your data"?
The hibernated program wouldn't get a chance to flush its data.
Result: Corrupted USB hard drive.)
And imagine the havoc if you could take the hibernated process
and copy it to another machine, and then attempt to restore it there.
If you want some sort of "checkpoint / fast restore" functionality
in your program, you'll have to write it yourself.
Then you will have to deal explicitly with issues like the above.
("I want to open this file, but somebody deleted it in the meantime.
What should I do?"
"Okay, I'm about to create a checkpoint, I'd better purge all my buffers
and mark all my cached data as invalid because the thing I'm
caching might change while I'm in suspended animation.")
A friend of mine used to work on the development of the
USB specification and subsequent
implementation. One of the things that happens at these
meetings is that hardware companies would show off the great
USB hardware they were working on. It also gave them a chance
to try out their hardware with various USB host manufacturers
and operating systems to make sure everything worked properly
One of the earlier demonstrations was a company that was making
USB floppy drives. The company representative talked about how
well the drives were doing and mentioned that they make two versions,
one for PCs and one for Macs.
"That's strange," the committee members thought to themselves.
"Why are there separate PC and Mac versions? The specification
is very careful to make sure that the same floppy drive works
on both systems. You shouldn't need to make two versions."
So one of the members asked the obvious question.
"Why do you have two versions? What's the difference?
If there's a flaw in our specification, let us know and we can
The company representative answered,
"Oh, the two floppy drives are completely the same electronically.
The only difference is that the Mac version comes in translucent
blue plastic and costs more."
This company was of course not the only one to try to capitalize
on the iMac-inspired translucent plastic craze. My favorite
is the iMac-styled
George Foreman Grill.
(I'm told the graphite ones cook faster.)
In an earlier comment, Larry Osterman described why Windows 3.0 was
such a runaway success. He got a little of the timeline wrong,
so I'll correct it here.
Windows 2.0 did support protected mode.
And it was Windows/386, which came out before Windows 3.0,
which first used the new virtual-x86 mode of the 80386 processor
to support pre-emptively multitasked DOS boxes.
The old Windows 2.0 program was renamed "Windows/286" to keep
the names in sync.
The three modes of Windows then became "real mode" (Windows 1.0 style),
"standard mode" (Windows/286 style) and "enhanced mode" (Windows/386 style).
Amazingly, even though the way the operating system used the processor was
radically different in each of the three modes, a program written for
"real mode" successfully ran without change in the other two modes.
You could write a single program that ran on all three operating systems.
And then Windows 3.0 came out and the world changed.
Sales were through the roof.
I remember that some major software reseller (Egghead?)
was so pleased with the success of Windows 3.0 that
it bought bought every Microsoft employee a Dove ice cream bar.
(Even the employees like me who were working on OS/2.)
I was sitting in my office and some people came in
with a big box of ice cream bars and they handed me one.
"This is from Egghead. Thank you for making Windows 3.0 a success," they said.
It was a strange feeling, getting a thank-you for something
you not only didn't work on, but something which totally destroyed
the project you were working on!
[Raymond is currently on vacation; this message was pre-recorded.]
Sometimes you'll see somebody brag about how many words are
in their spell-checking dictionary.
It turns out that having too many words in a spell checker's dictionary
is worse than having too few.
Suppose you had a spell checker whose
dictionary contained every word in the
Oxford English Dictionary.
Then you hand it this sentence:
Therf werre eyght bokes.
That sentence would pass with flying colors, because all of the
words in the above sentence are valid English words, though
most people would be hard-pressed to provide definitions.
The English language has so many words that if you included them all,
then common typographical errors would often match (by coincidence)
a valid English word and therefore not be detected by the spell checker.
Which would go against the whole point of a spell checker: To catch
So be glad that your spell checker doesn't have the largest dictionary
possible. If it did, it would end up doing a worse job.
After I wrote this article, I found
a nice discussion of the subject of spell check dictionary size
on the Wintertree Software web site.
Along the lines of
Windows as Rorschach test,
here's an example of someone attributing malicious behavior
Among the logon pictures that come with Windows XP is
a martial arts kick.
I remember one bug we got that went something like this:
"Windows XP is racist.
It put a picture of a kung fu fighter
next to my name - just because my name is Chinese.
This is an insult!"
The initial user picture is chosen at random from
among the pictures in the "%ALLUSERSPROFILE%\Application
Data\Microsoft\User Account Pictures\Default Pictures" directory.
It just so happened that the random number generator
picked the martial arts kick out of the 21 available pictures.
I'm also frustrated by people who find quirks in spellcheckers
and attribute malicious intent to them.
You know what I'm talking about.
"Go to Word and type in <some name that's not in the
dictionary> and tell it to spellcheck. Word will flag the
word and recommend <some other word that is somehow opposite
to the first word in meaning> instead. This is an insult!
Microsoft intentionally taught the spellchecker to suggest
<that word> when you type <this word>.
This is clear proof of <some bad thing>."
More on spell checking tomorrow.
Luna was the code name for the Windows XP "look".
The designers did a lot of research (and got off to a lot of false
starts, as you might expect) before they came
to the design they ultimately settled upon.
During the Luna studies,
that people's reaction to Luna was often,
"Wow this would be a great UI for X," where X was
"my dad" or "my employees" or "my daughter".
People didn't look at it as the UI for themselves;
rather, they thought it was a great UI for somebody else.
It was sometimes quite amusing to read the feedback.
One person would write,
"I can see how this UI would work great
in a business environment, but it wouldn't
work on a home computer." and the very next person would
write "I can see how this UI would work great
on a home computer, but it wouldn't
work in a business environment."
(And interestingly, even though armchair usability experts
claim that the "dumbed-down UI" is a hindrance, our studies
showed that people were actually more
productive with the so-called "dumb" UI.
Armchair usability experts also claim that the Luna look
is "too silly for serious business purposes", but in reality it
tested very well on the "looks professional" scale.)
Aero is the code name for the Longhorn "look".
With Aero, the designers have turned an important corner.
Now, when they show Aero to people, the reaction is,
"Wow, this would be a great UI for me to use."
People want Luna for others, but they want Aero for themselves.