Archives

Archives / 2009
  • Windows Web Services FAIL

    In 2007 I published an article about the cool XmlLite API introduced with Windows Vista. Although the XmlLite developers wanted to provide a redistributable for Windows XP, they never managed to get it past the Microsoft lawyers. Eventually Windows XP Service Pack 3 was released including XmlLite but by then many developers had given up on it. I felt that this was a great embarrassment for Microsoft. But that was in the Windows Vista era. Surely things have improved in the Windows 7 timeframe.

  • Travel

    Today I’m leaving for South Africa where I’ll spend 2.5 months with my family. If you have any questions about Window Clippings or my articles please be patient as I may not be able to get online to check my email as regularly.

  • Windows Web Services versus ATL SOAP

    After publishing the WWS article I received some questions about how this compares to ATL’s SOAP stack. I’m certainly not trying to convince anyone to switch over to WWS but it has some benefits that may be useful in some scenarios. I also haven’t used the ATL/ServerXMLHTTP stack much so I’m probably not the best person to do a comparison. From what I can tell however it uses either WinHTTP or WinInet and MSXML. Given that there are some things I can point out

  • October 2009 issue of MSDN Magazine

    Those of you expecting my Windows with C++ column about Windows Web Services to appear in the October issue will have to wait another month as the article was bumped due to space constraints. I just found out yesterday myself. In the mean time you should read Rick Molloy’s latest article on the Concurrency Runtime.

  • Zune Fail

    The Zune hardware products are fantastic. The new Zune HD is particularly impressive. The Zune software is a joy to use when compared to that other product that controls 99% of the market. But until Microsoft figures out how to make the Zune Marketplace and the Zune Pass subscription service available in the rest of the world (outside of the USA) this isn’t going to go anywhere.

  • I just don’t get twitter

    I think I’m with Mickey on this one and may never post anything more, but to ensure that nobody confuses me with a few other notorious Kenny Kerr’s out there my twitter account is “kennykerr”.

  • Lenovo Website Blues

    I’ve been dreaming of getting a Lenovo laptop for a few years. Don’t get me wrong, I love my Dell D630 but it may be time to upgrade soon. What frustrates me is how bad the Lenovo website experience is. Take the very appealing new T400s’ customization page:

  • On the move again

    Our house is now officially on the market. Anyone want to live in Tonbridge in Kent? We’re on our way back to Ontario in Canada after two years in England. This will be our last move!

    In other news there have been some hiccups with scheduling at MSDN Magazine. My next article, on Direct2D again, will now appear in the September 2009 issue. I’ve also just finished another really fun article on the new Windows Web Services API that I’m really excited about. That’ll be in the October 2009 issue and I’ll probably write some more about it for the December 2009 issue.

    We’re really looking forward to being back in Canada! Just as soon as we sell this house...

  • Asynchronous Agents

    Rick Molloy, one of the masterminds behind the new concurrency runtime (concrt) and parallel patterns library (PPL), has written an article in the latest issue of MSDN Magazine demonstrating the new asynchronous agents library with the classic dining philosophers problem.

  • WTL 8.1 is coming!

    After almost two years of silence there appears to be activity around WTL again. Of course this makes sense since Windows 7 is almost done. I just noticed build 8.1.9127 posted over on SourceForge.NET.

  • Visual Studio 2010 and .NET Framework 4 Beta 1 are here!

    Microsoft has finally released an update to the Visual Studio 2010 preview build that showed so much promise but unfortunately was so unreliable. If you have an MSDN subscription just head over to subscriber downloads and start downloading now!

  • C++ Exception Handling

    A while ago I made a passing remark on my blog that I prefer not to use exceptions in native code. Some readers asked me to justify this position and I’ve been a bit reluctant to do so only because it’s a lengthy argument that I’m sure will bring a lot of passionate responses that I don’t really have the time to deal with. I was reminded of this again last night when I walked past one of our bookshelves at home and picked up my copy of John Robbins’ excellent debugging book and noticed that it has a chapter on crash handlers within which John does a good job of covering many of the reasons why I don’t use exception handling in native code. If you’re interested in this topic I would encourage you to read John’s book.

  • Exciting Changes

    I’ve made a few changes to my professional life. I’ve had the opportunity to work with some really talented developers in London and I’m sorry to say goodbye to them. I’ll talk more about that in the coming weeks and months but one of the outcomes is that I’ll have much more time for my software projects. To unwind from employment (e.g. slavery :) ) I took Karin and the kids camping and boy did things change in the world of Microsoft technology in just one week. Here are just some of the announcements.

  • More on COM Safe Arrays and .NET Interop

    A few years ago I wrote about P/Invoke and how it can provide benefits even when C++ Interop is available on the consuming end. Recently I’ve had to do a bit of work consuming COM safe arrays from C#. I’ve seen safe arrays trip up developers time and again so I thought I’d share some thoughts and tips on the subject.

    This discussion focuses on the use of two-dimensional safe arrays. Single-dimensional safe arrays are marshalled automatically by the CLR (in most cases) but it is two-dimensional safe arrays that are often used to communicate key-value pairs such as for a map or dictionary of some kind. The trouble is that a two-dimensional safe array is really just a table of values. You can think of it as having an X axis and a Y axis. Storing key-value pairs in the table then requires a decision to be made regarding whether the keys will be stored down the Y axis as rows or along the X axis as columns. You could argue about which is better but at the end of the day you’re likely going to be at the mercy of whatever native API you’re calling.

    If keys are stored down the Y axis then a particular key is indexed with the safe array’s first dimension. The first dimension will thus have as many elements as there are pairs. The second dimension will have exactly two elements with the first storing the key and the second storing the value.

    On the other hand if keys are stored along the X axis then a particular key is indexed not by the first dimension but by the second. The second dimension will thus have as many elements as there are pairs. The first dimension will have exactly two elements with the first storing all the keys and the second storing all the values.

    Of course not everyone naturally thinks in terms of the same coordinate space and you may need to apply a transform before it makes sense to you. Apologies to graphics developers everywhere.  :)

    Let’s make this a bit more concrete with an example. Here is a native container of string-double pairs implemented by ATL’s CAtlMap class:

    typedef CAtlMap<CString, double> Map;
    Map m_map;


    The following function creates and returns a safe array keyed along the X axis using ATL’s safe array wrapper classes:

    #define HR(expr) { hr = expr; if (FAILED(hr)) return hr; }

    HRESULT __stdcall GetDictionaryX(SAFEARRAY** dictionary)
    {
        HRESULT hr;

        if (0 == dictionary)
        {
            return E_POINTER;
        }

        CComSafeArrayBound bounds[2] =
        {
            CComSafeArrayBound(2),
            CComSafeArrayBound(m_map.GetCount())
        };

        CComSafeArray<VARIANT> safeArray;
        HR(safeArray.Create(bounds, _countof(bounds)));

        LONG indices[2] = { 0 };
        POSITION position = m_map.GetStartPosition();

        for (; 0 != position; ++indices[1])
        {
            const Map::CPair* pair = m_map.GetNext(position);

            indices[0] = 0;
            HR(safeArray.MultiDimSetAt(indices, CComVariant(pair->m_key)));

            indices[0] = 1;
            HR(safeArray.MultiDimSetAt(indices, CComVariant(pair->m_value)));
        }

        *dictionary = safeArray.Detach();
        return S_OK;
    }


    Briefly, the bounds define the dimensions of the safe array and the indices are used to set the values in the table.

    The following function does the same thing but returns a safe array keyed along the Y axis:

    HRESULT __stdcall GetDictionaryY(SAFEARRAY** dictionary)
    {
        HRESULT hr;

        if (0 == dictionary)
        {
            return E_POINTER;
        }

        CComSafeArrayBound bounds[2] =
        {
            CComSafeArrayBound(m_map.GetCount()),
            CComSafeArrayBound(2)
        };

        CComSafeArray<VARIANT> safeArray;
        HR(safeArray.Create(bounds, _countof(bounds)));

        LONG indices[2] = { 0 };
        POSITION position = m_map.GetStartPosition();

        for (; 0 != position; ++indices[0])
        {
            const Map::CPair* pair = m_map.GetNext(position);

            indices[1] = 0;
            HR(safeArray.MultiDimSetAt(indices, CComVariant(pair->m_key)));

            indices[1] = 1;
            HR(safeArray.MultiDimSetAt(indices, CComVariant(pair->m_value)));
        }

        *dictionary = safeArray.Detach();
        return S_OK;
    }

    With the native code out of the way let’s see how we can call these functions from C#. For simplicity lets assume they’re just exported functions and not COM interface methods. The same principals apply but it’s just less sample code for me to write.

    The first step is to import the functions as follows:

    [DllImport("Server.dll", EntryPoint = "GetDictionaryY", PreserveSig = false)]
    [return: MarshalAs(UnmanagedType.SafeArray)]
    static extern object[,] NativeGetDictionaryY();

    [DllImport("Server.dll", EntryPoint = "GetDictionaryX", PreserveSig = false)]
    [return: MarshalAs(UnmanagedType.SafeArray)]
    static extern object[,] NativeGetDictionaryX();

    This just adds some metadata needed by the CLR to call the LoadLibrary and GetProcAddress functions on your behalf, how to marshal the parameters and return value, and what to do with the HRESULT.

    The next step is to determine how many key-value pairs the two-dimensional array consists of. The array’s GetLength method comes in handy as you can specify the dimension whose length you are interested in:

    object[,] array = NativeGetDictionaryX();
    int count = array.GetLength(1);


    Given the count you can now enumerate the key-value pairs using a for loop and a bit of casting:

    for (int i = 0; i < count; ++i)
    {
        string key = (string)array[0, i];
        double value = (double)array[1, i];

        Console.WriteLine(key + "=" + value);
    }

    Needless to say this is quite error prone. It would be more desirable to use a foreach loop but the enumerator provided by the multi-dimensional array doesn’t know anything about the key-value pairs so it just returns it in a flat list. The good news is that it’s pretty easy to write your own enumerator or to be precise let the C# compiler generate one for you.

    Here’s an implementation of the generic IEnumerable<TKey, TValue> interface that does just what you want for arrays keyed along the X axis:

    class SafeArrayEnumerableX<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>
    {
        private readonly object[,] m_array;

        public SafeArrayEnumerableX(object[,] array)
        {
            Debug.Assert(null != array);
            Debug.Assert(2 == array.GetLength(0));

            m_array = array;
        }

        public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
        {
            int count = m_array.GetLength(1);

            for (int i = 0; i < count; ++i)
            {
                yield return new KeyValuePair<TKey, TValue>((TKey)m_array[0, i], (TValue)m_array[1, i]);
            }
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }


    Notice that it’s effectively doing the same looping and casting as the hand-rolled approach but in such a way that you end up with a reusable enumerator that hides all the nasty indexing and casting. With the enumerator providing a sequence of generic KeyValuePair<TKey, TValue> structures, enumerating over the pairs now becomes much more elegant:

    static SafeArrayEnumerableX<string, double> GetDictionaryX()
    {
        return new SafeArrayEnumerableX<string, double>(NativeGetDictionaryX());
    }

    foreach (var pair in GetDictionaryX())
    {
        string key = pair.Key;
        double value = pair.Value;

        Console.WriteLine(key + "=" + value);
    }


    And that’s all there is to it. For completeness, here’s the equivalent enumerable implementation for arrays keyed along the Y axis:

    class SafeArrayEnumerableY<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>
    {
        private readonly object[,] m_array;

        public SafeArrayEnumerableY(object[,] array)
        {
            Debug.Assert(null != array);
            Debug.Assert(2 == array.GetLength(1));

            m_array = array;
        }

        public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
        {
            int count = m_array.GetLength(0);

            for (int i = 0; i < count; ++i)
            {
                yield return new KeyValuePair<TKey, TValue>((TKey)m_array[i, 0], (TValue)m_array[i, 1]);
            }
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }


    I hope that helps.

  • Manifest View support for DLLs

    Since I blogged about my Manifest View tool I’ve had a few requests to add support for viewing manifests embedded within DLLs. It originally only supported viewing manifests embedded within executables.