Figure 1   Rewriting GetData


   // IDL
   HRESULT GetData ([out] int*  pCount,
       [out, size_is (,*pCount)] unsigned char** ppBuffer);
 
   // Caller
   int nCount;
   unsigned char* pBuffer;
   HRESULT hr = pInterface->GetData (&nCount, &pBuffer);
   if (SUCCEEDED (hr)) {
       // pBuffer points to data and nCount holds length
 •
 •
 •
      CoTaskMemFree (pBuffer); // Important!
   }
 
   // Callee
   int nSize = 1024;
   *ppBuffer = (unsigned char*) CoTaskMemAlloc (nSize);
   if (*ppBuffer == NULL)
       return E_OUTOFMEMORY;
   // Copy nSize bytes to the address in *ppBuffer
   *pCount = nSize; // Return count to caller
   return S_OK;

Figure 2   Rewriting GetText


   // IDL
   HRESULT GetText ([out, string] wchar_t** ppBuffer);
 
   // Caller
   wchar_t* pBuffer;
   HRESULT hr = pInterface->GetText (&pBuffer);
   if (SUCCEEDED (hr)) {
       // pBuffer now holds a valid string pointer
 •
 •
 •
      CoTaskMemFree (pBuffer);
   }
 
   // Callee
   wchar_t* pText = L"Hello, world";
   *ppBuffer = (wchar_t*) CoTaskMemAlloc ((wcslen (pText) + 1) * 2);
   if (*ppBuffer == NULL)
       return E_OUTOFMEMORY;
   wcscpy (*ppBuffer, pText);
   return S_OK;

Figure 3   GetLine


   // Caller
   LINE line;
   HRESULT hr = pInterface->GetLine (&line);
   if (SUCCEEDED (hr)) {
       int x1 = line.pFrom->x;
       int y1 = line.pFrom->y;
       int x2 = line.pTo->x;
       int y2 = line.pTo->y;
       CoTaskMemFree (line.pFrom);
       CoTaskMemFree (line.pTo);
   }
 
   // Callee
   POINT* pFrom = (POINT*) CoTaskMemAlloc (sizeof (POINT));
   if (pFrom == NULL)
       return E_OUTOFMEMORY;
 
   POINT* pTo = (POINT*) CoTaskMemAlloc (sizeof (POINT));
   if (pTo == NULL) {
       CoTaskMemFree (pFrom);
       return E_OUTOFMEMORY;
   }
 
   pFrom->x = 0;
   pFrom->y = 0;
   pTo->x = 100;
   pTo->y = 50;
   pLine->pFrom = pFrom;
   pLine->pTo = pTo;
   return S_OK;

Figure 4   Passing a Linked List


   // IDL
   typedef struct tagITEM {
       int nVal;
       struct tagITEM* pNext;
   } ITEM;
 
   HRESULT GetList ([out] ITEM** ppList);
 
   // Caller
   ITEM* pItem;
   HRESULT hr = pInterface->GetList (&pItem);
   if (SUCCEEDED (hr)) {
       while (pItem != NULL) {
 •
 •
 •
          ITEM* pNext = pItem->pNext;
           CoTaskMemFree (pItem);
           pItem = pNext;
       }
   }
 
   // Callee
   ITEM* pItem1 = (ITEM*) CoTaskMemAlloc (sizeof (ITEM));
   if (pItem1 == NULL)
       return E_OUTOFMEMORY;
 
   ITEM* pItem2 = (ITEM*) CoTaskMemAlloc (sizeof (ITEM));
   if (pItem2 == NULL) {
       CoTaskMemFree (pItem1);
       return E_OUTOFMEMORY;
   }
 
   ITEM* pItem3 = (ITEM*) CoTaskMemAlloc (sizeof (ITEM));
   if (pItem3 == NULL) {
       CoTaskMemFree (pItem1);
       CoTaskMemFree (pItem2);
       return E_OUTOFMEMORY;
   }
 
   pItem1->nVal = 1;
   pItem1->pNext = pItem2;
   pItem2->nVal = 2;
   pItem2->pNext = pItem3;
   pItem3->nVal = 3;
   pItem3->pNext = NULL;
 
   *ppList = pItem1;
   return S_OK;