Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / .NET Framework / Interop / April 2004

Tip: Looking for answers? Try searching our database.

IDataObject Marshalling

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Abh Khush - 15 Apr 2004 06:21 GMT
Resending:

Hi,

I am writing a .Net wrapper for the MS object picker, but I am
running into a marshalling problem.

I am having trouble retrieving data returned after selecting users and
clicking OK. When I call the dataObj.GetData (...) it returns a handle
inside STGMEDIUM that is invalid. The GetLastWin32Error returns an
Error Code 6. (ERROR_INVALID_HANDLE)

Please see code below.

Ill appreciate any input on this issue.

Thanks in advance,
Abhinav

/**********************************************
This is code to extract the data
***********************************************/
       private string ProcessSelectedObjects (IDataObject dataObj)
       {
           STGMEDIUM stg = new STGMEDIUM ();
           stg.tymed = (uint) TYMED.TYMED_HGLOBAL;
           stg.pUnkForRelease = null;
           stg.hGlobal = IntPtr.Zero;

           FORMATETC fetc = new FORMATETC ();
           fetc.cfFormat = PInvoke.RegisterClipboardFormat
(CLIPBOARD_FORMAT.CFSTR_DSOP_DS_SELECTION_LIST);
           fetc.ptd = 0;
           fetc.dwAspect = (uint) DVASPECT.DVASPECT_CONTENT;
           fetc.lindex = -1;
           fetc.tymed = (uint) TYMED.TYMED_HGLOBAL;

           int hr = dataObj.GetData (ref fetc, ref stg);

           if (hr != HRESULT.S_OK)
           {
               //error
           }

           int error = 0;
           
           IntPtr ptr = PInvoke.GlobalLock(stg.hGlobal);

           if (ptr == IntPtr.Zero)
           {
               error = Marshal.GetLastWin32Error ();
           }

           PInvoke.GlobalUnlock(ptr);
       }

/*********************************
These are the structures
**********************************/
  /* Interfaces */
   [
   ComImport,
   CLSCompliant(false),
   Guid("0000010e-0000-0000-C000-000000000046"),
   InterfaceType(ComInterfaceType.InterfaceIsIUnknown)
   ]
   public interface IDataObject
   {
       [PreserveSig ()]
       int GetData(ref FORMATETC pFormatEtc, ref STGMEDIUM b);

       void GetDataHere(ref FORMATETC pFormatEtc, ref STGMEDIUM b);

       [PreserveSig()]
       int QueryGetData(IntPtr a);

       [PreserveSig()]
       int GetCanonicalFormatEtc(IntPtr a, IntPtr b);

       [PreserveSig()]
       int SetData(IntPtr a, IntPtr b, int c);

       [PreserveSig()]
       int EnumFormatEtc(uint a, IntPtr b);

       [PreserveSig()]
       int DAdvise(IntPtr a, uint b, IntPtr c, ref uint d);

       [PreserveSig()]
       int DUnadvise(uint a);

       [PreserveSig()]
       int EnumDAdvise(IntPtr a);
   }

   [
   CLSCompliant(false),
   StructLayout(LayoutKind.Sequential)
   ]
   public struct FORMATETC
   {
       public int cfFormat;
       public int ptd;
       public uint dwAspect;
       public int lindex;
       public uint tymed;
   }

   [
   CLSCompliant(false),
   StructLayout(LayoutKind.Sequential)
   ]
   public struct STGMEDIUM
   {
       public uint tymed;
       public IntPtr hGlobal;
       public Object pUnkForRelease;
   }

/********************************************
Call to INvokeDialog
********************************************/
       public override string InvokeDialog (IntPtr handle)
       {
           IDsObjectPicker idop = null;
           idop = Initialize ();

           IDataObject dataObj = null;
           idop.InvokeDialog(handle, out dataObj);

           //have to process dataObj and return SID string
           return ProcessSelectedObjects (dataObj);
       }
Mattias Sj?gren - 15 Apr 2004 13:14 GMT
>I am writing a .Net wrapper for the MS object picker, but I am
>running into a marshalling problem.
[quoted text clipped - 7 lines]
>
>Ill appreciate any input on this issue.

Your code looks find to me. I could take it, fill in the missing
pieces and it worked great here. So I'm not sure why it fails for you.

To be fully correct, you should change FORMATETC.cfFormat to a
(u)short and probably tag STGMEDIUM.pUnkForRelease with
[MarshalAs(UnmanagedType.IUnknown)]. But I don't think any of these
will fix your problem.

What does your code in Initialize look like? Are you sure that
IDsObjectPicker.Initialize succeeds? What's the actual value of
stg.hGlobal after the GetData call? Have you tried calling
IDataObject.QueryGetData?

Mattias

Signature

Mattias Sjögren [MVP]  mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.

Abh Khush - 15 Apr 2004 20:19 GMT
HI Mattias,

Thanks for the reply.

In the Initialize method I am setting the objectSid which is what seems
to be causing my IDataObject.GetData to fail. If I set
initInfo.cAttributesToFetch = 0 then I am able to retrieve the STGMEDIUM
successfully and am able read the Name and the AdsPath. So it looks like
I am not setting the initInfo.apwzAttributeNames correctly to be
interpreted as WCHAR* array[].

So, the question now is how does one pass an array of strings inside a
structure from .net to COM so that it is interpreted correctly.

BTW, www.dotnetinterop.com stuff is good work.

Thanks,
Abhinav

/***********Snippet of Initialize
           // Init DSOP_INIT_INFO

           IntPtr refScopeInitInfo = Marshal.AllocHGlobal
(Marshal.SizeOf (typeof (DSOP_SCOPE_INIT_INFO)) * 2);
           Marshal.StructureToPtr (scopeInitInfo[0], refScopeInitInfo,
true);
           Marshal.StructureToPtr (scopeInitInfo[1],
               (IntPtr) ((int) refScopeInitInfo + Marshal.SizeOf
(typeof (DSOP_SCOPE_INIT_INFO))),
               true);

           string attrName = "objectSid";
           IntPtr refAttrName = Marshal.StringToHGlobalUni (attrName);

           DSOP_INIT_INFO initInfo = new DSOP_INIT_INFO ();
           initInfo.cbSize = (uint) Marshal.SizeOf (initInfo);
           initInfo.pwzTargetComputer = "";
           initInfo.cDsScopeInfos = 2;
           initInfo.aDsScopeInfos = refScopeInitInfo;
           initInfo.flOptions =
               DSOP_INIT_INFO_FLAGS.DSOP_FLAG_MULTISELECT;
           initInfo.cAttributesToFetch = 1;
           initInfo.apwzAttributeNames = refAttrName;

           idop.Initialize (ref initInfo);
*********End snipped of initialize************/
Abhinav Khushraj - 17 Apr 2004 03:02 GMT
HI Mattias,

Thanks for the reply.

In the Initialize method I am setting the objectSid which
is what seems
to be causing my IDataObject.GetData to fail. If I set
initInfo.cAttributesToFetch = 0 then I am able to
retrieve the STGMEDIUM
successfully and am able read the Name and the AdsPath.
So it looks like
I am not setting the initInfo.apwzAttributeNames
correctly to be
interpreted as WCHAR* array[].

So, the question now is how does one pass an array of
strings inside a
structure from .net to COM so that it is interpreted
correctly.

BTW, www.dotnetinterop.com stuff is good work.

Thanks,
Abhinav

/***********Snippet of Initialize
// Init DSOP_INIT_INFO

IntPtr refScopeInitInfo = Marshal.AllocHGlobal
(Marshal.SizeOf (typeof (DSOP_SCOPE_INIT_INFO)) * 2);
Marshal.StructureToPtr (scopeInitInfo[0],
refScopeInitInfo,
true);
Marshal.StructureToPtr (scopeInitInfo[1],
(IntPtr) ((int) refScopeInitInfo + Marshal.SizeOf
(typeof (DSOP_SCOPE_INIT_INFO))),
true);

string attrName = "objectSid";
IntPtr refAttrName = Marshal.StringToHGlobalUni
(attrName);

DSOP_INIT_INFO initInfo = new DSOP_INIT_INFO ();
initInfo.cbSize = (uint) Marshal.SizeOf (initInfo);
initInfo.pwzTargetComputer = "";
initInfo.cDsScopeInfos = 2;
initInfo.aDsScopeInfos = refScopeInitInfo;
initInfo.flOptions =
DSOP_INIT_INFO_FLAGS.DSOP_FLAG_MULTISELECT;
initInfo.cAttributesToFetch = 1;
initInfo.apwzAttributeNames = refAttrName;

idop.Initialize (ref initInfo);
*********End snipped of initialize************/

Rate this thread:







Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.