# February, 2004

• #### Why are RECTs endpoint-exclusive?

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 +1's everywhere.

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.

"But that's silly -- who ever does magnification or 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 anti-aliasing.

With apologies to Alvy Ray, I think the best way to interpret this is to view pixels as living between coordinates, not at them. For example, 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).)

 10 11 10 11

With this interpretation, the exclusion of the endpoint becomes much more natural. For example, here's the rectangle (10,10)-(13,12):

 10 11 12 13 10 11 12

Observe that this rectangle starts at (10,10) and ends at (13,12), just like its coordinates say.

• #### GetDialogBaseUnits is a crock

There are two functions that let you convert dialog units (DLUs) to pixels. One is GetDialogBaseUnits, which returns the base units directly (leaving you to do the math), and another is MapDialogRect, which takes a rectangle in DLUs and returns a rectangle in pixels.

What's the difference?

As you can guess from the title of this entry, GetDialogBaseUnits is a crock. Since there is no HWND parameter to GetDialogBaseUnits, it doesn't know which dialog box's DLUs you want to retrieve. So it guesses.

And it always guesses wrong.

GetDialogBaseUnits returns the dialog base units for dialog boxes that use the default system font. But nobody uses the default system font any more. It screams "old and dorky". But it remains the default for compatibility reasons. (And therefore so too does GetDialogBaseUnits.)

Everybody selects a custom font for their dialog box, usually "MS Sans Serif 8" or possibly "Tahoma" if they are one of those hip Windows 2000 folks.

That is why you must use MapDialogRect. The MapDialogRect function accepts a dialog box handle so it can use the correct font.

• #### The social skills of a thermonuclear device

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...?"

• #### The arms race between programs and users

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.

• "I don't want anybody to kill my process." vs. "How do I kill this runaway process?"
• "I want to shove this critical dialog in the user's face." vs. "How do I stop programs from stealing focus?"
• "I don't want anybody to delete this file." vs. "How do I delete this file that refuses to be deleted?"
• "How do I prevent this program from showing up in Task Manager?" vs. "How can I see all the programs that are running on my computer?"

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 privileges).

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?

• #### So what's to do in Sweden?

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.) Definitely hit Vasamuseet, Nobelmuseet, 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?

• #### The Seattle Improbable Show (2004)

An overflow crowd attended The Seattle Improbable Show. It was, as expected, a rollicking good time.

Mark Abrahams emceed and gave presentations, one on each of last year's Ig Nobel Prize winners, another chronicling various stages in the development of Project Grizzly. Other speakers were allotted five minutes (strictly and amusingly enforced) to expound on their chosen subjects, my favorite of which was Yoram Bauman's thought-provoking Translation of Mankiw's Ten Principles of Economics. (Don't miss footnote 3!)

Note to self: Next time, bring more paper. (For making and throwing paper airplanes, of course.) I brought only two this time. Need more.

• #### Bad version number checks

Version numbers. Very important. And so many people check them wrong.

This is why Windows 95's GetVersion function returned 3.95 instead of 4.0. A lot of code checked the version number like this:

```  UINT Ver = GetVersion();
UINT MajorVersion = LOBYTE(uVer);
UINT MinorVersion = HIBYTE(uVer);
if (MajorVersion < 3 || MinorVersion < 10) {
Error("This program requires Windows 3.1");
}
```

Now consider what happens when the version number is reported as 4.0. The major version check passes, but the minor version check fails since 0 is less than 10.

This bug was so rife that we gave up shimming every app that had the problem and just decided, "Fine. If anybody asks, say that the Windows version is 3.95."

I suspect this is also why DirectX always reports its version as 4.x.

• #### Stories of going through airport security

I went through security three times at Seattle-Tacoma International Airport before my flight to Newark.

My original flight was cancelled due to inclement weather in Newark, so I get rescheduled onto another flight that arrived three hours later. I thought to myself, "That's strange. Both flights are going to Newark. It's not like the weather in Newark is nicer on the second flight."

Not surprisingly, after about an hour, the second flight was also cancelled.

Anyway, when going through security the first time, I spotted the monitor on one of the X-ray machines and was somewhat amused to see the Windows 98 boot screen. Windows 98: Not dead yet. (Actually, this was probably Windows 98 Embedded. I remember having to debug a problem with Windows 95 Embedded just last year. The product key validation algorithm was failing because the "issued date" in the product key was failing a sanity check and being rejected as "ridiculously out of range".) I decided not to take a picture, though. Security people get really nervous when you take their picture...

While going through security the second time, they decided that my knitting needles may be a problem. This was the first time anybody had given me trouble over my needles. Eventually they decided that I wasn't going to attack somebody by poking them with a knitting needle, but not before doing a more detailed search of my bag and my person. (Mind you, they were Number 2 needles, pointier than your average knitting needle.)

On my return from Newark to Seattle, the security person also made note of my knitting needles, but only to compliment me on my hobby.

• #### TEXT vs. _TEXT vs. _T, and UNICODE vs. _UNICODE

So what's with all these different ways of saying the same thing?

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, for example. 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.