L'errore di compilazione è dovuto quasi certamente al fatto che non stai importando la libreria OLE32 che definisce la funzione, come del resto hai giustamente ipotizzato tu. Verifica nelle proprietà del progetto che, sotto la categoria Linker/Input, nel campo Additional Dependencies, ci sia ole32.lib nell'elenco e, nel caso manchi, aggiungilo. Vedrai che in questo modo risolverai il problema.

Senza entrare troppo nel dettaglio della questione, ti spiego brevemente perchè è necessario utilizzare CoTaskMemAlloc() in questo caso.
Di fatto la DLL C e l'applicazione .NET sono due entità diverse e vivono in due ambienti isolati, pur coabitando nello stesso processo: ciò che viene creato in uno è visibile sono in quello e non nell'altro (e viceversa).
La funzione della C standard library malloc() e la sua controparte new in C++ utilizzano l'heap per l'allocazione ma non sanno nulla di ciò che c'è all'esterno. Per scambiare dati che non siano di dimensione nota (e che quindi possono essere comodamente passati nello stack) è necessario trovare sistemi "comuni" ai due ecosistemi.
A differenza di malloc() e new che vengono forniti dal compilatore, CoTaskMemAlloc() è una API del sistema operativo che alloca memoria sempre nello heap, ma che è accessibile ovunque nello stesso processo. Per dovere di cronaca c'è da dire che non è l'unica API in grado di fare ciò ma CoTaskMemAlloc() è quella che viene utilizzata quando si ha a che fare con oggetti COM perchè ne rende semplice il marshalling.
Una cosa che ho dimenticato di dire nel post precedente è che nell'esempio riportato non c'è bisogno di deallocare la memoria in quanto se ne occupa direttamente .NET, ma se la DLL dovesse essere utilizzata da altri, ad esempio un'applicazione C++, allora è necessario effettuare in modo esplicito la deallocazione con CoTaskMemFree().

Non mi dilungo oltre, ma spero di averti chiarito il dubbio. Per dettagli sui vari metodi di allocazione puoi leggere questa pagina MSDN: http://msdn.microsoft.com/en-us/libr...sktop/aa366533(v=vs.85).aspx