2007-04-25 Jonathan Pobst <monkey@jpobst.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 //
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                                 throw new Exception("Yeah baby, gimme a ride to WM_DROPFILES land");
793
794                                 #if InTheFuture
795                                 ComIDataObjectUnmanaged data_object;
796                                 FORMATETC               format;
797                                 STGMEDIUM               medium;
798                                 uint                    result;
799                                 IntPtr                  mem;
800
801
802                                 data_object = new ComIDataObjectUnmanaged(pDataObj);
803
804                                 format = new FORMATETC();
805                                 format.cfFormat = ClipboardFormats.CF_HDROP;
806                                 format.ptd = IntPtr.Zero;
807                                 format.dwAspect = DVASPECT.DVASPECT_CONTENT;
808                                 format.lindex = -1;
809                                 format.tymed = TYMED.TYMED_HGLOBAL;
810
811                                 medium = new STGMEDIUM();
812                                 medium.tymed = TYMED.TYMED_HGLOBAL;
813
814                                 //mem = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr)));
815                                 //result = data_object.QueryInterface(IID_IDataObject, mem);
816                                 //Marshal.FreeHGlobal(mem);
817
818                                 //result = data_object.AddRef();
819
820                                 result = data_object.QueryGetData(format);
821
822                                 result = data_object.GetData(format, ref medium);
823
824                                 return E_NOTIMPL;
825                                 #endif
826                         }
827                 }
828
829                 internal static bool HandleWMDropFiles(ref MSG msg) {
830                         IntPtr          hDrop;
831                         int             count;
832                         StringBuilder   sb;
833                         string[]        dropfiles;
834
835                         hDrop = msg.wParam;
836                         count = Win32DragQueryFile(hDrop, -1, IntPtr.Zero, 0);
837
838                         dropfiles = new string[count];
839
840                         sb = new StringBuilder(256);
841                         for (int i = 0; i < count; i++) {
842                                 Win32DragQueryFile(hDrop, i, sb, sb.Capacity);
843                                 dropfiles[i] = sb.ToString();
844                         }
845
846                         DragDropEventArgs.Data.SetData(DataFormats.FileDrop, dropfiles);
847
848                         Control.FromHandle(msg.hwnd).DndDrop(DragDropEventArgs);
849
850                         return true;
851                 }
852
853                 private static bool AddFormatAndMedium(ClipboardFormats cfFormat, object data) {
854                         STGMEDIUM       medium;
855                         FORMATETC       format;
856                         IntPtr          hmem;
857                         IntPtr          hmem_ptr;
858                         byte[]          b;
859
860                         switch(cfFormat) {
861                                 case ClipboardFormats.CF_TEXT: {
862                                         hmem = Marshal.StringToHGlobalAnsi((string)data);
863                                         break;
864                                 }
865
866                                 case ClipboardFormats.CF_UNICODETEXT: {
867                                         hmem = Marshal.StringToHGlobalUni((string)data);
868                                         break;
869                                 }
870
871                                 case ClipboardFormats.CF_HDROP: {
872                                         IEnumerator     e;
873                                         StringBuilder   sb;
874                                         long            hmem_string_ptr;
875                                         IntPtr          string_buffer;
876                                         int             string_buffer_size;
877
878                                         sb = new StringBuilder();
879
880                                         // Make sure object is enumerable; otherwise
881                                         if ((data is string) || !(data is IEnumerable)) {
882                                                 sb.Append(data.ToString());
883                                                 sb.Append('\0');
884                                                 sb.Append('\0');
885                                         } else {
886                                                 e = ((IEnumerable)data).GetEnumerator();
887                                                 while (e.MoveNext()) {
888                                                         sb.Append(e.Current.ToString());
889                                                         sb.Append('\0');
890                                                 }
891                                                 sb.Append('\0');
892                                         }
893
894                                         string_buffer = Marshal.StringToHGlobalUni(sb.ToString());
895                                         string_buffer_size = (int)XplatUIWin32.Win32GlobalSize(string_buffer);
896
897                                         // Write DROPFILES structure
898                                         hmem = XplatUIWin32.Win32GlobalAlloc(XplatUIWin32.GAllocFlags.GMEM_MOVEABLE | XplatUIWin32.GAllocFlags.GMEM_DDESHARE, 0x14 + string_buffer_size);
899                                         hmem_ptr = XplatUIWin32.Win32GlobalLock(hmem);
900                                         Marshal.WriteInt32(hmem_ptr, 0x14);                                     // pFiles
901                                         Marshal.WriteInt32(hmem_ptr, 1 * Marshal.SizeOf(typeof(uint)), 0);      // point.x
902                                         Marshal.WriteInt32(hmem_ptr, 2 * Marshal.SizeOf(typeof(uint)), 0);      // point.y
903                                         Marshal.WriteInt32(hmem_ptr, 3 * Marshal.SizeOf(typeof(uint)), 0);      // fNc
904                                         Marshal.WriteInt32(hmem_ptr, 4 * Marshal.SizeOf(typeof(uint)), 1);      // fWide
905
906                                         hmem_string_ptr = (long)hmem_ptr;
907                                         hmem_string_ptr += 0x14;
908
909                                         XplatUIWin32.Win32CopyMemory(new IntPtr(hmem_string_ptr), string_buffer, string_buffer_size);
910                                         Marshal.FreeHGlobal(string_buffer);
911                                         XplatUIWin32.Win32GlobalUnlock(hmem_ptr);
912
913                                         break;
914                                 }
915
916                                 case ClipboardFormats.CF_DIB: {
917                                         b = XplatUIWin32.ImageToDIB((Image)data);
918
919                                         hmem = XplatUIWin32.Win32GlobalAlloc(XplatUIWin32.GAllocFlags.GMEM_MOVEABLE | XplatUIWin32.GAllocFlags.GMEM_DDESHARE, b.Length);
920                                         hmem_ptr = XplatUIWin32.Win32GlobalLock(hmem);
921                                         Marshal.Copy(b, 0, hmem_ptr, b.Length);
922                                         XplatUIWin32.Win32GlobalUnlock(hmem);
923                                         break;
924                                 }
925
926                                 default: {
927                                         hmem = IntPtr.Zero;
928                                         break;
929                                 }
930                         }
931
932                         if (hmem != IntPtr.Zero) {
933                                 medium = new STGMEDIUM();
934                                 medium.tymed = TYMED.TYMED_HGLOBAL;
935                                 medium.hHandle = hmem;
936                                 medium.pUnkForRelease = IntPtr.Zero;
937                                 DragMediums.Add(medium);
938
939                                 format = new FORMATETC();
940                                 format.ptd = IntPtr.Zero;
941                                 format.dwAspect = DVASPECT.DVASPECT_CONTENT;
942                                 format.lindex = -1;
943                                 format.tymed = TYMED.TYMED_HGLOBAL;
944                                 format.cfFormat = cfFormat;
945                                 DragFormats.Add(format);
946
947                                 return true;
948                         }
949
950                         return false;
951                 }
952
953                 private static int FindFormat(FORMATETC pformatetc) {
954                         for (int i = 0; i < DragFormats.Count; i++) {
955                                 if ((((FORMATETC)DragFormats[i]).cfFormat == pformatetc.cfFormat) &&
956                                         (((FORMATETC)DragFormats[i]).dwAspect  == pformatetc.dwAspect) &&
957                                         ((((FORMATETC)DragFormats[i]).tymed & pformatetc.tymed)) != 0) {
958                                         return i;
959                                 }
960                         }
961                         return -1;
962                 }
963
964                 private static void BuildFormats(object data) {
965
966                         DragFormats.Clear();
967                         DragMediums.Clear();
968
969                         // Build our formats based on object data
970                         if (data is String) {
971                                 AddFormatAndMedium(ClipboardFormats.CF_TEXT, data);
972                                 AddFormatAndMedium(ClipboardFormats.CF_UNICODETEXT, data);
973                                 AddFormatAndMedium(ClipboardFormats.CF_HDROP, data);
974                         } else if (data is Bitmap) {
975                                 AddFormatAndMedium(ClipboardFormats.CF_DIB, data);
976                         } else if (data is ICollection) {
977                                 // FIXME - test with .Net and found how this is handled
978                                 AddFormatAndMedium(ClipboardFormats.CF_HDROP, data);
979                         } else if (data is ISerializable) {
980                                 // FIXME - test with .Net and found how this is handled
981                         }
982                 }
983
984                 internal static DragDropEffects StartDrag(IntPtr Window, object data, DragDropEffects allowed) {
985                         IntPtr  result;
986                         IntPtr  data_object;
987                         IntPtr  drop_source;
988
989                         BuildFormats(data);
990
991                         data_object = ComIDataObject.GetUnmanaged();
992                         drop_source = ComIDropSource.GetUnmanaged(Window);
993
994                         result = (IntPtr)DragDropEffects.None;
995
996                         Win32DoDragDrop(data_object, drop_source, (IntPtr)allowed, ref result);
997
998                         // Cleanup again
999                         ComIDataObject.ReleaseUnmanaged(data_object);
1000                         ComIDropSource.ReleaseUnmanaged(drop_source);
1001                         DragFormats.Clear();
1002                         DragFormatArray = null;
1003                         DragMediums.Clear();
1004
1005                         return (DragDropEffects)result.ToInt32();
1006                 }
1007
1008                 internal static bool UnregisterDropTarget(IntPtr Window) {
1009                         Win32RevokeDragDrop(Window);
1010                         return true;
1011                 }
1012
1013                 internal static bool RegisterDropTarget(IntPtr Window) {
1014                         Hwnd    hwnd;
1015                         IntPtr  drop_target;
1016                         uint    result;
1017
1018                         hwnd = Hwnd.ObjectFromWindow(Window);
1019                         if (hwnd == null) {
1020                                 return false;
1021                         }
1022
1023                         drop_target = ComIDropTarget.GetUnmanaged(Window);
1024                         hwnd.marshal_free_list.Add(drop_target);
1025                         result = Win32RegisterDragDrop(Window, drop_target);
1026
1027                         if (result != S_OK) {
1028                                 return false;
1029                         }
1030                         return true;
1031                 }
1032
1033                 // Thanks, Martin
1034                 static MethodInfo CreateFuncPtrInterface(AssemblyBuilder assembly, string MethodName, Type ret_type, int param_count) {
1035                         ModuleBuilder   mb;
1036                         TypeBuilder     tb;
1037                         Type[]          il_param_types;
1038                         Type[]          param_types;
1039
1040                         mb = assembly.DefineDynamicModule("XplatUIWin32.FuncInterface" + MethodName);
1041                         tb = mb.DefineType ("XplatUIWin32.FuncInterface" + MethodName, TypeAttributes.Public);
1042
1043                         param_types = new Type[param_count];
1044                         il_param_types = new Type[param_count + 1];
1045
1046                         il_param_types[param_count] = typeof(IntPtr);
1047                         for (int i = 0; i < param_count; i++) {
1048                                 param_types[i] = typeof(IntPtr);
1049                                 il_param_types[i] = typeof(IntPtr);
1050                         }
1051
1052                         MethodBuilder method = tb.DefineMethod (
1053                                 MethodName, MethodAttributes.Static | MethodAttributes.Public,
1054                                 ret_type, il_param_types);
1055
1056                         ILGenerator ig = method.GetILGenerator ();
1057                         if (param_count > 5) ig.Emit (OpCodes.Ldarg_S, 6);
1058                         if (param_count > 4) ig.Emit (OpCodes.Ldarg_S, 5);
1059                         if (param_count > 3) ig.Emit (OpCodes.Ldarg_S, 4);
1060                         if (param_count > 2) ig.Emit (OpCodes.Ldarg_3);
1061                         if (param_count > 1) ig.Emit (OpCodes.Ldarg_2);
1062                         if (param_count > 0) ig.Emit (OpCodes.Ldarg_1);
1063                         ig.Emit (OpCodes.Ldarg_0);
1064                         ig.EmitCalli (OpCodes.Calli, CallingConvention.StdCall, ret_type, param_types);
1065                         ig.Emit (OpCodes.Ret);
1066
1067                         Type t = tb.CreateType ();
1068                         MethodInfo m = t.GetMethod (MethodName);
1069
1070                         return m;
1071                 }
1072
1073                 [DllImport ("ole32.dll", EntryPoint="RegisterDragDrop", CallingConvention=CallingConvention.StdCall)]
1074                 private extern static uint Win32RegisterDragDrop(IntPtr Window, IntPtr pDropTarget);
1075
1076                 [DllImport ("ole32.dll", EntryPoint="RevokeDragDrop", CallingConvention=CallingConvention.StdCall)]
1077                 private extern static int Win32RevokeDragDrop(IntPtr Window);
1078
1079                 [DllImport ("ole32.dll", EntryPoint="DoDragDrop", CallingConvention=CallingConvention.StdCall)]
1080                 private extern static uint Win32DoDragDrop(IntPtr pDataObject, IntPtr pDropSource, IntPtr dwOKEffect, ref IntPtr pdwEffect);
1081
1082                 //[DllImport ("shell32.dll", EntryPoint="DragAcceptFiles", CallingConvention=CallingConvention.StdCall)]
1083                 //private extern static int Win32DragAcceptFiles(IntPtr Window, bool fAccept);
1084
1085                 [DllImport ("ole32.dll", EntryPoint="OleInitialize", CallingConvention=CallingConvention.StdCall)]
1086                 private extern static int Win32OleInitialize(IntPtr pvReserved);
1087
1088                 [DllImport ("shell32.dll", EntryPoint="DragQueryFileW", CharSet=CharSet.Unicode, CallingConvention=CallingConvention.StdCall)]
1089                 private extern static int Win32DragQueryFile(IntPtr hDrop, int iFile, IntPtr lpszFile, int cch);
1090
1091                 [DllImport ("shell32.dll", EntryPoint="DragQueryFileW", CharSet=CharSet.Unicode, CallingConvention=CallingConvention.StdCall)]
1092                 private extern static int Win32DragQueryFile(IntPtr hDrop, int iFile, StringBuilder lpszFile, int cch);
1093
1094                 [DllImport ("shell32.dll", EntryPoint="SHCreateStdEnumFmtEtc", CallingConvention=CallingConvention.StdCall)]
1095                 private extern static uint Win32SHCreateStdEnumFmtEtc(uint cfmt, FORMATETC[] afmt, ref IntPtr ppenumFormatEtc);
1096         }
1097 }