April, 2013

  • The Old New Thing

    The most expensive notepads in Microsoft history

    • 9 Comments

    Many years ago, I visited the office of a colleague who worked on Internet Explorer in order to work on some problem or other. As we investigated the issue, we took notes on a 5"×7" tear-off notepad which bore the logo Forms³.

    My colleague then pointed out to me that we were taking notes on the most expensive notepads in Microsoft history.

    Forms³ (pronounced "forms-cubed") was the code name for the project that was the precursor to Trident, the layout engine that powers Internet Explorer. As I recall the story as it was told to me, project management thought it would be cool to have custom notepads made for their project. The people responsible for converting this idea into reality designed a logo, laid it out, and found a vendor to produce the notepads. But there was some sort of misunderstanding (maybe the asked for too many colors? didn't order enough notepads to trigger the bulk discount?), and the price for the notepads ended up being something ridiculous like $10 for a 50-page notepad.

    That's how the most expensive notepads in Microsoft history came to be.

    Bonus chatter: Oh, by the way, the word "precursor" I used up there? Yeah, that was a euphemism for "cancelled (but used as a learning opportunity)." Microsoft engineers are fond of black humor when it comes to software (especially software made by Microsoft) as a way of coping with adversity, and after the Forms³ project was cancelled, there was a subculture of engineers who morbidly called it Forms tubed.

  • The Old New Thing

    Dentistry in the Brazil-like future

    • 14 Comments

    I dreamed that I was living in a nursing home in some Brazil-like dystopic future.

    In this future, people had become so horribly disfigured that they wore flesh-colored suits under their clothes all the time just so they would look good "naked". This vanity extended only to people under the age of around 40. The old people in the home were just your average old people, with spotted, wrinkly skin. Nothing particularly ugly about them; just your average old people. In the dream, I was my current age, but I was living in the home anyway, probably because I became prematurely senile.

    A dentist spontaneously appeared to give me a futuristic dental procedure. ("Hey, how'd you get here and what is that zappy thing in my mouth?" Did I mention that I was senile?) After she was done, the dentist said, "I fixed your back four teeth."

    "You made them last longer?" I asked.

    "No, they'll fail at about the same time as before. They'll just fail differently now."

    "What did you do?" I asked.

    "I'd rather not say. You can look in the mirror."

    With trepidation, I looked in the mirror. My eyes were no good, so I had to ask somebody to tell me what happened.

    "Dear God, she installed leeches in your mouth! Mind you, she did a really nice job, getting them to criss-cross like that."

    Bonus details: The dentist and dental assistant were hideously disfigured, and I did not notice until later that each had one arm and one stump. The dentist's and assistant's stumps snapped together like a garden hose, making them a grotesque conjoined dental crew.

  • The Old New Thing

    Getting the display name for a shell property

    • 2 Comments

    Today's Little Program takes the symbolic name for a shell property and returns a string suitable for display to the end-user, translated into the user's specified display language.

    #include <windows.h>
    #include <ole2.h>
    #include <propsys.h>
    #include <propkey.h>
    #include <atlbase.h>
    #include <atlalloc.h>
    
    int __cdecl wmain(int argc, PWSTR argv[])
    {
     CCoInitialize init;
     if (SUCCEEDED(init) && argc == 2) {
      CComPtr<IPropertyDescription> spdesc;
      if (SUCCEEDED(PSGetPropertyDescriptionByName(
                       argv[1], IID_PPV_ARGS(&spdesc)))) {
       CComHeapPtr<wchar_t> spszName;
       if (SUCCEEDED(spdesc->GetDisplayName(&spszName))) {
        wprintf(L"%ls\n", static_cast<PWSTR>(spszName));
       }
      }
     }
     return 0;
    }
    

    Run this program with the string System.Music.Album­Artist on the command line, and the result is the message Album artist on English-language systems.

    The actual workings of the program is pretty straightward. We ask the property system for an interface that describes the property name, and ask that interface to give us the display name, which we print out.

    Nothing fancy here. The trick is just knowing that the function exists in the first place.

  • The Old New Thing

    Fake film project tries to create real film to hide fakeness (and fails)

    • 17 Comments

    In 2010, a group of scam artists pretended that they were making a film, appropriately titled A Landscape of Lies. They did this so that they could claim over £2.7 million in tax credits intended to boost the British film industry. Her Majesty's Revenue and Customs began to suspect something was up when no apparent progress was being made on the project and the film company's "office" was an empty room. The scammers tried to make the project look legitimate by actually making a movie for £84,000 and releasing it on DVD. (You can watch the trailer here.) The fake movie was convincing enough to trick one film festival into giving it an award (which it later had to take back.)

    Related: The claimed DHS-based television show turns out also to have been a scam.

  • The Old New Thing

    Another way to create a process with attributes, maybe worse maybe better

    • 17 Comments
    Adam Rosenfield noted that "those sure are a lot of hoops you have to jump through to solve this unusual problem" of specifying which handles are inherited by a new process.

    Well, first of all, what's so wrong with that? You have to jump through a lot of hoops when you are in an unusual situation. But by definition, most people are not in an unusual situation, so it's an instance of the Pay for Play principle: The simple case should be easy, and it's okay for the complicated case to be hard. (It's usually difficult to make the complicated case easy; that's why it's called the complicated case.)

    The complexity mostly comes from managing the general-purpose PROC_THREAD_ATTRIBUTE_LIST, which is used for things other than just controlling inherited handles. It's a generic way of passing up to N additional parameters to Create­Process without having to create 2ᴺ different variations of Create­Process.

    The Create­Process­With­Explicit­Handles function was just one of the N special-purpose functions that the PROC_THREAD_ATTRIBUTE_LIST tried to avoid having to create. And the special-purpose function naturally takes the special-purpose case and applies the general solution to it. It's complicated because you are now doing something complicated.

    That said, here's one attempt to make it less complicated: By putting all the complicated stuff closer to the complicated function:

    typedef struct PROCTHREADATTRIBUTE {
     DWORD_PTR Attribute;
     PVOID lpValue;
     SIZE_T cbSize;
    } PROCTHREADATTRIBUTE;
    
    BOOL CreateProcessWithAttributes(
      __in_opt     LPCTSTR lpApplicationName,
      __inout_opt  LPTSTR lpCommandLine,
      __in_opt     LPSECURITY_ATTRIBUTES lpProcessAttributes,
      __in_opt     LPSECURITY_ATTRIBUTES lpThreadAttributes,
      __in         BOOL bInheritHandles,
      __in         DWORD dwCreationFlags,
      __in_opt     LPVOID lpEnvironment,
      __in_opt     LPCTSTR lpCurrentDirectory,
      __in         LPSTARTUPINFO lpStartupInfo,
      __out        LPPROCESS_INFORMATION lpProcessInformation,
        // here is the new stuff
        __in       DWORD cAttributes,
        __in_ecount(cAttributes) const PROCTHREADATTRIBUTE rgAttributes[])
    {
     BOOL fSuccess;
     BOOL fInitialized = FALSE;
     SIZE_T size = 0;
     LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList = NULL;
    
     fSuccess = InitializeProcThreadAttributeList(NULL, cAttributes, 0, &size) ||
                GetLastError() == ERROR_INSUFFICIENT_BUFFER;
    
     if (fSuccess) {
      lpAttributeList = reinterpret_cast<LPPROC_THREAD_ATTRIBUTE_LIST>
                                    (HeapAlloc(GetProcessHeap(), 0, size));
      fSuccess = lpAttributeList != NULL;
     }
     if (fSuccess) {
      fSuccess = InitializeProcThreadAttributeList(lpAttributeList,
                        cAttributes, 0, &size);
     }
     if (fSuccess) {
      fInitialized = TRUE;
      for (DWORD index = 0; index < cAttributes && fSuccess; index++) {
       fSuccess = UpdateProcThreadAttribute(lpAttributeList,
                         0, rgAttributes[index].Attribute,
                         rgAttributes[index].lpValue,
                         rgAttributes[index].cbSize, NULL, NULL);
      }
     }
     if (fSuccess) {
      STARTUPINFOEX info;
      ZeroMemory(&info, sizeof(info));
      info.StartupInfo = *lpStartupInfo;
      info.StartupInfo.cb = sizeof(info);
      info.lpAttributeList = lpAttributeList;
      fSuccess = CreateProcess(lpApplicationName,
                               lpCommandLine,
                               lpProcessAttributes,
                               lpThreadAttributes,
                               bInheritHandles,
                               dwCreationFlags | EXTENDED_STARTUPINFO_PRESENT,
                               lpEnvironment,
                               lpCurrentDirectory,
                               &info.StartupInfo,
                               lpProcessInformation);
     }
    
     if (fInitialized) DeleteProcThreadAttributeList(lpAttributeList);
     if (lpAttributeList) HeapFree(GetProcessHeap(), 0, lpAttributeList);
     return fSuccess;
    }
    

    There, now the complexity is there because you're a generic complex function, so you have no reason to complain.

    A caller of this function might go like this:

      HANDLE handles[2] = { handle1, handle2 };
      const PROCTHREADATTRIBUTE attributes[] = {
       {
        PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
        handles,
        sizeof(handles),
       },
      };
    
      fSuccess = CreateProcessWithAttributes(
                               lpApplicationName,
                               lpCommandLine,
                               lpProcessAttributes,
                               lpThreadAttributes,
                               bInheritHandles,
                               dwCreationFlags,
                               lpEnvironment,
                               lpCurrentDirectory,
                               lpStartupInfo,
                               lpProcessInformation,
                               ARRAYSIZE(attributes),
                               attributes);
    

    Adam hates the "chained success" style and prefers the "goto" style; on the other hand, other people hate gotos. So to be fair, I will choose a coding style that nobody likes. That way everybody is equally unhappy.

    BOOL CreateProcessWithAttributes(
      __in_opt     LPCTSTR lpApplicationName,
      __inout_opt  LPTSTR lpCommandLine,
      __in_opt     LPSECURITY_ATTRIBUTES lpProcessAttributes,
      __in_opt     LPSECURITY_ATTRIBUTES lpThreadAttributes,
      __in         BOOL bInheritHandles,
      __in         DWORD dwCreationFlags,
      __in_opt     LPVOID lpEnvironment,
      __in_opt     LPCTSTR lpCurrentDirectory,
      __in         LPSTARTUPINFO lpStartupInfo,
      __out        LPPROCESS_INFORMATION lpProcessInformation,
        // here is the new stuff
        __in       DWORD cAttributes,
        __in_ecount(cAttributes) const PROCTHREADATTRIBUTE rgAttributes[])
    {
     BOOL fSuccess = FALSE;
     SIZE_T size = 0;
    
     if (InitializeProcThreadAttributeList(NULL, cAttributes, 0, &size) ||
         GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
      LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList =
             reinterpret_cast<LPPROC_THREAD_ATTRIBUTE_LIST>
                                    (HeapAlloc(GetProcessHeap(), 0, size));
      if (lpAttributeList != NULL) {
       if (InitializeProcThreadAttributeList(lpAttributeList,
                         cAttributes, 0, &size)) {
        DWORD index;
        for (index = 0;
             index < cAttributes &&
             UpdateProcThreadAttribute(lpAttributeList,
                           0, rgAttributes[index].Attribute,
                           rgAttributes[index].lpValue,
                           rgAttributes[index].cbSize, NULL, NULL);
             index++) {
        }
        if (index >= cAttributes) {
         STARTUPINFOEX info;
         ZeroMemory(&info, sizeof(info));
         info.StartupInfo = *lpStartupInfo;
         info.StartupInfo.cb = sizeof(info);
         info.lpAttributeList = lpAttributeList;
         fSuccess = CreateProcess(
                               lpApplicationName,
                               lpCommandLine,
                               lpProcessAttributes,
                               lpThreadAttributes,
                               bInheritHandles,
                               dwCreationFlags | EXTENDED_STARTUPINFO_PRESENT,
                               lpEnvironment,
                               lpCurrentDirectory,
                               &info.StartupInfo,
                               lpProcessInformation);
        }
        DeleteProcThreadAttributeList(lpAttributeList);
       }
       HeapFree(GetProcessHeap(), 0, lpAttributeList);
      }
     }
    
     return fSuccess;
    }
    

    Those who are really adventuresome could try a version of Create­Process­With­Attributes that uses varargs or std::initializer_list.

  • The Old New Thing

    If you're going to use an interlocked operation to generate a unique value, you need to use it before it's gone

    • 35 Comments

    Is the Interlocked­Increment function broken? One person seemed to think so.

    We're finding that the Interlocked­Increment is producing duplicate values. Are there are any know bugs in Interlocked­Increment?

    Because of course when something doesn't work, it's because you are the victim of a vast conspiracy. There is a fundamental flaw in the Interlocked­Increment function that only you can see. You are not a crackpot.

    LONG g_lNextAvailableId = 0;
    
    DWORD GetNextId()
    {
      // Increment atomically
      InterlockedIncrement(&g_lNextAvailableId);
    
      // Subtract 1 from the current value to get the value
      // before the increment occurred.
      return (DWORD)g_lNextAvailableId - 1;
    }
    

    Recall that Interlocked­Increment function increments a value atomically and returns the incremented value. If you are interested in the result of the increment, you need to use the return value directly and not try to read the variable you incremented, because that variable may have been modified by another thread in the interim.

    Consider what happens when two threads call Get­Next­Id simultaneously (or nearly so). Suppose the initial value of g_lNext­Available­Id is 4.

    • First thread calls Interlocked­Increment to increment from 4 to 5. The return value is 5.
    • Second thread calls Interlocked­Increment to increment from 5 to 6. The return value is 6.
    • First thread ignores the return value and instead reads the current value of g_lNext­Available­Id, which is 6. It subtracts 1, leaving 5, and returns it.
    • Second thread ignores the return value and instead reads the current value of g_lNext­Available­Id, which is still 6. It subtracts 1, leaving 5, and returns it.

    Result: Both calls to Get­Next­Id return 5. Interpretation: "Interlocked­Increment is broken."

    Actually, Interlocked­Increment is working just fine. What happened is that the code threw away the unique information that Interlocked­Increment returned and instead went back to the shared variable, even though the shared variable changed its value in the meantime.

    Since this code cares about the result of the increment, it needs to use the value returned by Interlocked­Increment.

    DWORD GetNextId()
    {
      // Increment atomically and subtract 1 from the
      // incremented value to get the value before the
      // increment occurred.
      return (DWORD)InterlockedIncrement(&g_lNextAvailableId) - 1;
    }
    

    Exercise: Criticize this implementation of IUnknown::Release:

    STDMETHODIMP_(ULONG) CObject::Release()
    {
     InterlockedDecrement(&m_cRef);
     if (m_cRef == 0)
     {
      delete this;
      return 0;
     }
     return m_cRef;
    }
    
  • The Old New Thing

    Dark corners of C/C++: The typedef keyword doesn't need to be the first word on the line

    • 29 Comments

    Here are some strange but legal declarations in C/C++:

    int typedef a;
    short unsigned typedef b;
    

    By convention, the typedef keyword comes at the beginning of the line, but this is not actually required by the language. The above declarations are equivalent to

    typedef int a;
    typedef short unsigned b;
    

    The C language (but not C++) also permits you to say typedef without actually defining a type!

    typedef enum { c }; // legal in C, not C++
    

    In the above case, the typedef is ignored, and it's the same as just declaring the enum the plain boring way.

    enum { c };
    

    Other weird things you can do with typedef in C:

    typedef;
    typedef int;
    typedef int short;
    

    None of the above statements do anything, but they are technically legal in pre-C89 versions of the C language. They are just alternate manifestations of the quirk in the grammar that permits you to say typedef without actually defining a type. (In C89, this loophole was closed: Clause 6.7 Constraint 2 requires that "A declaration shall declare at least a declarator, a tag, or the members of an enumeration.")

    That last example of typedef int short; is particularly misleading, since at first glance it sounds like it's redefining the short data type. But then you realize that int short and short int are equivalent, and this is just an empty declaration of the short int data type. It doesn't actually widen your shorts. If you need to widen your shorts, go see a tailor.¹

    Note that just because it's legal doesn't mean it's recommended. You should probably stick to using typedef the way most people use it, unless you're looking to enter the IOCCC.

    ¹ The primary purpose of this article was to tell that one stupid joke. And it's not even my joke!

  • The Old New Thing

    Microspeak: Tenet

    • 18 Comments

    In standard English, a tenet is a fundamental belief held by a group of people. At Microsoft, the term tenet is used as a generalization of what we previously called taxes: Things that everybody has to do in order to be a good software citizen.

    While taxes are typically very low-level and specific, like supporting roaming user profiles or multiple monitors, tenets are broader concepts like reliability or compatibility or API design and documentation.

    The word doesn't escape the halls of Microsoft very often. Most of the citations I have are internal, but here's a case where Jon DeVaan let it slip into a keynote address:

    And together we've improved reliability on Vista huge amount. And when you look at the compatibility tenet that we have for Windows 7, all of this work translates immediately to the reliability of Windows 7 on day one.

    Occasionally, somebody will confuse the word tenet with the superficially-similar tenant.

    We still have many bugs marked as High tenant impact.

    Remember:

    • tenant: Somebody who is renting from you.
    • tenet: An important principle or belief.

    Bad pun alert: I guess a bug could be high tenant impact if it's a bedbug or lice.

  • The Old New Thing

    Dreaming about games based on Unicode

    • 20 Comments

    I dreamed that two of my colleagues were playing a game based on pantomiming Unicode code points. One of them got LOW QUOTATION MARK, and the other got a variety of ARROW POINTING NORTHEAST, ARROW POINTING EAST, ARROW POINTING SOUTHWEST.

    I wonder how you would pantomime ZERO WIDTH NON-JOINER.

  • The Old New Thing

    Getting the current selection from an Explorer window

    • 8 Comments

    Today's Little Program prints the current selection in all open Explorer windows. (This is an alternative to the C++ version that involves a ridiculous amount of typing.)

    var shellWindows = new ActiveXObject("Shell.Application").Windows();
    for (var i = 0; i < shellWindows.Count; i++) {
     var w = shellWindows.Item(i);
     WScript.StdOut.WriteLine(w.LocationName);
     var sel = w.Document.SelectedItems();
     for (var j = 0; j < sel.Count; j++) {
      var item = sel.Item(j);
      WScript.StdOut.WriteLine(item.Name);
      WScript.StdOut.WriteLine(item.Path);
     }
    }
    

    I have no idea why you would want to do this, but there you have it. (If you want the focused item rather than the selection, then get the Focused­Item property.)

    Okay, maybe you can use this as a quick-and-dirty way to get the parsing name for a shell item: Open an Explorer window, select the item you are interested in, then run the script to see what gets printed out as the Path.

Page 1 of 3 (30 items) 123