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