all groups > dotnet interop > august 2006 >
You're in the

dotnet interop

group:

Returning COM Interface from Unmanaged DLL Function via PInvoke


Returning COM Interface from Unmanaged DLL Function via PInvoke jorfei
8/11/2006 2:54:02 AM
dotnet interop:
What is the marshaling behavior for a COM interface returned with an output
parameter from a function in an unmanaged DLL called via the Platform Invoke?
An example of this is the function

HRESULT CoGetMalloc(DWORD dwMemContext, LPMALLOC * ppMalloc);

or its declaration in C#

[System.Runtime.InteropServices.DllImport("ole32.dll")]
int CoGetMalloc(uint dwMemContext, out IMalloc ppMalloc);

I couldn't locate any information about this in the documentation of the
..NET Framework.

In particular, will the marshaling layer make one extra AddRef call on the
COM interface in addition to the original AddRef call in the implementation
of the function. The latter call, as you know, is required by the reference
counting rule of COM.

Thanks.
RE: Returning COM Interface from Unmanaged DLL Function via PInvoke jorfei
8/11/2006 3:01:02 AM
Correction, the declaration in C# should read

[System.Runtime.InteropServices.DllImport("ole32.dll")]
public static extern int CoGetMalloc(uint dwMemContext, out IMalloc ppMalloc);

Thanks.

[quoted text, click to view]
Re: Returning COM Interface from Unmanaged DLL Function via PInvoke TDC
8/11/2006 5:04:34 AM
I don't know the answer to your question, so I could be way off here.
But I wonder if it matters considering that your .NET code will utilize
the RCW for the COM object, and the RCW will make sure the COM object
won't go out-of-scope (get released) as long as the wrapper itself is
reachable. (In fact, people generally have the opposite problem...that
their COM objects live *longer* than they intended).

Tom

[quoted text, click to view]
Re: Returning COM Interface from Unmanaged DLL Function via PInvok jorfei
8/11/2006 10:47:01 AM
It is exactly with this opposite effect that I'm concerned. If the marshaling
layer has called AddRef on the COM interface returned, it means when the RCW
is garbage-collected, the corresponding COM object will not be destroyed. The
reference counting rule of COM requires that the callee (i.e. the
implementation) returning the COM interface to increment the reference count
so that the caller needs only to call Release on the COM interface when the
COM interface is no longer required.

Thanks.

[quoted text, click to view]
Re: Returning COM Interface from Unmanaged DLL Function via PInvok v-phuang NO[at]SPAM online.microsoft.com (
8/14/2006 12:00:00 AM
Hi,

Currently I am researching the issue, and I will update you ASAP.
BTW: In .NET, we have a method Marshal.AllocCoTaskMem which will do the
same job, did you have any concern to use it directly?

Best regards,

Peter Huang

Microsoft Online Community Support
==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
Re: Returning COM Interface from Unmanaged DLL Function via PInvok jorfei
8/14/2006 2:51:01 AM
Hi Peter,

I'm aware of that. I'm just quoting this function as an example. Thanks.

Best regards,
jorfei

[quoted text, click to view]
Re: Returning COM Interface from Unmanaged DLL Function via PInvok TDC
8/14/2006 10:58:53 AM
Do you have any reason to believe that .NET interop will behave
incorrectly in this manner?

It seems like it should be a simple thing to test the behavior one way
or the other. If I get a chance I'll do so and post my results.

Good luck,
Tom

[quoted text, click to view]
Re: Returning COM Interface from Unmanaged DLL Function via PInvok v-phuang NO[at]SPAM online.microsoft.com (
8/16/2006 12:00:00 AM
Hi Jorfei,

So far I am still researching the issue and I will update you with new
information ASAP.
Thanks for your understanding, please feel free to let me know.


Best regards,

Peter Huang

Microsoft Online Community Support
==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
Re: Returning COM Interface from Unmanaged DLL Function via PInvok v-phuang NO[at]SPAM online.microsoft.com (
8/21/2006 12:00:00 AM
Hi Jorfei,

Sorry for delay response, because the concrete implement of .NET 2.0 CLR is
not public, and based on my research I did not find information about the
detailed implement detailed.

But from the sample from the code project we should call the
Marshal.ReleaseComObject to release the IntPtr from P/Invoke.
http://www.codeproject.com/csharp/csdoesshell1.asp

http://dotnetdebug.blogspot.com/2005/07/marshalreleasecomobject-and-cpu.html

Also I do recommend you call Marshal.ReleaseComObject to explicitly release
a com object when you will not use the COM any longer.

If you have any concern, please feel free to let me know.

Best regards,

Peter Huang

Microsoft Online Community Support
==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
Re: Returning COM Interface from Unmanaged DLL Function via PInvok jorfei
12/22/2006 11:27:00 AM
Hi Peter,

I check through the code in
http://www.codeproject.com/csharp/csdoesshell1.asp and doubt that it is
entirely correct. In the code SHGetMalloc is declared as below:

[DllImport("shell32.dll")]
public static extern Int32 SHGetMalloc(out IntPtr hObject);

Without further qualification, how could the runtime know that hObject is an
interface pointer and know how to release it properly after use? Indeed this
is where the author of the article has missed. Marshal.ReleaseComObject only
releases the interface pointer up to the point where
Marshal.GetTypedObjectForIUnknown is called and a call to Marshal.Release is
required to fully release the interface pointer:

Marshal.Release(hObject);

I have written simple COM servers to research further on returning COM
interface from an unmanaged DLL via PInvoke. For the benefit of other
readers, the outcome of my research follows.

Using SHGetMalloc as an example, the following three methods are equally
correct way of getting an interface pointer via PInvoke and properly
releasing it after use (error handling has been omitted).

Method 1:
[DllImport("shell32.dll")]
public static extern int SHGetMalloc(out IMalloc pMalloc);

IMalloc pMalloc;
SHGetMalloc(out pMalloc);
// Do something useful with pMalloc here
Marshal.ReleaseComObject(pMalloc);
// Calling Marshal.ReleaseComObject is optional
// If it is not called, the runtime will release pMalloc when it is garbage
collected

Method 2:
[DllImport("shell32.dll")]
public static extern int SHGetMalloc(out IntPtr malloc);

IntPtr malloc;
SHGetMalloc(out malloc);
IMalloc pMalloc = (IMalloc)Marshal.GetObjectForIUnknown(malloc);
// Do something useful with pMalloc here
Marshal.ReleaseComObject(pMalloc);
// Calling Marshal.ReleaseComObject is optional
// If it is not called, the runtime will release pMalloc when it is garbage
collected
Marshal.Release(malloc);

Method 3:
[DllImport("shell32.dll")]
public static extern int SHGetMalloc([MarshalAs(UnmanagedType.Interface)]
out object malloc);

object malloc;
SHGetMalloc(out malloc);
IMalloc pMalloc = (IMalloc)malloc;
// Do something useful with pMalloc here
Marshal.ReleaseComObject(pMalloc);
// Equivalently Marshal.ReleaseComObject(malloc);
// Calling Marshal.ReleaseComObject is optional
// If it is not called, the runtime will release pMalloc / malloc
// when it is garbage collected

Thanks.

Best regards,
jorfei

[quoted text, click to view]
Re: Returning COM Interface from Unmanaged DLL Function via PInvok v-phuang NO[at]SPAM online.microsoft.com (
12/25/2006 12:00:00 AM
Hi Jorfei,

Thanks for your knowledge sharing.
If you still have any concern, please feel free to post in the newsgroup.

Best regards,

Perter Huang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
AddThis Social Bookmark Button