Since a lot of our resource management issues are made simpler by using smart pointers to MSXML's DOM interfaces, we really need to pay attention to only a few things.
CoInitialize(NULL), returns HRESULT : In every program that uses a COM component the COM library must be initialized using this call. By convention and following the sample code from Microsoft and other authors, I call this early in the main line of the main routine. Values other than NULL can be specified if you are, for example, working with a multi threaded application.
CoUninitialize(), returns void : This closes the COM library. Every CoInitialize call should be matched with a CoUninitialize call. Again, by convention and following the sample code from Microsoft and other authors, I call this in the main line of the main routine right before the return.
CreateInstance(SBCS clsidString), returns HRESULT : This creates a COM object. In our use of MSXML we create an object that represents a DOM document. In (almost) all our code the clsidString we use is the value returned by the uuidof keyword for DOMDocument40. CreateInstance is a method of the smart pointer class for the IXMLDOMDocument interface. There is a corresponding CoCreateInstance call for dumb pointers if you are using them.
Release(), returns void : This releases a COM interface. We will usually let smart pointers handle this, but in rare cases we may use it directly so we can reuse a pointer.
CAUTION Make Sure to Release Resources and Close Down Cleanly!
Until I figured out what was happening, I consistently got an unhandled exception with an access violation at 0xC0000005 in, of all places, the return statement in my main routine. This started happening when, like a good doobie, I put in the CoUninitialize call to close down the COM library. The exception finally went away after I called the Release methods on all my IXMLDOMMumblePtr objects. I finally made things simpler by just declaring the IXMLDOMMumblePtr objects in the try block instead of my usual place at the beginning of the routine. Exiting the try block made them go out of scope, called their destructors, and cleaned things up for me without having to invoke Release.
Commenting out the CoUninitialize call also made the exception go away. However, I'm a bit dubious and too cautious to rely solely on the C++ return statement and program termination to properly clean up everything. I've seen enough weirdness and instability in the various Windows operating systems to want to avoid risking the introduction of any more such problems. In addition, if you are using MSXML in only one routine of a complex application that will keep running when you're finished with XML, you really want to clean up properly.
CAUTION Call the Correct Release Method!
If you're going to call a Release method, make sure you call the right one. This is another bit of COM complexity. As noted earlier, our smart pointers can be used like regular C++ pointers, but they aren't simple pointers at all. Although they point to DOM objects, they are themselves objects with properties and methods. Adding to the confusion is that both the pointer and the pointee have Release methods. You want to call the Release method in the Ptr object and not the one in the thing it points to. For example, call spDocInput.Release() instead of spDocInput->Release(). Doing the former will work. Doing the latter may result in an unhandled exception at program termination. You can identify these by a report of an access violation at an address other than 0xC0000005 when you return in your main routine.