472,127 Members | 1,728 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,127 software developers and data experts.

How to marshal unmanaged memory for IQueryInfo

Hi all,

I'm trying to write an InfoTip extension for my filetype in explorer
(running on WinXP & W2K). The interface IQueryInfo supports this
feature (with some help from IPersistFile), through the function call
GetInfoTip. GetInfoTip requires that you return a string for the
InfoTip that is allocated off of CoTaskMem, so that the calling
process (Explorer) can deallocate it.

I'm running into some conceptual trouble with implementing this in the
managed world.

I've used the following interface definition:
[ComImport(),
Guid("00021500-0000-0000-C000-000000000046"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown )]
public interface IQueryInfo
{
int GetInfoTip(
[In] int dwFlags,
[Out, MarshalAs(UnmanagedType.BStr)] out string ppwszTip);
int GetInfoFlags([Out] int pdwFlags);
}
I started by naively returning a string directly:
public int GetInfoTip(int dwFlags, out string ppwszTip)
{
Debug.WriteLine("ShellSupport.GetInfoTip(" + dwFlags + ")");
ppwszTip = "Hello world.";
return 0;
}
and while the infotip shows up briefly, the Explorer promptly crashes
(I assume because it is trying to de-allocate the string.)
So I _read_ the documentation and realized I probably should be doing
this instead:
public int GetInfoTip(int dwFlags, out string ppwszTip)
{
Debug.WriteLine("ShellSupport.GetInfoTip(" + dwFlags + ")");
ppwszTip = Marshal.StringToCoTaskMemAuto("Hello world.");
return 0;
}
but of course, ppwszTip is a *string*, not an *IntPtr*, so this won't
compile. If I change the second argument in the interface to
[Out, MarshalAs(UnmanagedType.BStr)] out IntPtr ppwszTip
then my function isn't entered at all (the COM signature is too
different?)

All told, I'm conceptually stuck, trying to figure out how to return a
..NET System.String that points to unmanaged memory. I don't think
that can be done, but I'm certain that a C# info tip _can_ be written.
What am I missing?

Any help appreciated,
Alan Bahm
ab***@feico.com
Nov 16 '05 #1
2 2972
Alan,
int GetInfoTip(
[In] int dwFlags,
[Out, MarshalAs(UnmanagedType.BStr)] out string ppwszTip);
int GetInfoFlags([Out] int pdwFlags);
}
The return types should be void, unless you really want to explicitly
return the HRESULT, in which case you should add the [PreserveSig]
attribute to the methods.

The string parameter should be an LPWSTR, not a BSTR, so use
UnmanagedType.LPWStr instead.

pdwFlags should be an out parameter. Note that out == [Out] ref, so
using only the [Out] attribute isn't enough.

and while the infotip shows up briefly, the Explorer promptly crashes
(I assume because it is trying to de-allocate the string.)
More likely because your method signatures are incorrect.

If I change the second argument in the interface to
[Out, MarshalAs(UnmanagedType.BStr)] out IntPtr ppwszTip
then my function isn't entered at all (the COM signature is too
different?)


That should work too if you remove the MarshalAs attribute. But the
runtime returns out strings in CoTaskMemAlloc'ed memory by default so
using a string should be easier.

Mattias

--
Mattias Sjögren [MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
Nov 16 '05 #2
Mattias,

Thank you very much! I didn't realize that the interop takes care of
the string allocation.
You were right - I went back over the signatures, and I got it working
after changing the int return value to void.

Best regards,
Alan
Nov 16 '05 #3

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.