out parameter in COM method

3 views
Skip to first unread message

JJ

unread,
May 15, 2006, 7:11:02 PM5/15/06
to
I wonder how COM allocates and releases out parameter memory.
I programmed CORBA before. In CORBA, if a method has out string parameter,
server allocates memory and client is responsible to release the memory. Does
COM work the same way? Can someone help?
JJ

Igor Tandetnik

unread,
May 15, 2006, 8:28:55 PM5/15/06
to
"JJ" <J...@discussions.microsoft.com> wrote in message
news:73BB8AF5-29FE-4E5A...@microsoft.com

> I wonder how COM allocates and releases out parameter memory.

The callee allocates, and the caller later releases when it no longer
needs the data.

> I programmed CORBA before. In CORBA, if a method has out string
> parameter, server allocates memory and client is responsible to
> release the memory. Does COM work the same way?

Yes, COM works the same way.
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925


JJ

unread,
May 16, 2006, 2:25:01 PM5/16/06
to
Thank you. Is there a book or some web sites have detailed explaination for
this topic? I tried to search the answer myself, but I could not find it.
JJ

Alexander Nickolov

unread,
May 16, 2006, 2:30:13 PM5/16/06
to
Pretty much any book on COM should explain that. The
standard beginner's COM book is:

"Inside COM" by Dale Rogerson, MS Press

--
=====================================
Alexander Nickolov
Microsoft MVP [VC], MCSD
email: agnic...@mvps.org
MVP VC FAQ: http://www.mvps.org/vcfaq
=====================================

"JJ" <J...@discussions.microsoft.com> wrote in message

news:B012FE4D-3D58-4340...@microsoft.com...

JJ

unread,
May 16, 2006, 4:36:02 PM5/16/06
to
Thank you.
JJ

Snow

unread,
May 22, 2006, 2:40:29 AM5/22/06
to
I have a struct with dynamic size, how do I marshall this struct? I do not
want to use another parameter for marshalling size, ie [out,
size_is(dwSize)] and I only want an "out" direction. Is this possible?

HRESULT GetStruct ( [out] TestStructType** ppStruct)
ppStruct has dynamic size

Thanks in advance

"Igor Tandetnik" <itand...@mvps.org> wrote in message
news:OiUyt%23HeGH...@TK2MSFTNGP03.phx.gbl...

Igor Tandetnik

unread,
May 22, 2006, 8:04:46 AM5/22/06
to
"Snow" <filame...@hotmail.com> wrote in message
news:es$2fqWfG...@TK2MSFTNGP05.phx.gbl

> I have a struct with dynamic size, how do I marshall this struct?

You don't. Standard marshalling does not support variable length
structures. Make it a fixed struct with a pointer to dynamically
allocated variable size array.

> I
> do not want to use another parameter for marshalling size, ie [out,
> size_is(dwSize)] and I only want an "out" direction. Is this possible?

A [size_is] member can be part of the structure:

struct MyData {
DWORD dwSize;
[size_is(dwSize)] BYTE* pData;

Alexander Nickolov

unread,
May 22, 2006, 3:15:02 PM5/22/06
to
You can, but using a trick. For example, using a local/call_as
pair of methods and some code you write for the P/S DLL:

[local]
HRESULT GetStruct([out] TestStructType** ppStruct);

[call_as(GetStruct)]]
HRESULT GetStruct_remote([out] long* psz, [out, size_is(*psz)] BYTE**
ppStruct);

You need to manually code the conversion routines for
your interface and compile and link them in the P/S DLL
(note this is in C, not C++):

#define COBJINTERFACES
#include "MIDL_header.h"

HRESULT STDMETHODCALLTYPE IFace_GetStruct_Proxy(LPVOID pThis, struct
TestStructType** ppStruct)
{
long sz;
return IFace_GetStruct_remote_Proxy(pThis, &sz, (BYTE**)ppStruct);
}

HRESULT STDMETHODCALLTYPE IFace_GetStruct_Stub(LPVOID pThis, long* psz,
BYTE** ppStruct)
{
HRESULT hr = IFace_GetStruct(pThis, (struct TestStructType**)ppStruct);
if (SUCCEEDED(hr)) {
*psz = ?; // From the struct data
} else {
*psz = 0;
}
return hr;
}

Note I typed this based on the MIDL documentation after correcting
glaring errors, but I haven't actually compiled it.

Also note, I assumed the struct doesn't have embedded pointers.
If it does, you need to serailize it at the stub and then recreate it
at the proxy making this a true excersize in marshaling :)...

I leave the excersize in passing the struct as an [in] parameter
to you. It shouldn't be very different, but you'd be passing the
data in the opposite direction.

You'd probably quickly realize that writing a pair of methods
and the associated code each time you want to transmit a struct
quickly gets old. MIDL has more advanced mechanisms, but
I haven't used them myself, so can't provide you with snippets.
Look at the following MIDL attributes: transmit_as, represent_as,
wire_marshal, user_marshal. I'd suggest [wire_marshal] based
on the MIDL description.

--
=====================================
Alexander Nickolov
Microsoft MVP [VC], MCSD
email: agnic...@mvps.org
MVP VC FAQ: http://www.mvps.org/vcfaq
=====================================

"Snow" <filame...@hotmail.com> wrote in message
news:es$2fqWfG...@TK2MSFTNGP05.phx.gbl...

Snow

unread,
May 23, 2006, 11:51:50 PM5/23/06
to
Thanks for the detailed explaination but I'm not writing my own PS :P.
However its still a good piece of information :)

"Alexander Nickolov" <agnic...@mvps.org> wrote in message
news:ee3iHQdf...@TK2MSFTNGP02.phx.gbl...

Snow

unread,
May 24, 2006, 12:02:27 AM5/24/06
to
I tried your method but getting access violation. Not sure whether I'm doing it the right way or not.
 
typedef struct _tagTestStruct2Type
{
    DWORD dwSize;
    [size_is(dwSize)] BYTE* pData;
} TestStruct2Type;
 
typedef struct _tagMoreTestStructType
{
    DWORD dwData;
    LONG lData;
    INT iData;
} MoreTestStructType;
 
[helpstring("method GetStruct2")] HRESULT GetStruct2([out] TestStruct2Type** ppStruct);
 
STDMETHODIMP CTestStruct::GetStruct2(TestStruct2Type** ppStruct)
{
    ULONG ulSize = sizeof(TestStruct2Type) + sizeof(MoreTestStructType);
    *ppStruct = (TestStruct2Type*)CoTaskMemAlloc(ulSize);
    ZeroMemory(*ppStruct, ulSize);
 
    TestStruct2Type* pStruct2 = (TestStruct2Type*)*ppStruct;
    pStruct2->dwSize = ulSize;
 
    MoreTestStructType* pMore = (MoreTestStructType*)&pStruct2->pData;
    pMore->dwData = 0x5050;
    pMore->lData = 512;
    pMore->iData = 1024;
 
    return S_OK;
}
 
"Igor Tandetnik" <itand...@mvps.org> wrote in message news:O06bnfZf...@TK2MSFTNGP02.phx.gbl...

Igor Tandetnik

unread,
May 24, 2006, 8:32:54 AM5/24/06
to
"Snow" <filame...@hotmail.com> wrote in message
news:uogmgbuf...@TK2MSFTNGP05.phx.gbl

> I tried your method but getting access violation. Not sure whether
> I'm doing it the right way or not.
>
> typedef struct _tagTestStruct2Type
> {
> DWORD dwSize;
> [size_is(dwSize)] BYTE* pData;
> } TestStruct2Type;
>
> typedef struct _tagMoreTestStructType
> {
> DWORD dwData;
> LONG lData;
> INT iData;
> } MoreTestStructType;
>
> [helpstring("method GetStruct2")] HRESULT GetStruct2([out]
> TestStruct2Type** ppStruct);
>
> STDMETHODIMP CTestStruct::GetStruct2(TestStruct2Type** ppStruct)
> {
> ULONG ulSize = sizeof(TestStruct2Type) +
> sizeof(MoreTestStructType);
> *ppStruct = (TestStruct2Type*)CoTaskMemAlloc(ulSize);

No, that's not the way you do it. You have to use CoTaskMemAlloc to
allocate memory for TestStruct2Type structure alone, then a separate
CoTaskMemAlloc call to allocate a buffer and store it in
TestStruct2Type::pData. Set TestStruct2Type::dwSize to the size of this
latter buffer.

Alexander Nickolov

unread,
May 24, 2006, 1:53:11 PM5/24/06
to
Well, you asked for it :), it's certainly doable, only the effort
is a bit higher.

--
=====================================
Alexander Nickolov
Microsoft MVP [VC], MCSD
email: agnic...@mvps.org
MVP VC FAQ: http://www.mvps.org/vcfaq
=====================================

"Snow" <filame...@hotmail.com> wrote in message

news:eWewkVuf...@TK2MSFTNGP05.phx.gbl...

Reply all
Reply to author
Forward
0 new messages