Figure 4   IDL and Code Guide for Typical COM Situations

Scenario IDL Client Method
String Input
HRESULT f([in, string] const OLECHAR *pwsz);
p->f(OLESTR("Hello"));
HRESULT f(const OLECHAR* wsz) {
 // ... use string ...
}
String Output: CA
HRESULT f([out, string] OLECHAR *wsz,
          [in] long cchMax);
OLECHAR wsz[1024];
 p->f(wsz, 1024);
HRESULT f(OLECHAR *wsz, long cMax) {
 wcscpy(wsz, OLESTR("Bob"));
 return S_OK;
}
String Output: OA
HRESULT f([out, string] OLECHAR **wsz);
OLECHAR *pwsz = 0;
if (SUCCEEDED(p->f(&pwsz)) {
 // ... use string ...
 CoTaskMemFree(pwsz);
}
HRESULT f(OLECHAR **ppwsz) {
  int cb = (wcslen(OLESTR("Bob")) + 1);
  cb *= sizeof(OLECHAR);
  *ppwsz = (OLECHAR*)CoTaskMemAlloc(cb);
  if (*ppwsz == 0) return E_OUTOFMEMORY;
  wcscpy(*ppwsz, OLESTR("Bob"));
  return S_OK;
}
Non-string Array Input
HRESULT f([in, size_is(cMax)] short *rgs, 
          [in] long cMax);
short rgs[] = { 1, 2, 3 };
p->f(rgs, 3);
HRESULT f(short *rgs, long cMax) {
 for (long n = 0; n < cMax; n++)
  total += rgs[n];
 return S_OK;
}
Non-string Array Output: CA
HRESULT f([out, size_is(cMax), 
length_is(*pcActual)] short *rgs, 
          [in] long cMax, 
          [out] long *pcActual);
short rgs[10];
long cActual = 0;
p->f(rgs, 10, &cActual);
HRESULT f(short *rgs, long cMax, 
          long *pcActual){
 *pcActual = min(cMax, 5);
 for (int n = 0; n < *pcActual; n++)
  rgs[n] = n * n; 
 return S_OK;
}
Non-string Array Output: OA
HRESULT f([out, size_is(,*pcMax)] short **pprgs, 
          [out] long *pcMax);
short *prgs = 0;
long cMax = 0;
hr = p->f(&prgs, &cMax);
if (SUCCEEDED(hr)) {
 // ... use array ...
 CoTaskMemFree(prgs);
}
HRESULT f(short **pprgs, long *pcMax){
 *pcMax = 5;
 int cb = *pcMax * sizeof(**pprgs);
 *pprgs = (short*) CoTaskMemAlloc(cb);
 if (*pprgs == 0) return E_OUTOFMEMORY;
 for (int n = 0; n < *pcMax; n++)
  (*pprgs)[n] = n * n; 
 return S_OK;
}
CA: Caller Allocated Buffer
OA: Object Allocated Buffer (preferred)