September, 2013

  • The Old New Thing

    Sometimes my dreams are entirely uneventful

    • 19 Comments

    I dreamed that I was washing dishes with my lovely wife.

  • The Old New Thing

    Playing a sound every time the foreground window changes

    • 22 Comments

    Today's Little Program plays a little sound every time the foreground window changes. One of my colleagues wondered if such a program was possible, "so that I stop accidentally typing the second halves of paragraphs into windows that pop up and steal focus." It's not clear whether this program will actually solve the bigger problem, but it was fun writing the program, and maybe you can use it for something.

    #define STRICT
    #include <windows.h>
    #include <mmsystem.h>
    
    void CALLBACK WinEventProc(
        HWINEVENTHOOK hWinEventHook,
        DWORD event,
        HWND hwnd,
        LONG idObject,
        LONG idChild,
        DWORD dwEventThread,
        DWORD dwmsEventTime
    )
    {
      if (hwnd &&
          idObject == OBJID_WINDOW &&
          idChild == CHILDID_SELF &&
          event == EVENT_SYSTEM_FOREGROUND) {
       PlaySound(TEXT("C:\\Windows\\Media\\Speech Misrecognition.wav"),
                 NULL, SND_FILENAME | SND_ASYNC);
     }
    }
    
    int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hinstPrev,
                       LPSTR lpCmdLine, int nShowCmd)
    {
      HWINEVENTHOOK hWinEventHook = SetWinEventHook(
         EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND,
         NULL, WinEventProc, 0, 0,
         WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS);
    
      MSG msg;
      while (GetMessage(&msg, NULL, 0, 0)) {
       TranslateMessage(&msg);
       DispatchMessage(&msg);
      }
    
      if (hWinEventHook) UnhookWinEvent(hWinEventHook);
    
      return 0;
    }
    

    This program installs an accessibility hook that listens for changes to the system foreground. And when it happens, we play a little sound.

    I chose the Windows 7 Speech Misrecognition sound because it's relatively unobtrusive. And the sound is played asynchronously so as not to block the message pump thread. It also has as a pleasant side-effect that if the foreground changes many times rapidly, the new sound will interrupt the old one rather than queueing up behind it.

    Note that there is no way to exit this program short of killing it in Task Manager. That's why it's a Little Program rather than a real program.

  • The Old New Thing

    2013 Q3 link clearance: Microsoft blogger edition

    • 9 Comments

    It's that time again: Linking to other Microsoft bloggers, and once again, the links are all from the excellent NT Debugging blog.

  • The Old New Thing

    How can I determine how responsive my application is to input?

    • 0 Comments

    A customer was adding diagnostics to their application and wanted to know if there was a way to detect that the application was being slow in processing its input. These sorts of delays manifest themselves to the end user as a sluggish application which is slow to respond to input events.

    They already had a watchdog timer that was reset every time their Get­Message call returned a message, so they could capture stack traces if their application stopped processing messages for more than X milliseconds. They wanted to extend this diagnostic information to input delays.

    Fortunately, there's an easy way to tell. The Get­Message­Time will tell you the time the message was added to the queue, so by subtracting that time from the current Get­Tick­Count, you can determine how long the input message sat in the queue. (Sent messages are not queued messages, so calling Get­Message­Time for a sent message doesn't work.)

    There's a catch, here, though.

    Since mouse messages are generated on demand, the Get­Message­Time for a WM_MOUSE­MOVE message is usually "Just now." (It could be older if you forced a mouse move message to be generated but left it in the queue.) To get the actual time the mouse moved, you need to use Get­Mouse­Move­Points­Ex.

  • The Old New Thing

    Don't forget, Unicode includes formatting characters which can be used to influence output formatting

    • 17 Comments

    Consider this simple function:

    void Reminder(HWND hwnd)
    {
        MessageBoxW(nullptr,
            L"Please print out this form in triplicate "
            L"and bring it to the assistance desk "
            L"on level 2.",
            L"Reminder", MB_OK);
    }
    

    Depending on your screen resolution and font choices, this may end up displaying like this:

    Reminder
    Please print out this form in triplicate and bring it to the assistance desk on level
    2.

    That line break was awfully unfortunate, stranding the number 2 on a line by itself. (In publishingspeak, this is known as a orphan.)

    You can't control where the Message­Box function will insert line breaks, but you can try to influence it with the use of Unicode formatting characters. Here, we can change the space before the 2 to a Unicode non-breaking space, U+00A0.

    void Reminder(HWND hwnd)
    {
        MessageBoxW(nullptr,
            L"Please print out this form in triplicate "
            L"and bring it to the assistance desk "
            L"on level" L"\u00A0" L"2.",
            // could also have been written
            // L"on level\u00A02.",
            // but is harder to read
            L"Reminder", MB_OK);
    }
    

    The result is slightly less awful.

    Reminder
    Please print out this form in triplicate and bring it to the assistance desk on
    level 2.

    Unfortunately, I haven't had much luck with the soft hyphen, but the zero-width space seems to work.

        MessageBoxW(nullptr,
            L"Gooooooo\u200Booooooo\u200Booooooo\u200Booooooo\u200B"
            L"ooooooo\u200Booooooo\u200Booooooo\u200Booooooo\u200B"
            L"ooooooo\u200Booooooo\u200Booooooo\u200Booooooo\u200B"
            L"ooooooo\u200Booooooo\u200Booooooo\u200Booooooo\u200B"
            L"ooooooo\u200Bal!",
            L"Gentle reminder", MB_OK);
    
  • The Old New Thing

    How can I tell that somebody used the MAKEINTRESOURCE macro to smuggle an integer inside a pointer?

    • 22 Comments

    Many functions and interfaces provide the option of passing either a string or an integer. The parameter is formally declared as a string, and if you want to pass an integer, you smuggle the integer inside a pointer by using the MAKE­INT­RESOURCE macro. For example, the Find­Resource function lets you load an resource specified by integer identifier by passing the identifier in the form MAKE­INT­RESOURCE(ID). You can tell that it was the resource-loading functions who created the macro in the first place, since the name of the macro is "make integer resource."

    But other functions use the MAKE­INT­RESOURCE convention, too. The Get­Proc­Address function lets you obtain a function exported by ordinal if you smuggle the ordinal inside a pointer: Get­Proc­Address(hModule, MAKE­INT­RESOURCEA(ordinal)). (You have to use MAKE­INT­RESOURCEA because Get­Proc­Address explicitly takes an ANSI string.)

    What if you're implementing a function whose interface requires you to accept both strings and integers-smuggled-inside strings? For example, maybe you're implementing IContext­Menu::Invoke­Command, which needs to look at the CM­INVOKE­COMMAND­INFO.lpVerb member and determine whether the invoker passed a string or a menu offset.

    You can use the IS_INT­RESOURCE macro. It will return non-FALSE if the pointer you passed is really an integer smuggled inside a pointer.

    How does MAKE­INT­RESOURCE work? It just stashes the integer in the bottom 16 bits of a pointer, leaving the upper bits zero. This relies on the convention that the first 64KB of address space is never mapped to valid memory, a convention that is enforced starting in Windows 7.

  • The Old New Thing

    Punctuation is becoming increasingly decorative and less functional

    • 40 Comments

    The "Blog" of "Unnecessary" Quotation Marks calls out abuse of the quotation mark. For some reason, quotation marks are being increasingly used as a form of emphasis (a usage which remains controversial), by people unaware that such use, when interpreted as scare quotes, serves to undermine their original point.

    Mind you, the emphasis theory doesn't explain all misuses of quotation marks I've seen. I'm led to believe that some people simply enjoy seeing quotation marks and place them around randomly-selected words.

    Apostrophes are another commonly-misused punctuation mark. So much so that the city of Birmingham has simply given up and deleted them from all their street signs. Other cities followed suit.

    Tying together all this is a sign I saw in an airport dining facility:

    SORRY NO FREE
    REFILLL'S
    AFTER LEAVING
    FACILITY"

    The challenge isn't so much finding what's wrong with the sign as it is finding what's still right. (As a bonus, the sign was next to another sign that read "No free refills", which only served to create more confusion, because the first sign suggests that refills are free if you stay inside the facility, but the second sign denies it.)

    Today is National Punctuation Day.

  • The Old New Thing

    Wait, so does moving a file recalculate inherited permissions or doesn't it?

    • 15 Comments

    A customer had a question about whether moving a file recalculated inherited permissions. They found that on their Windows Server 2008 R2 machine, if they moved a file between directories with different inheritable ACEs, then the security descriptor is recalculated to match the destination folder, if they perform the move from the machine itself. The same thing happens if they go to a machine running Windows 7, However, if they repeat the experiment from a machine running Windows XP or Windows Server 2003, then the security descriptor is preserved across the move.

    The customer is confused. Why does the behavior change based on the version of Windows running on the client, even though the files themselves are kept on the same server?

    The explanation is given in a few places:

    Even with these explanations, the customer remained confused.

    "Why does the permission depend on the operating system running on the client? The files are on the server, so regardless of the client operating system, it should be following the rules which apply to the server, right?"

    There are two different operations here.

    Suppose I told you, "When you buy clothes from the store, it will have the store sticker on it. You must remove the sticker yourself, and you should also wash the clothes before wearing it the first time, because the store puts powder in the bag to keep the clothes from getting moldy."

    You then say, "That is not true. When I go to my closet to get clothes I recently bought from the store, the store stickers are already gone, and there is no powder."

    That's because you live with your parents, and your mother takes your clothes, removes the stickers, washes the clothes, and then hangs them up in your closet.

    The underlying file system "move" operation preserves the ACLs from the source.

    On the other hand, if you use Explorer to move the files, then you are not using the underlying file system "move" operation directly. Your mother is moving the files. And when mother Explorer moves the files, she also edits the ACLs based on the nature of the source and destination folders, as described in the aforementioned Knowledge Base articles. Furthermore, different versions of mother Explorer edit the ACLs in different ways.

    That is why the behavior is dependent upon the client operating system. When you move the file from a client machine connected to the server, the client machine asks the server to move the files (which preserve the ACLs since that's what the low-level "move" operation does), and then the client machine goes back in and edits the ACLs in a client-specific way.

    It is therefore the client operating system which controls how the ACL editing is performed, because it is the client operating system which is editing the ACLs.

  • The Old New Thing

    I dreamed that I was in an alternate-universe Samuel L. Jackson movie

    • 16 Comments

    I dreamed that I was part of the crew of an underwater spaceship, and we had to deal with an alligator that got on board. How the alligator got on board was never explained, but now is not the time to ask questions because, you know, alligator.

    The plan was to flood the ship and wash the alligator out. There were only enough air pills for the female crew members. The men would have to hold their breath and hope for the best, with the expectation that not all would make it. But before we could execute the plan, the door caved in and the ship began to fill with water.

    At this point, I transferred to another dream in which I discussed cookbook organization techniques with a friend of mine. "Do you organize alphabetically by title? By main ingredient? By frequency of use?"

    None of the cookbooks had any alligator recipes.

  • The Old New Thing

    Providing a custom autocomplete source for an edit control

    • 15 Comments

    Today's Little Program shows a custom source for autocomplete. It's nothing exciting, but at least's it's something you can use as a starting point for your own customizations.

    We start with a dialog template, whose edit control will be the target of a custom autocomplete.

    // scratch.rc
    #include <windows.h>
    
    1 DIALOGEX DISCARDABLE  32, 32, 200, 56
    STYLE DS_MODALFRAME |  WS_POPUP |
          WS_VISIBLE | WS_CAPTION | WS_SYSMENU
    CAPTION "Sample"
    FONT 8, "MS Shell Dlg"
    BEGIN
     LTEXT "What is your favorite Seattle restaurant?",-1,7,8,184,10
     EDITTEXT 100,7,18,184,14
     PUSHBUTTON "OK",IDOK,146,38,50,14
    END
    

    Just for fun, I wrote the program in ATL. Instead of complaining that my code is hard to understand because I didn't use an application framework, people can now complain that my code is hard to understand because I used the wrong application framework.

    // scratch.cpp
    
    #include <windows.h>
    #include <ole2.h>
    #include <windowsx.h>
    #include <shlobj.h>
    #include <atlbase.h>
    #include <atlcom.h>
    
    CComModule _Module;
    

    To save some typing, I define a shorthand name for "the predefined ATL object for enumerating strings via IEnum­String."

    typedef CComEnum<IEnumString,
                     &IID_IEnumString,
                     LPOLESTR,
                     _Copy<LPOLESTR> > CComEnumString;
    

    To initialize the dialog, we do the following things:

    • Create a predefined ATL object for implementing IEnum­String.
    • Tell the predefined ATL object to enumerate a hard-coded list of restaurant suggestions.
    • Create an autocomplete object.
    • Connect the autocomplete object to the edit control in the dialog and to the IEnum­String object.
    • Just for fun, change some of the default settings for autocomplete.
    LPOLESTR c_rgpszSuggestions[] = {
        L"Brave Horse Tavern",
        L"Cuoco",
        L"Dahlia Bakery",
        L"Dahlia Lounge",
        L"Etta's",
        L"Lola",
        L"Palace Kitchen",
        L"Seatown",
        L"Serious Pie",
        L"Ting Momo",
    };
    
    void OnInitDialog(HWND hdlg)
    {
      CComPtr<IAutoComplete2> spac;
      CComObject<CComEnumString> *pes;
      HRESULT hr = CComObject<CComEnumString>::CreateInstance(&pes);
      CComPtr<IEnumString> spes(pes);
      if (SUCCEEDED(hr) &&
          SUCCEEDED(pes->Init(&c_rgpszSuggestions[0],
                              &c_rgpszSuggestions[ARRAYSIZE(c_rgpszSuggestions)],
                              NULL)) &&
          SUCCEEDED(spac.CoCreateInstance(CLSID_AutoComplete)) &&
          SUCCEEDED(spac->Init(GetDlgItem(hdlg, 100), spes, NULL, NULL)) &&
          SUCCEEDED(spac->SetOptions(ACO_AUTOSUGGEST | ACO_UPDOWNKEYDROPSLIST))) {
      }
    }
    

    The rest is just boilerplate.

    INT_PTR CALLBACK DlgProc(HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
      switch (uMsg) {
      case WM_INITDIALOG:
        OnInitDialog(hdlg);
        return TRUE;
    
      case WM_COMMAND:
        switch (GET_WM_COMMAND_ID(wParam, lParam)) {
        case IDOK:
          EndDialog(hdlg, 0);
          break;
        }
      }
      return FALSE;
    }
    
    int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hinstPrev,
                       LPSTR lpCmdLine, int nShowCmd)
    {
      if (SUCCEEDED(CoInitialize(NULL))) {
        DialogBox(hinst, MAKEINTRESOURCE(1), NULL, DlgProc);
        CoUninitialize();
      }
      return 0;
    }
    

    Now, one of the reasons for using a framework is that it hides a lot of details from you. But if you are trying to understand how to port code from one framework to another, those hidden details become an obstacle to progress rather than a convenience. You may port the overall structure from one framework to another, but if the two frameworks behave differently in the hidden parts, your conversion was incorrect.

    For example, one subtlety hidden in the above code is how the strings are returned by the IEnum­String::Next method. Recall that COM interfaces use the task allocator to pass memory between objects, so the string returned by IEnum­String::Next is allocated by Co­Task­Mem­Alloc, with the expectation that the caller will call Co­Task­Mem­Free to free it.

    Unless you happen to be familiar with this detail of ATL, you would never have guessed it from the code above. You might have thought that the enumerator handed out the literal string pointers used to initialize it, and then you'll start wondering why your program crashes at random times (because you introduced a heap corruption bug).

Page 1 of 3 (29 items) 123