Holy cow, I wrote a book!
Here is where Raymond gets to abuse his power as a blogger
to get some free travel advice.
I will likely travel to Sweden in mid-March,
with a whopping total of five months of Swedish under my belt.
I'm sure I will embarrass myself horribly,
but that's sort of the point, after all.
The question is, "So what's to do in Sweden?"
I was thinking of flying in to Stockholm,
spending the first day recovering from jet lag,
then spending maybe a week exploring whatever there is
to see there.
(Well, I'll actually be staying with a friend in Uppsala,
but there appears to be regular train service to/from Stockholm.)
and Gamla Stan.
I'm sure there's other stuff too.
Then I figure I'd hop a train to Göteborg
and spend the remaining three days there doing,
um, I have no idea. But I'm told it's a nice city.
Yes, this plan means that I miss out on Gotland,
Skåne, the -Köppings, and all the northern bits.
But then again, you can't see a whole country in just ten days.
So am I nuts?
Ironically, Dunkin Donuts is really a coffee shop
disguised as a doughnut shop. (Doughnuts account for only 20% of
their sales; coffee 50%.)
So during my travels through Manhattan, I walked past one
of the twenty-five zillion Dunkin Donuts stores there
and popped in for a toasted coconut doughnut.
One bite and I was a little kid again.
Some people say that DD's doughnuts are awful, but that's
pretty much irrelevant to me by now.
It's all about the memories that are invoked.
And besides, those people are wrong.
I don't understand the appeal of KK donuts.
They have no flavor; it's just sugar.
There is a constant struggle between people who write
programs and the people who actually use them.
For example, you often see questions like,
"How do I make my program so the user can't kill it?"
Now, imagine if there were a way to do this.
Ask yourself, "What would the world be like if this were possible?"
Well, then there would be some program, say, xyz.exe,
that is unkillable. Now suppose you're the user.
There's this program xyz.exe that has gone haywire,
so you want to exit it. But it won't let you exit.
So you try to kill it, but you can't kill it either.
This is just one of several arms races that you can imagine.
Eventually you have to decide which side wins,
and Windows has decided to
keep users in control of their own programs and data,
and keep administrators in control of their own computer.
So users can kill any process they want (given sufficient
privileges), they can stop any program from stealing focus,
and they can delete any file they want (again, given sufficient
Programs can try to make themselves more difficult to kill
(deny PROCESS_TERMINATE access,
deny PROCESS_CREATE_THREAD access
so people can't CreateRemoteThread(EndProcess),
deny PROCESS_VM_WRITE so people can't
scribble into your stack and make you doublefault,
deny PROCESS_SUSPEND_RESUME so they can't suspend you),
but eventually you just can't stop them from,
say, elevating to Debug privilege,
debugging your process, and moving EIP to "ExitProcess".
Notice that you can kill CSRSS.EXE and WINLOGON.EXE if you like.
Your computer will get very angry at you, but you can do it.
(Save you work first!)
Another useful question to ask yourself:
"What's to prevent a virus from doing the same thing?"
If there were a way to do these things, then a virus
could take advantage of them and make itself invisible
to Task Manager, undeletable, and unkillable.
Clearly you don't want that, do you?
There were various capability GUIDs defined, things like
GUID_CanStretchAlpha to ask the driver whether it was
capable of stretching a bitmap with an alpha channel.
There was one driver that returned TRUE when you called
DoesDriverSupport(GUID_XYZ), but when DirectDraw
tried to use that capability, it failed, and in a pretty
So one of the DirectDraw developers called the vendor and
asked them, "So does your card do XYZ?"
Their response: "What's XYZ?"
Turns out that their driver's implementation of DoesDriverSupport
was something like this:
BOOL DoesDriverSupport(REFGUID guidCapability)
In other words, whenever DirectX asked, "Can you do this?"
they answered, "Sure, we do that," without even checking what
the question was.
(The driver must have been written by the sales department.)
So the DirectDraw folks changed the way they queried for
driver capabilities. One of the developers went into his
boss's office, took a network card, extracted the
MAC address, and then smashed the card with a hammer.
You see, this last step was important: The GUID generation
algorithm is based on a combination of time and space.
When you ask CoCreateGuid to create a new GUID, it encodes
the time of your request in the first part of the GUID
and information that uniquely identifies your machine
(the network card's MAC address, which is required
to be unique by the standards that apply to network card).
By smashing the network card with a hammer, he prevented
that network card from ever being used to generate a GUID.
Somebody@somewhere.else described me as having the social skills
of a thermonuclear device.
I don't remember the incident in question, but I'll have to accept
that it happened.
I have a very low tolerance for laziness.
If you come to me for help,
I expect you to have done your homework.
(Though I try to scale my expectations to your position.
If you're in a coding position then you had better know
how to use a debugger.
If you're in a testing position, then you had better know
at least how to install the debugger.
This is considered part of the standard skill set for a tester.)
But the absolute worst thing you can do is start a conversation by
saying, "Hey, Raymond, since you know everything,
can you do this for me...?"
And if you do it wrong, focus will get all messed up.
If you are finished with a modal dialog, your temptation
would be to clean up in the following order:
But if you do that, you'll find that foreground activation doesn't go back
to your owner. Instead, it goes to some random other window.
Explicitly setting activation to the intended owner "fixes"
the problem, but you still have all the flicker,
and the Z-order of the interloper window gets all messed up.
What's going on?
When you destroy the modal dialog, you are destroying
the window with foreground activation.
The window manager now needs to find somebody else to give
It tries to give it to the dialog's owner, but the owner is
so the window manager skips it and looks for some other
window, somebody who is not disabled.
That's why you get the weird interloper window.
The correct order for destroying a modal dialog is
This time, when the modal dialog is destroyed, the
window manager looks to the owner and hey this time
it's enabled, so it inherits activation.
There's actually a method behind the madness.
The plain versions without the underscore affect the character set
the Windows header files treat as default. So if you define UNICODE,
then GetWindowText will map to GetWindowTextW instead of GetWindowTextA,
Similarly, the TEXT macro will map to L"..." instead of "...".
The versions with the underscore affect the character set
the C runtime header files treat as default. So if you define _UNICODE,
then _tcslen will map to wcslen instead of strlen, for example.
Similarly, the _TEXT macro will map to L"..." instead of "...".
What about _T? Okay, I don't know about that one.
Maybe it was just to save somebody some typing.
The Win32 COM calling convention specifies the layout of
the virtual method table (vtable) of an object.
If a language/compiler wants to support COM, it must lay
out its object in the specified manner so other components
can use it.
It is no coincidence that the Win32 COM object layout matches
closely the C++ object layout. Even though COM was originally
developed when C was the predominant programming language,
the designers saw fit to "play friendly" with the up-and-coming
new language C++.
The layout of a COM object is made explicit in the header files
for the various
interfaces. For example, here's IPersist from objidl.h, after cleaning
up some macros.
typedef struct IPersistVtbl
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
IPersist * This,
/* [in] */ REFIID riid,
/* [iid_is][out] */ void **ppvObject);
ULONG ( STDMETHODCALLTYPE *AddRef )(
IPersist * This);
ULONG ( STDMETHODCALLTYPE *Release )(
IPersist * This);
HRESULT ( STDMETHODCALLTYPE *GetClassID )(
IPersist * This,
/* [out] */ CLSID *pClassID);
const struct IPersistVtbl *lpVtbl;
This corresponds to the following memory layout:
What does this mean?
A COM interface pointer is a pointer to a structure that consists
of just a vtable.
The vtable is a structure that contains a bunch of function pointers.
Each function in the list takes that interface pointer (p) as its first
The magic to all this is that since your function gets p
as its first parameter, you can "hang" additional
stuff onto that vtable:
The functions in the vtable can use offsets relative to the
interface pointer to access its other stuff.
If an object implements multiple interfaces but they are all descendants
of each other, then a single vtable can be used for all of them.
For example, the object above is already set to be used either as
an IUnknown or as an IPersist, since IUnknown is a subset of IPersist.
On the other hand, if an object implements multiple interfaces
that are not descendants of each other, then you get multiple
inheritance, in which case the object is typically laid out in
memory like this:
If you are using an interface that comes from the first vtable, then
the interface pointer is p. But if you're using an interface that
comes from the second vtable, then the interface pointer is q.
Hang onto that diagram, because
tomorrow we will learn about those mysterious "adjustor thunks".
Endpoint-exclusive RECTs and lines are much easier to work with.
For example, the width of a rectangle is right - left,
and its height is bottom - top.
If rectangles were endpoint-inclusive, then there would be annoying
right - left
bottom - top
End-point exclusive rectangles also scale properly.
For example, suppose you have two rectangles (0,0)-(100,100) and
(100,100)-(200,200). These two rectangles barely touch at the
corner. Now suppose you magnify these rectangles by 2, so they
are now (0,0)-(200,200) and (200,200)-(400,400). Notice that
they still barely touch at the corner. Also the length of each
edge doubled from 100 to 200.
Now suppose endpoints were inclusive, so the two rectangles would
be (0,0)-(99,99) and (100,100)-(199,199). Now when you double
them, you get (0,0)-(198,198) and (200,200)-(398,398). Notice
that they no longer touch any more because (199,199) is missing.
Note also that the length of the side of the square is now 199
pixels instead of 200.
Similar problems occur if you need to do subpixel computations.
Well, magnification is used more than you think. In addition to
the obvious things like zooming in/out, it's also used in
printing (since printers are 300dpi but the screen is usually
much lower resolution) and in GDI mapping (ScaleWindowExtEx,
StretchBlt). And subpixel computations are used in
With apologies to Alvy Ray,
I think the best way to interpret this is to view pixels
as living between coordinates, not at them.
here's a picture of the pixel that lives between (10,10) and (11,11).
(In other words, this pixel is the rectangle (10,10)-(11,11).)
Observe that this rectangle starts at (10,10) and ends at (13,12),
just like its coordinates say.
The long answer:
When balloon tips were first developed, there was no ability
to embed links.
Consequently, programs were free to put insecure text in balloon tips,
since there was no risk that they would become "live".
So, for example, a virus scanner might say
"The document 'XYZ' has been scanned and found to be
free of viruses."
Now suppose hotlinks were supported in balloon tips.
Look at how this can be exploited:
I can write a web page that goes
You download the message and since you are a cautious person,
you ask your virus scanner to check it out.
The balloon appears:
"Oh, how convenient," you say to yourself.
"The virus scanner even included a hotlink to the document
so I can read it."
And then you click on it and your hard drive gets reformatted.
"So why don't you add a NIF_PARSELINKS flag, so people
who want to enable hotlinks in their balloon tips can do so,
and still remain compatible with people who wrote to the old API?"
(I've heard of one person trying to pass a TTF_PARSELINKS flag
member and wondering why it wasn't
working. I hope it's obvious to everybody why this had no chance
Because that would just be passing the buck.
Anybody who used this proposed flag would then have to
be extra-careful not to put untrusted links in their balloon
tips. Most people would just say, "Wow! A new flag!
That's awesome!" and start using it without considering
the serious security implications.
Then somebody can trick the program into putting untrusted
text into a balloon tip and thereby exploit the security hole.
"Aw, come on, who would be so stupid as to write code without
considering all the security implications?"
The best way to make sure things are secure is to make it
impossible to be insecure.