MSXML4 Is Going To Be Kill-Bitted

Win32, XML No Comments »

In an effort to EOL MSXML 4 and encourage developers to use MSXML 6, the MSXML team is going to kill-bit MSXML4 in Q4 2007. This means that you will no longer be able to create instances of MSXML 4 from within Internet Explorer.

Be sure to update your applications accordingly. For this, the MSXML team’s post Upgrading to MSXML 6.0 may prove quite useful.

Delta Compression Application Programming Interface

Win32 No Comments »

Apparently Microsoft has an API for just about everything. Today I read about Microsoft’s Delta Compression Application Programming Interface, an API for creating and applying binary diffs. This API looks ideal for building an application’s incremental online update facility.

Win32 Shell Lightweight Utility API (shlwapi.dll)

Win32 No Comments »

The Win32 shell lightweight utility API (shlwapi.dll) is a cornucopia of useful functions. It appears to be Microsoft’s “dumping ground” for functions without a better home. (I believe Microsoft internal DLL ownership also played a part.) Had I known about shlwapi years ago, it would have saved me considerable programming effort.

Particularly useful are SHCreateStreamOnFile, the path family of functions (e.g. PathCombine), and the registry family of functions (e.g. SHRegGetPath).

However, it appears that Microsoft is slowly moving functionality out of shlwapi into other places. For example, many of shlwapi’s string handling functions have better-designed replacements in Microsoft’s safe string library strsafe. Similarly, shlwapi’s SHRegGetValue has been deprecated in favor of advapi32.dll’s RegGetValue.

Be sure to look at all the functionality shlwapi provides — you may find a hidden gem of your own!

Smart Pointers Aren’t Quite Smart Enough…

C++, COM No Comments »

What’s wrong with this code? (It is adapted from something I wrote yesterday)

  1. void f()
  2. {
  3.     HRESULT hr;
  4.  
  5.     hr = ::CoInitialize(NULL);
  6.     if (SUCCEEDED(hr)) {
  7.         MSXML2::IMXWriterPtr spMXWriter;
  8.         hr = spMXWriter.CreateInstance(__uuidof(MSXML2::MXXMLWriter30));
  9.         if (SUCCEEDED(hr)) {
  10.             // Use spMXWriter
  11.         }
  12.  
  13.         ::CoUninitialize();
  14.     }
  15. }

Read the rest of this entry »

Writing Streaming XML Using MSXML

C++, COM, Win32, XML No Comments »

In my posts Implementing IXmlWriter Series, I wrote a streaming XML writing class whose interface is based on .NET’s XmlWriter. I recently discovered that MSXML provides its own method to write streaming XML through the class MXXMLWriter.

MXXMLWriter supports a large set of functionality including encoding, indentation, disabling output escaping, and writing XML fragments. The generated XML can be written to an IStream, a BSTR, or a DOMDocument object. However, it’s interface leaves much to be desired. Usage looks like this:

  1. #import <msxml3.dll>
  2.  
  3.  
  4. // I’m using the #import-generated _com_ptr_t-based smart pointers
  5. MSXML2::IMXWriterPtr spMXWriter;
  6. hr = spMXWriter.CreateInstance(__uuidof(MSXML2::MXXMLWriter30));
  7. _ASSERT(SUCCEEDED(hr)); // TODO
  8.  
  9. // Configure the IMXWriter as appropriate.  We will be using the default of
  10. // writing to a BSTR which can be retrieved using spMXWriter->get_output().
  11.  
  12. MSXML2::ISAXContentHandlerPtr spSAXContentHandler(spMXWriter);
  13. _ASSERT(spSAXContentHandler != NULL); // TODO
  14.  
  15. // Be sure to check the hrs below
  16.  
  17. hr = spSAXContentHandler->startDocument();
  18. hr = spSAXContentHandler->startElement(L"", 0, L"root", 4, L"root", 4, NULL);
  19. hr = spSAXContentHandler->characters(L"text", 4);
  20. // endElement also takes the element name.  This means we may need to
  21. // maintain our own open element stack.
  22. hr = spSAXContentHandler->endElement(L"", 0, L"root", 4, L"root", 4);
  23. hr = spSAXContentHandler->endDocument();

The rough IXmlWriter equivalent is:

  1. #include "StringXmlWriter.h"
  2.  
  3.  
  4. StringXmlWriter xw;
  5. xw.WriteStartDocument();
  6.   xw.WriteStartElement("root");
  7.     xw.WriteString("text");
  8.   xw.WriteEndElement(); // /root
  9. xw.WriteEndDocument();

However, there might be a case to change IXmlWriter to use MXXMLWriter internally.

MSXML Versions

Win32, XML No Comments »

The Microsoft XML team recently posted in their blog a set of recommendations on which version of MSXML to use. In short, they recommend using MSXML 6.0 but falling back to 3.0 if it isn’t available.

My product currently tries MSXML 4.0 first — but only SP2 and above. We ran into bugs with previous versions of MSXML 4.0. I will have to evaluate moving to MSXML 6.0.

Best Practices For Creating DLLs

Win32 No Comments »

Best Practices for Creating DLLs

Win32 LD_PRELOAD Revisited

Win32 No Comments »

I was intending to revisit and possibly rewrite my Win32 LD_PRELOAD application when I discovered Microsoft Research has written something which does far, far more: Detours.

Win32 Custom Controls

Win32 No Comments »

I was about to write a tutorial on how to create a custom Win32 control in C when I found that someone had beat me to it: Creating Custom Controls From Scratch. Overall it is quite good, and I learned a few new things myself. (By the way, the entire Catch22 Tutorials site is filled with fascinating material for Win32 developers.)

One thing to note: If you separate your custom control into a DLL, you will need to create an initialization function which registers the window classes (similar to InitCommonControls()). Be sure to pass the CS_GLOBALCLASS flag to RegisterClass() to register it as application global. If you don’t, you will only be able to instantiate your control manually by passing the DLL’s HMODULE as a parameter to CreateWindow().

By the way, MFC seems to support customizing controls primarily through window subclassing, which is a related but slightly different mechanism.

COM DLL Self-Registration

COM No Comments »

Here is a block of code which correctly performs the COM self-registration process on a DLL (distilled from the source code of regsvr32.exe):

BOOL SelfRegisterDll(LPCTSTR szDllName)
{
    BOOL bRet = FALSE;
    if (SUCCEEDED(OleInitialize(NULL))) {
        HMODULE hm = LoadLibraryEx(szDllName, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
        if (hm != NULL) {
            FARPROC fp = GetProcAddress(hm, "DllRegisterServer");
            if (fp != NULL) {
                typedef HRESULT (STDAPICALLTYPE *FnDllRegisterServer)(void);
                FnDllRegisterServer fn = (FnDllRegisterServer) fp;

                HRESULT hr = (*fn)();
                if (SUCCEEDED(hr)) {
                    bRet = TRUE;
                }
            }
            FreeLibrary(hm);
        }
        OleUninitialize();
    }
    return bRet;
}

The most notable subtlety is the use of LoadLibraryEx() with the LOAD_WITH_ALTERED_SEARCH_PATH flag instead of LoadLibrary(). As the MSDN article Dynamic-Link Library Search Order explains, the LOAD_WITH_ALTERED_SEARCH_PATH tells Windows to first look for DLL dependencies in the directory which contains the loading DLL as opposed to the directory from which the application loaded.

This flag turns out to be rather important. I recently was informed of a bug in which the COM DLL self-registration part of an installer created with InstallShield 5.5 would fail, but regsvr32 on the DLL succeeded. Apparently InstallShield 5.5 uses its own self-registration code which does not use the LOAD_WITH_ALTERED_SEARCH_PATH to LoadLibraryEx. This caused the COM DLL to attempt to load an incompatible, third-party DLL dependency from the SYSTEM32 directory (which was installed by another product) rather than the correct version from the application directory1.

[1] Because multiple, incompatible versions of this DLL exist with identical names, the best solution for this particular issue was to rename the version of the DLL that we ship.
WP Theme & Icons by N.Design Studio
Entries RSS Comments RSS Log in