Create Word Document in C++ I am new to COM programming in C++ and while this code works welcome suggestions to improve readability/reliability. This creates a blank word document and adds the text Hello, World.

// The Microsoft Office Object type library (mso.dll)
    #import "libid:2DF8D04C-5BFA-101B-BDE5-00AA0044DE52" raw_interfaces_only, named_guids,\
        rename("DocumentProperties", "_DocumentProperties"), \
        rename("SearchPath", "_SearchPath"), \
        rename("RGB", "_RGB")

     //  The Microsoft Office Word Object type library (msword.olb)
    #import "libid:00020905-0000-0000-C000-000000000046" raw_interfaces_only,\
        rename("ExitWindows", "_ExitWindows"), \
        rename("ReplaceText", "_ReplaceText"), \
        rename("FindText", "_FindText"), \
        rename("RGB", "_RGB")
    #include &lt;Windows.h&gt;

    int main()
    {
        HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
        Word::_ApplicationPtr pWordApp;
        Word::DocumentsPtr pWordDocs;
        Word::_DocumentPtr pWordDoc;
        Word::RangePtr pRange;
        hr = pWordApp.CreateInstance(__uuidof(Word::Application));
        pWordApp-&gt;put_Visible(VARIANT_TRUE);
        pWordApp-&gt;get_Documents(&amp;pWordDocs);

        pWordDoc.CreateInstance(__uuidof(Word::Document));
        pRange.CreateInstance(__uuidof(Word::Range));
        VARIANT vTemplate;
        VariantInit(&amp;vTemplate);
        vTemplate.vt = VT_BSTR;
        vTemplate.bstrVal = SysAllocString(L"");

        VARIANT vNewTemplate;
        VariantInit(&amp;vNewTemplate);
        vNewTemplate.vt = VT_BOOL;
        vNewTemplate.boolVal = false;

        VARIANT vDocType;
        VariantInit(&amp;vDocType);
        vDocType.vt = VT_I4;
        vDocType.iVal = Word::WdNewDocumentType::wdNewBlankDocument;

        VARIANT vVisible;
        VariantInit(&amp;vVisible);
        vVisible.vt = VT_BOOL;
        vVisible.boolVal = true;

        VARIANT vStart;
        VariantInit(&amp;vStart);
        vStart.vt = VT_I4;
        vStart.iVal = 0;

        VARIANT vEnd;
        VariantInit(&amp;vEnd);
        vEnd.vt = VT_I4;
        vEnd.iVal = 0;

        pWordDocs-&gt;Add(&amp;vTemplate, &amp;vNewTemplate, &amp;vDocType, &amp;vVisible, &amp;pWordDoc);
        pWordDoc-&gt;Range(&amp;vStart, &amp;vEnd, &amp;pRange);

        BSTR str = SysAllocString(L"Hello, World!");
        pRange-&gt;put_Text(str);
        SysFreeString(str); 
    }
First off, I think it's worth thinking carefully about whether C++ is the best tool for this task.  It certainly can be done, but you may find better documentation/more support for COM/interop from C# or VBA.  Particularly for such a simple task.



HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);


You need to check the result of CoInitializeEx and every other API call you make.  Think of each API call as a polite request.  Windows may (and frequently does) decline requests.  In your program, these errors will be really hard to diagnose because you will simply not see your desired result.  A better idea is to use a function/macro to check the result is correct.  In this case, it should look something like:

assert(S_OK == CoInitializeEx(NULL, COINIT_APARTMENTTHREADED));


You may want to get fancier with the macro.  This way you will know where (and where not) to spend time debugging.



Quoting MSDN:


  To close the COM library gracefully on a thread, each successful call to CoInitialize or CoInitializeEx, including any call that returns S_FALSE, must be balanced by a corresponding call to CoUninitialize.


You forgot to call CoUninitialize.  Your program (well, actually your thread) is supposed to tell Windows when it will start using COM and when it is done.

This is a great place to use RAII:

struct COMThread {
    COMThread() {
        assert(S_OK == CoInitializeEx(NULL, COINIT_APARTMENTTHREADED));
    }

    ~ COMThread() {
        CoUninitialize(); // returns void, no need to check return value
    }
};


In general you should read MSDN for every function you call and probably write a few comments summarizing your findings (and maybe even a URL... sometimes the docs are hard to re-find IMO).



vTemplate.bstrVal = SysAllocString(L"")


Did you forget to deallocate this BSTR?  This could be another RAII wrapper.



VARIANT vTemplate;
VariantInit(&amp;vTemplate);
vTemplate.vt = VT_BSTR;


Once again, there is a free function VariantClear which could be RAII.  A wrapper around variant is not a bad idea -- most of your code creates/clears variants.



I could not find docs for the specific Word functions you are calling, but I suspect there is a way to achieve this without using so many variants (based on some experience using other parts of the COM API).  I know this is not as helpful as it could be.



Despite a few things to clean up, I think you're off to a good start.  You have the general procedure down which is the most important thing.