opengl32: Avoid generating a wrapper for internal functions when we can call the...
[wine] / dlls / ole32 / usrmarshal.c
1 /*
2  * Miscellaneous Marshaling Routines
3  *
4  * Copyright 2005 Robert Shearman
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include <stdio.h>
22 #include <stdarg.h>
23 #include <string.h>
24
25 #define COBJMACROS
26 #define NONAMELESSUNION
27 #define NONAMELESSSTRUCT
28
29 #include "windef.h"
30 #include "winbase.h"
31 #include "wingdi.h"
32 #include "winuser.h"
33 #include "winerror.h"
34
35 #include "ole2.h"
36 #include "oleauto.h"
37 #include "rpcproxy.h"
38 #include "wine/debug.h"
39
40 WINE_DEFAULT_DEBUG_CHANNEL(ole);
41
42 #define ALIGNED_LENGTH(_Len, _Align) (((_Len)+(_Align))&~(_Align))
43 #define ALIGNED_POINTER(_Ptr, _Align) ((LPVOID)ALIGNED_LENGTH((ULONG_PTR)(_Ptr), _Align))
44 #define ALIGN_LENGTH(_Len, _Align) _Len = ALIGNED_LENGTH(_Len, _Align)
45 #define ALIGN_POINTER(_Ptr, _Align) _Ptr = ALIGNED_POINTER(_Ptr, _Align)
46
47 static const char* debugstr_user_flags(ULONG *pFlags)
48 {
49     char buf[12];
50     const char* loword;
51     switch (LOWORD(*pFlags))
52     {
53     case MSHCTX_LOCAL:
54         loword="MSHCTX_LOCAL";
55         break;
56     case MSHCTX_NOSHAREDMEM:
57         loword="MSHCTX_NOSHAREDMEM";
58         break;
59     case MSHCTX_DIFFERENTMACHINE:
60         loword="MSHCTX_DIFFERENTMACHINE";
61         break;
62     case MSHCTX_INPROC:
63         loword="MSHCTX_INPROC";
64         break;
65     default:
66         sprintf(buf, "%d", LOWORD(*pFlags));
67         loword=buf;
68     }
69
70     if (HIWORD(*pFlags) == NDR_LOCAL_DATA_REPRESENTATION)
71         return wine_dbg_sprintf("MAKELONG(NDR_LOCAL_REPRESENTATION, %s)", loword);
72     else
73         return wine_dbg_sprintf("MAKELONG(0x%04x, %s)", HIWORD(*pFlags), loword);
74 }
75
76 /******************************************************************************
77  *           CLIPFORMAT_UserSize [OLE32.@]
78  *
79  * Calculates the buffer size required to marshal a clip format.
80  *
81  * PARAMS
82  *  pFlags       [I] Flags. See notes.
83  *  StartingSize [I] Starting size of the buffer. This value is added on to
84  *                   the buffer size required for the clip format.
85  *  pCF          [I] Clip format to size.
86  *
87  * RETURNS
88  *  The buffer size required to marshal a clip format plus the starting size.
89  *
90  * NOTES
91  *  Even though the function is documented to take a pointer to an unsigned
92  *  long in pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
93  *  the first parameter is an unsigned long.
94  *  This function is only intended to be called by the RPC runtime.
95  */
96 ULONG __RPC_USER CLIPFORMAT_UserSize(ULONG *pFlags, ULONG StartingSize, CLIPFORMAT *pCF)
97 {
98     ULONG size = StartingSize;
99
100     TRACE("(%s, %d, %p\n", debugstr_user_flags(pFlags), StartingSize, pCF);
101
102     size += sizeof(userCLIPFORMAT);
103
104     /* only need to marshal the name if it is not a pre-defined type and
105      * we are going remote */
106     if ((*pCF >= 0xc000) && (LOWORD(*pFlags) == MSHCTX_DIFFERENTMACHINE))
107     {
108         WCHAR format[255];
109         INT ret;
110         size += 3 * sizeof(INT);
111         /* urg! this function is badly designed because it won't tell us how
112          * much space is needed without doing a dummy run of storing the
113          * name into a buffer */
114         ret = GetClipboardFormatNameW(*pCF, format, sizeof(format)/sizeof(format[0])-1);
115         if (!ret)
116             RaiseException(DV_E_CLIPFORMAT, 0, 0, NULL);
117         size += (ret + 1) * sizeof(WCHAR);
118     }
119     return size;
120 }
121
122 /******************************************************************************
123  *           CLIPFORMAT_UserMarshal [OLE32.@]
124  *
125  * Marshals a clip format into a buffer.
126  *
127  * PARAMS
128  *  pFlags  [I] Flags. See notes.
129  *  pBuffer [I] Buffer to marshal the clip format into.
130  *  pCF     [I] Clip format to marshal.
131  *
132  * RETURNS
133  *  The end of the marshaled data in the buffer.
134  *
135  * NOTES
136  *  Even though the function is documented to take a pointer to an unsigned
137  *  long in pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
138  *  the first parameter is an unsigned long.
139  *  This function is only intended to be called by the RPC runtime.
140  */
141 unsigned char * __RPC_USER CLIPFORMAT_UserMarshal(ULONG *pFlags, unsigned char *pBuffer, CLIPFORMAT *pCF)
142 {
143     wireCLIPFORMAT wirecf = (wireCLIPFORMAT)pBuffer;
144
145     TRACE("(%s, %p, &0x%04x\n", debugstr_user_flags(pFlags), pBuffer, *pCF);
146
147     wirecf->u.dwValue = *pCF;
148     pBuffer += sizeof(*wirecf);
149
150     /* only need to marshal the name if it is not a pre-defined type and
151      * we are going remote */
152     if ((*pCF >= 0xc000) && (LOWORD(*pFlags) == MSHCTX_DIFFERENTMACHINE))
153     {
154         WCHAR format[255];
155         INT len;
156         wirecf->fContext = WDT_REMOTE_CALL;
157         len = GetClipboardFormatNameW(*pCF, format, sizeof(format)/sizeof(format[0])-1);
158         if (!len)
159             RaiseException(DV_E_CLIPFORMAT, 0, 0, NULL);
160         len += 1;
161         *(INT *)pBuffer = len;
162         pBuffer += sizeof(INT);
163         *(INT *)pBuffer = 0;
164         pBuffer += sizeof(INT);
165         *(INT *)pBuffer = len;
166         pBuffer += sizeof(INT);
167         TRACE("marshaling format name %s\n", debugstr_wn(format, len-1));
168         lstrcpynW((LPWSTR)pBuffer, format, len);
169         pBuffer += len * sizeof(WCHAR);
170         *(WCHAR *)pBuffer = '\0';
171         pBuffer += sizeof(WCHAR);
172     }
173     else
174         wirecf->fContext = WDT_INPROC_CALL;
175
176     return pBuffer;
177 }
178
179 /******************************************************************************
180  *           CLIPFORMAT_UserUnmarshal [OLE32.@]
181  *
182  * Unmarshals a clip format from a buffer.
183  *
184  * PARAMS
185  *  pFlags  [I] Flags. See notes.
186  *  pBuffer [I] Buffer to marshal the clip format from.
187  *  pCF     [O] Address that receive the unmarshaled clip format.
188  *
189  * RETURNS
190  *  The end of the marshaled data in the buffer.
191  *
192  * NOTES
193  *  Even though the function is documented to take a pointer to an unsigned
194  *  long in pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
195  *  the first parameter is an unsigned long.
196  *  This function is only intended to be called by the RPC runtime.
197  */
198 unsigned char * __RPC_USER CLIPFORMAT_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, CLIPFORMAT *pCF)
199 {
200     wireCLIPFORMAT wirecf = (wireCLIPFORMAT)pBuffer;
201
202     TRACE("(%s, %p, %p\n", debugstr_user_flags(pFlags), pBuffer, pCF);
203
204     pBuffer += sizeof(*wirecf);
205     if (wirecf->fContext == WDT_INPROC_CALL)
206         *pCF = (CLIPFORMAT)wirecf->u.dwValue;
207     else if (wirecf->fContext == WDT_REMOTE_CALL)
208     {
209         CLIPFORMAT cf;
210         INT len = *(INT *)pBuffer;
211         pBuffer += sizeof(INT);
212         if (*(INT *)pBuffer != 0)
213             RaiseException(RPC_S_INVALID_BOUND, 0, 0, NULL);
214         pBuffer += sizeof(INT);
215         if (*(INT *)pBuffer != len)
216             RaiseException(RPC_S_INVALID_BOUND, 0, 0, NULL);
217         pBuffer += sizeof(INT);
218         if (((WCHAR *)pBuffer)[len] != '\0')
219             RaiseException(RPC_S_INVALID_BOUND, 0, 0, NULL);
220         TRACE("unmarshaling clip format %s\n", debugstr_w((LPCWSTR)pBuffer));
221         cf = RegisterClipboardFormatW((LPCWSTR)pBuffer);
222         pBuffer += (len + 1) * sizeof(WCHAR);
223         if (!cf)
224             RaiseException(DV_E_CLIPFORMAT, 0, 0, NULL);
225         *pCF = cf;
226     }
227     else
228         /* code not really appropriate, but nearest I can find */
229         RaiseException(RPC_S_INVALID_TAG, 0, 0, NULL);
230     return pBuffer;
231 }
232
233 /******************************************************************************
234  *           CLIPFORMAT_UserFree [OLE32.@]
235  *
236  * Frees an unmarshaled clip format.
237  *
238  * PARAMS
239  *  pFlags  [I] Flags. See notes.
240  *  pCF     [I] Clip format to free.
241  *
242  * RETURNS
243  *  The end of the marshaled data in the buffer.
244  *
245  * NOTES
246  *  Even though the function is documented to take a pointer to an unsigned
247  *  long in pFlags, it actually takes a pointer to a USER_MARSHAL_CB
248  *  structure, of which the first parameter is an unsigned long.
249  *  This function is only intended to be called by the RPC runtime.
250  */
251 void __RPC_USER CLIPFORMAT_UserFree(ULONG *pFlags, CLIPFORMAT *pCF)
252 {
253     /* there is no inverse of the RegisterClipboardFormat function,
254      * so nothing to do */
255 }
256
257 static ULONG __RPC_USER handle_UserSize(ULONG *pFlags, ULONG StartingSize, HANDLE *handle)
258 {
259     if (LOWORD(*pFlags) == MSHCTX_DIFFERENTMACHINE)
260     {
261         ERR("can't remote a local handle\n");
262         RaiseException(RPC_S_INVALID_TAG, 0, 0, NULL);
263         return StartingSize;
264     }
265     return StartingSize + sizeof(RemotableHandle);
266 }
267
268 static unsigned char * __RPC_USER handle_UserMarshal(ULONG *pFlags, unsigned char *pBuffer, HANDLE *handle)
269 {
270     RemotableHandle *remhandle = (RemotableHandle *)pBuffer;
271     if (LOWORD(*pFlags) == MSHCTX_DIFFERENTMACHINE)
272     {
273         ERR("can't remote a local handle\n");
274         RaiseException(RPC_S_INVALID_TAG, 0, 0, NULL);
275         return pBuffer;
276     }
277     remhandle->fContext = WDT_INPROC_CALL;
278     remhandle->u.hInproc = (LONG_PTR)*handle;
279     return pBuffer + sizeof(RemotableHandle);
280 }
281
282 static unsigned char * __RPC_USER handle_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, HANDLE *handle)
283 {
284     RemotableHandle *remhandle = (RemotableHandle *)pBuffer;
285     if (remhandle->fContext != WDT_INPROC_CALL)
286         RaiseException(RPC_X_BAD_STUB_DATA, 0, 0, NULL);
287     *handle = (HANDLE)remhandle->u.hInproc;
288     return pBuffer + sizeof(RemotableHandle);
289 }
290
291 static void __RPC_USER handle_UserFree(ULONG *pFlags, HANDLE *phMenu)
292 {
293     /* nothing to do */
294 }
295
296 #define IMPL_WIREM_HANDLE(type) \
297     ULONG __RPC_USER type##_UserSize(ULONG *pFlags, ULONG StartingSize, type *handle) \
298     { \
299         TRACE("(%s, %d, %p\n", debugstr_user_flags(pFlags), StartingSize, handle); \
300         return handle_UserSize(pFlags, StartingSize, (HANDLE *)handle); \
301     } \
302     \
303     unsigned char * __RPC_USER type##_UserMarshal(ULONG *pFlags, unsigned char *pBuffer, type *handle) \
304     { \
305         TRACE("(%s, %p, &%p\n", debugstr_user_flags(pFlags), pBuffer, *handle); \
306         return handle_UserMarshal(pFlags, pBuffer, (HANDLE *)handle); \
307     } \
308     \
309     unsigned char * __RPC_USER type##_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, type *handle) \
310     { \
311         TRACE("(%s, %p, %p\n", debugstr_user_flags(pFlags), pBuffer, handle); \
312         return handle_UserUnmarshal(pFlags, pBuffer, (HANDLE *)handle); \
313     } \
314     \
315     void __RPC_USER type##_UserFree(ULONG *pFlags, type *handle) \
316     { \
317         TRACE("(%s, &%p\n", debugstr_user_flags(pFlags), *handle); \
318         return handle_UserFree(pFlags, (HANDLE *)handle); \
319     }
320
321 IMPL_WIREM_HANDLE(HACCEL)
322 IMPL_WIREM_HANDLE(HMENU)
323 IMPL_WIREM_HANDLE(HWND)
324
325 /******************************************************************************
326  *           HGLOBAL_UserSize [OLE32.@]
327  */
328 ULONG __RPC_USER HGLOBAL_UserSize(ULONG *pFlags, ULONG StartingSize, HGLOBAL *phGlobal)
329 {
330     ULONG size = StartingSize;
331
332     TRACE("(%s, %d, %p\n", debugstr_user_flags(pFlags), StartingSize, phGlobal);
333
334     ALIGN_LENGTH(size, 3);
335
336     size += sizeof(ULONG);
337
338     if (LOWORD(*pFlags == MSHCTX_INPROC))
339         size += sizeof(HGLOBAL);
340     else
341     {
342         size += sizeof(ULONG);
343         if (*phGlobal)
344         {
345             SIZE_T ret;
346             size += 3 * sizeof(ULONG);
347             ret = GlobalSize(*phGlobal);
348             size += (ULONG)ret;
349         }
350     }
351     
352     return size;
353 }
354
355 unsigned char * __RPC_USER HGLOBAL_UserMarshal(ULONG *pFlags, unsigned char *pBuffer, HGLOBAL *phGlobal)
356 {
357     TRACE("(%s, %p, &%p\n", debugstr_user_flags(pFlags), pBuffer, *phGlobal);
358
359     ALIGN_POINTER(pBuffer, 3);
360
361     if (LOWORD(*pFlags == MSHCTX_INPROC))
362     {
363         if (sizeof(*phGlobal) == 8)
364             *(ULONG *)pBuffer = WDT_INPROC64_CALL;
365         else
366             *(ULONG *)pBuffer = WDT_INPROC_CALL;
367         pBuffer += sizeof(ULONG);
368         *(HGLOBAL *)pBuffer = *phGlobal;
369         pBuffer += sizeof(HGLOBAL);
370     }
371     else
372     {
373         *(ULONG *)pBuffer = WDT_REMOTE_CALL;
374         pBuffer += sizeof(ULONG);
375         *(ULONG *)pBuffer = (ULONG)*phGlobal;
376         pBuffer += sizeof(ULONG);
377         if (*phGlobal)
378         {
379             const unsigned char *memory;
380             SIZE_T size = GlobalSize(*phGlobal);
381             *(ULONG *)pBuffer = (ULONG)size;
382             pBuffer += sizeof(ULONG);
383             *(ULONG *)pBuffer = (ULONG)*phGlobal;
384             pBuffer += sizeof(ULONG);
385             *(ULONG *)pBuffer = (ULONG)size;
386             pBuffer += sizeof(ULONG);
387
388             memory = GlobalLock(*phGlobal);
389             memcpy(pBuffer, memory, size);
390             pBuffer += size;
391             GlobalUnlock(*phGlobal);
392         }
393     }
394
395     return pBuffer;
396 }
397
398 unsigned char * __RPC_USER HGLOBAL_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, HGLOBAL *phGlobal)
399 {
400     ULONG fContext;
401
402     TRACE("(%s, %p, &%p\n", debugstr_user_flags(pFlags), pBuffer, *phGlobal);
403
404     ALIGN_POINTER(pBuffer, 3);
405
406     fContext = *(ULONG *)pBuffer;
407     pBuffer += sizeof(ULONG);
408
409     if (((fContext == WDT_INPROC_CALL) && (sizeof(*phGlobal) < 8)) ||
410         ((fContext == WDT_INPROC64_CALL) && (sizeof(*phGlobal) == 8)))
411     {
412         *phGlobal = *(HGLOBAL *)pBuffer;
413         pBuffer += sizeof(*phGlobal);
414     }
415     else if (fContext == WDT_REMOTE_CALL)
416     {
417         ULONG handle;
418
419         handle = *(ULONG *)pBuffer;
420         pBuffer += sizeof(ULONG);
421
422         if (handle)
423         {
424             ULONG size;
425             void *memory;
426
427             size = *(ULONG *)pBuffer;
428             pBuffer += sizeof(ULONG);
429             /* redundancy is bad - it means you have to check consistency like
430              * this: */
431             if (*(ULONG *)pBuffer != handle)
432             {
433                 RaiseException(RPC_X_BAD_STUB_DATA, 0, 0, NULL);
434                 return pBuffer;
435             }
436             pBuffer += sizeof(ULONG);
437             /* redundancy is bad - it means you have to check consistency like
438              * this: */
439             if (*(ULONG *)pBuffer != size)
440             {
441                 RaiseException(RPC_X_BAD_STUB_DATA, 0, 0, NULL);
442                 return pBuffer;
443             }
444             pBuffer += sizeof(ULONG);
445
446             /* FIXME: check size is not too big */
447
448             *phGlobal = GlobalAlloc(GMEM_MOVEABLE, size);
449             memory = GlobalLock(*phGlobal);
450             memcpy(memory, pBuffer, size);
451             pBuffer += size;
452             GlobalUnlock(*phGlobal);
453         }
454         else
455             *phGlobal = NULL;
456     }
457     else
458         RaiseException(RPC_S_INVALID_TAG, 0, 0, NULL);
459
460     return pBuffer;
461 }
462
463 /******************************************************************************
464  *           HGLOBAL_UserFree [OLE32.@]
465  */
466 void __RPC_USER HGLOBAL_UserFree(ULONG *pFlags, HGLOBAL *phGlobal)
467 {
468     TRACE("(%s, &%p\n", debugstr_user_flags(pFlags), *phGlobal);
469
470     if (LOWORD(*pFlags != MSHCTX_INPROC) && *phGlobal)
471         GlobalFree(*phGlobal);
472 }
473
474 ULONG __RPC_USER HBITMAP_UserSize(ULONG *pFlags, ULONG StartingSize, HBITMAP *phBmp)
475 {
476     FIXME(":stub\n");
477     return StartingSize;
478 }
479
480 unsigned char * __RPC_USER HBITMAP_UserMarshal(ULONG *pFlags, unsigned char *pBuffer, HBITMAP *phBmp)
481 {
482     FIXME(":stub\n");
483     return pBuffer;
484 }
485
486 unsigned char * __RPC_USER HBITMAP_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, HBITMAP *phBmp)
487 {
488     FIXME(":stub\n");
489     return pBuffer;
490 }
491
492 void __RPC_USER HBITMAP_UserFree(ULONG *pFlags, HBITMAP *phBmp)
493 {
494     FIXME(":stub\n");
495 }
496
497 ULONG __RPC_USER HDC_UserSize(ULONG *pFlags, ULONG StartingSize, HDC *phdc)
498 {
499     FIXME(":stub\n");
500     return StartingSize;
501 }
502
503 unsigned char * __RPC_USER HDC_UserMarshal(ULONG *pFlags, unsigned char *pBuffer, HDC *phdc)
504 {
505     FIXME(":stub\n");
506     return pBuffer;
507 }
508
509 unsigned char * __RPC_USER HDC_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, HDC *phdc)
510 {
511     FIXME(":stub\n");
512     return pBuffer;
513 }
514
515 void __RPC_USER HDC_UserFree(ULONG *pFlags, HDC *phdc)
516 {
517     FIXME(":stub\n");
518 }
519
520 ULONG __RPC_USER HPALETTE_UserSize(ULONG *pFlags, ULONG StartingSize, HPALETTE *phPal)
521 {
522     FIXME(":stub\n");
523     return StartingSize;
524 }
525
526 unsigned char * __RPC_USER HPALETTE_UserMarshal(ULONG *pFlags, unsigned char *pBuffer, HPALETTE *phPal)
527 {
528     FIXME(":stub\n");
529     return pBuffer;
530 }
531
532 unsigned char * __RPC_USER HPALETTE_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, HPALETTE *phPal)
533 {
534     FIXME(":stub\n");
535     return pBuffer;
536 }
537
538 void __RPC_USER HPALETTE_UserFree(ULONG *pFlags, HPALETTE *phPal)
539 {
540     FIXME(":stub\n");
541 }
542
543
544 ULONG __RPC_USER HENHMETAFILE_UserSize(ULONG *pFlags, ULONG StartingSize, HENHMETAFILE *phEmf)
545 {
546     ULONG size = StartingSize;
547
548     TRACE("(%s, %d, %p\n", debugstr_user_flags(pFlags), StartingSize, *phEmf);
549
550     size += sizeof(ULONG);
551     if (LOWORD(*pFlags) == MSHCTX_INPROC)
552         size += sizeof(ULONG_PTR);
553     else
554     {
555         size += sizeof(ULONG);
556
557         if (*phEmf)
558         {
559             UINT emfsize;
560     
561             size += 2 * sizeof(ULONG);
562             emfsize = GetEnhMetaFileBits(*phEmf, 0, NULL);
563             size += emfsize;
564         }
565     }
566
567     return size;
568 }
569
570 unsigned char * __RPC_USER HENHMETAFILE_UserMarshal(ULONG *pFlags, unsigned char *pBuffer, HENHMETAFILE *phEmf)
571 {
572     TRACE("(%s, %p, &%p\n", debugstr_user_flags(pFlags), pBuffer, *phEmf);
573
574     if (LOWORD(*pFlags) == MSHCTX_INPROC)
575     {
576         if (sizeof(*phEmf) == 8)
577             *(ULONG *)pBuffer = WDT_INPROC64_CALL;
578         else
579             *(ULONG *)pBuffer = WDT_INPROC_CALL;
580         pBuffer += sizeof(ULONG);
581         *(HENHMETAFILE *)pBuffer = *phEmf;
582         pBuffer += sizeof(HENHMETAFILE);
583     }
584     else
585     {
586         *(ULONG *)pBuffer = WDT_REMOTE_CALL;
587         pBuffer += sizeof(ULONG);
588         *(ULONG *)pBuffer = (ULONG)(ULONG_PTR)*phEmf;
589         pBuffer += sizeof(ULONG);
590     
591         if (*phEmf)
592         {
593             UINT emfsize = GetEnhMetaFileBits(*phEmf, 0, NULL);
594     
595             *(ULONG *)pBuffer = emfsize;
596             pBuffer += sizeof(ULONG);
597             *(ULONG *)pBuffer = emfsize;
598             pBuffer += sizeof(ULONG);
599             GetEnhMetaFileBits(*phEmf, emfsize, pBuffer);
600             pBuffer += emfsize;
601         }
602     }
603
604     return pBuffer;
605 }
606
607 unsigned char * __RPC_USER HENHMETAFILE_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, HENHMETAFILE *phEmf)
608 {
609     ULONG fContext;
610
611     TRACE("(%s, %p, %p\n", debugstr_user_flags(pFlags), pBuffer, phEmf);
612
613     fContext = *(ULONG *)pBuffer;
614     pBuffer += sizeof(ULONG);
615
616     if (((fContext == WDT_INPROC_CALL) && (sizeof(*phEmf) < 8)) ||
617         ((fContext == WDT_INPROC64_CALL) && (sizeof(*phEmf) == 8)))
618     {
619         *phEmf = *(HENHMETAFILE *)pBuffer;
620         pBuffer += sizeof(*phEmf);
621     }
622     else if (fContext == WDT_REMOTE_CALL)
623     {
624         ULONG handle;
625
626         handle = *(ULONG *)pBuffer;
627         pBuffer += sizeof(ULONG);
628
629         if (handle)
630         {
631             ULONG size;
632             size = *(ULONG *)pBuffer;
633             pBuffer += sizeof(ULONG);
634             if (size != *(ULONG *)pBuffer)
635             {
636                 RaiseException(RPC_X_BAD_STUB_DATA, 0, 0, NULL);
637                 return pBuffer;
638             }
639             pBuffer += sizeof(ULONG);
640             *phEmf = SetEnhMetaFileBits(size, pBuffer);
641             pBuffer += size;
642         }
643         else 
644             *phEmf = NULL;
645     }
646     else
647         RaiseException(RPC_S_INVALID_TAG, 0, 0, NULL);
648
649     return pBuffer;
650 }
651
652 void __RPC_USER HENHMETAFILE_UserFree(ULONG *pFlags, HENHMETAFILE *phEmf)
653 {
654     TRACE("(%s, &%p\n", debugstr_user_flags(pFlags), *phEmf);
655
656     if (LOWORD(*pFlags) != MSHCTX_INPROC)
657         DeleteEnhMetaFile(*phEmf);
658 }
659
660 ULONG __RPC_USER STGMEDIUM_UserSize(ULONG *pFlags, ULONG StartingSize, STGMEDIUM *pStgMedium)
661 {
662     ULONG size = StartingSize;
663
664     TRACE("(%s, %d, %p\n", debugstr_user_flags(pFlags), StartingSize, pStgMedium);
665
666     ALIGN_LENGTH(size, 3);
667
668     size += 2 * sizeof(DWORD);
669     if (pStgMedium->tymed != TYMED_NULL)
670         size += sizeof(DWORD);
671
672     switch (pStgMedium->tymed)
673     {
674     case TYMED_NULL:
675         TRACE("TYMED_NULL\n");
676         break;
677     case TYMED_HGLOBAL:
678         TRACE("TYMED_HGLOBAL\n");
679         size = HGLOBAL_UserSize(pFlags, size, &pStgMedium->u.hGlobal);
680         break;
681     case TYMED_FILE:
682         FIXME("TYMED_FILE\n");
683         break;
684     case TYMED_ISTREAM:
685         FIXME("TYMED_ISTREAM\n");
686         break;
687     case TYMED_ISTORAGE:
688         FIXME("TYMED_ISTORAGE\n");
689         break;
690     case TYMED_GDI:
691         FIXME("TYMED_GDI\n");
692         break;
693     case TYMED_MFPICT:
694         FIXME("TYMED_MFPICT\n");
695         break;
696     case TYMED_ENHMF:
697         TRACE("TYMED_ENHMF\n");
698         size = HENHMETAFILE_UserSize(pFlags, size, &pStgMedium->u.hEnhMetaFile);
699         break;
700     default:
701         RaiseException(DV_E_TYMED, 0, 0, NULL);
702     }
703
704     if (pStgMedium->pUnkForRelease)
705         FIXME("buffer size pUnkForRelease\n");
706
707     return size;
708 }
709
710 unsigned char * __RPC_USER STGMEDIUM_UserMarshal(ULONG *pFlags, unsigned char *pBuffer, STGMEDIUM *pStgMedium)
711 {
712     TRACE("(%s, %p, %p\n", debugstr_user_flags(pFlags), pBuffer, pStgMedium);
713
714     ALIGN_POINTER(pBuffer, 3);
715
716     *(DWORD *)pBuffer = pStgMedium->tymed;
717     pBuffer += sizeof(DWORD);
718     if (pStgMedium->tymed != TYMED_NULL)
719     {
720         *(DWORD *)pBuffer = (DWORD)(DWORD_PTR)pStgMedium->u.pstg;
721         pBuffer += sizeof(DWORD);
722     }
723     *(DWORD *)pBuffer = (DWORD)(DWORD_PTR)pStgMedium->pUnkForRelease;
724     pBuffer += sizeof(DWORD);
725
726     switch (pStgMedium->tymed)
727     {
728     case TYMED_NULL:
729         TRACE("TYMED_NULL\n");
730         break;
731     case TYMED_HGLOBAL:
732         TRACE("TYMED_HGLOBAL\n");
733         pBuffer = HGLOBAL_UserMarshal(pFlags, pBuffer, &pStgMedium->u.hGlobal);
734         break;
735     case TYMED_FILE:
736         FIXME("TYMED_FILE\n");
737         break;
738     case TYMED_ISTREAM:
739         FIXME("TYMED_ISTREAM\n");
740         break;
741     case TYMED_ISTORAGE:
742         FIXME("TYMED_ISTORAGE\n");
743         break;
744     case TYMED_GDI:
745         FIXME("TYMED_GDI\n");
746         break;
747     case TYMED_MFPICT:
748         FIXME("TYMED_MFPICT\n");
749         break;
750     case TYMED_ENHMF:
751         TRACE("TYMED_ENHMF\n");
752         pBuffer = HENHMETAFILE_UserMarshal(pFlags, pBuffer, &pStgMedium->u.hEnhMetaFile);
753         break;
754     default:
755         RaiseException(DV_E_TYMED, 0, 0, NULL);
756     }
757
758     if (pStgMedium->pUnkForRelease)
759         FIXME("marshal pUnkForRelease\n");
760
761     return pBuffer;
762 }
763
764 unsigned char * __RPC_USER STGMEDIUM_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, STGMEDIUM *pStgMedium)
765 {
766     DWORD content;
767     DWORD releaseunk;
768
769     ALIGN_POINTER(pBuffer, 3);
770
771     TRACE("(%s, %p, %p\n", debugstr_user_flags(pFlags), pBuffer, pStgMedium);
772
773     pStgMedium->tymed = *(DWORD *)pBuffer;
774     pBuffer += sizeof(DWORD);
775     if (pStgMedium->tymed != TYMED_NULL)
776     {
777         content = *(DWORD *)pBuffer;
778         pBuffer += sizeof(DWORD);
779     }
780     releaseunk = *(DWORD *)pBuffer;
781     pBuffer += sizeof(DWORD);
782
783     switch (pStgMedium->tymed)
784     {
785     case TYMED_NULL:
786         TRACE("TYMED_NULL\n");
787         break;
788     case TYMED_HGLOBAL:
789         TRACE("TYMED_HGLOBAL\n");
790         pBuffer = HGLOBAL_UserUnmarshal(pFlags, pBuffer, &pStgMedium->u.hGlobal);
791         break;
792     case TYMED_FILE:
793         FIXME("TYMED_FILE\n");
794         break;
795     case TYMED_ISTREAM:
796         FIXME("TYMED_ISTREAM\n");
797         break;
798     case TYMED_ISTORAGE:
799         FIXME("TYMED_ISTORAGE\n");
800         break;
801     case TYMED_GDI:
802         FIXME("TYMED_GDI\n");
803         break;
804     case TYMED_MFPICT:
805         FIXME("TYMED_MFPICT\n");
806         break;
807     case TYMED_ENHMF:
808         TRACE("TYMED_ENHMF\n");
809         pBuffer = HENHMETAFILE_UserUnmarshal(pFlags, pBuffer, &pStgMedium->u.hEnhMetaFile);
810         break;
811     default:
812         RaiseException(DV_E_TYMED, 0, 0, NULL);
813     }
814
815     pStgMedium->pUnkForRelease = NULL;
816     if (releaseunk)
817         FIXME("unmarshal pUnkForRelease\n");
818
819     return pBuffer;
820 }
821
822 void __RPC_USER STGMEDIUM_UserFree(ULONG *pFlags, STGMEDIUM *pStgMedium)
823 {
824     TRACE("(%s, %p\n", debugstr_user_flags(pFlags), pStgMedium);
825
826     ReleaseStgMedium(pStgMedium);
827 }
828
829 ULONG __RPC_USER ASYNC_STGMEDIUM_UserSize(ULONG *pFlags, ULONG StartingSize, ASYNC_STGMEDIUM *pStgMedium)
830 {
831     FIXME(":stub\n");
832     return StartingSize;
833 }
834
835 unsigned char * __RPC_USER ASYNC_STGMEDIUM_UserMarshal(  ULONG *pFlags, unsigned char *pBuffer, ASYNC_STGMEDIUM *pStgMedium)
836 {
837     FIXME(":stub\n");
838     return pBuffer;
839 }
840
841 unsigned char * __RPC_USER ASYNC_STGMEDIUM_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, ASYNC_STGMEDIUM *pStgMedium)
842 {
843     FIXME(":stub\n");
844     return pBuffer;
845 }
846
847 void __RPC_USER ASYNC_STGMEDIUM_UserFree(ULONG *pFlags, ASYNC_STGMEDIUM *pStgMedium)
848 {
849     FIXME(":stub\n");
850 }
851
852 ULONG __RPC_USER FLAG_STGMEDIUM_UserSize(ULONG *pFlags, ULONG StartingSize, FLAG_STGMEDIUM *pStgMedium)
853 {
854     FIXME(":stub\n");
855     return StartingSize;
856 }
857
858 unsigned char * __RPC_USER FLAG_STGMEDIUM_UserMarshal(  ULONG *pFlags, unsigned char *pBuffer, FLAG_STGMEDIUM *pStgMedium)
859 {
860     FIXME(":stub\n");
861     return pBuffer;
862 }
863
864 unsigned char * __RPC_USER FLAG_STGMEDIUM_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, FLAG_STGMEDIUM *pStgMedium)
865 {
866     FIXME(":stub\n");
867     return pBuffer;
868 }
869
870 void __RPC_USER FLAG_STGMEDIUM_UserFree(ULONG *pFlags, FLAG_STGMEDIUM *pStgMedium)
871 {
872     FIXME(":stub\n");
873 }
874
875 ULONG __RPC_USER SNB_UserSize(ULONG *pFlags, ULONG StartingSize, SNB *pSnb)
876 {
877     FIXME(":stub\n");
878     return StartingSize;
879 }
880
881 unsigned char * __RPC_USER SNB_UserMarshal(  ULONG *pFlags, unsigned char *pBuffer, SNB *pSnb)
882 {
883     FIXME(":stub\n");
884     return pBuffer;
885 }
886
887 unsigned char * __RPC_USER SNB_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, SNB *pSnb)
888 {
889     FIXME(":stub\n");
890     return pBuffer;
891 }
892
893 void __RPC_USER SNB_UserFree(ULONG *pFlags, SNB *pSnb)
894 {
895     FIXME(":stub\n");
896 }