Why are the rules for GetWindowText so weird?


Joel Spolsky rightly points out that the rules for GetWindowText exhibit abstraction leakage. Why are the rules for GetWindowText so weird?

Set the wayback machine to 1983. Your typical PC had an 8086 processor running at a whopping 4.7MHz, two 360K 5¼-inch floppy drives (or if you were really loaded, one floppy drive and a 10MB hard drive), and 256KB of memory. [Original entry said 256MB - oops. Thanks to Joe Beda for pointing this out.]

This was the world of Windows 1.0.

Windows 1.0 was a coöperatively-multitasked system. No pre-emptive multitasking here. When your program got control, it had control for as long as it wanted it. Only when you called a function like PeekMessage or GetMessage did you release control to other applications.

This was important, because in the absence of a hardware memory manager, you really had to make sure that your memory didn't get ripped out from under you.

One important consequence of coöperative multitasking is that if your program is running, not only do you know that no other program is running, but you also know that every window is responding to messages. Why? Because if they were hung, they wouldn't have released control to you!

This means that it is always safe to send a message. You never had to worry about the possibility of sending a message to a hung window, since you knew that no windows were hung.

In this simpler world, GetWindowText was a straightforward function:

int WINAPI
GetWindowText(HWND hwnd, LPSTR pchBuf, int cch)
{
    // ah for the simpler days
    return SendMessage(hwnd, WM_GETTEXT, (WPARAM)cch, (LPARAM)pchBuf);
}

This worked for all windows, all the time. No special handling of windows in a different process.

It was the transition to Win32 and pre-emptive multitasking that forced the change in the rules, because for the first time, there was the possibility that (gasp) the window you were trying to communicate with was not responding to messages.

Now you have the backwards compatibility problem. As I described in my original article, many parts of the system and many programs rely on the ability to retrieve window text without hanging. So how do you make it possible to retrieve window text without hanging, while still giving controls like the edit control the ability to do their own window text management?

The Win32 rules on GetWindowText are the result of this attempt to reconcile conflicting goals.

(This same story, with slight changes, also works as a discussion of why DDE works the way it does. But fewer people use DDE nowadays, so the effect is not as dramatic.)

Comments (8)
  1. Anonymous says:

    Hey Raymond,

    256MB? Do you mean KB?

  2. Anonymous says:

    Even 256KB would be quite a lot… how much memory could the 8086 support anyway? (I recall it was somewhere near 1MB, but you couldn’t use that much)

  3. Anonymous says:

    An 80×86 can handle 640KB in real mode (that’s 16 bit). Even though addresses were handled in 32 bits, the system addressing was overlapped (multiply the upper 16 bits by 16 and add the lower 16 bits).

  4. Anonymous says:

    Martin: It’s more complicated than that. The 8086 which is what’s Damit was asking about had 20 address pins. 2^20 results in 1MB of address space. The IBM PC developers decided that of that 1MB, 384K should be reserved for mapping in devices and 640K should be available to address main memory. The 640K limitation is a PC thing, not a x86 thing. And of course then it gets even more complicated, if you look at the 286 and 386 (and perhaps 186 but I can’t remember) where there were more than 20 address pins you could actually address that extra 64K beyond 1MB that became known as the High Memory Area and was used by DOS 5 and QEMM and such.

  5. Anonymous says:

    I always loved how the 65816 (the 16 bit version of the 6502) went from 16 bit addresses to 24-bit addresses without really obnoxious segment registers. The segment register was 8 bits slapped on the side without any of the usual funkieness.

    Although, the segment registers like that did prevent a few tricks that were useful when you were doing graphics, i.e. setting the segment register to the beginning of a bitmap and using the 16 bit addresses.

    I love the history of computing. ;)

  6. Anonymous says:

    "coöperatively." "preëmptive." I thought only The New Yorker rose to that level of prëtënsïön.

  7. Anonymous says:

    That would be 8088 and 4.77 MHz, wouldn’t it?

Comments are closed.