November, 2006

Larry Osterman's WebLog

Confessions of an Old Fogey
  • Larry Osterman's WebLog

    The Sounds of Vista

    • 18 Comments

    I actually didn't think this would be a big deal.  Shows you what little I know.

     

    It started yesterday afternoon.  I had an errand to run (Parent Teacher conferences), so I left work at about 12:00.  When I got back, I noticed a NorthWestCableNews van sitting outside our building.  I'm used to limos outside the building (we sometimes get celebrities and other dignitaries showing up in the building and they usually come via limo), but not TV news trucks, so I wasn't quite sure what was up.

    Then  got to my floor of building 50, and I realized that there was a television crew in Steve Ball's office.  And they were talking about the Vista sounds!

    And then I noticed that Jim Allchin had posted this post describing some of the creative process involved in the Vista startup sound.

     

    And this morning, while listening to the radio as we got up, Valorie shouted out: Hey, that's Steve Ball on NPR! (ok, she didn't shout, when I came back from feeding the cats, she asked "Did you hear the article about the Vista sounds on NPR?".

    And Long Zheng posted up a phenominal comparison between the XP and Vista sounds which clearly shows off the work that the sound design team did to work on improving the XP sounds.

     

    I had no idea that this would be this big.  Cool :)

     

    And thus the tidal wave of Vista truly begins.

  • Larry Osterman's WebLog

    Resolution to my IE CTRL-D problem

    • 18 Comments

    A long time ago, I complained to the IE team on their blog:

    So how do I disable the CTRL-D "add-to-favorites" behavior?  It's my one major objection to IE6.
    The problem is that CTRL-D is also the "delete email" link, and I have my email on one monitor and IE on the other.  It's not always clear which window has the focus, so I get random pages added to my favorites when I don't want them.
    It's a royal pain to delete a favorite (requires two clicks, and popup), I'd rather not get them in the first place.

    The good news is that one of the leads on the IE team noticed my complaint and it appears that the IE7 guys fixed my problem!

    Or rather, they mitigated it quite neatly.

    Now, when you hit CTRL-D, you get:

    I really like this solution - it keeps the CTRL-D favorite, but the user now gets to cancel out, which means that random pages don't show up as favorites.

    Thanks guys!

  • Larry Osterman's WebLog

    Four years ago...

    • 21 Comments

    I was working in building 50, the SCP project was clearly approaching it's end-of-life, and I was casting around the company looking for new opportunities.  When a project is end-of-lifed, the powers that be usually try to find a new home for all the people involved on the project.

    I was in my office, and this guy named Dennis Flanagan stopped by my office and asked me if I'd be interested in taking on a new project in the group that would be known as WMDG (the Windows Media and Devices Group).  You see, they had this wacky idea of building up infrastructure that would allow Windows to discover UPnP devices and create PnP devnodes for those devices (which would mean that the devices would show up in the Windows Device Manager).  I started working right away and had a prototype working relatively quickly.  The problem was that the project needed external evangelism, and I didn't have the contacts or skills to move it forward. So the project sat on the shelf and the concepts were eventually integrated into the Function Discovery and the UMDF

    For whatever reason, I had been slotted into a team that was sort-of a mishmash of different functions.  There was me, another developer who was working on something called "device discovery" (which later evolved into Function Discovery), a team of a couple of developers working on UI for audio for Windows Codename Longhorn, and a team of a couple of developers working on the supporting infrastructure for Windows Codename Longhorn.

    My manager at the time, Frank Yerrace, had a bunch of work that needed to be done in the audio infrastructure team, and he saw that I had essentially been idled, so he asked if I would mind driving a chunk of the new audio infrastructure known as the policy engine.

    Thus began my time working on the Longhorn project.

     

    Over the past four years, there have been a number of memorable milestones.  There was time when Alper Selcuk first got the new audio engine playing sounds.  There was the whole Longhorn Reset and the birth of Windows Vista.  And then there was my 43rd birthday present: We RI'ed the new audio engine into Vista.  At that point we were 100% committed - we HAD to make the new audio stack work in Vista, there was no way to turn back.

     

    Other milestones: Vista Beta 1 (July of 2005), the Audio team's final Beta 2 push which included the final integration of the audio policy infrastructure I started back in 2002 (August 2005), the death of my father (August 15, 2005), Vista Beta 2 (May 2006), Vista RC1 (September 2006), and ultimately Vista RTM (November 2006).

     

    Over the years, we've lost friends and family. Syon Bhattacharya lost his battle with stomach cancer in 2004. Steve Swenson, who designed most of the architecture of the Vista audio engine passed on September 11, 2005.  My father passed on August 15th, 2005, other members of the team have also lost parents and other loved ones.

    But after all was said and done, as of 11:00AM today, it's official.  You can put a fork in it, Windows Vista is finally DONE.  That's it, it's off to manufacturing.

     

    This one's for you guys.

  • Larry Osterman's WebLog

    What's wrong with this code, part 19

    • 16 Comments

    Wow, I've done 19 of these?  Cool.

    I got an email question from a reader earlier today, and I realized that his question would make a great "What's wrong with this code" question.

    He has a C++ function "GetValue" that is used to retrieve a value from something (it doesn't actually matter what).  His function is intended to be called from OLE automation, so it has three versions, one which takes a VARIANT, one which takes an integer index, one which takes a BSTR key.  If the input VARIANT is an integer, it assumes that it's an index, if the input VARIANT is a string, it assumes that it's a key.

    Here's the version of the code as provided by the reader:

    HRESULT GetValue(VARIANT Index, VARIANT& Value)
    {
        // Try Index as offset
        HRESULT hr = VariantChangeType(&Index, &Index, 0, VT_I4);
        if(SUCCEEDED(hr))
            return GetValue(Index.lVal, Value);

        // Try Index as key
        hr = VariantChangeType(&Index, &Index, 0, VT_BSTR); 
        if(SUCCEEDED(hr))
            return GetValue(Index.bstrVal, Value);

        // Bad Index
        return E_INVALIDARG;
    }

    His idea was that the function would be called like this:

    void SomeFunction()
    {
        CComVariant Value;
        GetValue(CComVariant(_T("1")), Value);
    }

    Unfortunately, this doesn't quite work :(.  Why not?

     

    As always Kudos and comments tomorrow.

    Edit: I can't count :)

     

  • Larry Osterman's WebLog

    Flattening the world

    • 16 Comments

    Yesterday, I finally decided to bite the bullet and flatten my dev machine.  I got this machine in 2003, and obviously installed XP on it, I've been self-hosting Vista on it since some time around April of this year, upgrading just about every week.

    The thing about upgrades of interim builds of the OS is that sometimes things don't quite work right after the upgrade.  Sometimes things get ACL'ed incorrectly, sometimes registry settings get migrated that should be reset, sometimes stuff gets put in the wrong place.  These problems get noticed and fixed after they occur, but they sometimes leave little bits and pieces behind.

    One great example hit about 2 months ago - I suddenly lost my ability to view JPGs in the sidebar.  They worked just fine everywhere else (I thought), but not from the sidebar.  Digging into the sidebar code, I realized that the sidebar was just calling ShellExecuteEx on the JPG file, which led me to realize that I couldn't launch JPGs from the command interpreter either.  Digging into the ShellExecuteEx code, I realized that the file association handler for JPG files wasn't working correctly - it was loading a DLL, but the object hosted in that DLL didn't implement some class.

    I looked at the COM registration in regedit, and it looked ok, so I asked for the shell team for help.  They asked me to get a regmon trace, and using the trace, they figured out what had happened.  It turns out that the handler for some COM class was moved from one DLL to another DLL back in July.  No big deal, the COM registry had been fixed up so it wasn't a problem.  The problem for me was that an upgrade back in June had accidentally virtualized the COM registration for the object that contained this class.  When the registry was updated, the virtualized registry wasn't updated (because the system didn't know about it).

    Our customers would never see this bug, neither would any user performing a clean upgrade, it only showed up because I upgraded from build-to-build - if I'd clean installed it would never have hit me.

     

    So yesterday, I decided that it was time to flatten my dev machine[1].  I've had enough "wierd" things happen (strange Outlook behaviors, etc) that I decided it would just be safer to reset the world.

    It's weird, I've not reinstalled an OS on my of my machines in a VERY long time (at least a couple of years now), it felt strange.

    But I figured it had to be done.  First thing I did was to uninstall all the software on my machine that I didn't think I used day-to-day (I had a LOT of junk that had built up over time).  I wrote down all the stuff I knew I would need, and made sure that I had copies of the software to reinstall.  I next used the Windows Easy Transfer (migration wizard) tool to back up my user settings, and reinstalled the OS.  So far so good.  I next used the migration wizard to put my stuff back, and reinstalled all my apps.

     

    The cool thing is that it worked just about perfectly.  I now have a newly scrubbed clean machine, all my data's back (and even then, my old data's not been lost - the upgrade copied all the data that was going to be reset to the Windows.old directory on my hard disk).  I'm still going through confirming that I didn't leave any data behind that I cared about, currently it looks perfect. 

     

     

    [1] Flatten vs. Pave over.  To flatten a machine is to reinstall the OS clean, to pave a machine is to reformat the hard disk.  You flatten a machine to resolve OS corruptions, you pave over a machine to recover from a virus infection[2].

    [2] KC Lemson is getting to me :)

     

    Edit: Fixed stupid typo.

  • Larry Osterman's WebLog

    Proofreading...

    • 7 Comments

    So this morning, I was reading the PI's Microsoft blog and noticed this post: Google, Microsoft, Yahoo in 'SiteMaps' pact.  Cool!

     

    So I went to the Live Search blog post mentioned in the PI article, and went to the Sitemaps.Org site.

    I was curious, so I clicked on the protocol link, and found the protocol page.

    The very first example of a sitemap was (as of 10:20 PST on November 16, 2006):

    <?xml version="1.0" encoding="UTF-8"?>
    <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">    <url>
          <loc>http://www.example.com/</loc>
          <lastmod>2005-01-01</lastmod>
          <changefreq>monthly</changefreq>
          <priority>0.8</priority>

    </urlset>

     

    What's wrong with this XML?

    Come on guys.  At least make sure your protocol examples are correct before you go live with a major announcement.

     

    The good news is that it appears that only the first sitemap example given on the site has the problem.

  • Larry Osterman's WebLog

    What's wrong with this code, part 19 - the answer

    • 6 Comments

    In yesterday's post, I asked about a relatively simple piece of code that tried to use the COM type conversion logic to determine if a parameter to a function is an integer index or string key.

    Here's the code, for reference:

    HRESULT GetValue(VARIANT Index, VARIANT& Value)
    {
        // Try Index as offset
        HRESULT hr = VariantChangeType(&Index, &Index, 0, VT_I4);
        if(SUCCEEDED(hr))
            return GetValue(Index.lVal, Value);

        // Try Index as key
        hr = VariantChangeType(&Index, &Index, 0, VT_BSTR); 
        if(SUCCEEDED(hr))
            return GetValue(Index.bstrVal, Value);

        // Bad Index
        return E_INVALIDARG;
    }

    This function was called as:

    void SomeFunction()
    {
        CComVariant Value;
        GetValue(CComVariant(_T("1")), Value);
    }

    The problem occurs on the call to VariantChangeType in GetValue - on this example, VariantChangeType calls SysFreeString on Index.bstrValue and sets Index.intValue to 1.  When the call returns to the invoker, the destructor for the CComVariant attempts to call SysFreeString on its Index variable, and that results in a double free.

    When I originally thought about the problem, I thought that the problem was with the invocation.  I thought that the problem was that the CComVariant didn't have a copy constructor that implemented a deep copy, since the default rule for C++ is to perform a shallow copy.  But that's not the root of the problem.

    You can easily see this if you rewrite the invocation without using C++ at all:

    void SomeFunction()
    {
        VARIANT Value, CallersIndex;
        VariantInit(&CallersIndex);
        CallersIndex.vt = VT_BSTR;
        CallersIndex.bstrVal = SysAllocString(_T("1"));
        GetValue(CallersIndex, &Value);


        VariantClear(&CallersIndex);
    }
     

    There's no copy constructor, because this is straight C code (there are some type issues with the Value parameter).  C uses a shallow copy, so it will allocate a temporary variable for Index on the stack and perform a bitwise copy of the members of Index onto the temporary on the stack.  And the exact same problem will happen once again - the GetValue routine will once again free the value in the Index parameter (which points to the same memory as in the CallersIndex variable (it was a shallow copy, remember)).

    The real root cause of the problem is in the GetValue function:

        // Try Index as offset
        HRESULT hr = VariantChangeType(&Index, &Index, 0, VT_I4);
        if(SUCCEEDED(hr))
            return GetValue(Index.lVal, Value);

    The problem is that the VariantChangeType call uses the same Index variable for the VariantChangeType call.  Now the documentation for VariantChangeType says that it's ok to call the API in place ("If this is the same as pvarSrc, the variant will be converted in place").  But an in-place conversion of a string to an integer will result in the string being freed, leading to the root problem.

    Since there's no action that the caller can possibly take to resolve this, the onus is on the GetValue function to fix the problem - functions that take by value parameters MUST NOT modify those parameters in externally visible ways (unless the modification is explicitly spelled out by the API contract).  When the value parameter to a function is a simple data type, this is obvious, but when it is a complex type (like VARIANT), it can become complex (as in this example).

     

    Kudos:

    Tzagotta initially went off on the wrong tangent, but on the 2nd try, he/she nailed the problem.

    Adrian sort-of caught it, and Igor Tandetnik noticed that it was ok to call VariantChangeType in-place.

    ChrisR pointed out the issue with shallow vs. deep copies.

    And Michael G pointed out that ultimately this was a contract issue.

Page 1 of 1 (7 items)