2007-11-13 Everaldo Canuto <ecanuto@novell.com>
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / Win32DnD.cs
1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
8 // 
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
11 // 
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19 //
20 // Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
21 //
22 // Authors:
23 //      Peter Bartok    (pbartok@novell.com)
24 //      Srikanth Madikeri       (csri_1986@yahoo.com) - Win32 Drop files.
25 // 
26
27 // NOT COMPLETE
28
29 using System;
30 using System.Collections;
31 using System.Drawing;
32 using System.Reflection;
33 using System.Reflection.Emit;
34 using System.Runtime.InteropServices;
35 using System.Runtime.Serialization;
36 using System.Text;
37
38 namespace System.Windows.Forms {
39         internal class Win32DnD {
40                 #region Local Variables
41                 private const uint DATADIR_GET                  = 1;
42                 private const uint S_OK                         = 0x00000000;
43                 private const uint S_FALSE                      = 0x00000001;
44                 private const uint DRAGDROP_S_DROP              = 0x00040100;
45                 private const uint DRAGDROP_S_CANCEL            = 0x00040101;
46                 private const uint DRAGDROP_S_USEDEFAULTCURSORS = 0x00040102;
47                 private const uint E_NOTIMPL                    = unchecked((uint)0x80004001);
48                 private const uint E_NOINTERFACE                = unchecked((uint)0x80004002);
49                 private const uint E_FAIL                       = unchecked((uint)0x80004005);
50                 private const uint OLE_E_ADVISENOTSUPPORTED     = unchecked((uint)0x80040003);
51                 private const uint DV_E_FORMATETC               = unchecked((uint)0x80040064);
52
53                 // To call function pointers
54                 //private static object[]                               GetDataArgs;
55
56                 // IDataObject Delegates
57                 private static QueryInterfaceDelegate           DOQueryInterface;
58                 private static AddRefDelegate                   DOAddRef;
59                 private static ReleaseDelegate                  DORelease;
60                 private static GetDataDelegate                  GetData;
61                 private static GetDataHereDelegate              GetDataHere;
62                 private static QueryGetDataDelegate             QueryGetData;
63                 private static GetCanonicalFormatEtcDelegate    GetCanonicalFormatEtc;
64                 private static SetDataDelegate                  SetData;
65                 private static EnumFormatEtcDelegate            EnumFormatEtc;
66                 private static DAdviseDelegate                  DAdvise;
67                 private static DUnadviseDelegate                DUnadvise;
68                 private static EnumDAdviseDelegate              EnumDAdvise;
69
70                 // IDropSource Delegates
71                 private static QueryInterfaceDelegate           DSQueryInterface;
72                 private static AddRefDelegate                   DSAddRef;
73                 private static ReleaseDelegate                  DSRelease;
74                 private static QueryContinueDragDelegate        QueryContinueDrag;
75                 private static GiveFeedbackDelegate             GiveFeedback;
76
77                 // IDropTarget Delegates
78                 private static QueryInterfaceDelegate           DTQueryInterface;
79                 private static AddRefDelegate                   DTAddRef;
80                 private static ReleaseDelegate                  DTRelease;
81                 private static DragEnterDelegate                DragEnter;
82                 private static DragOverDelegate                 DragOver;
83                 private static DragLeaveDelegate                DragLeave;
84                 private static DropDelegate                     Drop;
85
86                 private static DragEventArgs                    DragDropEventArgs;
87                 private static GiveFeedbackEventArgs            DragFeedbackEventArgs;
88                 private static QueryContinueDragEventArgs       DragContinueEventArgs;
89                 private static ArrayList                        DragFormats;
90                 private static FORMATETC[]                      DragFormatArray;
91                 private static ArrayList                        DragMediums;
92                 #endregion      // Local Variables
93
94                 #region Delegate Definitions
95                 // IUnknown
96                 internal delegate uint QueryInterfaceDelegate(IntPtr @this, ref Guid riid, IntPtr ppvObject);
97                 internal delegate uint AddRefDelegate(IntPtr @this);
98                 internal delegate uint ReleaseDelegate(IntPtr @this);
99
100                 // IDataObject
101                 internal delegate uint GetDataDelegate(IntPtr @this, ref FORMATETC pformatetcIn, IntPtr pmedium);
102                 internal delegate uint GetDataHereDelegate(IntPtr @this, ref FORMATETC pformatetc, ref STGMEDIUM pmedium);
103                 internal delegate uint QueryGetDataDelegate(IntPtr @this, ref FORMATETC pformatetc);
104                 internal delegate uint GetCanonicalFormatEtcDelegate(IntPtr @this, ref FORMATETC pformatetcIn, IntPtr pformatetcOut);
105                 internal delegate uint SetDataDelegate(IntPtr @this, ref FORMATETC pformatetc, ref STGMEDIUM pmedium, bool release);
106                 internal delegate uint EnumFormatEtcDelegate(IntPtr @this, uint direction, IntPtr ppenumFormatEtc);
107                 internal delegate uint DAdviseDelegate(IntPtr @this, ref FORMATETC pformatetc, uint advf, IntPtr pAdvSink, ref uint pdwConnection);
108                 internal delegate uint DUnadviseDelegate(IntPtr @this, uint pdwConnection);
109                 internal delegate uint EnumDAdviseDelegate(IntPtr @this, IntPtr ppenumAdvise);
110
111                 // IDropSource
112                 internal delegate uint QueryContinueDragDelegate(IntPtr @this, bool fEscapePressed, uint grfkeyState);
113                 internal delegate uint GiveFeedbackDelegate(IntPtr @this, uint pdwEffect);
114
115                 // IDropTarget
116                 internal delegate uint DragEnterDelegate(IntPtr @this, IntPtr pDataObj, uint grfkeyState, IntPtr pt_x, IntPtr pt_y, IntPtr pdwEffect);
117                 internal delegate uint DragOverDelegate(IntPtr @this, uint grfkeyState, IntPtr pt_x, IntPtr pt_y, IntPtr pdwEffect);
118                 internal delegate uint DragLeaveDelegate(IntPtr @this);
119                 internal delegate uint DropDelegate(IntPtr @this, IntPtr pDataObj, uint grfkeyState, IntPtr pt_x, IntPtr pt_y, IntPtr pdwEffect);
120                 #endregion      // Delegate Definitions
121
122                 [StructLayout(LayoutKind.Sequential)]
123                         internal struct FORMATETC {
124                         [MarshalAs(UnmanagedType.U2)]
125                         internal ClipboardFormats       cfFormat;
126                         internal IntPtr                 ptd;
127                         internal DVASPECT               dwAspect;
128                         internal int                    lindex;
129                         internal TYMED                  tymed;
130                 }
131
132                 [StructLayout(LayoutKind.Sequential)]
133                 internal struct STGMEDIUM {
134                         internal TYMED          tymed;
135                         internal IntPtr         hHandle;
136                         internal IntPtr         pUnkForRelease;
137                 }
138
139                 [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
140                 internal struct DROPFILES { 
141                         internal uint           pFiles;
142                         internal uint           pt_x;
143                         internal uint           pt_y;
144                         internal bool           fNC;
145                         internal bool           fWide;
146                         internal string         pText;
147                 }
148
149                 internal enum DVASPECT {
150                         DVASPECT_CONTENT        = 1,
151                         DVASPECT_THUMBNAIL      = 2,
152                         DVASPECT_ICON           = 4,
153                         DVASPECT_DOCPRINT       = 8
154                 }
155
156                 internal enum TYMED {
157                         TYMED_HGLOBAL           = 1,
158                         TYMED_FILE              = 2,
159                         TYMED_ISTREAM           = 4,
160                         TYMED_ISTORAGE          = 8,
161                         TYMED_GDI               = 16,
162                         TYMED_MFPICT            = 32,
163                         TYMED_ENHMF             = 64,
164                         TYMED_NULL              = 0
165                 }
166
167                 private static readonly Guid IID_IUnknown = new Guid("00000000-0000-0000-C000-000000000046");
168                 private static readonly Guid IID_IDataObject = new Guid("0000010e-0000-0000-C000-000000000046");
169                 private static readonly Guid IID_IDropSource = new Guid("00000121-0000-0000-C000-000000000046");
170                 private static readonly Guid IID_IDropTarget = new Guid("00000122-0000-0000-C000-000000000046");
171
172                 static Win32DnD()
173                 {
174                         // Required for all other OLE functions to work
175                         Win32OleInitialize(IntPtr.Zero);
176
177                         // We reuse those
178                         DragDropEventArgs = new DragEventArgs(new DataObject(DataFormats.FileDrop, new string[0]), 0, 0, 0, DragDropEffects.None, DragDropEffects.None);
179                         DragFeedbackEventArgs = new GiveFeedbackEventArgs(DragDropEffects.None, true);
180                         DragContinueEventArgs = new QueryContinueDragEventArgs(0, false, DragAction.Continue);
181                         DragFormats = new ArrayList();
182                         DragFormatArray = new FORMATETC[0];
183                         DragMediums = new ArrayList();
184
185                         // Set up delegates
186                         // IDataObject
187                         DOQueryInterface = new QueryInterfaceDelegate(ComIDataObject.QueryInterface);
188                         DOAddRef = new AddRefDelegate(ComIDataObject.AddRef);
189                         DORelease = new ReleaseDelegate(ComIDataObject.Release);
190                         GetData = new GetDataDelegate(ComIDataObject.GetData);
191                         GetDataHere = new GetDataHereDelegate(ComIDataObject.GetDataHere);
192                         QueryGetData = new QueryGetDataDelegate(ComIDataObject.QueryGetData);
193                         GetCanonicalFormatEtc = new GetCanonicalFormatEtcDelegate(ComIDataObject.GetCanonicalFormatEtc);
194                         SetData = new SetDataDelegate(ComIDataObject.SetData);
195                         EnumFormatEtc = new EnumFormatEtcDelegate(ComIDataObject.EnumFormatEtc);
196                         DAdvise = new DAdviseDelegate(ComIDataObject.DAdvise);
197                         DUnadvise = new DUnadviseDelegate(ComIDataObject.DUnadvise);
198                         EnumDAdvise = new EnumDAdviseDelegate(ComIDataObject.EnumDAdvise);
199
200                         // IDropSource
201                         DSQueryInterface = new QueryInterfaceDelegate(ComIDropSource.QueryInterface);
202                         DSAddRef = new AddRefDelegate(ComIDropSource.AddRef);
203                         DSRelease = new ReleaseDelegate(ComIDropSource.Release);
204                         QueryContinueDrag = new QueryContinueDragDelegate(ComIDropSource.QueryContinueDrag);
205                         GiveFeedback = new GiveFeedbackDelegate(ComIDropSource.GiveFeedback);
206
207                         // IDropTarget
208                         DTQueryInterface = new QueryInterfaceDelegate(ComIDropTarget.QueryInterface);
209                         DTAddRef = new AddRefDelegate(ComIDropTarget.AddRef);
210                         DTRelease = new ReleaseDelegate(ComIDropTarget.Release);
211                         DragEnter = new DragEnterDelegate(ComIDropTarget.DragEnter);
212                         DragOver = new DragOverDelegate(ComIDropTarget.DragOver);
213                         DragLeave = new DragLeaveDelegate(ComIDropTarget.DragLeave);
214                         Drop = new DropDelegate(ComIDropTarget.Drop);
215                 }
216
217                 internal class ComIDataObject {
218                         [StructLayout(LayoutKind.Sequential)]
219                         internal struct DataObjectStruct {
220                                 internal IntPtr                         vtbl;
221                                 internal QueryInterfaceDelegate         QueryInterface;
222                                 internal AddRefDelegate                 AddRef;
223                                 internal ReleaseDelegate                Release;
224                                 internal GetDataDelegate                GetData;
225                                 internal GetDataHereDelegate            GetDataHere;
226                                 internal QueryGetDataDelegate           QueryGetData;
227                                 internal GetCanonicalFormatEtcDelegate  GetCanonicalFormatEtc;
228                                 internal SetDataDelegate                SetData;
229                                 internal EnumFormatEtcDelegate          EnumFormatEtc;
230                                 internal DAdviseDelegate                DAdvise;
231                                 internal DUnadviseDelegate              DUnadvise;
232                                 internal EnumDAdviseDelegate            EnumDAdvise;
233                         }
234
235                         internal static IntPtr GetUnmanaged() {
236                                 DataObjectStruct        data_object;
237                                 IntPtr                  data_object_ptr;
238                                 long                    offset;
239
240                                 data_object = new DataObjectStruct();
241
242                                 data_object.QueryInterface = Win32DnD.DOQueryInterface;
243                                 data_object.AddRef = Win32DnD.DOAddRef;
244                                 data_object.Release = Win32DnD.DORelease;
245                                 data_object.GetData = Win32DnD.GetData;
246                                 data_object.GetDataHere = Win32DnD.GetDataHere;
247                                 data_object.QueryGetData = Win32DnD.QueryGetData;
248                                 data_object.GetCanonicalFormatEtc = Win32DnD.GetCanonicalFormatEtc;
249                                 data_object.SetData = Win32DnD.SetData;
250                                 data_object.EnumFormatEtc = Win32DnD.EnumFormatEtc;
251                                 data_object.DAdvise = Win32DnD.DAdvise;
252                                 data_object.DUnadvise = Win32DnD.DUnadvise;
253                                 data_object.EnumDAdvise = Win32DnD.EnumDAdvise;
254
255                                 data_object_ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(DataObjectStruct)));
256                                 Marshal.StructureToPtr(data_object, data_object_ptr, false);
257
258                                 // Update vtbl pointer
259                                 offset = data_object_ptr.ToInt64();
260                                 offset += Marshal.SizeOf(typeof(IntPtr));
261                                 Marshal.WriteIntPtr(data_object_ptr, new IntPtr(offset));
262                                 
263                                 return data_object_ptr;
264                         }
265
266                         internal static void ReleaseUnmanaged(IntPtr data_object_ptr) {
267                                 Marshal.FreeHGlobal(data_object_ptr);
268                         }
269
270                         internal static uint QueryInterface(IntPtr @this, ref Guid riid, IntPtr ppvObject) {
271                                 try {
272                                         if (IID_IUnknown.Equals(riid) || IID_IDataObject.Equals(riid)) {
273                                                 Marshal.WriteIntPtr(ppvObject, @this);
274                                                 return S_OK;
275                                         }
276                                 }
277
278                                 catch (Exception e) {
279                                         Console.WriteLine("Got exception {0}", e.Message);
280                                 }
281
282                                 Marshal.WriteIntPtr(ppvObject, IntPtr.Zero);
283                                 return E_NOINTERFACE;
284                         }
285
286                         internal static uint AddRef(IntPtr @this) {
287                                 // We only use this for DnD, try and fake it
288                                 return 1;
289                         }
290
291                         internal static uint Release(IntPtr @this) {
292                                 // We only use this for DnD, try and fake it
293                                 return 0;
294                         }
295
296                         internal static         STGMEDIUM       medium = new STGMEDIUM();
297                         internal static uint GetData(IntPtr this_, ref FORMATETC pformatetcIn, IntPtr pmedium) {
298                                 int             index;
299
300                                 index = FindFormat(pformatetcIn);
301                                 if (index != -1) {
302                                         medium.tymed = TYMED.TYMED_HGLOBAL;
303                                         medium.hHandle = XplatUIWin32.DupGlobalMem(((STGMEDIUM)DragMediums[index]).hHandle);
304                                         medium.pUnkForRelease = IntPtr.Zero;
305                                         try {
306                                                 Marshal.StructureToPtr(medium, pmedium, false);
307                                         }
308                                         catch (Exception e) {
309                                                 Console.WriteLine("Error: {0}", e.Message);
310                                         }
311                                         return S_OK;
312                                 }
313
314                                 return DV_E_FORMATETC;
315                         }
316
317                         internal static uint GetDataHere(IntPtr @this, ref FORMATETC pformatetc, ref STGMEDIUM pmedium) {
318                                 return DV_E_FORMATETC;
319                         }
320
321                         internal static uint QueryGetData(IntPtr @this, ref FORMATETC pformatetc) {
322                                 if (FindFormat(pformatetc) != -1) {
323                                         return S_OK;
324                                 }
325                                 return DV_E_FORMATETC;
326                         }
327
328                         internal static uint GetCanonicalFormatEtc(IntPtr @this, ref FORMATETC pformatetcIn, IntPtr pformatetcOut) {
329                                 Marshal.WriteIntPtr(pformatetcOut, Marshal.SizeOf(typeof(IntPtr)), IntPtr.Zero);
330                                 return E_NOTIMPL;
331                         }
332
333                         internal static uint SetData(IntPtr this_, ref FORMATETC pformatetc, ref STGMEDIUM pmedium, bool release) {
334                                 return E_NOTIMPL;
335                         }
336
337                         internal static uint EnumFormatEtc(IntPtr this_, uint direction, IntPtr ppenumFormatEtc) {
338                                 if (direction == DATADIR_GET) {
339                                         IntPtr  ppenum_ptr;
340
341                                         ppenum_ptr = IntPtr.Zero;
342                                         DragFormatArray = new FORMATETC[DragFormats.Count];
343
344                                         for (int i = 0; i < DragFormats.Count; i++) {
345                                                 DragFormatArray[i] = (FORMATETC)DragFormats[i];
346                                         }
347                                         Win32SHCreateStdEnumFmtEtc((uint)DragFormatArray.Length, DragFormatArray, ref ppenum_ptr);
348                                         Marshal.WriteIntPtr(ppenumFormatEtc, ppenum_ptr);
349                                         return S_OK;
350                                 }
351                                 return E_NOTIMPL;
352                         }
353
354                         internal static uint DAdvise(IntPtr this_, ref FORMATETC pformatetc, uint advf, IntPtr pAdvSink, ref uint pdwConnection) {
355                                 return OLE_E_ADVISENOTSUPPORTED;
356                         }
357
358                         internal static uint DUnadvise(IntPtr this_, uint pdwConnection) {
359                                 return OLE_E_ADVISENOTSUPPORTED;
360                         }
361
362                         internal static uint EnumDAdvise(IntPtr this_, IntPtr ppenumAdvise) {
363                                 return OLE_E_ADVISENOTSUPPORTED;
364                         }
365                 }
366
367                 internal class ComIDataObjectUnmanaged {
368                         [StructLayout(LayoutKind.Sequential)]
369                                 internal struct IDataObjectUnmanaged {
370                                 internal IntPtr         QueryInterface;
371                                 internal IntPtr         AddRef;
372                                 internal IntPtr         Release;
373                                 internal IntPtr         GetData;
374                                 internal IntPtr         GetDataHere;
375                                 internal IntPtr         QueryGetData;
376                                 internal IntPtr         GetCanonicalFormatEtc;
377                                 internal IntPtr         SetData;
378                                 internal IntPtr         EnumFormatEtc;
379                                 internal IntPtr         DAdvise;
380                                 internal IntPtr         DUnadvise;
381                                 internal IntPtr         EnumDAdvise;
382                         }
383
384                         private static bool             Initialized;
385                         private static MethodInfo       GetDataMethod;
386                         //private static MethodInfo     GetDataHereMethod;
387                         private static MethodInfo       QueryGetDataMethod;
388                         //private static MethodInfo     GetCanonicalFormatEtcMethod;
389                         //private static MethodInfo     SetDataMethod;
390                         //private static MethodInfo     EnumFormatEtcMethod;
391                         //private static MethodInfo     DAdviseMethod;
392                         //private static MethodInfo     DUnadviseMethod;
393                         //private static MethodInfo     EnumDAdviseMethod;
394                         private static object[]         MethodArguments;
395
396                         private IDataObjectUnmanaged    vtbl;
397                         private IntPtr                  @this;
398
399                         internal ComIDataObjectUnmanaged(IntPtr data_object_ptr) {
400                                 if (!Initialized) {
401                                         Initialize();
402                                 }
403
404                                 vtbl = new IDataObjectUnmanaged();
405                                 @this = data_object_ptr;
406                                 try {
407                                         vtbl = (IDataObjectUnmanaged)Marshal.PtrToStructure(Marshal.ReadIntPtr(data_object_ptr), typeof(IDataObjectUnmanaged));
408                                 }
409
410                                 catch (Exception e) {
411                                         Console.WriteLine("Exception {0}", e.Message);
412                                 }
413                         }
414
415                         private static void Initialize() {
416                                 AssemblyName    assembly;
417                                 AssemblyBuilder assembly_builder;
418
419                                 if (Initialized) {
420                                         return;
421                                 }
422
423                                 assembly = new AssemblyName();
424                                 assembly.Name = "XplatUIWin32.FuncPtrInterface";
425                                 assembly_builder = AppDomain.CurrentDomain.DefineDynamicAssembly(assembly, AssemblyBuilderAccess.Run);
426
427                                 MethodArguments = new object[6];
428                                 GetDataMethod = CreateFuncPtrInterface(assembly_builder, "GetData", typeof(uint), 3);
429                                 //GetDataHereMethod = CreateFuncPtrInterface(assembly_builder, "GetDataHere", typeof(uint), 3);
430                                 QueryGetDataMethod = CreateFuncPtrInterface(assembly_builder, "QueryGetData", typeof(uint), 2);
431                                 //GetCanonicalFormatEtcMethod = CreateFuncPtrInterface(assembly_builder, "GetCanonicalFormatEtc", typeof(uint), 3);
432                                 //SetDataMethod = CreateFuncPtrInterface(assembly_builder, "SetData", typeof(uint), 4);
433                                 //EnumFormatEtcMethod = CreateFuncPtrInterface(assembly_builder, "EnumFormatEtc", typeof(uint), 3);
434                                 //DAdviseMethod = CreateFuncPtrInterface(assembly_builder, "DAdvise", typeof(uint), 5);
435                                 //DUnadviseMethod = CreateFuncPtrInterface(assembly_builder, "DUnadvise", typeof(uint), 2);
436                                 //EnumDAdviseMethod = CreateFuncPtrInterface(assembly_builder, "EnumDAdvise", typeof(uint), 2);
437
438                                 Initialized = true;
439                         }
440
441                         internal uint QueryInterface(Guid riid, IntPtr ppvObject) {
442                                 uint    ret;
443                                 IntPtr  riid_ptr;
444
445                                 riid_ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Guid)));
446                                 Marshal.StructureToPtr(riid, riid_ptr, false);
447
448                                 MethodArguments[0] = vtbl.QueryInterface;
449                                 MethodArguments[1] = this.@this;
450                                 MethodArguments[2] = riid_ptr;
451                                 MethodArguments[3] = ppvObject;
452
453                                 try {
454                                         ret = (uint)GetDataMethod.Invoke(null, MethodArguments);
455                                 }
456
457                                 catch (Exception e) {
458                                         Console.WriteLine("Caught exception {0}", e.Message);
459                                         ret = E_FAIL;
460                                 }
461
462                                 Marshal.FreeHGlobal(riid_ptr);
463
464                                 return ret;
465                         }
466
467                         internal uint AddRef() {
468                                 // We only use this for DnD, try and fake it
469                                 return 1;
470                         }
471
472                         internal uint Release() {
473                                 // We only use this for DnD, try and fake it
474                                 return 0;
475                         }
476
477                         internal uint GetData(FORMATETC pformatetcIn, ref STGMEDIUM pmedium) {
478                                 uint    ret;
479                                 IntPtr  pformatetcIn_ptr;
480                                 IntPtr  pmedium_ptr;
481
482                                 pformatetcIn_ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(FORMATETC)));
483                                 Marshal.StructureToPtr(pformatetcIn, pformatetcIn_ptr, false);
484
485                                 pmedium_ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(STGMEDIUM)));
486
487                                 MethodArguments[0] = vtbl.GetData;
488                                 MethodArguments[1] = this.@this;
489                                 MethodArguments[2] = pformatetcIn_ptr;
490                                 MethodArguments[3] = pmedium_ptr;
491
492                                 try {
493                                         ret = (uint)GetDataMethod.Invoke(null, MethodArguments);
494                                         Marshal.PtrToStructure(pmedium_ptr, pmedium);
495                                 }
496
497                                 catch (Exception e) {
498                                         Console.WriteLine("Caught exception {0}", e.Message);
499                                         ret = E_FAIL;
500                                 }
501
502                                 Marshal.FreeHGlobal(pformatetcIn_ptr);
503                                 Marshal.FreeHGlobal(pmedium_ptr);
504
505                                 return ret;
506                         }
507
508                         internal uint GetDataHere(FORMATETC pformatetc, ref STGMEDIUM pmedium) {
509                                 return E_NOTIMPL;
510                         }
511
512                         internal uint QueryGetData(FORMATETC pformatetc) {
513                                 uint    ret;
514                                 IntPtr  pformatetc_ptr;
515
516                                 pformatetc_ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(FORMATETC)));
517                                 Marshal.StructureToPtr(pformatetc, pformatetc_ptr, false);
518
519                                 MethodArguments[0] = vtbl.GetData;
520                                 MethodArguments[1] = this.@this;
521                                 MethodArguments[2] = pformatetc_ptr;
522
523                                 try {
524                                         ret = (uint)QueryGetDataMethod.Invoke(null, MethodArguments);
525                                 }
526
527                                 catch (Exception e) {
528                                         Console.WriteLine("Caught exception {0}", e.Message);
529                                         ret = E_FAIL;
530                                 }
531
532                                 Marshal.FreeHGlobal(pformatetc_ptr);
533
534                                 return ret;
535                         }
536
537                         internal uint GetCanonicalFormatEtc(FORMATETC pformatetcIn, ref FORMATETC pformatetcOut) {
538                                 return E_NOTIMPL;
539                         }
540
541                         internal uint SetData(FORMATETC pformatetc, STGMEDIUM pmedium, bool release) {
542                                 return E_NOTIMPL;
543                         }
544
545                         internal uint EnumFormatEtc(uint direction, IntPtr ppenumFormatEtc) {
546                                 return E_NOTIMPL;
547                         }
548
549                         internal uint DAdvise(FORMATETC pformatetc, uint advf, IntPtr pAdvSink, ref uint pdwConnection) {
550                                 return OLE_E_ADVISENOTSUPPORTED;
551                         }
552
553                         internal uint DUnadvise(uint pdwConnection) {
554                                 return OLE_E_ADVISENOTSUPPORTED;
555                         }
556
557                         internal uint EnumDAdvise(IntPtr ppenumAdvise) {
558                                 return OLE_E_ADVISENOTSUPPORTED;
559                         }
560                 }
561
562
563                 internal class ComIDropSource {
564                         [StructLayout(LayoutKind.Sequential)]
565                                 internal struct IDropSource {
566                                 internal IntPtr                         vtbl;
567                                 internal IntPtr                         Window;
568                                 internal QueryInterfaceDelegate         QueryInterface;
569                                 internal AddRefDelegate                 AddRef;
570                                 internal ReleaseDelegate                Release;
571                                 internal QueryContinueDragDelegate      QueryContinueDrag;
572                                 internal GiveFeedbackDelegate           GiveFeedback;
573                         }
574
575                         internal static IntPtr GetUnmanaged(IntPtr Window) {
576                                 IDropSource     drop_source;
577                                 IntPtr          drop_source_ptr;
578                                 long            offset;
579
580                                 drop_source = new IDropSource();
581                                 drop_source.QueryInterface = Win32DnD.DSQueryInterface;
582                                 drop_source.AddRef = Win32DnD.DSAddRef;
583                                 drop_source.Release = Win32DnD.DSRelease;
584                                 drop_source.QueryContinueDrag = Win32DnD.QueryContinueDrag;
585                                 drop_source.GiveFeedback = Win32DnD.GiveFeedback;
586                                 drop_source.Window = Window;
587
588                                 drop_source_ptr = Marshal.AllocHGlobal(Marshal.SizeOf(drop_source));
589                                 Marshal.StructureToPtr(drop_source, drop_source_ptr, false);
590
591                                 // Update vtbl pointer
592                                 offset = drop_source_ptr.ToInt64();
593                                 offset += 2 * Marshal.SizeOf(typeof(IntPtr));
594                                 Marshal.WriteIntPtr(drop_source_ptr, new IntPtr(offset));
595                                 
596                                 return drop_source_ptr;
597                         }
598
599                         internal static void ReleaseUnmanaged(IntPtr drop_source_ptr) {
600                                 Marshal.FreeHGlobal(drop_source_ptr);
601                         }
602
603                         internal static uint QueryInterface(IntPtr @this, ref Guid riid, IntPtr ppvObject) {
604                                 try {
605                                         if (IID_IUnknown.Equals(riid) || IID_IDropSource.Equals(riid)) {
606                                                 Marshal.WriteIntPtr(ppvObject, @this);
607                                                 return S_OK;
608                                         }
609                                 }
610
611                                 catch (Exception e) {
612                                         Console.WriteLine("Got exception {0}", e.Message);
613                                 }
614
615                                 Marshal.WriteIntPtr(ppvObject, IntPtr.Zero);
616                                 return E_NOINTERFACE;
617                         }
618
619                         internal static uint AddRef(IntPtr @this) {
620                                 // We only use this for DnD, try and fake it
621                                 return 1;
622                         }
623
624                         internal static uint Release(IntPtr @this) {
625                                 // We only use this for DnD, try and fake it
626                                 return 0;
627                         }
628
629                         internal static uint QueryContinueDrag(IntPtr @this, bool fEscapePressed, uint grfkeyState) {
630                                 IntPtr          window;
631
632                                 window = Marshal.ReadIntPtr(@this, Marshal.SizeOf(typeof(IntPtr)));
633
634                                 // LAMESPEC? - according to MSDN, when the any mousebutton is *pressed* it defaults to Drop.
635                                 // According to COM customary behaviour it's the other way round; which is what we do here
636                                 if (fEscapePressed) {
637                                         DragContinueEventArgs.drag_action = DragAction.Cancel;
638                                 } else if ((grfkeyState & (1+2+16)) == 0) {             // Left, middle and right mouse button not pressed
639                                         DragContinueEventArgs.drag_action = DragAction.Drop;
640                                 } else {
641                                         DragContinueEventArgs.drag_action = DragAction.Continue;
642                                 }
643
644                                 DragContinueEventArgs.escape_pressed = fEscapePressed;
645                                 DragContinueEventArgs.key_state = (int)grfkeyState;
646
647                                 Control.FromHandle(window).DndContinueDrag(DragContinueEventArgs);
648
649                                 if (DragContinueEventArgs.drag_action == DragAction.Cancel) {
650                                         return DRAGDROP_S_CANCEL;
651                                 } else if (DragContinueEventArgs.drag_action == DragAction.Drop) {
652                                         return DRAGDROP_S_DROP;
653                                 }
654                                 return S_OK;
655                         }
656
657                         internal static uint GiveFeedback(IntPtr @this, uint pdwEffect) {
658                                 IntPtr          window;
659
660                                 window = Marshal.ReadIntPtr(@this, Marshal.SizeOf(typeof(IntPtr)));
661
662                                 DragFeedbackEventArgs.effect = (DragDropEffects)pdwEffect;
663                                 DragFeedbackEventArgs.use_default_cursors = true;
664
665                                 Control.FromHandle(window).DndFeedback(DragFeedbackEventArgs);
666
667                                 if (DragFeedbackEventArgs.use_default_cursors) {
668                                         return DRAGDROP_S_USEDEFAULTCURSORS;
669                                 }
670                                 return S_OK;
671                         }
672                 }
673
674                 internal class ComIDropTarget {
675                         [StructLayout(LayoutKind.Sequential)]
676                                 internal struct IDropTarget {
677                                 internal IntPtr                         vtbl;
678                                 internal IntPtr                         Window;
679                                 internal QueryInterfaceDelegate         QueryInterface;
680                                 internal AddRefDelegate                 AddRef;
681                                 internal ReleaseDelegate                Release;
682
683                                 internal DragEnterDelegate              DragEnter;
684                                 internal DragOverDelegate               DragOver;
685                                 internal DragLeaveDelegate              DragLeave;
686                                 internal DropDelegate                   Drop;
687                         }
688
689                         internal static IntPtr GetUnmanaged(IntPtr Window) {
690                                 IDropTarget     drop_target;
691                                 IntPtr          drop_target_ptr;
692                                 long            offset;
693
694                                 drop_target = new IDropTarget();
695                                 drop_target.QueryInterface = Win32DnD.DTQueryInterface;
696                                 drop_target.AddRef = Win32DnD.DTAddRef;
697                                 drop_target.Release = Win32DnD.DTRelease;
698                                 drop_target.DragEnter = Win32DnD.DragEnter;
699                                 drop_target.DragOver = Win32DnD.DragOver;
700                                 drop_target.DragLeave = Win32DnD.DragLeave;
701                                 drop_target.Drop = Win32DnD.Drop;
702                                 drop_target.Window = Window;
703
704                                 drop_target_ptr = Marshal.AllocHGlobal(Marshal.SizeOf(drop_target));
705                                 Marshal.StructureToPtr(drop_target, drop_target_ptr, false);
706
707                                 // Update vtbl pointer
708                                 offset = drop_target_ptr.ToInt64();
709                                 offset += 2 * Marshal.SizeOf(typeof(IntPtr));
710                                 Marshal.WriteIntPtr(drop_target_ptr, new IntPtr(offset));
711                                 
712                                 return drop_target_ptr;
713                         }
714
715                         internal static void ReleaseUnmanaged(IntPtr drop_target_ptr) {
716                                 Marshal.FreeHGlobal(drop_target_ptr);
717                         }
718
719                         internal static uint QueryInterface(IntPtr @this, ref Guid riid, IntPtr ppvObject) {
720                                 try {
721                                         if (IID_IUnknown.Equals(riid) || IID_IDropTarget.Equals(riid)) {
722                                                 Marshal.WriteIntPtr(ppvObject, @this);
723                                                 return S_OK;
724                                         }
725                                 }
726
727                                 catch (Exception e) {
728                                         Console.WriteLine("Got exception {0}", e.Message);
729                                 }
730
731                                 Marshal.WriteIntPtr(ppvObject, IntPtr.Zero);
732                                 return E_NOINTERFACE;
733                         }
734
735                         internal static uint AddRef(IntPtr @this) {
736                                 // We only use this for DnD, try and fake it
737                                 return 1;
738                         }
739
740                         internal static uint Release(IntPtr @this) {
741                                 // We only use this for DnD, try and fake it
742                                 return 0;
743                         }
744
745                         internal static uint DragEnter(IntPtr @this, IntPtr pDataObj, uint grfkeyState, IntPtr pt_x, IntPtr pt_y, IntPtr pdwEffect) {
746                                 IntPtr          window;
747
748                                 window = Marshal.ReadIntPtr(@this, Marshal.SizeOf(typeof(IntPtr)));
749
750                                 DragDropEventArgs.x = pt_x.ToInt32();
751                                 DragDropEventArgs.y = pt_y.ToInt32();
752                                 DragDropEventArgs.allowed_effect = (DragDropEffects)Marshal.ReadIntPtr(pdwEffect).ToInt32();
753                                 DragDropEventArgs.current_effect = DragDropEventArgs.AllowedEffect;
754                                 DragDropEventArgs.keystate = (int)grfkeyState;
755
756                                 Control.FromHandle(window).DndEnter(DragDropEventArgs);
757
758                                 Marshal.WriteInt32(pdwEffect, (int)DragDropEventArgs.Effect);
759
760                                 return S_OK;
761                         }
762
763                         internal static uint DragOver(IntPtr @this, uint grfkeyState, IntPtr pt_x, IntPtr pt_y, IntPtr pdwEffect) {
764                                 IntPtr window;
765
766                                 window = Marshal.ReadIntPtr(@this, Marshal.SizeOf(typeof(IntPtr)));
767
768                                 DragDropEventArgs.x = pt_x.ToInt32();
769                                 DragDropEventArgs.y = pt_y.ToInt32();
770                                 DragDropEventArgs.allowed_effect = (DragDropEffects)Marshal.ReadIntPtr(pdwEffect).ToInt32();
771                                 DragDropEventArgs.current_effect = DragDropEventArgs.AllowedEffect;
772                                 DragDropEventArgs.keystate = (int)grfkeyState;
773
774                                 Control.FromHandle(window).DndOver(DragDropEventArgs);
775
776                                 Marshal.WriteInt32(pdwEffect, (int)DragDropEventArgs.Effect);
777
778                                 return S_OK;
779                         }
780
781                         internal static uint DragLeave(IntPtr @this) {
782                                 IntPtr window;
783
784                                 window = Marshal.ReadIntPtr(@this, Marshal.SizeOf(typeof(IntPtr)));
785
786                                 Control.FromHandle(window).DndLeave(EventArgs.Empty);
787
788                                 return S_OK;
789                         }
790
791                         internal static uint Drop(IntPtr @this, IntPtr pDataObj, uint grfkeyState, IntPtr pt_x, IntPtr pt_y, IntPtr pdwEffect)
792                         {
793                                 IntPtr window;
794                                 
795                                 window = Marshal.ReadIntPtr (@this, Marshal.SizeOf (typeof (IntPtr)));
796
797                                 DragDropEventArgs.x = pt_x.ToInt32 ();
798                                 DragDropEventArgs.y = pt_y.ToInt32 ();
799                                 DragDropEventArgs.allowed_effect = (DragDropEffects) Marshal.ReadIntPtr (pdwEffect).ToInt32();
800                                 DragDropEventArgs.current_effect = DragDropEventArgs.AllowedEffect;
801                                 DragDropEventArgs.keystate = (int) grfkeyState;
802
803                                 Control control = Control.FromHandle (window);
804                                 if (control == null) {
805                                         control.DndDrop (DragDropEventArgs);
806                                         return S_FALSE;
807                                 }
808  
809                                 Marshal.WriteInt32 (pdwEffect, (int) DragDropEventArgs.Effect);
810
811                                 return S_OK;
812                         }
813                 }
814
815                 internal static bool HandleWMDropFiles(ref MSG msg) {
816                         IntPtr          hDrop;
817                         int             count;
818                         StringBuilder   sb;
819                         string[]        dropfiles;
820
821                         hDrop = msg.wParam;
822                         count = Win32DragQueryFile(hDrop, -1, IntPtr.Zero, 0);
823
824                         dropfiles = new string[count];
825
826                         sb = new StringBuilder(256);
827                         for (int i = 0; i < count; i++) {
828                                 Win32DragQueryFile(hDrop, i, sb, sb.Capacity);
829                                 dropfiles[i] = sb.ToString();
830                         }
831
832                         DragDropEventArgs.Data.SetData(DataFormats.FileDrop, dropfiles);
833
834                         Control.FromHandle(msg.hwnd).DndDrop(DragDropEventArgs);
835
836                         return true;
837                 }
838
839                 private static bool AddFormatAndMedium(ClipboardFormats cfFormat, object data) {
840                         STGMEDIUM       medium;
841                         FORMATETC       format;
842                         IntPtr          hmem;
843                         IntPtr          hmem_ptr;
844                         byte[]          b;
845
846                         switch(cfFormat) {
847                                 case ClipboardFormats.CF_TEXT: {
848                                         hmem = Marshal.StringToHGlobalAnsi((string)data);
849                                         break;
850                                 }
851
852                                 case ClipboardFormats.CF_UNICODETEXT: {
853                                         hmem = Marshal.StringToHGlobalUni((string)data);
854                                         break;
855                                 }
856
857                                 case ClipboardFormats.CF_HDROP: {
858                                         IEnumerator     e;
859                                         StringBuilder   sb;
860                                         long            hmem_string_ptr;
861                                         IntPtr          string_buffer;
862                                         int             string_buffer_size;
863
864                                         sb = new StringBuilder();
865
866                                         // Make sure object is enumerable; otherwise
867                                         if ((data is string) || !(data is IEnumerable)) {
868                                                 sb.Append(data.ToString());
869                                                 sb.Append('\0');
870                                                 sb.Append('\0');
871                                         } else {
872                                                 e = ((IEnumerable)data).GetEnumerator();
873                                                 while (e.MoveNext()) {
874                                                         sb.Append(e.Current.ToString());
875                                                         sb.Append('\0');
876                                                 }
877                                                 sb.Append('\0');
878                                         }
879
880                                         string_buffer = Marshal.StringToHGlobalUni(sb.ToString());
881                                         string_buffer_size = (int)XplatUIWin32.Win32GlobalSize(string_buffer);
882
883                                         // Write DROPFILES structure
884                                         hmem = XplatUIWin32.Win32GlobalAlloc(XplatUIWin32.GAllocFlags.GMEM_MOVEABLE | XplatUIWin32.GAllocFlags.GMEM_DDESHARE, 0x14 + string_buffer_size);
885                                         hmem_ptr = XplatUIWin32.Win32GlobalLock(hmem);
886                                         Marshal.WriteInt32(hmem_ptr, 0x14);                                     // pFiles
887                                         Marshal.WriteInt32(hmem_ptr, 1 * Marshal.SizeOf(typeof(uint)), 0);      // point.x
888                                         Marshal.WriteInt32(hmem_ptr, 2 * Marshal.SizeOf(typeof(uint)), 0);      // point.y
889                                         Marshal.WriteInt32(hmem_ptr, 3 * Marshal.SizeOf(typeof(uint)), 0);      // fNc
890                                         Marshal.WriteInt32(hmem_ptr, 4 * Marshal.SizeOf(typeof(uint)), 1);      // fWide
891
892                                         hmem_string_ptr = (long)hmem_ptr;
893                                         hmem_string_ptr += 0x14;
894
895                                         XplatUIWin32.Win32CopyMemory(new IntPtr(hmem_string_ptr), string_buffer, string_buffer_size);
896                                         Marshal.FreeHGlobal(string_buffer);
897                                         XplatUIWin32.Win32GlobalUnlock(hmem_ptr);
898
899                                         break;
900                                 }
901
902                                 case ClipboardFormats.CF_DIB: {
903                                         b = XplatUIWin32.ImageToDIB((Image)data);
904
905                                         hmem = XplatUIWin32.Win32GlobalAlloc(XplatUIWin32.GAllocFlags.GMEM_MOVEABLE | XplatUIWin32.GAllocFlags.GMEM_DDESHARE, b.Length);
906                                         hmem_ptr = XplatUIWin32.Win32GlobalLock(hmem);
907                                         Marshal.Copy(b, 0, hmem_ptr, b.Length);
908                                         XplatUIWin32.Win32GlobalUnlock(hmem);
909                                         break;
910                                 }
911
912                                 default: {
913                                         hmem = IntPtr.Zero;
914                                         break;
915                                 }
916                         }
917
918                         if (hmem != IntPtr.Zero) {
919                                 medium = new STGMEDIUM();
920                                 medium.tymed = TYMED.TYMED_HGLOBAL;
921                                 medium.hHandle = hmem;
922                                 medium.pUnkForRelease = IntPtr.Zero;
923                                 DragMediums.Add(medium);
924
925                                 format = new FORMATETC();
926                                 format.ptd = IntPtr.Zero;
927                                 format.dwAspect = DVASPECT.DVASPECT_CONTENT;
928                                 format.lindex = -1;
929                                 format.tymed = TYMED.TYMED_HGLOBAL;
930                                 format.cfFormat = cfFormat;
931                                 DragFormats.Add(format);
932
933                                 return true;
934                         }
935
936                         return false;
937                 }
938
939                 private static int FindFormat(FORMATETC pformatetc) {
940                         for (int i = 0; i < DragFormats.Count; i++) {
941                                 if ((((FORMATETC)DragFormats[i]).cfFormat == pformatetc.cfFormat) &&
942                                         (((FORMATETC)DragFormats[i]).dwAspect  == pformatetc.dwAspect) &&
943                                         ((((FORMATETC)DragFormats[i]).tymed & pformatetc.tymed)) != 0) {
944                                         return i;
945                                 }
946                         }
947                         return -1;
948                 }
949
950                 private static void BuildFormats(object data) {
951
952                         DragFormats.Clear();
953                         DragMediums.Clear();
954
955                         // Build our formats based on object data
956                         if (data is String) {
957                                 AddFormatAndMedium(ClipboardFormats.CF_TEXT, data);
958                                 AddFormatAndMedium(ClipboardFormats.CF_UNICODETEXT, data);
959                                 AddFormatAndMedium(ClipboardFormats.CF_HDROP, data);
960                         } else if (data is Bitmap) {
961                                 AddFormatAndMedium(ClipboardFormats.CF_DIB, data);
962                         } else if (data is ICollection) {
963                                 // FIXME - test with .Net and found how this is handled
964                                 AddFormatAndMedium(ClipboardFormats.CF_HDROP, data);
965                         } else if (data is ISerializable) {
966                                 // FIXME - test with .Net and found how this is handled
967                         }
968                 }
969
970                 internal static DragDropEffects StartDrag(IntPtr Window, object data, DragDropEffects allowed) {
971                         IntPtr  result;
972                         IntPtr  data_object;
973                         IntPtr  drop_source;
974
975                         BuildFormats(data);
976
977                         data_object = ComIDataObject.GetUnmanaged();
978                         drop_source = ComIDropSource.GetUnmanaged(Window);
979
980                         result = (IntPtr)DragDropEffects.None;
981
982                         Win32DoDragDrop(data_object, drop_source, (IntPtr)allowed, ref result);
983
984                         // Cleanup again
985                         ComIDataObject.ReleaseUnmanaged(data_object);
986                         ComIDropSource.ReleaseUnmanaged(drop_source);
987                         DragFormats.Clear();
988                         DragFormatArray = null;
989                         DragMediums.Clear();
990
991                         return (DragDropEffects)result.ToInt32();
992                 }
993
994                 internal static bool UnregisterDropTarget(IntPtr Window) {
995                         Win32RevokeDragDrop(Window);
996                         return true;
997                 }
998
999                 internal static bool RegisterDropTarget(IntPtr Window) {
1000                         Hwnd    hwnd;
1001                         IntPtr  drop_target;
1002                         uint    result;
1003
1004                         hwnd = Hwnd.ObjectFromWindow(Window);
1005                         if (hwnd == null) {
1006                                 return false;
1007                         }
1008
1009                         drop_target = ComIDropTarget.GetUnmanaged(Window);
1010                         hwnd.marshal_free_list.Add(drop_target);
1011                         result = Win32RegisterDragDrop(Window, drop_target);
1012
1013                         if (result != S_OK) {
1014                                 return false;
1015                         }
1016                         return true;
1017                 }
1018
1019                 // Thanks, Martin
1020                 static MethodInfo CreateFuncPtrInterface(AssemblyBuilder assembly, string MethodName, Type ret_type, int param_count) {
1021                         ModuleBuilder   mb;
1022                         TypeBuilder     tb;
1023                         Type[]          il_param_types;
1024                         Type[]          param_types;
1025
1026                         mb = assembly.DefineDynamicModule("XplatUIWin32.FuncInterface" + MethodName);
1027                         tb = mb.DefineType ("XplatUIWin32.FuncInterface" + MethodName, TypeAttributes.Public);
1028
1029                         param_types = new Type[param_count];
1030                         il_param_types = new Type[param_count + 1];
1031
1032                         il_param_types[param_count] = typeof(IntPtr);
1033                         for (int i = 0; i < param_count; i++) {
1034                                 param_types[i] = typeof(IntPtr);
1035                                 il_param_types[i] = typeof(IntPtr);
1036                         }
1037
1038                         MethodBuilder method = tb.DefineMethod (
1039                                 MethodName, MethodAttributes.Static | MethodAttributes.Public,
1040                                 ret_type, il_param_types);
1041
1042                         ILGenerator ig = method.GetILGenerator ();
1043                         if (param_count > 5) ig.Emit (OpCodes.Ldarg_S, 6);
1044                         if (param_count > 4) ig.Emit (OpCodes.Ldarg_S, 5);
1045                         if (param_count > 3) ig.Emit (OpCodes.Ldarg_S, 4);
1046                         if (param_count > 2) ig.Emit (OpCodes.Ldarg_3);
1047                         if (param_count > 1) ig.Emit (OpCodes.Ldarg_2);
1048                         if (param_count > 0) ig.Emit (OpCodes.Ldarg_1);
1049                         ig.Emit (OpCodes.Ldarg_0);
1050                         ig.EmitCalli (OpCodes.Calli, CallingConvention.StdCall, ret_type, param_types);
1051                         ig.Emit (OpCodes.Ret);
1052
1053                         Type t = tb.CreateType ();
1054                         MethodInfo m = t.GetMethod (MethodName);
1055
1056                         return m;
1057                 }
1058
1059                 [DllImport ("ole32.dll", EntryPoint="RegisterDragDrop", CallingConvention=CallingConvention.StdCall)]
1060                 private extern static uint Win32RegisterDragDrop(IntPtr Window, IntPtr pDropTarget);
1061
1062                 [DllImport ("ole32.dll", EntryPoint="RevokeDragDrop", CallingConvention=CallingConvention.StdCall)]
1063                 private extern static int Win32RevokeDragDrop(IntPtr Window);
1064
1065                 [DllImport ("ole32.dll", EntryPoint="DoDragDrop", CallingConvention=CallingConvention.StdCall)]
1066                 private extern static uint Win32DoDragDrop(IntPtr pDataObject, IntPtr pDropSource, IntPtr dwOKEffect, ref IntPtr pdwEffect);
1067
1068                 //[DllImport ("shell32.dll", EntryPoint="DragAcceptFiles", CallingConvention=CallingConvention.StdCall)]
1069                 //private extern static int Win32DragAcceptFiles(IntPtr Window, bool fAccept);
1070
1071                 [DllImport ("ole32.dll", EntryPoint="OleInitialize", CallingConvention=CallingConvention.StdCall)]
1072                 private extern static int Win32OleInitialize(IntPtr pvReserved);
1073
1074                 [DllImport ("shell32.dll", EntryPoint="DragQueryFileW", CharSet=CharSet.Unicode, CallingConvention=CallingConvention.StdCall)]
1075                 private extern static int Win32DragQueryFile(IntPtr hDrop, int iFile, IntPtr lpszFile, int cch);
1076
1077                 [DllImport ("shell32.dll", EntryPoint="DragQueryFileW", CharSet=CharSet.Unicode, CallingConvention=CallingConvention.StdCall)]
1078                 private extern static int Win32DragQueryFile(IntPtr hDrop, int iFile, StringBuilder lpszFile, int cch);
1079
1080                 [DllImport ("shell32.dll", EntryPoint="SHCreateStdEnumFmtEtc", CallingConvention=CallingConvention.StdCall)]
1081                 private extern static uint Win32SHCreateStdEnumFmtEtc(uint cfmt, FORMATETC[] afmt, ref IntPtr ppenumFormatEtc);
1082         }
1083 }