• The Old New Thing

    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?

  • The Old New Thing

    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 Old New Thing

    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.

  • The Old New Thing

    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.

  • The Old New Thing

    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.

  • The Old New Thing

    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.

  • The Old New Thing

    Improbable Research comes to Seattle

    The lunatics behind The Annals of Improbable Research and The Ig Nobel Prize will be in Seattle tomorrow night, Feburary 13. The meeting schedule lists the AIR presentation as "8:00PM-10:30PM, Special Event: Annals of Improbable Research (open to all registrants), Sheraton Hotel, Third Floor, Metropolitan Ballroom". The AIR folks said "Open to the public"; maybe they won't be checking for an AAAS membership card at the door.
  • The Old New Thing

    Sure, we do that

    The DirectX video driver interface for Windows 95 had a method that each driver exposed called something like "DoesDriverSupport(REFGUID guidCapability)" where we handed it a capability GUID and it said whether or not that feature was supported.

    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 spectacular manner.

    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)
      return TRUE;

    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.

    Next, he added code to DirectDraw so that when it starts up, it manufactures a random GUID based on that network card (which - by its having been destroyed - can never be validly created) and passes it to DoesDriverSupport. If the driver says, "Sure, we do that", DirectDraw says, "Aha! Caught you! I will not believe anything you say from now on."
  • The Old New Thing

    Dunkin Donuts vs. Krispy Kreme

    Having grown up on the east coast, I imprinted on Dunkin Donuts. Once a month we would stop at DD on the way home and buy a shoebox of doughnuts. Toasted coconut and butternut, those were my favorites.

    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.

  • The Old New Thing

    Answer to exercise: Pointer to member function cast


    Yesterday's exercise asked you to predict and explain the codegen for the following fragment:

    class Base1 { int b1; void Base1Method(); };
    class Base2 { int b2; void Base2Method(); };
    class Derived : public Base1, Base2
      { int d; void DerivedMethod(); };
    class Derived2 : public Base3, public Derived { };
    void (Derived::*pfnDerived)();
    void (Derived2::*pfnDerived2();
    pfnDerived2 = pfnDerived;

    Well, the codegen might go something like this:

      mov  ecx, pfnDerived[0]       ; ecx = address
      mov  pfnDerived2[0], ecx
      mov  ecx, pfnDerived2[4]      ; ecx = adjustor
      add  ecx, sizeof(Base3)       ; adjust the adjustor!
      mov  pfnDerived2[4], ecx

    Let's use one of our fancy pictures:


    Just for fun, I swapped the order of Base1 and Base2. There is no requirement in the standard about the order in which storage is allocated for base classes, so the compiler is completely within its rights to put Base2 first, if it thinks that would be more efficient.

    A pointer to member function for class Derived expects the "this" pointer to be at "q". So when we have a "p", we need to add sizeof(Base3) to it to convert it to "q", on top of whatever other adjustment the original function pointer wanted. That's why we add sizeof(Base3) to the existing adjustor to make a new combined adjustor.

Page 401 of 426 (4,251 items) «399400401402403»