• The Old New Thing

    Project Update 3: Voyage to Our Hollow Earth

    • 8 Comments

    Alas, the original plan for the trip to the hole in the Arctic Ocean had to be scrapped due to the passing of organizer Steven Currey. But hollow earthers, don't give up hope! U.S. scientist Brooks Agnew has announced his plans to take the place of Mr. Currey, chartering the same ship and taking the same itinerary with the same goal.

    We'll check in next year to see what they've found.

  • The Old New Thing

    Why can't I create my dialog box? Rookie mistake #2

    • 8 Comments

    Another class of rookie mistake is less obvious from looking at the code.

    #define DLG_SAMPLE 1
    
    DLG_SAMPLE DIALOGEX 32, 32, 210, 200
    ...
    BEGIN
     ...
     CONTROL "",IDC_LISTVIEW,WC_LISTVIEW,LVS_REPORT |
             WS_TABSTOP | WS_BORDER,
             14,92,182, 80
     ...
    END
    
    DialogBox(hinst, MAKEINTRESOURCE(DLG_SAMPLE),
              hwnd, SampleDlgProc);
    

    The problem with this code is that we forgot to call InitCommonControlsEx to register the listview class. More generally, the problem is that one of the controls on the dialog uses a window class that was not registered. (For example, maybe there's a rich edit control on the dialog, but nobody remembered to load the rich edit library.)

    Next time, a sophomore version of this mistake.

  • The Old New Thing

    Reading a contract from the other side: Simulating a drop

    • 8 Comments

    Most people, when they think of the IDropTarget interface, think only of implementing a drop target. But you can read the contract from the other side, because the description of how a drag source interacts with a drop target tells you how to be a drag source.

    To summarize, the sequence of drop target operations go like this:

    • IDropTarget::DragEnter is called to indicate that an object has been dragged into the drop target. If the drop target returns a failure code, then the drop operation ends immediately.
    • Otherwise, IDropTarget::DragOver calls are made to advise the drop target as to the object's location.
    • If the user completes the drop operation, then call IDropTarget::Drop. Otherwise call IDropTarget::Leave. A drop operation can fail to complete because the user hit the Escape key, for example, or dragged the mouse out of the drop target.

    Let's write a simple program that drops one file onto another.

    #include <windows.h>
    #include <shlobj.h>
    #include <shellapi.h>
    #include <tchar.h>
    
    ... Insert the function GetUIObjectOfFile here ...
    
    int __cdecl wmain(int argc, WCHAR **argv)
    {
     if (argc == 3 && SUCCEEDED(CoInitialize(NULL))) {
      IDataObject *pdto;
      if (SUCCEEDED(GetUIObjectOfFile(NULL, argv[1],
                             IID_IDataObject, (void**)&pdto))) {
       IDropTarget *pdt;
       if (SUCCEEDED(GetUIObjectOfFile(NULL, argv[2],
                              IID_IDropTarget, (void**)&pdt))) {
        POINTL pt = { 0, 0 };
        DWORD dwEffect = DROPEFFECT_COPY | DROPEFFECT_LINK;
        if (SUCCEEDED(pdt->DragEnter(pdto, MK_LBUTTON,
                                     pt, &dwEffect))) {
         dwEffect &= DROPEFFECT_COPY | DROPEFFECT_LINK;
         if (dwEffect) {
          pdt->Drop(pdto, MK_LBUTTON, pt, &dwEffect);
         } else {
          pdt->DragLeave();
         }
        }
        pdt->Release();
       }
       pdto->Release();
      }
      CoUninitialize();
     }
     return 0;
    }
    

    This is a pretty straightforward implementation of the host side of the drag/drop protocol. Run this program with the full paths to two files, the first being the file to drop, and the second being the file you want to drop it onto. (Modifying this program to accept relative paths is left as an exercise for the reader.) For example, you might try

    fakedrop c:\autoexec.bat c:\windows\notepad.exe
    

    Now, sure, dropping a file on a program is nothing exciting. You could've just run the program with the file as the command line argument, after all. But that's looking at it too narrowly; you are simulating a drop operation, after all. For example, you can drop a file onto a shortcut to a printer, and the file will print; or you can drop a file onto a folder and it will be copied there (since we specified DROPEFFECT_COPY | DROPEFFECT_LINK, but folders prefer copy to link if the Ctrl+Shift keys are not held down); or you can drop a file onto the Mail Recipient.MAPIMail shortcut in your "Send To" folder to create a mail message with the file as an attachment.

    Oh wait, that last example with Mail Recipient.MAPIMail doesn't work. We'll look at why next time, although I suspect you already know the reason.

  • The Old New Thing

    The best building name on the University of Washington campus

    • 8 Comments

    The best building name on the University of Washington campus is Sieg Hall, for many years home to the computer science department, and named after former university president Lee Paul Sieg.

  • The Old New Thing

    Disable your wireless network card to speed up VPN'ing

    • 8 Comments

    As a follow-up to my tip on speeding up connecting via RAS and a SmartCard, I've been told that another trick you can do is to disable your wireless networking card before initiating the VPN connection. Wireless networking cards are a huge attack surface, and the VPN software spends a lot of time trying to secure it.

    I don't have a wireless networking card on the machine I use at home to connect to the work network, so I haven't tried it, but who knows, maybe it'll work for you.

  • The Old New Thing

    Meet the authors: Mario Hewardt and Daniel Pravat, authors of Advanced Windows Debugging

    • 8 Comments

    My colleague Mario Hewart just let me know that he and Daniel Pravat will be presenting at the PDC pre-con. In case you don't recognize the names, they're the authors of Advanced Windows Debugging, a book which I reviewed late last year.

    So if you want to get your debugging tips directly from the source, you know where to go.

    Besides, Mario speaks Swedish, so he's already awesome by default.

    [Raymond is currently away; this message was pre-recorded.]

  • The Old New Thing

    Ah, local Los Angeles television news, how I miss thee

    • 8 Comments

    Sitting in my hotel room the night before the 2008 PDC, I'm watching the Los Angeles local news, and the field reporter just said, "The police say this is an isolated incident, but it could happen anywhere."

  • The Old New Thing

    Follow-up: That shopautodotca seocontest online contest

    • 8 Comments

    So I didn't win the shopautodotca seocontest search engine optimization contest, so I decided to check on how the actual winners were faring. After all, one of the winners was supposed to become the company's SEO manager.

    The top prize winners in the Google category and in the MSN category have both complained that they haven't received their prizes yet and have threatened to file a fraud claim. (Dead link to forum.) The top prize winner in the Yahoo category hasn't said anything one way or the other.

    Meanwhile, the forum hosted by the contest organizers was emptied of all messages, rendering it a breeding ground for message board spam. (It was subsequently taken down late last year.)

    I suspect that's the last I'll hear of this contest; I don't anticipate any resolution to emerge.

  • The Old New Thing

    You didn't know you could add properties by atom, and it's a good thing you didn't know

    • 8 Comments

    As I noted a few days ago, there is weirdness associated with properties added by atom. This weirdness stems from the fact that adding properties by atom is really a hole in the original implementation rather than something designed on purpose.

    The original 16-bit code for adding and removing properties went roughly like this:

    BOOL SetProp(HWND hwnd, LPSTR pszName, HANDLE hValue)
    {
        ... let's look only at the part that adds a new property ...
    
        ATOM atm = HIWORD(pszName) ? GlobalAddAtom(pszName) : LOWORD(pszName);
        if (atm == 0) return FALSE;
    
        ... add the atom "atm" to the property list ...
    }
    
    HANDLE RemoveProp(HWND hwnd, LPSTR pszName)
    {
        ATOM atm = HIWORD(pszName) ? GlobalFindAtom(pszName) : LOWORD(pszName);
        if (atm == 0) return NULL;
    
        ... look for the atom "atm" in the property list and remove it ...
        if (!found) return NULL;
    
        // clean up the atom
        if (HIWORD(pszName)) GlobalDeleteAtom(atm);
    }
    
    void CleanPropertiesWhenWindowIsDestroyed(HWND hwnd)
    {
        for (each property on the window) {
            if (atm >= MAXINTATOM) GlobalDeleteAtom(atm);
        }
        .. delete memory used for recording properties ...
    }
    

    First, let's look at properties set and removed via integer atoms. These are simple: When setting the property, we just add it to the property list, and when removing the property, we remove it. Nothing fancy going on here.

    Similarly, there's nothing particularly exciting going on if a property is set and removed by name. When setting the property, we use GlobalAddAtom to convert the string to an atom (incrementing the reference count), and when removing it, we use GlobalDeleteAtom to clean it up (decrementing the reference count and removing the atom if the reference count goes to zero).

    Finally, when a window is destroyed with outstanding properties, we clean them up by calling GlobalDeleteAtom on all the string atoms, counteracting the GlobalAddAtom we performed when we added the property.

    So what's the big deal? Looks great, right?

    See if you can find the hole in this implementation.

    Hint 1: There are actually three ways of adding and removing properties from a window, not the two I led you to believe.

    Hint 2: What happens if you mix and match these three methods?

    Hint 3: What happens to each of the three types of properties when the window manager is forced to clean them up?

    These problems with properties were fixed a long time ago, but old-timers remain wary of adding named properties by string atom. It's one of those superstitions.

  • The Old New Thing

    I just discovered that the Scandinavian Gift Shop in Ballard is closing

    • 8 Comments

    When in Ballard for SeafoodFest, I was saddened to discover that one of the last remaining Scandinavian businesses in Ballard, the Scandinavian Gift Shop, is closing. They were in their final stages of "everything must go!", and I picked up a small number of Glad Påsk greeting cards, some pretty napkins (including a set that would be illegal if U.S. law applied to the Swedish flag), and a dozen tiny Swedish flag stick-pins. Fortunately, Olsen's Scandinavian Foods is still there, because you never know when you're going to get a hankering for some homemade pickled herring.

    I don't get to Ballard very often during business hours, but when I do, I try to make a point of vising Olsen's just to browse around the store, amuse myself at all the Norwegian packaging (most of the stuff comes from Norway), and maybe pick up an item or two. I think the previous time I was there, one of the Endresen sisters was working the register, because she very politely translated the instructions on the back of a package of asparagus soup for me. I would have waved her off and saved her the trouble, except I didn't know what vann was. (I now know that it is vatten = water.)

Page 385 of 453 (4,528 items) «383384385386387»