• The Old New Thing

    Why do I get a QueryInterface(IID_IMarshal) and then nothing?

    A common problem when trying to get your new COM object off the ground is that you can't seem to be able to get it created. The object comes out of the class factory, and it gets a QueryInterface for IMarshal, and then nothing. What's going on?

    This is a sure sign that you didn't register your CLSID properly; most likely you forgot to set your threading model properly. (And if you fail to specify a threading model at all, then you get the dreaded "main" threading model.)

    If somebody tries to create a COM object from a thread whose model is incompatible with the threading model of the COM object, then a whole bunch of marshalling stuff kicks in. And if the marshalling stuff isn't there, then COM can't use your object.

    There is a long and very technical article in MSDN on COM threading models which has lots of scary-looking diagrams and tables. In particular, the second scary table in the "In-process servers: (almost) totally dependent on their clients" chapter lists all the combinations of thread models with object threading models, and what COM tries to do in each case.

    In particular, notice that if you have a (mistakenly marked) "main"-threaded object and somebody on any thread other than the main thread tries to create it, marshalling will try to kick in.

    So watch those threading models. The failure modes when you get them wrong are quite baffling.
  • The Old New Thing

    Sorry the posts are late lately

    Somehow the server is in a wonky state and my autopilot script that posts a new article at 7 every morning is getting error 500 back (internal server error). So I'm posting manually for the nonce. Expect erratic posting times until the problem is resolved.
  • The Old New Thing

    No code is an island

    Norman Diamond noted in a comment that on Windows 2003 Server, the Display Adapter Troubleshooting slider still lists "full acceleration" as the recommended setting even though the default for Server is "full minus one".

    This is one of those "Oh, that's an easy change" bugs. The discussion probably went like this:

    Some guy whose idea this was: "For stability reasons, we want to lower the default video acceleration for Server a notch. Dear Video Setup team, can you do that for us?"

    Video Setup team: "Sure thing, that's no problem. The default setting is all done by us; it should not have any impact on anybody else. We'll just do it and be done with it."

    Guy: "Sweet. Thanks."

    And bingo, the default video acceleration dropped to one notch below full on Server, and everyone was happy.

    Except that there's this text tucked away in the Display control panel that has the word "(recommended)" next to "full acceleration". That didn't get updated. Oops. (I wouldn't be surprised if there is also some help text that didn't get updated for this change.)

    No code is an island.

    So when you complain, "Aw come on, it's a one-line change. What's taking so long?" think about the little video acceleration slider.
  • The Old New Thing

    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

    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

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

  • The Old New Thing

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

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

Page 404 of 429 (4,287 items) «402403404405406»