December, 2013

  • The Old New Thing

    2013 year-end link clearance

    • 11 Comments

    Another round of the semi-annual link clearance.

    And, as always, the obligatory plug for my column in TechNet Magazine:

    The retirement of TechNet Magazine also spells the end of the Windows Confidential column, so this is the last of the obligatory plugs, at least until I have some other obligatory thing to plug.

  • The Old New Thing

    New Year's Eve is sometimes a stressful occasion

    • 18 Comments

    Today is New Year's Eve, another opportunity for to mark that an approximately-integral number of revolutions of the earth have occurred since some point in time that wasn't even calculated correctly in the first place. (We retain it for backward compatibility.)

    December 31, 1999 was a particularly anxious day in the technology sector. Microsoft's Director of Y2K Readiness and vice president of Product Support Services described some of the steps that were being taken to prepare for any timekeeping-related issues that would arise as the calendar ticked over to 2000.

    We've analyzed phone capacity, IT systems backup for both data and power, and additional lab environments for enhanced product support capabilities. We have redundant power systems, including back-up generators, at key locations in the unlikely event we lose power.

    I got to see one of those key locations, or at least I saw it from a distance.

    Parked outside Building 26, the home of the Core Operating Systems Division, were semi-trailers filled with computers and back-up generators, ready to spring into action in case of a disaster of biblical proportions and somebody needed to develop a hotfix to Windows on the spot as civilized society collapsed into anarchy all around. (Personally, I would think that if civilization were collapsing, you would have more important things to worry about than patching an operating system.)

    At least to make things more pleasant for the people who had to remain at work that night, Microsoft threw "a New Year's Eve party with a disc jockey, dinner, and a champagne toast at midnight. Our employees can bring their spouses and children, and we'll even host a separate children's party."

    Actually, it sounds like they had more fun than I did that night. I think I stayed at home and watched television.

    It turns out that civilization did not collapse into anarchy. There were minor glitches, but nothing serious. "No problems were seen in Angola, Uganda and Kenya, where the telephone system was said to be functioning as erratically as usual. Italy, one of the worst-prepared countries in the West, also appeared to cross into the new century without any major trouble." Nice to know you can be snarky in a newspaper article.

    (Nitpicker's corner: January 1, 2000 was not the first day of a new century.)

    Depending on how you look at it, Y2K was either an overhyped event created to generate revenue for the technology industry, or was a demonstration of how people can solve a major problem if they just worked hard and coöperated.

    Reality is probably a mix of the two.

    Happy new year, everybody. See you on the other side.

  • The Old New Thing

    There's no seating up there, so you just have to hang on for dear life

    • 5 Comments

    I dreamed that through a friend, I got to join a handful of other people atop Prince Charles's carriage as it wound its way through London. There was no seating up there, so you just have to hang on for dear life. When we reached Buckingham Palace, the assembled crowd and reporters swarmed the carriage for an opportunity to meet the Prince. This provided a sufficient diversion to allow us to climb down from the roof and sneak into the palace undetected.

    We've come to the end of the year, so that's all for Monday dream blogging. For those of you who hated it: You can uncover your eyes now.

  • The Old New Thing

    How can I get the list of programs the same way that Programs and Features gets it?

    • 25 Comments

    A customer wanted to get the list of programs the same way that the Programs and Features folder gets it.

    Here, here's an idea: Instead of trying to mimic the Programs and Features folder, just ask the Programs and Features folder for its contents! That way, no matter what changes are made to how the Programs and Features folder obtains its contents (and those changes occur pretty often), your program will always match it, because you're just showing the same thing.

    Here's the basic idea, in scripting language since it's quicker:

    var shell = new ActiveXObject("Shell.Application");
    var programsFolder = shell.Namespace(
        "::{26EE0668-A00A-44D7-9371-BEB064C98683}\\8\\" +
        "::{7B81BE6A-CE2B-4676-A29E-EB907A5126C5}");
    var items = programsFolder.Items();
    for (var i = 0; i < items.Count; i++) {
        var item = items.Item(i);
        WScript.StdOut.WriteLine(item);
        WScript.StdOut.WriteLine("Size = " + item.ExtendedProperty("System.Size"));
        WScript.StdOut.WriteLine("------------");
    }
    

    Okay, first of all, how did I get that magic string for the Programs and Features folder? I opened the Control Panel and dragged the Uninstall a program link onto the program from a few weeks ago.

    The program itself is pretty straightforward. It's the standard enumerate everything in a folder and print it program we've seen before. The only trick was finding the folder.

    As for the C++ version, it should also look familiar, because we've done it before more than once. The only difference is the way we create the folder and the details we choose to display. (For extra credit: Change this program to bind to the persisted pidl instead of the parsing name.)

    int __cdecl wmain(int argc, wchar_t **argv)
    {
     CCoInitialize init;
     CComPtr<IShellItem> spPrinters;
     SHCreateItemFromParsingName(
       L"::{26EE0668-A00A-44D7-9371-BEB064C98683}\\8\\"
       L"::{7B81BE6A-CE2B-4676-A29E-EB907A5126C5}", nullptr,
       IID_PPV_ARGS(&spPrograms));
     CComPtr<IEnumShellItems> spEnum;
     spPrograms->BindToHandler(nullptr, BHID_EnumItems,
                                  IID_PPV_ARGS(&spEnum));
     for (CComPtr<IShellItem> spProgram;
          spEnum->Next(1, &spProgram, nullptr) == S_OK;
          spProgram.Release()) {
      CComHeapPtr<wchar_t> spszName;
      spProgram->GetDisplayName(SIGDN_NORMALDISPLAY, &spszName);
      wprintf(L"%ls\n", spszName);
      PrintDetail(CComQIPtr<IShellItem2>(spProgram), &PKEY_Size, L"Size");
     }
     return 0;
    }
    

    Bonus script: You can even see what verbs are available.

    var shell = new ActiveXObject("Shell.Application");
    var programsFolder = shell.Namespace(
        "::{26EE0668-A00A-44D7-9371-BEB064C98683}\\8\\" +
        "::{7B81BE6A-CE2B-4676-A29E-EB907A5126C5}");
    var items = programsFolder.Items();
    for (var i = 0; i < items.Count; i++) {
        var item = items.Item(i);
        WScript.StdOut.WriteLine(item);
        WScript.StdOut.WriteLine("Size = " + item.ExtendedProperty("System.Size"));
        var verbs = item.Verbs();
        for (var j = 0; j < verbs.Count; j++) {
           var verb = verbs.Item(j);
           WScript.StdOut.WriteLine("Action: " + verb.Name);
        }
        WScript.StdOut.WriteLine("------------");
    }
    

    And if you're really ambitious, you can even call verb.DoIt to carry out the action. Don't use this power for evil.

    Note: Since we are working with the Programs and Features folder, we are necessarily targeting Windows Vista and later, since that was the version of Windows in which the Programs and Features folder was introduced. Therefore, I am free to use functionality introduced in Windows Vista.

    I've been doing Little Programs for a year now. I kind of like it, so I'm going to continue for another year, but I'm going to relax the rules a bit: The Little Programs are now just programs that I think are interesting for whatever reason. They don't need to actually solve a problem.

  • The Old New Thing

    Brief Q&A on the HeapEnableTerminationOnCorruption heap information flag

    • 13 Comments

    Question: What type of heaps are controlled by the Heap­Enable­Termination­On­Corruption flag?

    Answer: Any user-mode heap created by the Heap­Create function. This includes the process heap (Get­Process­Heap) but not the managed heap. Some components use Heap­Create under the hood. If so, then those heaps would also be affected.

    Question: What versions of Windows support Heap­Enable­Termination­On­Corruption?

    Answer: The flag was introduced in Windows Vista and Windows Server 2008. It is also available on Windows XP Service Pack 3. In table form:

    Support Client Server

    Not Available
    ...
    Windows 2000
    Windows XP RTM, SP1, SP2
    ...
    Windows Server 2000
    Windows Server 2003
    Available
    Windows XP SP3
    Windows Vista
    Windows 7
    ...

    Windows Server 2008
    Windows Server 2008 R2
    ...

    Question: For operating systems that support it, under what conditions will termination on corruption be enabled?

    Answer:

    1. For all 64-bit processes.
    2. For all 32-bit processes whose executable sets the subsystem major version to 6 or higher in the image header.
    3. If you call Heap­Set­Information with the Heap­Enable­Termination­On­Corruption parameter.

    Question: What is the effect of setting the subsystem major version in a DLL? Will that control whether termination on corruption is enabled for any heaps created by my DLL?

    Answer: No. For the purpose of rule 2 above, it is the major subsystem of the executable that decides whether termination on corruption. The major subsystem of any DLLs loaded by the process have no effect. This is consistent with other process decisions.

    Question: Can I enable termination on corruption for some heaps but not others?

    Answer: No. Turning on termination on corruption turns it on for all heaps in the process.

    Question: Can I disable termination on corruption after it has been enabled?

    Answer: No. It is a one-way door.

  • The Old New Thing

    I think we're going to be getting frozen leftovers for lunch today

    • 10 Comments

    There are a few times a year when a large fraction of employees are out on vacation at the same time, such as a single work day wedged between a holiday and a weekend (as happened this year on July 5). The most extreme case of this is the week between the Christmas holiday and New Year's Day, where the offices are practically empty. On these days of low demand, many services are scaled back and some choose to close entirely so that they can do inventory, perform routine maintenance, or upgrade equipment.

    One of the most visible service reductions is in food service. Smaller locations (such as snack bars) are closed, and the kitchens which remain open offer a reduced menu. But just because most people are on vacation doesn't mean that nobody is watching. Here's a menu from one kitchen that was posted almost exactly one year ago:

    Breakfast Roberts Waffles
    Breakfast Burrito
    Warm Tortilla filled with Scrambled Egg, Golden Hash Browns, Onion Green Chiles, Monterey Jack Cheese and Salsa.
    Today's Soups Clam Chowder
    Tomato Basil Bisque
    Exhibition Station Closed for Holiday
    Shanghai Shanghai
    Greek Potato Salad
    A delicious blend of potatoes, tomatoes, red onions, flavored with mustard, parsley, dill seed, mint and lemon juice.
    Wild Greens Grill and Greens
    Chef's Table Station Closed for Holiday
    Pizza Specialty Pizza by the Slice
    Deli Mozzarella, Tomato and Basil Panini
    Mozzarella, Tomato and Basil Panini
    Spcied [sic] Cranberry Turkey Salad Served on a Flaky Crossaint [sic]
    Entrée Check Freezer
    Grill Tuna Melt
    Steak Frites
  • The Old New Thing

    Why is GetWindowLongPtr returning a garbage value on 64-bit Windows?

    • 33 Comments

    A customer was running into problems with their application on 64-bit Windows 8. They claimed that on Windows 8, the Get­Window­Long­Ptr is returning a garbage pointer, which causes their program to crash. The same program works fine on 64-bit Windows 7. They asked the Windows team why they broke Get­Window­Long­Ptr.

    An investigation of the customer's code quickly turned up the issue:

    INT_PTR CALLBACK AwesomeDialogProc(
        HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
      Awesome *pThis = (Awesome*)GetWindowLongPtr(hdlg, DWLP_USER);
    
      switch (uMsg) {
      case WM_INITDIALOG:
        pThis = (Awesome*)lParam;
        SetWindowLongPtr(hdlg, DWLP_USER, (LONG)pThis);
        ...
        return TRUE;
    
       case WM_COMMAND:
         if (pThis != nullptr) {
           // This line crashes with pThis = garbage nonzero value
           return pThis->OnCommand(wParam, lParam);
         }
         return FALSE;
    
       ...
      }
      return FALSE;
    }
    

    See if you can spot the problem.

    The error is in the line that calls Set­Window­Long­Ptr. It takes the 64-bit pointer value pThis and casts it to a LONG, which is a 32-bit integer type. This truncates the pointer and throws away the upper 32 bits of data. Therefore, when read back, the pointer looks like garbage because the top 32 bits were set to zero (or to 0xFFFFFFFF, depending on the value of bit 31).

    Windows 8 made some improvements to the memory manager, and a side effect was a seemingly harmless change to the way memory is allocated in 64-bit processes. As a result of the change, pointer values greater than 4GB are much more common, which means that the pointer truncation will actually destroy data. (In Windows 7, the default heap tended to hang out below the 2GB boundary, so the code merely truncated zeros, which is mostly harmless.)

    What I found particularly interesting about this error is that the DWL_USER window long was specifically renamed to DWLP_USER in 64-bit Windows in order to force a build break. Therefore, developers had to go in and convert each separate use of [GS]et­Window­Long with DWL_USER to a version that used [GS]et­Window­Long­Ptr with DWLP_USER, being careful not to truncate the pointer.

    This customer missed that last little bit about not truncating the pointer, and all they did was a global search/replace:

    s/\bGetWindowLong\b/GetWindowLongPtr/g;
    s/\bSetWindowLong\b/SetWindowLongPtr/g;
    s/\bDWL_USER\b/DWLP_USER/g;
    

    "There, I fixed it."

  • The Old New Thing

    The chain of stories triggered by seeing a package of Ahoj-Brause

    • 12 Comments

    While surfing the Web aimlessly doing valuable background research, I happened across a page that had a picture of a package of Ahoj-Brause (pronounced ahoy browse-uh). Seeing that package triggered a bunch of memories.

    My emergency vacation from several years ago included a visit to a friend spending the year at Uppsala University in Sweden. The following year, he invited one of his classmates (a student from Germany) to the United States to join his family for the Christmas holiday season.

    She brought with her some small gifts, among them a package of Ahoj-Brause. On its own, Ahoj-Brause is just a drink mix powder, but those in the know consume it by dumping the contents of a packet into your mouth, then adding a shot of vodka.

    (When written by hand, it looks like Ahoj-Braŭse with a breve over the u. That's a trait of German handwriting: A breve is written over the u so that it isn't confused with a handwritten n. Compare putting a slash through a 0 or a crossbar through a 7 to avoid confusion with O and 1, respectively.)

    During her visit, I got to practice some German, telling her the story of Bill Gates and the hotel next door. Her conclusion was that my German was fairly good, and with one month's immersion, I could become fluent. Unfortunately, it's not practical for me to spend a month in Germany just to bring my German skills from "fairly good" to "fluent". For one thing, my wife would be pretty annoyed. (And this is completely setting aside the question of "Why would you devote an entire month of your life to becoming fluent in German? If you're going to devote an entire month of your life to becoming fluent in another language, shouldn't it be Chinese?")

    Man, that's a lot of digressions before getting the story I actually wanted to tell.

    My friend's classmate wanted to head into downtown Seattle to do touristy things, so she was taken to the neighborhood bus stop and given instructions on which bus number to take and where to get off in downtown. That part of the plan worked great. The part that didn't work so great was returning home.

    When you're unfamiliar with an area, traveling a road in the opposite direction doesn't quite trigger the memory cells. My friend's classmate got on the return bus, but couldn't quite remember where to get off to get back home. She got off somewhere close, but the houses didn't look familiar. "Okay, now I'm lost. What do I do?" She had my friend's address and phone number, but she didn't have a mobile phone or a map of the residential neighborhood.

    She walked down the street and saw a house with the sign Mi casa es tu casa hanging by the front door. She considered this an indication that the people in the house were friendly and welcoming, so she knocked on the door. She was okay with the possibility that the people in the house spoke only Spanish, because she had been learning Spanish in anticipation of studying there the following semester. (For those who are keeping score, this means that my friend's classmate speaks at a minimum German, Swedish, English, and Spanish.)

    The assumption that they spoke Spanish was correct. (They also spoke English.) The assumption that the family was friendly and helpful also held up. What she didn't expect was that they spoke German, too! Apparently, the family spent a few years in Germany because the father was assigned there by his work.

    It so happens that she was only two blocks or so from my friend's home; the hard part of course is knowing which two blocks to go.

    The family was so enamored of their unexpected German-and-English-and-Spanish-speaking visitor that they invited her to stay for dinner, but she had to decline due to other plans for the evening.

    Bonus chatter: When my friend sent back some photos from Uppsala, he didn't include any description with the photos, so I made up my own narrative. I had to make up names for all the people in the photos, and Astrid was the name I chose for the subject of today's story. She liked the name so much that she adopted it as a secret nickname.

  • The Old New Thing

    Essays from the funniest man in Microsoft Research

    • 16 Comments

    James Mickens has written a number of essays for ;login: magazine. The wall-of-text presentation is kind of scary, and the first time I encountered them, I skimmed the essays rather than reading them through. As a result, my reaction was, "I got tired." But if you follow the path and read the essays through, you realize that they are all brilliant.

    You can't just place a LISP book on top of an x86 chip and hope the hardware learns about lambda calculus by osmosis.

    and in the "so funny because it's true that it wraps around and isn't funny any more, but then wraps around a second time and is funny again, but with a tinge of sadness" category:

    I HAVE NO TOOLS BECAUSE I'VE DESTROYED MY TOOLS WITH MY TOOLS.
    ... because in those days, you could XOR anything with anything and get something useful.
    When researchers talk about mobile computers, they use visionary, exciting terms like "fast", "scalable", and "this solution will definitely work in practice."
    With careful optimization, only 14 gajillion messages are necessary.

    One of my colleagues found the stash of columns in the "Miscellaneous Excellence" section on Mickens' Web site and reacted with "This is better than getting free cookies."

    Here's an interview with "the funniest man in Microsoft Research".

    I would have done this for TechNet Magazine if I had known this was possible.

    Also if I had the talent.

    Mostly the talent part.

    Bonus Mickensian reading: What is art?

  • The Old New Thing

    That doesn't sound like South Frisian to me

    • 4 Comments

    I dreamed that I was back in college taking a course in South Frisian, but I suspected something was up because the words didn't sound Germanic at all, and we were taught the words to a Christmas carol as Nom Yom Hear What I Hear?

    Also, because the course was taught by known prevaricator/exaggerator Robert Irvine.

Page 1 of 4 (31 items) 1234