Home Search Contact us About us
Title How to work with BSTR
Summary When passing strings to and from COM objects BSTRs are used. This article covers when to allocate, reallocate and free the BSTR.
Contributor Vincent Minden and John McTainsh
Published 6-Feb-2001
Last updated 7-Feb-2001
Page rating   80% for 16 votes Useless Brilliant

Description.

Passing strings to and from COM is a very common practice but can be a little tricky if you don't allocate and deallocate correctly. All strings are passed as BSTR and can be used with CComBSTR, _btr_t and CString under most conditions. The following should help answer some of the allocation issues associated with using BSTRs.

What is a BSTR

Some might say that a BSTR is a pointer to an array of wchar_t , and in part they would be correct. However it is more. It contains the length of the string so it can contain embedded NULLs. For this reason it must be allocated using the SysAllocString functions and freed with SysFreeString .

The simple rules of [in] / [out]

  • For [in] type parameters, client allocates and de-allocates the data.
  • You may NOT modify BSTRs passed [in] to you.
  • For [in,out] type parameters, client allocates, server re-allocates, and client does a final de-alocation.
  • For [out] type parameters including [out,retval] parameters, the server allocates the data. The client de-allocates output.

Passing BSTR into a function. [in]

Client is responsible for allocating and deallocating the data.

    //In COM server implementation
    STDMETHODIMP CWhereAmI::SetThing( /*[in]*/BSTR bstrThing )
    {
        //I do not own it so I cannot modify it.
        USES_CONVERSION;
        CString sThing = W2T( bstrThing );
        return S_OK;
    }
...
...
...
    //When I am using it
    BSTR b1 = SysAllocString( L"Hello" );
    pSomeObj->SetThing( b1 );
    SysFreeString( b1 );           

Getting a BSTR from a function [out] or [out,retval].

Client is responsible for providing and unallocated BSTR which is populated by the function. The client must then deallocate the data.

    //In COM server implementation
    STDMETHODIMP CWhereAmI::GetThing( /*[out]*/ BSTR* pbstrThing )
    {
        //I create BSTR to return.
        *pbstrThing = SysAllocString( L"Some returned stuff" );
        return S_OK;
    }
...
...
...
    //When I am using it
    BSTR b2 = NULL;
    pSomeObj->GetThing( &b2 );
    //Use the b2 now...
    SysFreeString( b2 );           

Getting a BSTR from a function that is passed data in the same BSTR. [in,out]

Client is responsible for allocating the input data and deallocating the output data. However the server must free and allocate the data to modify. (Or use SysReAllocString)

    //In COM server implementation
    STDMETHODIMP CWhereAmI::ReverseThing( /*[in,out]*/ BSTR* pbstrThing )
    {
        USES_CONVERSION;
        CString sThing = W2T( *bstrThing );
        SysFreeString( *bstrThing );
        sThing.MakeReverse();
        //I create BSTR to return.
        *pbstrThing = sThing.AllocSysString();
        return S_OK;
    }
...
...
...
    //When I am using it
    BSTR b3 = SysAllocString( L"Foward Stuff" );
    pSomeObj->ReverseThing( &b3 );
    //Use the b2 now...
    //b3 should now contain "ffutS drawoF"
    SysFreeString( b3 );           

What else can I use.

Microsoft was kind enough to provide handy classes called CComBSTR and _btr_t to make handling BSTRs a little simpler. Both classes wrap the BSTR type to provide useful operators and methods. If you are doing more complex operations these classes provide a richer set of features.

Credits

I would like to thank Vincent Minden for his help with this article.

Further Reading

A good MSDN article on this topic is Article 3. Strings the OLE Way

Comments Date
Home Search Contact us About us