xref: /reactos/dll/win32/ole32/usrmarshal.c (revision c2c66aff)
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 "precomp.h"
22 
23 WINE_DEFAULT_DEBUG_CHANNEL(ole);
24 
25 #define ALIGNED_LENGTH(_Len, _Align) (((_Len)+(_Align))&~(_Align))
26 #define ALIGNED_POINTER(_Ptr, _Align) ((LPVOID)ALIGNED_LENGTH((ULONG_PTR)(_Ptr), _Align))
27 #define ALIGN_LENGTH(_Len, _Align) _Len = ALIGNED_LENGTH(_Len, _Align)
28 #define ALIGN_POINTER(_Ptr, _Align) _Ptr = ALIGNED_POINTER(_Ptr, _Align)
29 
30 #define USER_MARSHAL_PTR_PREFIX \
31   ( (DWORD)'U'         | ( (DWORD)'s' << 8 ) | \
32   ( (DWORD)'e' << 16 ) | ( (DWORD)'r' << 24 ) )
33 
34 static const char* debugstr_user_flags(ULONG *pFlags)
35 {
36     char buf[12];
37     const char* loword;
38     switch (LOWORD(*pFlags))
39     {
40     case MSHCTX_LOCAL:
41         loword="MSHCTX_LOCAL";
42         break;
43     case MSHCTX_NOSHAREDMEM:
44         loword="MSHCTX_NOSHAREDMEM";
45         break;
46     case MSHCTX_DIFFERENTMACHINE:
47         loword="MSHCTX_DIFFERENTMACHINE";
48         break;
49     case MSHCTX_INPROC:
50         loword="MSHCTX_INPROC";
51         break;
52     default:
53         sprintf(buf, "%d", LOWORD(*pFlags));
54         loword=buf;
55     }
56 
57     if (HIWORD(*pFlags) == NDR_LOCAL_DATA_REPRESENTATION)
58         return wine_dbg_sprintf("MAKELONG(%s, NDR_LOCAL_DATA_REPRESENTATION)", loword);
59     else
60         return wine_dbg_sprintf("MAKELONG(%s, 0x%04x)", loword, HIWORD(*pFlags));
61 }
62 
63 /******************************************************************************
64  *           CLIPFORMAT_UserSize [OLE32.@]
65  *
66  * Calculates the buffer size required to marshal a clip format.
67  *
68  * PARAMS
69  *  pFlags       [I] Flags. See notes.
70  *  StartingSize [I] Starting size of the buffer. This value is added on to
71  *                   the buffer size required for the clip format.
72  *  pCF          [I] Clip format to size.
73  *
74  * RETURNS
75  *  The buffer size required to marshal a clip format plus the starting size.
76  *
77  * NOTES
78  *  Even though the function is documented to take a pointer to an unsigned
79  *  long in pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
80  *  the first parameter is an unsigned long.
81  *  This function is only intended to be called by the RPC runtime.
82  */
83 ULONG __RPC_USER CLIPFORMAT_UserSize(ULONG *pFlags, ULONG StartingSize, CLIPFORMAT *pCF)
84 {
85     ULONG size = StartingSize;
86 
87     TRACE("(%s, %d, %p\n", debugstr_user_flags(pFlags), StartingSize, pCF);
88 
89     size += 8;
90 
91     /* only need to marshal the name if it is not a pre-defined type and
92      * we are going remote */
93     if ((*pCF >= 0xc000) && (LOWORD(*pFlags) == MSHCTX_DIFFERENTMACHINE))
94     {
95         WCHAR format[255];
96         INT ret;
97         size += 3 * sizeof(UINT);
98         /* urg! this function is badly designed because it won't tell us how
99          * much space is needed without doing a dummy run of storing the
100          * name into a buffer */
101         ret = GetClipboardFormatNameW(*pCF, format, sizeof(format)/sizeof(format[0])-1);
102         if (!ret)
103             RaiseException(DV_E_CLIPFORMAT, 0, 0, NULL);
104         size += (ret + 1) * sizeof(WCHAR);
105     }
106     return size;
107 }
108 
109 /******************************************************************************
110  *           CLIPFORMAT_UserMarshal [OLE32.@]
111  *
112  * Marshals a clip format into a buffer.
113  *
114  * PARAMS
115  *  pFlags  [I] Flags. See notes.
116  *  pBuffer [I] Buffer to marshal the clip format into.
117  *  pCF     [I] Clip format to marshal.
118  *
119  * RETURNS
120  *  The end of the marshaled data in the buffer.
121  *
122  * NOTES
123  *  Even though the function is documented to take a pointer to an unsigned
124  *  long in pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
125  *  the first parameter is an unsigned long.
126  *  This function is only intended to be called by the RPC runtime.
127  */
128 unsigned char * __RPC_USER CLIPFORMAT_UserMarshal(ULONG *pFlags, unsigned char *pBuffer, CLIPFORMAT *pCF)
129 {
130     TRACE("(%s, %p, &0x%04x\n", debugstr_user_flags(pFlags), pBuffer, *pCF);
131 
132     /* only need to marshal the name if it is not a pre-defined type and
133      * we are going remote */
134     if ((*pCF >= 0xc000) && (LOWORD(*pFlags) == MSHCTX_DIFFERENTMACHINE))
135     {
136         WCHAR format[255];
137         UINT len;
138 
139         *(DWORD *)pBuffer = WDT_REMOTE_CALL;
140         pBuffer += 4;
141         *(DWORD *)pBuffer = *pCF;
142         pBuffer += 4;
143 
144         len = GetClipboardFormatNameW(*pCF, format, sizeof(format)/sizeof(format[0])-1);
145         if (!len)
146             RaiseException(DV_E_CLIPFORMAT, 0, 0, NULL);
147         len += 1;
148         *(UINT *)pBuffer = len;
149         pBuffer += sizeof(UINT);
150         *(UINT *)pBuffer = 0;
151         pBuffer += sizeof(UINT);
152         *(UINT *)pBuffer = len;
153         pBuffer += sizeof(UINT);
154         TRACE("marshaling format name %s\n", debugstr_w(format));
155         memcpy(pBuffer, format, len * sizeof(WCHAR));
156         pBuffer += len * sizeof(WCHAR);
157     }
158     else
159     {
160         *(DWORD *)pBuffer = WDT_INPROC_CALL;
161         pBuffer += 4;
162         *(DWORD *)pBuffer = *pCF;
163         pBuffer += 4;
164     }
165 
166     return pBuffer;
167 }
168 
169 /******************************************************************************
170  *           CLIPFORMAT_UserUnmarshal [OLE32.@]
171  *
172  * Unmarshals a clip format from a buffer.
173  *
174  * PARAMS
175  *  pFlags  [I] Flags. See notes.
176  *  pBuffer [I] Buffer to marshal the clip format from.
177  *  pCF     [O] Address that receive the unmarshaled clip format.
178  *
179  * RETURNS
180  *  The end of the marshaled data in the buffer.
181  *
182  * NOTES
183  *  Even though the function is documented to take a pointer to an unsigned
184  *  long in pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
185  *  the first parameter is an unsigned long.
186  *  This function is only intended to be called by the RPC runtime.
187  */
188 unsigned char * __RPC_USER CLIPFORMAT_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, CLIPFORMAT *pCF)
189 {
190     LONG fContext;
191 
192     TRACE("(%s, %p, %p\n", debugstr_user_flags(pFlags), pBuffer, pCF);
193 
194     fContext = *(DWORD *)pBuffer;
195     pBuffer += 4;
196 
197     if (fContext == WDT_INPROC_CALL)
198     {
199         *pCF = *(CLIPFORMAT *)pBuffer;
200         pBuffer += 4;
201     }
202     else if (fContext == WDT_REMOTE_CALL)
203     {
204         CLIPFORMAT cf;
205         UINT len;
206 
207         /* pointer ID for registered clip format string */
208         if (*(DWORD *)pBuffer == 0)
209             RaiseException(RPC_S_INVALID_BOUND, 0, 0, NULL);
210         pBuffer += 4;
211 
212         len = *(UINT *)pBuffer;
213         pBuffer += sizeof(UINT);
214         if (*(UINT *)pBuffer != 0)
215             RaiseException(RPC_S_INVALID_BOUND, 0, 0, NULL);
216         pBuffer += sizeof(UINT);
217         if (*(UINT *)pBuffer != len)
218             RaiseException(RPC_S_INVALID_BOUND, 0, 0, NULL);
219         pBuffer += sizeof(UINT);
220         if (((WCHAR *)pBuffer)[len - 1] != '\0')
221             RaiseException(RPC_S_INVALID_BOUND, 0, 0, NULL);
222         TRACE("unmarshaling clip format %s\n", debugstr_w((LPCWSTR)pBuffer));
223         cf = RegisterClipboardFormatW((LPCWSTR)pBuffer);
224         pBuffer += len * sizeof(WCHAR);
225         if (!cf)
226             RaiseException(DV_E_CLIPFORMAT, 0, 0, NULL);
227         *pCF = cf;
228     }
229     else
230         /* code not really appropriate, but nearest I can find */
231         RaiseException(RPC_S_INVALID_TAG, 0, 0, NULL);
232     return pBuffer;
233 }
234 
235 /******************************************************************************
236  *           CLIPFORMAT_UserFree [OLE32.@]
237  *
238  * Frees an unmarshaled clip format.
239  *
240  * PARAMS
241  *  pFlags  [I] Flags. See notes.
242  *  pCF     [I] Clip format to free.
243  *
244  * RETURNS
245  *  The end of the marshaled data in the buffer.
246  *
247  * NOTES
248  *  Even though the function is documented to take a pointer to an unsigned
249  *  long in pFlags, it actually takes a pointer to a USER_MARSHAL_CB
250  *  structure, of which the first parameter is an unsigned long.
251  *  This function is only intended to be called by the RPC runtime.
252  */
253 void __RPC_USER CLIPFORMAT_UserFree(ULONG *pFlags, CLIPFORMAT *pCF)
254 {
255     /* there is no inverse of the RegisterClipboardFormat function,
256      * so nothing to do */
257 }
258 
259 static ULONG handle_UserSize(ULONG *pFlags, ULONG StartingSize, HANDLE *handle)
260 {
261     if (LOWORD(*pFlags) == MSHCTX_DIFFERENTMACHINE)
262     {
263         ERR("can't remote a local handle\n");
264         RaiseException(RPC_S_INVALID_TAG, 0, 0, NULL);
265         return StartingSize;
266     }
267     return StartingSize + sizeof(RemotableHandle);
268 }
269 
270 static unsigned char * handle_UserMarshal(ULONG *pFlags, unsigned char *pBuffer, HANDLE *handle)
271 {
272     RemotableHandle *remhandle = (RemotableHandle *)pBuffer;
273     if (LOWORD(*pFlags) == MSHCTX_DIFFERENTMACHINE)
274     {
275         ERR("can't remote a local handle\n");
276         RaiseException(RPC_S_INVALID_TAG, 0, 0, NULL);
277         return pBuffer;
278     }
279     remhandle->fContext = WDT_INPROC_CALL;
280     remhandle->u.hInproc = (LONG_PTR)*handle;
281     return pBuffer + sizeof(RemotableHandle);
282 }
283 
284 static unsigned char * handle_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, HANDLE *handle)
285 {
286     RemotableHandle *remhandle = (RemotableHandle *)pBuffer;
287     if (remhandle->fContext != WDT_INPROC_CALL)
288         RaiseException(RPC_X_BAD_STUB_DATA, 0, 0, NULL);
289     *handle = (HANDLE)(LONG_PTR)remhandle->u.hInproc;
290     return pBuffer + sizeof(RemotableHandle);
291 }
292 
293 static void handle_UserFree(ULONG *pFlags, HANDLE *handle)
294 {
295     /* nothing to do */
296 }
297 
298 #define IMPL_WIREM_HANDLE(type) \
299     ULONG __RPC_USER type##_UserSize(ULONG *pFlags, ULONG StartingSize, type *handle) \
300     { \
301         TRACE("(%s, %d, %p\n", debugstr_user_flags(pFlags), StartingSize, handle); \
302         return handle_UserSize(pFlags, StartingSize, (HANDLE *)handle); \
303     } \
304     \
305     unsigned char * __RPC_USER type##_UserMarshal(ULONG *pFlags, unsigned char *pBuffer, type *handle) \
306     { \
307         TRACE("(%s, %p, &%p\n", debugstr_user_flags(pFlags), pBuffer, *handle); \
308         return handle_UserMarshal(pFlags, pBuffer, (HANDLE *)handle); \
309     } \
310     \
311     unsigned char * __RPC_USER type##_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, type *handle) \
312     { \
313         TRACE("(%s, %p, %p\n", debugstr_user_flags(pFlags), pBuffer, handle); \
314         return handle_UserUnmarshal(pFlags, pBuffer, (HANDLE *)handle); \
315     } \
316     \
317     void __RPC_USER type##_UserFree(ULONG *pFlags, type *handle) \
318     { \
319         TRACE("(%s, &%p\n", debugstr_user_flags(pFlags), *handle); \
320         handle_UserFree(pFlags, (HANDLE *)handle); \
321     }
322 
323 IMPL_WIREM_HANDLE(HACCEL)
324 IMPL_WIREM_HANDLE(HMENU)
325 IMPL_WIREM_HANDLE(HWND)
326 IMPL_WIREM_HANDLE(HDC)
327 IMPL_WIREM_HANDLE(HICON)
328 IMPL_WIREM_HANDLE(HBRUSH)
329 
330 /******************************************************************************
331  *           HGLOBAL_UserSize [OLE32.@]
332  *
333  * Calculates the buffer size required to marshal an HGLOBAL.
334  *
335  * PARAMS
336  *  pFlags       [I] Flags. See notes.
337  *  StartingSize [I] Starting size of the buffer. This value is added on to
338  *                   the buffer size required for the clip format.
339  *  phGlobal     [I] HGLOBAL to size.
340  *
341  * RETURNS
342  *  The buffer size required to marshal an HGLOBAL plus the starting size.
343  *
344  * NOTES
345  *  Even though the function is documented to take a pointer to a ULONG in
346  *  pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
347  *  the first parameter is a ULONG.
348  *  This function is only intended to be called by the RPC runtime.
349  */
350 ULONG __RPC_USER HGLOBAL_UserSize(ULONG *pFlags, ULONG StartingSize, HGLOBAL *phGlobal)
351 {
352     ULONG size = StartingSize;
353 
354     TRACE("(%s, %d, %p\n", debugstr_user_flags(pFlags), StartingSize, phGlobal);
355 
356     ALIGN_LENGTH(size, 3);
357 
358     size += sizeof(ULONG);
359 
360     if (LOWORD(*pFlags == MSHCTX_INPROC))
361         size += sizeof(HGLOBAL);
362     else
363     {
364         size += sizeof(ULONG);
365         if (*phGlobal)
366         {
367             SIZE_T ret;
368             size += 3 * sizeof(ULONG);
369             ret = GlobalSize(*phGlobal);
370             size += (ULONG)ret;
371         }
372     }
373 
374     return size;
375 }
376 
377 /******************************************************************************
378  *           HGLOBAL_UserMarshal [OLE32.@]
379  *
380  * Marshals an HGLOBAL into a buffer.
381  *
382  * PARAMS
383  *  pFlags   [I] Flags. See notes.
384  *  pBuffer  [I] Buffer to marshal the clip format into.
385  *  phGlobal [I] HGLOBAL to marshal.
386  *
387  * RETURNS
388  *  The end of the marshaled data in the buffer.
389  *
390  * NOTES
391  *  Even though the function is documented to take a pointer to a ULONG in
392  *  pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
393  *  the first parameter is a ULONG.
394  *  This function is only intended to be called by the RPC runtime.
395  */
396 unsigned char * __RPC_USER HGLOBAL_UserMarshal(ULONG *pFlags, unsigned char *pBuffer, HGLOBAL *phGlobal)
397 {
398     TRACE("(%s, %p, &%p\n", debugstr_user_flags(pFlags), pBuffer, *phGlobal);
399 
400     ALIGN_POINTER(pBuffer, 3);
401 
402     if (LOWORD(*pFlags == MSHCTX_INPROC))
403     {
404         if (sizeof(*phGlobal) == 8)
405             *(ULONG *)pBuffer = WDT_INPROC64_CALL;
406         else
407             *(ULONG *)pBuffer = WDT_INPROC_CALL;
408         pBuffer += sizeof(ULONG);
409         *(HGLOBAL *)pBuffer = *phGlobal;
410         pBuffer += sizeof(HGLOBAL);
411     }
412     else
413     {
414         *(ULONG *)pBuffer = WDT_REMOTE_CALL;
415         pBuffer += sizeof(ULONG);
416         *(ULONG *)pBuffer = HandleToULong(*phGlobal);
417         pBuffer += sizeof(ULONG);
418         if (*phGlobal)
419         {
420             const unsigned char *memory;
421             SIZE_T size = GlobalSize(*phGlobal);
422             *(ULONG *)pBuffer = (ULONG)size;
423             pBuffer += sizeof(ULONG);
424             *(ULONG *)pBuffer = HandleToULong(*phGlobal);
425             pBuffer += sizeof(ULONG);
426             *(ULONG *)pBuffer = (ULONG)size;
427             pBuffer += sizeof(ULONG);
428 
429             memory = GlobalLock(*phGlobal);
430             memcpy(pBuffer, memory, size);
431             pBuffer += size;
432             GlobalUnlock(*phGlobal);
433         }
434     }
435 
436     return pBuffer;
437 }
438 
439 /******************************************************************************
440  *           HGLOBAL_UserUnmarshal [OLE32.@]
441  *
442  * Unmarshals an HGLOBAL from a buffer.
443  *
444  * PARAMS
445  *  pFlags   [I] Flags. See notes.
446  *  pBuffer  [I] Buffer to marshal the clip format from.
447  *  phGlobal [O] Address that receive the unmarshaled HGLOBAL.
448  *
449  * RETURNS
450  *  The end of the marshaled data in the buffer.
451  *
452  * NOTES
453  *  Even though the function is documented to take a pointer to an ULONG in
454  *  pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
455  *  the first parameter is an ULONG.
456  *  This function is only intended to be called by the RPC runtime.
457  */
458 unsigned char * __RPC_USER HGLOBAL_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, HGLOBAL *phGlobal)
459 {
460     ULONG fContext;
461 
462     TRACE("(%s, %p, &%p\n", debugstr_user_flags(pFlags), pBuffer, *phGlobal);
463 
464     ALIGN_POINTER(pBuffer, 3);
465 
466     fContext = *(ULONG *)pBuffer;
467     pBuffer += sizeof(ULONG);
468 
469     if (((fContext == WDT_INPROC_CALL) && (sizeof(*phGlobal) < 8)) ||
470         ((fContext == WDT_INPROC64_CALL) && (sizeof(*phGlobal) == 8)))
471     {
472         *phGlobal = *(HGLOBAL *)pBuffer;
473         pBuffer += sizeof(*phGlobal);
474     }
475     else if (fContext == WDT_REMOTE_CALL)
476     {
477         ULONG handle;
478 
479         handle = *(ULONG *)pBuffer;
480         pBuffer += sizeof(ULONG);
481 
482         if (handle)
483         {
484             ULONG size;
485             void *memory;
486 
487             size = *(ULONG *)pBuffer;
488             pBuffer += sizeof(ULONG);
489             /* redundancy is bad - it means you have to check consistency like
490              * this: */
491             if (*(ULONG *)pBuffer != handle)
492             {
493                 RaiseException(RPC_X_BAD_STUB_DATA, 0, 0, NULL);
494                 return pBuffer;
495             }
496             pBuffer += sizeof(ULONG);
497             /* redundancy is bad - it means you have to check consistency like
498              * this: */
499             if (*(ULONG *)pBuffer != size)
500             {
501                 RaiseException(RPC_X_BAD_STUB_DATA, 0, 0, NULL);
502                 return pBuffer;
503             }
504             pBuffer += sizeof(ULONG);
505 
506             /* FIXME: check size is not too big */
507 
508             *phGlobal = GlobalAlloc(GMEM_MOVEABLE, size);
509             memory = GlobalLock(*phGlobal);
510             memcpy(memory, pBuffer, size);
511             pBuffer += size;
512             GlobalUnlock(*phGlobal);
513         }
514         else
515             *phGlobal = NULL;
516     }
517     else
518         RaiseException(RPC_S_INVALID_TAG, 0, 0, NULL);
519 
520     return pBuffer;
521 }
522 
523 /******************************************************************************
524  *           HGLOBAL_UserFree [OLE32.@]
525  *
526  * Frees an unmarshaled HGLOBAL.
527  *
528  * PARAMS
529  *  pFlags   [I] Flags. See notes.
530  *  phGlobal [I] HGLOBAL to free.
531  *
532  * RETURNS
533  *  The end of the marshaled data in the buffer.
534  *
535  * NOTES
536  *  Even though the function is documented to take a pointer to a ULONG in
537  *  pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of
538  *  which the first parameter is a ULONG.
539  *  This function is only intended to be called by the RPC runtime.
540  */
541 void __RPC_USER HGLOBAL_UserFree(ULONG *pFlags, HGLOBAL *phGlobal)
542 {
543     TRACE("(%s, &%p\n", debugstr_user_flags(pFlags), *phGlobal);
544 
545     if (LOWORD(*pFlags != MSHCTX_INPROC) && *phGlobal)
546         GlobalFree(*phGlobal);
547 }
548 
549 /******************************************************************************
550  *           HBITMAP_UserSize [OLE32.@]
551  *
552  * Calculates the buffer size required to marshal a bitmap.
553  *
554  * PARAMS
555  *  pFlags       [I] Flags. See notes.
556  *  StartingSize [I] Starting size of the buffer. This value is added on to
557  *                   the buffer size required for the clip format.
558  *  phBmp        [I] Bitmap to size.
559  *
560  * RETURNS
561  *  The buffer size required to marshal an bitmap plus the starting size.
562  *
563  * NOTES
564  *  Even though the function is documented to take a pointer to a ULONG in
565  *  pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
566  *  the first parameter is a ULONG.
567  *  This function is only intended to be called by the RPC runtime.
568  */
569 ULONG __RPC_USER HBITMAP_UserSize(ULONG *pFlags, ULONG StartingSize, HBITMAP *phBmp)
570 {
571     FIXME(":stub\n");
572     return StartingSize;
573 }
574 
575 /******************************************************************************
576 *           HBITMAP_UserMarshal [OLE32.@]
577 *
578 * Marshals a bitmap into a buffer.
579 *
580 * PARAMS
581 *  pFlags  [I] Flags. See notes.
582 *  pBuffer [I] Buffer to marshal the clip format into.
583 *  phBmp   [I] Bitmap to marshal.
584 *
585 * RETURNS
586 *  The end of the marshaled data in the buffer.
587 *
588 * NOTES
589 *  Even though the function is documented to take a pointer to a ULONG in
590 *  pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
591 *  the first parameter is a ULONG.
592 *  This function is only intended to be called by the RPC runtime.
593 */
594 unsigned char * __RPC_USER HBITMAP_UserMarshal(ULONG *pFlags, unsigned char *pBuffer, HBITMAP *phBmp)
595 {
596     FIXME(":stub\n");
597     return pBuffer;
598 }
599 
600 /******************************************************************************
601  *           HBITMAP_UserUnmarshal [OLE32.@]
602  *
603  * Unmarshals a bitmap from a buffer.
604  *
605  * PARAMS
606  *  pFlags   [I] Flags. See notes.
607  *  pBuffer  [I] Buffer to marshal the clip format from.
608  *  phBmp    [O] Address that receive the unmarshaled bitmap.
609  *
610  * RETURNS
611  *  The end of the marshaled data in the buffer.
612  *
613  * NOTES
614  *  Even though the function is documented to take a pointer to an ULONG in
615  *  pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
616  *  the first parameter is an ULONG.
617  *  This function is only intended to be called by the RPC runtime.
618  */
619 unsigned char * __RPC_USER HBITMAP_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, HBITMAP *phBmp)
620 {
621     FIXME(":stub\n");
622     return pBuffer;
623 }
624 
625 /******************************************************************************
626  *           HBITMAP_UserFree [OLE32.@]
627  *
628  * Frees an unmarshaled bitmap.
629  *
630  * PARAMS
631  *  pFlags   [I] Flags. See notes.
632  *  phBmp    [I] Bitmap to free.
633  *
634  * RETURNS
635  *  The end of the marshaled data in the buffer.
636  *
637  * NOTES
638  *  Even though the function is documented to take a pointer to a ULONG in
639  *  pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of
640  *  which the first parameter is a ULONG.
641  *  This function is only intended to be called by the RPC runtime.
642  */
643 void __RPC_USER HBITMAP_UserFree(ULONG *pFlags, HBITMAP *phBmp)
644 {
645     FIXME(":stub\n");
646 }
647 
648 /******************************************************************************
649  *           HPALETTE_UserSize [OLE32.@]
650  *
651  * Calculates the buffer size required to marshal a palette.
652  *
653  * PARAMS
654  *  pFlags       [I] Flags. See notes.
655  *  StartingSize [I] Starting size of the buffer. This value is added on to
656  *                   the buffer size required for the clip format.
657  *  phPal        [I] Palette to size.
658  *
659  * RETURNS
660  *  The buffer size required to marshal a palette plus the starting size.
661  *
662  * NOTES
663  *  Even though the function is documented to take a pointer to a ULONG in
664  *  pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
665  *  the first parameter is a ULONG.
666  *  This function is only intended to be called by the RPC runtime.
667  */
668 ULONG __RPC_USER HPALETTE_UserSize(ULONG *pFlags, ULONG StartingSize, HPALETTE *phPal)
669 {
670     FIXME(":stub\n");
671     return StartingSize;
672 }
673 
674 /******************************************************************************
675  *           HPALETTE_UserMarshal [OLE32.@]
676  *
677  * Marshals a palette into a buffer.
678  *
679  * PARAMS
680  *  pFlags  [I] Flags. See notes.
681  *  pBuffer [I] Buffer to marshal the clip format into.
682  *  phPal   [I] Palette to marshal.
683  *
684  * RETURNS
685  *  The end of the marshaled data in the buffer.
686  *
687  * NOTES
688  *  Even though the function is documented to take a pointer to a ULONG in
689  *  pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
690  *  the first parameter is a ULONG.
691  *  This function is only intended to be called by the RPC runtime.
692  */
693 unsigned char * __RPC_USER HPALETTE_UserMarshal(ULONG *pFlags, unsigned char *pBuffer, HPALETTE *phPal)
694 {
695     FIXME(":stub\n");
696     return pBuffer;
697 }
698 
699 /******************************************************************************
700  *           HPALETTE_UserUnmarshal [OLE32.@]
701  *
702  * Unmarshals a palette from a buffer.
703  *
704  * PARAMS
705  *  pFlags   [I] Flags. See notes.
706  *  pBuffer  [I] Buffer to marshal the clip format from.
707  *  phPal    [O] Address that receive the unmarshaled palette.
708  *
709  * RETURNS
710  *  The end of the marshaled data in the buffer.
711  *
712  * NOTES
713  *  Even though the function is documented to take a pointer to an ULONG in
714  *  pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
715  *  the first parameter is an ULONG.
716  *  This function is only intended to be called by the RPC runtime.
717  */
718 unsigned char * __RPC_USER HPALETTE_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, HPALETTE *phPal)
719 {
720     FIXME(":stub\n");
721     return pBuffer;
722 }
723 
724 /******************************************************************************
725  *           HPALETTE_UserFree [OLE32.@]
726  *
727  * Frees an unmarshaled palette.
728  *
729  * PARAMS
730  *  pFlags   [I] Flags. See notes.
731  *  phPal    [I] Palette to free.
732  *
733  * RETURNS
734  *  The end of the marshaled data in the buffer.
735  *
736  * NOTES
737  *  Even though the function is documented to take a pointer to a ULONG in
738  *  pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of
739  *  which the first parameter is a ULONG.
740  *  This function is only intended to be called by the RPC runtime.
741  */
742 void __RPC_USER HPALETTE_UserFree(ULONG *pFlags, HPALETTE *phPal)
743 {
744     FIXME(":stub\n");
745 }
746 
747 
748 /******************************************************************************
749  *           HMETAFILE_UserSize [OLE32.@]
750  *
751  * Calculates the buffer size required to marshal a metafile.
752  *
753  * PARAMS
754  *  pFlags       [I] Flags. See notes.
755  *  StartingSize [I] Starting size of the buffer. This value is added on to
756  *                   the buffer size required for the clip format.
757  *  phmf         [I] Metafile to size.
758  *
759  * RETURNS
760  *  The buffer size required to marshal a metafile plus the starting size.
761  *
762  * NOTES
763  *  Even though the function is documented to take a pointer to a ULONG in
764  *  pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
765  *  the first parameter is a ULONG.
766  *  This function is only intended to be called by the RPC runtime.
767  */
768 ULONG __RPC_USER HMETAFILE_UserSize(ULONG *pFlags, ULONG StartingSize, HMETAFILE *phmf)
769 {
770     ULONG size = StartingSize;
771 
772     TRACE("(%s, %d, &%p\n", debugstr_user_flags(pFlags), StartingSize, *phmf);
773 
774     ALIGN_LENGTH(size, 3);
775 
776     size += sizeof(ULONG);
777     if (LOWORD(*pFlags) == MSHCTX_INPROC)
778         size += sizeof(ULONG_PTR);
779     else
780     {
781         size += sizeof(ULONG);
782 
783         if (*phmf)
784         {
785             UINT mfsize;
786 
787             size += 2 * sizeof(ULONG);
788             mfsize = GetMetaFileBitsEx(*phmf, 0, NULL);
789             size += mfsize;
790         }
791     }
792 
793     return size;
794 }
795 
796 /******************************************************************************
797  *           HMETAFILE_UserMarshal [OLE32.@]
798  *
799  * Marshals a metafile into a buffer.
800  *
801  * PARAMS
802  *  pFlags  [I] Flags. See notes.
803  *  pBuffer [I] Buffer to marshal the clip format into.
804  *  phEmf   [I] Metafile to marshal.
805  *
806  * RETURNS
807  *  The end of the marshaled data in the buffer.
808  *
809  * NOTES
810  *  Even though the function is documented to take a pointer to a ULONG in
811  *  pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
812  *  the first parameter is a ULONG.
813  *  This function is only intended to be called by the RPC runtime.
814  */
815 unsigned char * __RPC_USER HMETAFILE_UserMarshal(ULONG *pFlags, unsigned char *pBuffer, HMETAFILE *phmf)
816 {
817     TRACE("(%s, %p, &%p\n", debugstr_user_flags(pFlags), pBuffer, *phmf);
818 
819     ALIGN_POINTER(pBuffer, 3);
820 
821     if (LOWORD(*pFlags) == MSHCTX_INPROC)
822     {
823         if (sizeof(*phmf) == 8)
824             *(ULONG *)pBuffer = WDT_INPROC64_CALL;
825         else
826             *(ULONG *)pBuffer = WDT_INPROC_CALL;
827         pBuffer += sizeof(ULONG);
828         *(HMETAFILE *)pBuffer = *phmf;
829         pBuffer += sizeof(HMETAFILE);
830     }
831     else
832     {
833         *(ULONG *)pBuffer = WDT_REMOTE_CALL;
834         pBuffer += sizeof(ULONG);
835         *(ULONG *)pBuffer = (ULONG)(ULONG_PTR)*phmf;
836         pBuffer += sizeof(ULONG);
837 
838         if (*phmf)
839         {
840             UINT mfsize = GetMetaFileBitsEx(*phmf, 0, NULL);
841 
842             *(ULONG *)pBuffer = mfsize;
843             pBuffer += sizeof(ULONG);
844             *(ULONG *)pBuffer = mfsize;
845             pBuffer += sizeof(ULONG);
846             GetMetaFileBitsEx(*phmf, mfsize, pBuffer);
847             pBuffer += mfsize;
848         }
849     }
850 
851     return pBuffer;
852 }
853 
854 /******************************************************************************
855  *           HMETAFILE_UserUnmarshal [OLE32.@]
856  *
857  * Unmarshals a metafile from a buffer.
858  *
859  * PARAMS
860  *  pFlags   [I] Flags. See notes.
861  *  pBuffer  [I] Buffer to marshal the clip format from.
862  *  phmf     [O] Address that receive the unmarshaled metafile.
863  *
864  * RETURNS
865  *  The end of the marshaled data in the buffer.
866  *
867  * NOTES
868  *  Even though the function is documented to take a pointer to an ULONG in
869  *  pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
870  *  the first parameter is an ULONG.
871  *  This function is only intended to be called by the RPC runtime.
872  */
873 unsigned char * __RPC_USER HMETAFILE_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, HMETAFILE *phmf)
874 {
875     ULONG fContext;
876 
877     TRACE("(%s, %p, %p\n", debugstr_user_flags(pFlags), pBuffer, phmf);
878 
879     ALIGN_POINTER(pBuffer, 3);
880 
881     fContext = *(ULONG *)pBuffer;
882     pBuffer += sizeof(ULONG);
883 
884     if (((fContext == WDT_INPROC_CALL) && (sizeof(*phmf) < 8)) ||
885         ((fContext == WDT_INPROC64_CALL) && (sizeof(*phmf) == 8)))
886     {
887         *phmf = *(HMETAFILE *)pBuffer;
888         pBuffer += sizeof(*phmf);
889     }
890     else if (fContext == WDT_REMOTE_CALL)
891     {
892         ULONG handle;
893 
894         handle = *(ULONG *)pBuffer;
895         pBuffer += sizeof(ULONG);
896 
897         if (handle)
898         {
899             ULONG size;
900             size = *(ULONG *)pBuffer;
901             pBuffer += sizeof(ULONG);
902             if (size != *(ULONG *)pBuffer)
903             {
904                 RaiseException(RPC_X_BAD_STUB_DATA, 0, 0, NULL);
905                 return pBuffer;
906             }
907             pBuffer += sizeof(ULONG);
908             *phmf = SetMetaFileBitsEx(size, pBuffer);
909             pBuffer += size;
910         }
911         else
912             *phmf = NULL;
913     }
914     else
915         RaiseException(RPC_S_INVALID_TAG, 0, 0, NULL);
916 
917     return pBuffer;
918 }
919 
920 /******************************************************************************
921  *           HMETAFILE_UserFree [OLE32.@]
922  *
923  * Frees an unmarshaled metafile.
924  *
925  * PARAMS
926  *  pFlags   [I] Flags. See notes.
927  *  phmf     [I] Metafile to free.
928  *
929  * RETURNS
930  *  The end of the marshaled data in the buffer.
931  *
932  * NOTES
933  *  Even though the function is documented to take a pointer to a ULONG in
934  *  pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of
935  *  which the first parameter is a ULONG.
936  *  This function is only intended to be called by the RPC runtime.
937  */
938 void __RPC_USER HMETAFILE_UserFree(ULONG *pFlags, HMETAFILE *phmf)
939 {
940     TRACE("(%s, &%p\n", debugstr_user_flags(pFlags), *phmf);
941 
942     if (LOWORD(*pFlags) != MSHCTX_INPROC)
943         DeleteMetaFile(*phmf);
944 }
945 
946 /******************************************************************************
947 *           HENHMETAFILE_UserSize [OLE32.@]
948 *
949 * Calculates the buffer size required to marshal an enhanced metafile.
950 *
951 * PARAMS
952 *  pFlags       [I] Flags. See notes.
953 *  StartingSize [I] Starting size of the buffer. This value is added on to
954 *                   the buffer size required for the clip format.
955 *  phEmf        [I] Enhanced metafile to size.
956 *
957 * RETURNS
958 *  The buffer size required to marshal an enhanced metafile plus the starting size.
959 *
960 * NOTES
961 *  Even though the function is documented to take a pointer to a ULONG in
962 *  pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
963 *  the first parameter is a ULONG.
964 *  This function is only intended to be called by the RPC runtime.
965 */
966 ULONG __RPC_USER HENHMETAFILE_UserSize(ULONG *pFlags, ULONG StartingSize, HENHMETAFILE *phEmf)
967 {
968     ULONG size = StartingSize;
969 
970     TRACE("(%s, %d, %p\n", debugstr_user_flags(pFlags), StartingSize, *phEmf);
971 
972     size += sizeof(ULONG);
973     if (LOWORD(*pFlags) == MSHCTX_INPROC)
974         size += sizeof(ULONG_PTR);
975     else
976     {
977         size += sizeof(ULONG);
978 
979         if (*phEmf)
980         {
981             UINT emfsize;
982 
983             size += 2 * sizeof(ULONG);
984             emfsize = GetEnhMetaFileBits(*phEmf, 0, NULL);
985             size += emfsize;
986         }
987     }
988 
989     return size;
990 }
991 
992 /******************************************************************************
993  *           HENHMETAFILE_UserMarshal [OLE32.@]
994  *
995  * Marshals an enhance metafile into a buffer.
996  *
997  * PARAMS
998  *  pFlags  [I] Flags. See notes.
999  *  pBuffer [I] Buffer to marshal the clip format into.
1000  *  phEmf   [I] Enhanced metafile to marshal.
1001  *
1002  * RETURNS
1003  *  The end of the marshaled data in the buffer.
1004  *
1005  * NOTES
1006  *  Even though the function is documented to take a pointer to a ULONG in
1007  *  pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
1008  *  the first parameter is a ULONG.
1009  *  This function is only intended to be called by the RPC runtime.
1010  */
1011 unsigned char * __RPC_USER HENHMETAFILE_UserMarshal(ULONG *pFlags, unsigned char *pBuffer, HENHMETAFILE *phEmf)
1012 {
1013     TRACE("(%s, %p, &%p\n", debugstr_user_flags(pFlags), pBuffer, *phEmf);
1014 
1015     if (LOWORD(*pFlags) == MSHCTX_INPROC)
1016     {
1017         if (sizeof(*phEmf) == 8)
1018             *(ULONG *)pBuffer = WDT_INPROC64_CALL;
1019         else
1020             *(ULONG *)pBuffer = WDT_INPROC_CALL;
1021         pBuffer += sizeof(ULONG);
1022         *(HENHMETAFILE *)pBuffer = *phEmf;
1023         pBuffer += sizeof(HENHMETAFILE);
1024     }
1025     else
1026     {
1027         *(ULONG *)pBuffer = WDT_REMOTE_CALL;
1028         pBuffer += sizeof(ULONG);
1029         *(ULONG *)pBuffer = (ULONG)(ULONG_PTR)*phEmf;
1030         pBuffer += sizeof(ULONG);
1031 
1032         if (*phEmf)
1033         {
1034             UINT emfsize = GetEnhMetaFileBits(*phEmf, 0, NULL);
1035 
1036             *(ULONG *)pBuffer = emfsize;
1037             pBuffer += sizeof(ULONG);
1038             *(ULONG *)pBuffer = emfsize;
1039             pBuffer += sizeof(ULONG);
1040             GetEnhMetaFileBits(*phEmf, emfsize, pBuffer);
1041             pBuffer += emfsize;
1042         }
1043     }
1044 
1045     return pBuffer;
1046 }
1047 
1048 /******************************************************************************
1049  *           HENHMETAFILE_UserUnmarshal [OLE32.@]
1050  *
1051  * Unmarshals an enhanced metafile from a buffer.
1052  *
1053  * PARAMS
1054  *  pFlags   [I] Flags. See notes.
1055  *  pBuffer  [I] Buffer to marshal the clip format from.
1056  *  phEmf    [O] Address that receive the unmarshaled enhanced metafile.
1057  *
1058  * RETURNS
1059  *  The end of the marshaled data in the buffer.
1060  *
1061  * NOTES
1062  *  Even though the function is documented to take a pointer to an ULONG in
1063  *  pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
1064  *  the first parameter is an ULONG.
1065  *  This function is only intended to be called by the RPC runtime.
1066  */
1067 unsigned char * __RPC_USER HENHMETAFILE_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, HENHMETAFILE *phEmf)
1068 {
1069     ULONG fContext;
1070 
1071     TRACE("(%s, %p, %p\n", debugstr_user_flags(pFlags), pBuffer, phEmf);
1072 
1073     fContext = *(ULONG *)pBuffer;
1074     pBuffer += sizeof(ULONG);
1075 
1076     if (((fContext == WDT_INPROC_CALL) && (sizeof(*phEmf) < 8)) ||
1077         ((fContext == WDT_INPROC64_CALL) && (sizeof(*phEmf) == 8)))
1078     {
1079         *phEmf = *(HENHMETAFILE *)pBuffer;
1080         pBuffer += sizeof(*phEmf);
1081     }
1082     else if (fContext == WDT_REMOTE_CALL)
1083     {
1084         ULONG handle;
1085 
1086         handle = *(ULONG *)pBuffer;
1087         pBuffer += sizeof(ULONG);
1088 
1089         if (handle)
1090         {
1091             ULONG size;
1092             size = *(ULONG *)pBuffer;
1093             pBuffer += sizeof(ULONG);
1094             if (size != *(ULONG *)pBuffer)
1095             {
1096                 RaiseException(RPC_X_BAD_STUB_DATA, 0, 0, NULL);
1097                 return pBuffer;
1098             }
1099             pBuffer += sizeof(ULONG);
1100             *phEmf = SetEnhMetaFileBits(size, pBuffer);
1101             pBuffer += size;
1102         }
1103         else
1104             *phEmf = NULL;
1105     }
1106     else
1107         RaiseException(RPC_S_INVALID_TAG, 0, 0, NULL);
1108 
1109     return pBuffer;
1110 }
1111 
1112 /******************************************************************************
1113  *           HENHMETAFILE_UserFree [OLE32.@]
1114  *
1115  * Frees an unmarshaled enhanced metafile.
1116  *
1117  * PARAMS
1118  *  pFlags   [I] Flags. See notes.
1119  *  phEmf    [I] Enhanced metafile to free.
1120  *
1121  * RETURNS
1122  *  The end of the marshaled data in the buffer.
1123  *
1124  * NOTES
1125  *  Even though the function is documented to take a pointer to a ULONG in
1126  *  pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of
1127  *  which the first parameter is a ULONG.
1128  *  This function is only intended to be called by the RPC runtime.
1129  */
1130 void __RPC_USER HENHMETAFILE_UserFree(ULONG *pFlags, HENHMETAFILE *phEmf)
1131 {
1132     TRACE("(%s, &%p\n", debugstr_user_flags(pFlags), *phEmf);
1133 
1134     if (LOWORD(*pFlags) != MSHCTX_INPROC)
1135         DeleteEnhMetaFile(*phEmf);
1136 }
1137 
1138 /******************************************************************************
1139  *           HMETAFILEPICT_UserSize [OLE32.@]
1140  *
1141  * Calculates the buffer size required to marshal an metafile pict.
1142  *
1143  * PARAMS
1144  *  pFlags       [I] Flags. See notes.
1145  *  StartingSize [I] Starting size of the buffer. This value is added on to
1146  *                   the buffer size required for the clip format.
1147  *  phMfp        [I] Metafile pict to size.
1148  *
1149  * RETURNS
1150  *  The buffer size required to marshal a metafile pict plus the starting size.
1151  *
1152  * NOTES
1153  *  Even though the function is documented to take a pointer to a ULONG in
1154  *  pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
1155  *  the first parameter is a ULONG.
1156  *  This function is only intended to be called by the RPC runtime.
1157  */
1158 ULONG __RPC_USER HMETAFILEPICT_UserSize(ULONG *pFlags, ULONG StartingSize, HMETAFILEPICT *phMfp)
1159 {
1160     ULONG size = StartingSize;
1161 
1162     TRACE("(%s, %d, &%p)\n", debugstr_user_flags(pFlags), StartingSize, *phMfp);
1163 
1164     size += sizeof(ULONG);
1165 
1166     if(LOWORD(*pFlags) == MSHCTX_INPROC)
1167         size += sizeof(HMETAFILEPICT);
1168     else
1169     {
1170         size += sizeof(ULONG);
1171 
1172         if (*phMfp)
1173         {
1174             METAFILEPICT *mfpict = GlobalLock(*phMfp);
1175 
1176             /* FIXME: raise an exception if mfpict is NULL? */
1177             size += 3 * sizeof(ULONG);
1178             size += sizeof(ULONG);
1179 
1180             size = HMETAFILE_UserSize(pFlags, size, &mfpict->hMF);
1181 
1182             GlobalUnlock(*phMfp);
1183         }
1184     }
1185 
1186     return size;
1187 }
1188 
1189 /******************************************************************************
1190  *           HMETAFILEPICT_UserMarshal [OLE32.@]
1191  *
1192  * Marshals a metafile pict into a buffer.
1193  *
1194  * PARAMS
1195  *  pFlags  [I] Flags. See notes.
1196  *  pBuffer [I] Buffer to marshal the clip format into.
1197  *  phMfp   [I] Metafile pict to marshal.
1198  *
1199  * RETURNS
1200  *  The end of the marshaled data in the buffer.
1201  *
1202  * NOTES
1203  *  Even though the function is documented to take a pointer to a ULONG in
1204  *  pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
1205  *  the first parameter is a ULONG.
1206  *  This function is only intended to be called by the RPC runtime.
1207  */
1208 unsigned char * __RPC_USER HMETAFILEPICT_UserMarshal(ULONG *pFlags, unsigned char *pBuffer, HMETAFILEPICT *phMfp)
1209 {
1210     TRACE("(%s, %p, &%p)\n", debugstr_user_flags(pFlags), pBuffer, *phMfp);
1211 
1212     if (LOWORD(*pFlags) == MSHCTX_INPROC)
1213     {
1214         if (sizeof(HMETAFILEPICT) == 8)
1215             *(ULONG *)pBuffer = WDT_INPROC64_CALL;
1216         else
1217             *(ULONG *)pBuffer = WDT_INPROC_CALL;
1218         pBuffer += sizeof(ULONG);
1219         *(HMETAFILEPICT *)pBuffer = *phMfp;
1220         pBuffer += sizeof(HMETAFILEPICT);
1221     }
1222     else
1223     {
1224         *(ULONG *)pBuffer = WDT_REMOTE_CALL;
1225         pBuffer += sizeof(ULONG);
1226         *(ULONG *)pBuffer = (ULONG)(ULONG_PTR)*phMfp;
1227         pBuffer += sizeof(ULONG);
1228 
1229         if (*phMfp)
1230         {
1231             METAFILEPICT *mfpict = GlobalLock(*phMfp);
1232             remoteMETAFILEPICT * remmfpict = (remoteMETAFILEPICT *)pBuffer;
1233 
1234             /* FIXME: raise an exception if mfpict is NULL? */
1235             remmfpict->mm = mfpict->mm;
1236             remmfpict->xExt = mfpict->xExt;
1237             remmfpict->yExt = mfpict->yExt;
1238             pBuffer += 3 * sizeof(ULONG);
1239             *(ULONG *)pBuffer = USER_MARSHAL_PTR_PREFIX;
1240             pBuffer += sizeof(ULONG);
1241 
1242             pBuffer = HMETAFILE_UserMarshal(pFlags, pBuffer, &mfpict->hMF);
1243 
1244             GlobalUnlock(*phMfp);
1245         }
1246     }
1247     return pBuffer;
1248 }
1249 
1250 /******************************************************************************
1251  *           HMETAFILEPICT_UserUnmarshal [OLE32.@]
1252  *
1253  * Unmarshals an metafile pict from a buffer.
1254  *
1255  * PARAMS
1256  *  pFlags   [I] Flags. See notes.
1257  *  pBuffer  [I] Buffer to marshal the clip format from.
1258  *  phMfp    [O] Address that receive the unmarshaled metafile pict.
1259  *
1260  * RETURNS
1261  *  The end of the marshaled data in the buffer.
1262  *
1263  * NOTES
1264  *  Even though the function is documented to take a pointer to an ULONG in
1265  *  pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
1266  *  the first parameter is an ULONG.
1267  *  This function is only intended to be called by the RPC runtime.
1268  */
1269 unsigned char * __RPC_USER HMETAFILEPICT_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, HMETAFILEPICT *phMfp)
1270 {
1271     ULONG fContext;
1272 
1273     TRACE("(%s, %p, %p)\n", debugstr_user_flags(pFlags), pBuffer, phMfp);
1274 
1275     fContext = *(ULONG *)pBuffer;
1276     pBuffer += sizeof(ULONG);
1277 
1278     if ((fContext == WDT_INPROC_CALL) || fContext == WDT_INPROC64_CALL)
1279     {
1280         *phMfp = *(HMETAFILEPICT *)pBuffer;
1281         pBuffer += sizeof(HMETAFILEPICT);
1282     }
1283     else
1284     {
1285         ULONG handle = *(ULONG *)pBuffer;
1286         pBuffer += sizeof(ULONG);
1287         *phMfp = NULL;
1288 
1289         if(handle)
1290         {
1291             METAFILEPICT *mfpict;
1292             const remoteMETAFILEPICT *remmfpict;
1293             ULONG user_marshal_prefix;
1294 
1295             remmfpict = (const remoteMETAFILEPICT *)pBuffer;
1296 
1297             *phMfp = GlobalAlloc(GMEM_MOVEABLE, sizeof(METAFILEPICT));
1298             if (!*phMfp)
1299                 RpcRaiseException(E_OUTOFMEMORY);
1300 
1301             mfpict = GlobalLock(*phMfp);
1302             mfpict->mm = remmfpict->mm;
1303             mfpict->xExt = remmfpict->xExt;
1304             mfpict->yExt = remmfpict->yExt;
1305             pBuffer += 3 * sizeof(ULONG);
1306             user_marshal_prefix = *(ULONG *)pBuffer;
1307             pBuffer += sizeof(ULONG);
1308 
1309             if (user_marshal_prefix != USER_MARSHAL_PTR_PREFIX)
1310                 RpcRaiseException(RPC_X_INVALID_TAG);
1311 
1312             pBuffer = HMETAFILE_UserUnmarshal(pFlags, pBuffer, &mfpict->hMF);
1313 
1314             GlobalUnlock(*phMfp);
1315         }
1316     }
1317     return pBuffer;
1318 }
1319 
1320 /******************************************************************************
1321  *           HMETAFILEPICT_UserFree [OLE32.@]
1322  *
1323  * Frees an unmarshaled metafile pict.
1324  *
1325  * PARAMS
1326  *  pFlags   [I] Flags. See notes.
1327  *  phMfp    [I] Metafile pict to free.
1328  *
1329  * RETURNS
1330  *  The end of the marshaled data in the buffer.
1331  *
1332  * NOTES
1333  *  Even though the function is documented to take a pointer to a ULONG in
1334  *  pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of
1335  *  which the first parameter is a ULONG.
1336  *  This function is only intended to be called by the RPC runtime.
1337  */
1338 void __RPC_USER HMETAFILEPICT_UserFree(ULONG *pFlags, HMETAFILEPICT *phMfp)
1339 {
1340     TRACE("(%s, &%p)\n", debugstr_user_flags(pFlags), *phMfp);
1341 
1342     if ((LOWORD(*pFlags) != MSHCTX_INPROC) && *phMfp)
1343     {
1344         METAFILEPICT *mfpict;
1345 
1346         mfpict = GlobalLock(*phMfp);
1347         /* FIXME: raise an exception if mfpict is NULL? */
1348         HMETAFILE_UserFree(pFlags, &mfpict->hMF);
1349         GlobalUnlock(*phMfp);
1350 
1351         GlobalFree(*phMfp);
1352     }
1353 }
1354 
1355 /******************************************************************************
1356  *           WdtpInterfacePointer_UserSize [OLE32.@]
1357  *
1358  * Calculates the buffer size required to marshal an interface pointer.
1359  *
1360  * PARAMS
1361  *  pFlags       [I] Flags. See notes.
1362  *  RealFlags    [I] The MSHCTX to use when marshaling the interface.
1363  *  punk         [I] Interface pointer to size.
1364  *  StartingSize [I] Starting size of the buffer. This value is added on to
1365  *                   the buffer size required for the clip format.
1366  *  riid         [I] ID of interface to size.
1367  *
1368  * RETURNS
1369  *  The buffer size required to marshal an interface pointer plus the starting size.
1370  *
1371  * NOTES
1372  *  Even though the function is documented to take a pointer to a ULONG in
1373  *  pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
1374  *  the first parameter is a ULONG.
1375  */
1376 ULONG __RPC_USER WdtpInterfacePointer_UserSize(ULONG *pFlags, ULONG RealFlags, ULONG StartingSize, IUnknown *punk, REFIID riid)
1377 {
1378     DWORD marshal_size = 0;
1379     HRESULT hr;
1380 
1381     TRACE("(%s, 0%x, %d, %p, %s)\n", debugstr_user_flags(pFlags), RealFlags, StartingSize, punk, debugstr_guid(riid));
1382 
1383     hr = CoGetMarshalSizeMax(&marshal_size, riid, punk, LOWORD(RealFlags), NULL, MSHLFLAGS_NORMAL);
1384     if(FAILED(hr)) return StartingSize;
1385 
1386     ALIGN_LENGTH(StartingSize, 3);
1387     StartingSize += 2 * sizeof(DWORD);
1388     return StartingSize + marshal_size;
1389 }
1390 
1391 /******************************************************************************
1392  *           WdtpInterfacePointer_UserMarshal [OLE32.@]
1393  *
1394  * Marshals an interface pointer into a buffer.
1395  *
1396  * PARAMS
1397  *  pFlags    [I] Flags. See notes.
1398  *  RealFlags [I] The MSHCTX to use when marshaling the interface.
1399  *  pBuffer   [I] Buffer to marshal the clip format into.
1400  *  punk      [I] Interface pointer to marshal.
1401  *  riid      [I] ID of interface to marshal.
1402  *
1403  * RETURNS
1404  *  The end of the marshaled data in the buffer.
1405  *
1406  * NOTES
1407  *  Even though the function is documented to take a pointer to a ULONG in
1408  *  pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
1409  *  the first parameter is a ULONG.
1410  */
1411 unsigned char * WINAPI WdtpInterfacePointer_UserMarshal(ULONG *pFlags, ULONG RealFlags, unsigned char *pBuffer, IUnknown *punk, REFIID riid)
1412 {
1413     HGLOBAL h = GlobalAlloc(GMEM_MOVEABLE, 0);
1414     IStream *stm;
1415     DWORD size;
1416     void *ptr;
1417 
1418     TRACE("(%s, 0x%x, %p, &%p, %s)\n", debugstr_user_flags(pFlags), RealFlags, pBuffer, punk, debugstr_guid(riid));
1419 
1420     if(!h) return NULL;
1421     if(CreateStreamOnHGlobal(h, TRUE, &stm) != S_OK)
1422     {
1423         GlobalFree(h);
1424         return NULL;
1425     }
1426 
1427     if(CoMarshalInterface(stm, riid, punk, LOWORD(RealFlags), NULL, MSHLFLAGS_NORMAL) != S_OK)
1428     {
1429         IStream_Release(stm);
1430         return pBuffer;
1431     }
1432 
1433     ALIGN_POINTER(pBuffer, 3);
1434     size = GlobalSize(h);
1435 
1436     *(DWORD *)pBuffer = size;
1437     pBuffer += sizeof(DWORD);
1438     *(DWORD *)pBuffer = size;
1439     pBuffer += sizeof(DWORD);
1440 
1441     ptr = GlobalLock(h);
1442     memcpy(pBuffer, ptr, size);
1443     GlobalUnlock(h);
1444 
1445     IStream_Release(stm);
1446     return pBuffer + size;
1447 }
1448 
1449 /******************************************************************************
1450  *           WdtpInterfacePointer_UserUnmarshal [OLE32.@]
1451  *
1452  * Unmarshals an interface pointer from a buffer.
1453  *
1454  * PARAMS
1455  *  pFlags   [I] Flags. See notes.
1456  *  pBuffer  [I] Buffer to marshal the clip format from.
1457  *  ppunk    [I/O] Address that receives the unmarshaled interface pointer.
1458  *  riid     [I] ID of interface to unmarshal.
1459  *
1460  * RETURNS
1461  *  The end of the marshaled data in the buffer.
1462  *
1463  * NOTES
1464  *  Even though the function is documented to take a pointer to an ULONG in
1465  *  pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
1466  *  the first parameter is an ULONG.
1467  */
1468 unsigned char * WINAPI WdtpInterfacePointer_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, IUnknown **ppunk, REFIID riid)
1469 {
1470     HRESULT hr;
1471     HGLOBAL h;
1472     IStream *stm;
1473     DWORD size;
1474     void *ptr;
1475     IUnknown *orig;
1476 
1477     TRACE("(%s, %p, %p, %s)\n", debugstr_user_flags(pFlags), pBuffer, ppunk, debugstr_guid(riid));
1478 
1479     ALIGN_POINTER(pBuffer, 3);
1480 
1481     size = *(DWORD *)pBuffer;
1482     pBuffer += sizeof(DWORD);
1483     if(size != *(DWORD *)pBuffer)
1484         RaiseException(RPC_X_BAD_STUB_DATA, 0, 0, NULL);
1485 
1486     pBuffer += sizeof(DWORD);
1487 
1488     /* FIXME: sanity check on size */
1489 
1490     h = GlobalAlloc(GMEM_MOVEABLE, size);
1491     if(!h) RaiseException(RPC_X_NO_MEMORY, 0, 0, NULL);
1492 
1493     if(CreateStreamOnHGlobal(h, TRUE, &stm) != S_OK)
1494     {
1495         GlobalFree(h);
1496         RaiseException(RPC_X_NO_MEMORY, 0, 0, NULL);
1497     }
1498 
1499     ptr = GlobalLock(h);
1500     memcpy(ptr, pBuffer, size);
1501     GlobalUnlock(h);
1502 
1503     orig = *ppunk;
1504     hr = CoUnmarshalInterface(stm, riid, (void**)ppunk);
1505     IStream_Release(stm);
1506 
1507     if(hr != S_OK) RaiseException(hr, 0, 0, NULL);
1508 
1509     if(orig) IUnknown_Release(orig);
1510 
1511     return pBuffer + size;
1512 }
1513 
1514 /******************************************************************************
1515  *           WdtpInterfacePointer_UserFree [OLE32.@]
1516  *
1517  * Releases an unmarshaled interface pointer.
1518  *
1519  * PARAMS
1520  *  punk    [I] Interface pointer to release.
1521  *
1522  * RETURNS
1523  *  Nothing.
1524  */
1525 void WINAPI WdtpInterfacePointer_UserFree(IUnknown *punk)
1526 {
1527     TRACE("(%p)\n", punk);
1528     if(punk) IUnknown_Release(punk);
1529 }
1530 
1531 /******************************************************************************
1532 *           STGMEDIUM_UserSize [OLE32.@]
1533 *
1534 * Calculates the buffer size required to marshal an STGMEDIUM.
1535 *
1536 * PARAMS
1537 *  pFlags       [I] Flags. See notes.
1538 *  StartingSize [I] Starting size of the buffer. This value is added on to
1539 *                   the buffer size required for the clip format.
1540 *  pStgMedium   [I] STGMEDIUM to size.
1541 *
1542 * RETURNS
1543 *  The buffer size required to marshal an STGMEDIUM plus the starting size.
1544 *
1545 * NOTES
1546 *  Even though the function is documented to take a pointer to a ULONG in
1547 *  pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
1548 *  the first parameter is a ULONG.
1549 *  This function is only intended to be called by the RPC runtime.
1550 */
1551 ULONG __RPC_USER STGMEDIUM_UserSize(ULONG *pFlags, ULONG StartingSize, STGMEDIUM *pStgMedium)
1552 {
1553     ULONG size = StartingSize;
1554 
1555     TRACE("(%s, %d, %p\n", debugstr_user_flags(pFlags), StartingSize, pStgMedium);
1556 
1557     ALIGN_LENGTH(size, 3);
1558 
1559     size += 2 * sizeof(DWORD);
1560     if (pStgMedium->tymed != TYMED_NULL)
1561         size += sizeof(DWORD);
1562 
1563     switch (pStgMedium->tymed)
1564     {
1565     case TYMED_NULL:
1566         TRACE("TYMED_NULL\n");
1567         break;
1568     case TYMED_HGLOBAL:
1569         TRACE("TYMED_HGLOBAL\n");
1570         if (pStgMedium->u.hGlobal)
1571             size = HGLOBAL_UserSize(pFlags, size, &pStgMedium->u.hGlobal);
1572         break;
1573     case TYMED_FILE:
1574         TRACE("TYMED_FILE\n");
1575         if (pStgMedium->u.lpszFileName)
1576         {
1577             TRACE("file name is %s\n", debugstr_w(pStgMedium->u.lpszFileName));
1578             size += 3 * sizeof(DWORD) +
1579                 (strlenW(pStgMedium->u.lpszFileName) + 1) * sizeof(WCHAR);
1580         }
1581         break;
1582     case TYMED_ISTREAM:
1583         TRACE("TYMED_ISTREAM\n");
1584         if (pStgMedium->u.pstm)
1585         {
1586             IUnknown *unk;
1587             IStream_QueryInterface(pStgMedium->u.pstm, &IID_IUnknown, (void**)&unk);
1588             size = WdtpInterfacePointer_UserSize(pFlags, LOWORD(*pFlags), size, unk, &IID_IStream);
1589             IUnknown_Release(unk);
1590         }
1591         break;
1592     case TYMED_ISTORAGE:
1593         TRACE("TYMED_ISTORAGE\n");
1594         if (pStgMedium->u.pstg)
1595         {
1596             IUnknown *unk;
1597             IStorage_QueryInterface(pStgMedium->u.pstg, &IID_IUnknown, (void**)&unk);
1598             size = WdtpInterfacePointer_UserSize(pFlags, LOWORD(*pFlags), size, unk, &IID_IStorage);
1599             IUnknown_Release(unk);
1600         }
1601         break;
1602     case TYMED_GDI:
1603         TRACE("TYMED_GDI\n");
1604         if (pStgMedium->u.hBitmap)
1605         {
1606             FIXME("not implemented for GDI object %p\n", pStgMedium->u.hBitmap);
1607         }
1608         break;
1609     case TYMED_MFPICT:
1610         TRACE("TYMED_MFPICT\n");
1611         if (pStgMedium->u.hMetaFilePict)
1612             size = HMETAFILEPICT_UserSize(pFlags, size, &pStgMedium->u.hMetaFilePict);
1613         break;
1614     case TYMED_ENHMF:
1615         TRACE("TYMED_ENHMF\n");
1616         if (pStgMedium->u.hEnhMetaFile)
1617             size = HENHMETAFILE_UserSize(pFlags, size, &pStgMedium->u.hEnhMetaFile);
1618         break;
1619     default:
1620         RaiseException(DV_E_TYMED, 0, 0, NULL);
1621     }
1622 
1623     if (pStgMedium->pUnkForRelease)
1624         size = WdtpInterfacePointer_UserSize(pFlags, LOWORD(*pFlags), size, pStgMedium->pUnkForRelease, &IID_IUnknown);
1625 
1626     return size;
1627 }
1628 
1629 /******************************************************************************
1630  *           STGMEDIUM_UserMarshal [OLE32.@]
1631  *
1632  * Marshals a STGMEDIUM into a buffer.
1633  *
1634  * PARAMS
1635  *  pFlags  [I] Flags. See notes.
1636  *  pBuffer [I] Buffer to marshal the clip format into.
1637  *  pCF     [I] STGMEDIUM to marshal.
1638  *
1639  * RETURNS
1640  *  The end of the marshaled data in the buffer.
1641  *
1642  * NOTES
1643  *  Even though the function is documented to take a pointer to a ULONG in
1644  *  pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
1645  *  the first parameter is a ULONG.
1646  *  This function is only intended to be called by the RPC runtime.
1647  */
1648 unsigned char * __RPC_USER STGMEDIUM_UserMarshal(ULONG *pFlags, unsigned char *pBuffer, STGMEDIUM *pStgMedium)
1649 {
1650     TRACE("(%s, %p, %p\n", debugstr_user_flags(pFlags), pBuffer, pStgMedium);
1651 
1652     ALIGN_POINTER(pBuffer, 3);
1653 
1654     *(DWORD *)pBuffer = pStgMedium->tymed;
1655     pBuffer += sizeof(DWORD);
1656     if (pStgMedium->tymed != TYMED_NULL)
1657     {
1658         *(DWORD *)pBuffer = (DWORD)(DWORD_PTR)pStgMedium->u.pstg;
1659         pBuffer += sizeof(DWORD);
1660     }
1661     *(DWORD *)pBuffer = (DWORD)(DWORD_PTR)pStgMedium->pUnkForRelease;
1662     pBuffer += sizeof(DWORD);
1663 
1664     switch (pStgMedium->tymed)
1665     {
1666     case TYMED_NULL:
1667         TRACE("TYMED_NULL\n");
1668         break;
1669     case TYMED_HGLOBAL:
1670         TRACE("TYMED_HGLOBAL\n");
1671         if (pStgMedium->u.hGlobal)
1672             pBuffer = HGLOBAL_UserMarshal(pFlags, pBuffer, &pStgMedium->u.hGlobal);
1673         break;
1674     case TYMED_FILE:
1675         TRACE("TYMED_FILE\n");
1676         if (pStgMedium->u.lpszFileName)
1677         {
1678             DWORD len;
1679             len = strlenW(pStgMedium->u.lpszFileName);
1680             /* conformance */
1681             *(DWORD *)pBuffer = len + 1;
1682             pBuffer += sizeof(DWORD);
1683             /* offset */
1684             *(DWORD *)pBuffer = 0;
1685             pBuffer += sizeof(DWORD);
1686             /* variance */
1687             *(DWORD *)pBuffer = len + 1;
1688             pBuffer += sizeof(DWORD);
1689 
1690             TRACE("file name is %s\n", debugstr_w(pStgMedium->u.lpszFileName));
1691             memcpy(pBuffer, pStgMedium->u.lpszFileName, (len + 1) * sizeof(WCHAR));
1692         }
1693         break;
1694     case TYMED_ISTREAM:
1695         TRACE("TYMED_ISTREAM\n");
1696         if (pStgMedium->u.pstm)
1697         {
1698             IUnknown *unk;
1699             IStream_QueryInterface(pStgMedium->u.pstm, &IID_IUnknown, (void**)&unk);
1700             pBuffer = WdtpInterfacePointer_UserMarshal(pFlags, LOWORD(*pFlags), pBuffer, unk, &IID_IStream);
1701             IUnknown_Release(unk);
1702         }
1703         break;
1704     case TYMED_ISTORAGE:
1705         TRACE("TYMED_ISTORAGE\n");
1706         if (pStgMedium->u.pstg)
1707         {
1708             IUnknown *unk;
1709             IStorage_QueryInterface(pStgMedium->u.pstg, &IID_IUnknown, (void**)&unk);
1710             pBuffer = WdtpInterfacePointer_UserMarshal(pFlags, LOWORD(*pFlags), pBuffer, unk, &IID_IStorage);
1711             IUnknown_Release(unk);
1712         }
1713         break;
1714     case TYMED_GDI:
1715         TRACE("TYMED_GDI\n");
1716         if (pStgMedium->u.hBitmap)
1717         {
1718             FIXME("not implemented for GDI object %p\n", pStgMedium->u.hBitmap);
1719         }
1720         break;
1721     case TYMED_MFPICT:
1722         TRACE("TYMED_MFPICT\n");
1723         if (pStgMedium->u.hMetaFilePict)
1724             pBuffer = HMETAFILEPICT_UserMarshal(pFlags, pBuffer, &pStgMedium->u.hMetaFilePict);
1725         break;
1726     case TYMED_ENHMF:
1727         TRACE("TYMED_ENHMF\n");
1728         if (pStgMedium->u.hEnhMetaFile)
1729             pBuffer = HENHMETAFILE_UserMarshal(pFlags, pBuffer, &pStgMedium->u.hEnhMetaFile);
1730         break;
1731     default:
1732         RaiseException(DV_E_TYMED, 0, 0, NULL);
1733     }
1734 
1735     if (pStgMedium->pUnkForRelease)
1736         pBuffer = WdtpInterfacePointer_UserMarshal(pFlags, LOWORD(*pFlags), pBuffer, pStgMedium->pUnkForRelease, &IID_IUnknown);
1737 
1738     return pBuffer;
1739 }
1740 
1741 /******************************************************************************
1742  *           STGMEDIUM_UserUnmarshal [OLE32.@]
1743  *
1744  * Unmarshals a STGMEDIUM from a buffer.
1745  *
1746  * PARAMS
1747  *  pFlags     [I] Flags. See notes.
1748  *  pBuffer    [I] Buffer to marshal the clip format from.
1749  *  pStgMedium [O] Address that receive the unmarshaled STGMEDIUM.
1750  *
1751  * RETURNS
1752  *  The end of the marshaled data in the buffer.
1753  *
1754  * NOTES
1755  *  Even though the function is documented to take a pointer to an ULONG in
1756  *  pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
1757  *  the first parameter is an ULONG.
1758  *  This function is only intended to be called by the RPC runtime.
1759  */
1760 unsigned char * __RPC_USER STGMEDIUM_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, STGMEDIUM *pStgMedium)
1761 {
1762     DWORD content = 0;
1763     DWORD releaseunk;
1764 
1765     ALIGN_POINTER(pBuffer, 3);
1766 
1767     TRACE("(%s, %p, %p\n", debugstr_user_flags(pFlags), pBuffer, pStgMedium);
1768 
1769     pStgMedium->tymed = *(DWORD *)pBuffer;
1770     pBuffer += sizeof(DWORD);
1771     if (pStgMedium->tymed != TYMED_NULL)
1772     {
1773         content = *(DWORD *)pBuffer;
1774         pBuffer += sizeof(DWORD);
1775     }
1776     releaseunk = *(DWORD *)pBuffer;
1777     pBuffer += sizeof(DWORD);
1778 
1779     switch (pStgMedium->tymed)
1780     {
1781     case TYMED_NULL:
1782         TRACE("TYMED_NULL\n");
1783         break;
1784     case TYMED_HGLOBAL:
1785         TRACE("TYMED_HGLOBAL\n");
1786         if (content)
1787             pBuffer = HGLOBAL_UserUnmarshal(pFlags, pBuffer, &pStgMedium->u.hGlobal);
1788         break;
1789     case TYMED_FILE:
1790         TRACE("TYMED_FILE\n");
1791         if (content)
1792         {
1793             DWORD conformance;
1794             DWORD variance;
1795             conformance = *(DWORD *)pBuffer;
1796             pBuffer += sizeof(DWORD);
1797             if (*(DWORD *)pBuffer != 0)
1798             {
1799                 ERR("invalid offset %d\n", *(DWORD *)pBuffer);
1800                 RpcRaiseException(RPC_S_INVALID_BOUND);
1801                 return NULL;
1802             }
1803             pBuffer += sizeof(DWORD);
1804             variance = *(DWORD *)pBuffer;
1805             pBuffer += sizeof(DWORD);
1806             if (conformance != variance)
1807             {
1808                 ERR("conformance (%d) and variance (%d) should be equal\n",
1809                     conformance, variance);
1810                 RpcRaiseException(RPC_S_INVALID_BOUND);
1811                 return NULL;
1812             }
1813             if (conformance > 0x7fffffff)
1814             {
1815                 ERR("conformance 0x%x too large\n", conformance);
1816                 RpcRaiseException(RPC_S_INVALID_BOUND);
1817                 return NULL;
1818             }
1819             pStgMedium->u.lpszFileName = CoTaskMemAlloc(conformance * sizeof(WCHAR));
1820             if (!pStgMedium->u.lpszFileName) RpcRaiseException(ERROR_OUTOFMEMORY);
1821             TRACE("unmarshalled file name is %s\n", debugstr_wn((const WCHAR *)pBuffer, variance));
1822             memcpy(pStgMedium->u.lpszFileName, pBuffer, variance * sizeof(WCHAR));
1823             pBuffer += variance * sizeof(WCHAR);
1824         }
1825         else
1826             pStgMedium->u.lpszFileName = NULL;
1827         break;
1828     case TYMED_ISTREAM:
1829         TRACE("TYMED_ISTREAM\n");
1830         if (content)
1831         {
1832             pBuffer = WdtpInterfacePointer_UserUnmarshal(pFlags, pBuffer, (IUnknown**)&pStgMedium->u.pstm, &IID_IStream);
1833         }
1834         else
1835         {
1836             if (pStgMedium->u.pstm) IStream_Release( pStgMedium->u.pstm );
1837             pStgMedium->u.pstm = NULL;
1838         }
1839         break;
1840     case TYMED_ISTORAGE:
1841         TRACE("TYMED_ISTORAGE\n");
1842         if (content)
1843         {
1844             pBuffer = WdtpInterfacePointer_UserUnmarshal(pFlags, pBuffer, (IUnknown**)&pStgMedium->u.pstg, &IID_IStorage);
1845         }
1846         else
1847         {
1848             if (pStgMedium->u.pstg) IStorage_Release( pStgMedium->u.pstg );
1849             pStgMedium->u.pstg = NULL;
1850         }
1851         break;
1852     case TYMED_GDI:
1853         TRACE("TYMED_GDI\n");
1854         if (content)
1855         {
1856             FIXME("not implemented for GDI object\n");
1857         }
1858         else
1859             pStgMedium->u.hBitmap = NULL;
1860         break;
1861     case TYMED_MFPICT:
1862         TRACE("TYMED_MFPICT\n");
1863         if (content)
1864             pBuffer = HMETAFILEPICT_UserUnmarshal(pFlags, pBuffer, &pStgMedium->u.hMetaFilePict);
1865         else
1866             pStgMedium->u.hMetaFilePict = NULL;
1867         break;
1868     case TYMED_ENHMF:
1869         TRACE("TYMED_ENHMF\n");
1870         if (content)
1871             pBuffer = HENHMETAFILE_UserUnmarshal(pFlags, pBuffer, &pStgMedium->u.hEnhMetaFile);
1872         else
1873             pStgMedium->u.hEnhMetaFile = NULL;
1874         break;
1875     default:
1876         RaiseException(DV_E_TYMED, 0, 0, NULL);
1877     }
1878 
1879     if (releaseunk)
1880         pBuffer = WdtpInterfacePointer_UserUnmarshal(pFlags, pBuffer, &pStgMedium->pUnkForRelease, &IID_IUnknown);
1881     /* Unlike the IStream / IStorage ifaces, the existing pUnkForRelease
1882        is left intact if a NULL ptr is unmarshalled - see the tests. */
1883 
1884     return pBuffer;
1885 }
1886 
1887 /******************************************************************************
1888  *           STGMEDIUM_UserFree [OLE32.@]
1889  *
1890  * Frees an unmarshaled STGMEDIUM.
1891  *
1892  * PARAMS
1893  *  pFlags     [I] Flags. See notes.
1894  *  pStgmedium [I] STGMEDIUM to free.
1895  *
1896  * RETURNS
1897  *  The end of the marshaled data in the buffer.
1898  *
1899  * NOTES
1900  *  Even though the function is documented to take a pointer to a ULONG in
1901  *  pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of
1902  *  which the first parameter is a ULONG.
1903  *  This function is only intended to be called by the RPC runtime.
1904  */
1905 void __RPC_USER STGMEDIUM_UserFree(ULONG *pFlags, STGMEDIUM *pStgMedium)
1906 {
1907     TRACE("(%s, %p\n", debugstr_user_flags(pFlags), pStgMedium);
1908 
1909     ReleaseStgMedium(pStgMedium);
1910 }
1911 
1912 ULONG __RPC_USER ASYNC_STGMEDIUM_UserSize(ULONG *pFlags, ULONG StartingSize, ASYNC_STGMEDIUM *pStgMedium)
1913 {
1914     TRACE("\n");
1915     return STGMEDIUM_UserSize(pFlags, StartingSize, pStgMedium);
1916 }
1917 
1918 unsigned char * __RPC_USER ASYNC_STGMEDIUM_UserMarshal(  ULONG *pFlags, unsigned char *pBuffer, ASYNC_STGMEDIUM *pStgMedium)
1919 {
1920     TRACE("\n");
1921     return STGMEDIUM_UserMarshal(pFlags, pBuffer, pStgMedium);
1922 }
1923 
1924 unsigned char * __RPC_USER ASYNC_STGMEDIUM_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, ASYNC_STGMEDIUM *pStgMedium)
1925 {
1926     TRACE("\n");
1927     return STGMEDIUM_UserUnmarshal(pFlags, pBuffer, pStgMedium);
1928 }
1929 
1930 void __RPC_USER ASYNC_STGMEDIUM_UserFree(ULONG *pFlags, ASYNC_STGMEDIUM *pStgMedium)
1931 {
1932     TRACE("\n");
1933     STGMEDIUM_UserFree(pFlags, pStgMedium);
1934 }
1935 
1936 ULONG __RPC_USER FLAG_STGMEDIUM_UserSize(ULONG *pFlags, ULONG StartingSize, FLAG_STGMEDIUM *pStgMedium)
1937 {
1938     FIXME(":stub\n");
1939     return StartingSize;
1940 }
1941 
1942 unsigned char * __RPC_USER FLAG_STGMEDIUM_UserMarshal(  ULONG *pFlags, unsigned char *pBuffer, FLAG_STGMEDIUM *pStgMedium)
1943 {
1944     FIXME(":stub\n");
1945     return pBuffer;
1946 }
1947 
1948 unsigned char * __RPC_USER FLAG_STGMEDIUM_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, FLAG_STGMEDIUM *pStgMedium)
1949 {
1950     FIXME(":stub\n");
1951     return pBuffer;
1952 }
1953 
1954 void __RPC_USER FLAG_STGMEDIUM_UserFree(ULONG *pFlags, FLAG_STGMEDIUM *pStgMedium)
1955 {
1956     FIXME(":stub\n");
1957 }
1958 
1959 ULONG __RPC_USER SNB_UserSize(ULONG *pFlags, ULONG StartingSize, SNB *pSnb)
1960 {
1961     ULONG size = StartingSize;
1962 
1963     TRACE("(%s, %d, %p\n", debugstr_user_flags(pFlags), StartingSize, pSnb);
1964 
1965     ALIGN_LENGTH(size, 3);
1966 
1967     /* two counters from RemSNB header, plus one more ULONG */
1968     size += 3*sizeof(ULONG);
1969 
1970     /* now actual data length */
1971     if (*pSnb)
1972     {
1973         WCHAR **ptrW = *pSnb;
1974 
1975         while (*ptrW)
1976         {
1977             size += (strlenW(*ptrW) + 1)*sizeof(WCHAR);
1978             ptrW++;
1979         }
1980     }
1981 
1982     return size;
1983 }
1984 
1985 struct SNB_wire {
1986     ULONG charcnt;
1987     ULONG strcnt;
1988     ULONG datalen;
1989     WCHAR data[1];
1990 };
1991 
1992 unsigned char * __RPC_USER SNB_UserMarshal(ULONG *pFlags, unsigned char *pBuffer, SNB *pSnb)
1993 {
1994     struct SNB_wire *wire;
1995     ULONG size;
1996 
1997     TRACE("(%s, %p, %p)\n", debugstr_user_flags(pFlags), pBuffer, pSnb);
1998 
1999     ALIGN_POINTER(pBuffer, 3);
2000 
2001     wire = (struct SNB_wire*)pBuffer;
2002     wire->charcnt = wire->strcnt = 0;
2003     size = 3*sizeof(ULONG);
2004 
2005     if (*pSnb)
2006     {
2007         WCHAR **ptrW = *pSnb;
2008         WCHAR *dataW = wire->data;
2009 
2010         while (*ptrW)
2011         {
2012             ULONG len = strlenW(*ptrW) + 1;
2013 
2014             wire->strcnt++;
2015             wire->charcnt += len;
2016             memcpy(dataW, *ptrW, len*sizeof(WCHAR));
2017             dataW += len;
2018 
2019             size += len*sizeof(WCHAR);
2020             ptrW++;
2021         }
2022     }
2023 
2024     wire->datalen = wire->charcnt;
2025     return pBuffer + size;
2026 }
2027 
2028 unsigned char * __RPC_USER SNB_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, SNB *pSnb)
2029 {
2030     USER_MARSHAL_CB *umcb = (USER_MARSHAL_CB*)pFlags;
2031     struct SNB_wire *wire;
2032 
2033     TRACE("(%s, %p, %p)\n", debugstr_user_flags(pFlags), pBuffer, pSnb);
2034 
2035     wire = (struct SNB_wire*)pBuffer;
2036 
2037     if (*pSnb)
2038         umcb->pStubMsg->pfnFree(*pSnb);
2039 
2040     if (wire->datalen == 0)
2041         *pSnb = NULL;
2042     else
2043     {
2044         WCHAR *src = wire->data, *dest;
2045         WCHAR **ptrW;
2046         ULONG i;
2047 
2048         ptrW = *pSnb = umcb->pStubMsg->pfnAllocate((wire->strcnt+1)*sizeof(WCHAR*) + wire->datalen*sizeof(WCHAR));
2049         dest = (WCHAR*)(*pSnb + wire->strcnt + 1);
2050 
2051         for (i = 0; i < wire->strcnt; i++)
2052         {
2053             ULONG len = strlenW(src);
2054             memcpy(dest, src, (len + 1)*sizeof(WCHAR));
2055             *ptrW = dest;
2056             src += len + 1;
2057             dest += len + 1;
2058             ptrW++;
2059         }
2060         *ptrW = NULL;
2061     }
2062 
2063     return pBuffer + 3*sizeof(ULONG) + wire->datalen*sizeof(WCHAR);
2064 }
2065 
2066 void __RPC_USER SNB_UserFree(ULONG *pFlags, SNB *pSnb)
2067 {
2068     USER_MARSHAL_CB *umcb = (USER_MARSHAL_CB*)pFlags;
2069     TRACE("(%p)\n", pSnb);
2070     if (*pSnb)
2071         umcb->pStubMsg->pfnFree(*pSnb);
2072 }
2073 
2074 /* call_as/local stubs for unknwn.idl */
2075 
2076 HRESULT CALLBACK IClassFactory_CreateInstance_Proxy(
2077     IClassFactory* This,
2078     IUnknown *pUnkOuter,
2079     REFIID riid,
2080     void **ppvObject)
2081 {
2082     TRACE("(%p, %s, %p)\n", pUnkOuter, debugstr_guid(riid), ppvObject);
2083     *ppvObject = NULL;
2084     if (pUnkOuter)
2085     {
2086         ERR("aggregation is not allowed on remote objects\n");
2087         return CLASS_E_NOAGGREGATION;
2088     }
2089     return IClassFactory_RemoteCreateInstance_Proxy(This, riid,
2090                                                     (IUnknown **) ppvObject);
2091 }
2092 
2093 HRESULT __RPC_STUB IClassFactory_CreateInstance_Stub(
2094     IClassFactory* This,
2095     REFIID riid,
2096     IUnknown **ppvObject)
2097 {
2098     TRACE("(%s, %p)\n", debugstr_guid(riid), ppvObject);
2099     return IClassFactory_CreateInstance(This, NULL, riid, (void **) ppvObject);
2100 }
2101 
2102 HRESULT CALLBACK IClassFactory_LockServer_Proxy(
2103     IClassFactory* This,
2104     BOOL fLock)
2105 {
2106     FIXME(":stub\n");
2107     return E_NOTIMPL;
2108 }
2109 
2110 HRESULT __RPC_STUB IClassFactory_LockServer_Stub(
2111     IClassFactory* This,
2112     BOOL fLock)
2113 {
2114     FIXME(":stub\n");
2115     return E_NOTIMPL;
2116 }
2117 
2118 /* call_as/local stubs for objidl.idl */
2119 
2120 HRESULT CALLBACK IEnumUnknown_Next_Proxy(
2121     IEnumUnknown* This,
2122     ULONG celt,
2123     IUnknown **rgelt,
2124     ULONG *pceltFetched)
2125 {
2126     ULONG fetched;
2127     TRACE("(%p)->(%d, %p, %p)\n", This, celt, rgelt, pceltFetched);
2128     if (!pceltFetched) pceltFetched = &fetched;
2129     return IEnumUnknown_RemoteNext_Proxy(This, celt, rgelt, pceltFetched);
2130 }
2131 
2132 HRESULT __RPC_STUB IEnumUnknown_Next_Stub(
2133     IEnumUnknown* This,
2134     ULONG celt,
2135     IUnknown **rgelt,
2136     ULONG *pceltFetched)
2137 {
2138     HRESULT hr;
2139     TRACE("(%p)->(%d, %p, %p)\n", This, celt, rgelt, pceltFetched);
2140     *pceltFetched = 0;
2141     hr = IEnumUnknown_Next(This, celt, rgelt, pceltFetched);
2142     if (hr == S_OK) *pceltFetched = celt;
2143     return hr;
2144 }
2145 
2146 HRESULT CALLBACK IBindCtx_SetBindOptions_Proxy(
2147     IBindCtx* This,
2148     BIND_OPTS *pbindopts)
2149 {
2150     FIXME(":stub\n");
2151     return E_NOTIMPL;
2152 }
2153 
2154 HRESULT __RPC_STUB IBindCtx_SetBindOptions_Stub(
2155     IBindCtx* This,
2156     BIND_OPTS2 *pbindopts)
2157 {
2158     FIXME(":stub\n");
2159     return E_NOTIMPL;
2160 }
2161 
2162 HRESULT CALLBACK IBindCtx_GetBindOptions_Proxy(
2163     IBindCtx* This,
2164     BIND_OPTS *pbindopts)
2165 {
2166     FIXME(":stub\n");
2167     return E_NOTIMPL;
2168 }
2169 
2170 HRESULT __RPC_STUB IBindCtx_GetBindOptions_Stub(
2171     IBindCtx* This,
2172     BIND_OPTS2 *pbindopts)
2173 {
2174     FIXME(":stub\n");
2175     return E_NOTIMPL;
2176 }
2177 
2178 HRESULT CALLBACK IEnumMoniker_Next_Proxy(
2179     IEnumMoniker* This,
2180     ULONG celt,
2181     IMoniker **rgelt,
2182     ULONG *pceltFetched)
2183 {
2184     ULONG fetched;
2185     TRACE("(%p)->(%d, %p, %p)\n", This, celt, rgelt, pceltFetched);
2186     if (!pceltFetched) pceltFetched = &fetched;
2187     return IEnumMoniker_RemoteNext_Proxy(This, celt, rgelt, pceltFetched);
2188 }
2189 
2190 HRESULT __RPC_STUB IEnumMoniker_Next_Stub(
2191     IEnumMoniker* This,
2192     ULONG celt,
2193     IMoniker **rgelt,
2194     ULONG *pceltFetched)
2195 {
2196     HRESULT hr;
2197     TRACE("(%p)->(%d, %p, %p)\n", This, celt, rgelt, pceltFetched);
2198     *pceltFetched = 0;
2199     hr = IEnumMoniker_Next(This, celt, rgelt, pceltFetched);
2200     if (hr == S_OK) *pceltFetched = celt;
2201     return hr;
2202 }
2203 
2204 BOOL CALLBACK IRunnableObject_IsRunning_Proxy(
2205     IRunnableObject* This)
2206 {
2207     BOOL rv;
2208     FIXME(":stub\n");
2209     memset(&rv, 0, sizeof rv);
2210     return rv;
2211 }
2212 
2213 HRESULT __RPC_STUB IRunnableObject_IsRunning_Stub(
2214     IRunnableObject* This)
2215 {
2216     FIXME(":stub\n");
2217     return E_NOTIMPL;
2218 }
2219 
2220 HRESULT CALLBACK IMoniker_BindToObject_Proxy(
2221     IMoniker* This,
2222     IBindCtx *pbc,
2223     IMoniker *pmkToLeft,
2224     REFIID riidResult,
2225     void **ppvResult)
2226 {
2227     FIXME(":stub\n");
2228     return E_NOTIMPL;
2229 }
2230 
2231 HRESULT __RPC_STUB IMoniker_BindToObject_Stub(
2232     IMoniker* This,
2233     IBindCtx *pbc,
2234     IMoniker *pmkToLeft,
2235     REFIID riidResult,
2236     IUnknown **ppvResult)
2237 {
2238     FIXME(":stub\n");
2239     return E_NOTIMPL;
2240 }
2241 
2242 HRESULT CALLBACK IMoniker_BindToStorage_Proxy(
2243     IMoniker* This,
2244     IBindCtx *pbc,
2245     IMoniker *pmkToLeft,
2246     REFIID riid,
2247     void **ppvObj)
2248 {
2249     TRACE("(%p)->(%p %p %s %p)\n", This, pbc, pmkToLeft, debugstr_guid(riid), ppvObj);
2250     return IMoniker_RemoteBindToStorage_Proxy(This, pbc, pmkToLeft, riid, (IUnknown**)ppvObj);
2251 }
2252 
2253 HRESULT __RPC_STUB IMoniker_BindToStorage_Stub(
2254     IMoniker* This,
2255     IBindCtx *pbc,
2256     IMoniker *pmkToLeft,
2257     REFIID riid,
2258     IUnknown **ppvObj)
2259 {
2260     TRACE("(%p)->(%p %p %s %p)\n", This, pbc, pmkToLeft, debugstr_guid(riid), ppvObj);
2261     return IMoniker_BindToStorage(This, pbc, pmkToLeft, riid, (void**)ppvObj);
2262 }
2263 
2264 HRESULT CALLBACK IEnumString_Next_Proxy(
2265     IEnumString* This,
2266     ULONG celt,
2267     LPOLESTR *rgelt,
2268     ULONG *pceltFetched)
2269 {
2270     ULONG fetched;
2271     TRACE("(%p)->(%d, %p, %p)\n", This, celt, rgelt, pceltFetched);
2272     if (!pceltFetched) pceltFetched = &fetched;
2273     return IEnumString_RemoteNext_Proxy(This, celt, rgelt, pceltFetched);
2274 }
2275 
2276 HRESULT __RPC_STUB IEnumString_Next_Stub(
2277     IEnumString* This,
2278     ULONG celt,
2279     LPOLESTR *rgelt,
2280     ULONG *pceltFetched)
2281 {
2282     HRESULT hr;
2283     TRACE("(%p)->(%d, %p, %p)\n", This, celt, rgelt, pceltFetched);
2284     *pceltFetched = 0;
2285     hr = IEnumString_Next(This, celt, rgelt, pceltFetched);
2286     if (hr == S_OK) *pceltFetched = celt;
2287     return hr;
2288 }
2289 
2290 HRESULT CALLBACK ISequentialStream_Read_Proxy(
2291     ISequentialStream* This,
2292     void *pv,
2293     ULONG cb,
2294     ULONG *pcbRead)
2295 {
2296     ULONG read;
2297     HRESULT hr;
2298 
2299     TRACE("(%p)->(%p, %d, %p)\n", This, pv, cb, pcbRead);
2300 
2301     hr = ISequentialStream_RemoteRead_Proxy(This, pv, cb, &read);
2302     if(pcbRead) *pcbRead = read;
2303 
2304     return hr;
2305 }
2306 
2307 HRESULT __RPC_STUB ISequentialStream_Read_Stub(
2308     ISequentialStream* This,
2309     byte *pv,
2310     ULONG cb,
2311     ULONG *pcbRead)
2312 {
2313     TRACE("(%p)->(%p, %d, %p)\n", This, pv, cb, pcbRead);
2314     return ISequentialStream_Read(This, pv, cb, pcbRead);
2315 }
2316 
2317 HRESULT CALLBACK ISequentialStream_Write_Proxy(
2318     ISequentialStream* This,
2319     const void *pv,
2320     ULONG cb,
2321     ULONG *pcbWritten)
2322 {
2323     ULONG written;
2324     HRESULT hr;
2325 
2326     TRACE("(%p)->(%p, %d, %p)\n", This, pv, cb, pcbWritten);
2327 
2328     hr = ISequentialStream_RemoteWrite_Proxy(This, pv, cb, &written);
2329     if(pcbWritten) *pcbWritten = written;
2330 
2331     return hr;
2332 }
2333 
2334 HRESULT __RPC_STUB ISequentialStream_Write_Stub(
2335     ISequentialStream* This,
2336     const byte *pv,
2337     ULONG cb,
2338     ULONG *pcbWritten)
2339 {
2340     TRACE("(%p)->(%p, %d, %p)\n", This, pv, cb, pcbWritten);
2341     return ISequentialStream_Write(This, pv, cb, pcbWritten);
2342 }
2343 
2344 HRESULT CALLBACK IStream_Seek_Proxy(
2345     IStream* This,
2346     LARGE_INTEGER dlibMove,
2347     DWORD dwOrigin,
2348     ULARGE_INTEGER *plibNewPosition)
2349 {
2350     ULARGE_INTEGER newpos;
2351     HRESULT hr;
2352 
2353     TRACE("(%p)->(%s, %d, %p)\n", This, wine_dbgstr_longlong(dlibMove.QuadPart), dwOrigin, plibNewPosition);
2354 
2355     hr = IStream_RemoteSeek_Proxy(This, dlibMove, dwOrigin, &newpos);
2356     if(plibNewPosition) *plibNewPosition = newpos;
2357 
2358     return hr;
2359 }
2360 
2361 HRESULT __RPC_STUB IStream_Seek_Stub(
2362     IStream* This,
2363     LARGE_INTEGER dlibMove,
2364     DWORD dwOrigin,
2365     ULARGE_INTEGER *plibNewPosition)
2366 {
2367     TRACE("(%p)->(%s, %d, %p)\n", This, wine_dbgstr_longlong(dlibMove.QuadPart), dwOrigin, plibNewPosition);
2368     return IStream_Seek(This, dlibMove, dwOrigin, plibNewPosition);
2369 }
2370 
2371 HRESULT CALLBACK IStream_CopyTo_Proxy(
2372     IStream* This,
2373     IStream *pstm,
2374     ULARGE_INTEGER cb,
2375     ULARGE_INTEGER *pcbRead,
2376     ULARGE_INTEGER *pcbWritten)
2377 {
2378     ULARGE_INTEGER read, written;
2379     HRESULT hr;
2380 
2381     TRACE("(%p)->(%p, %s, %p, %p)\n", This, pstm, wine_dbgstr_longlong(cb.QuadPart), pcbRead, pcbWritten);
2382 
2383     hr = IStream_RemoteCopyTo_Proxy(This, pstm, cb, &read, &written);
2384     if(pcbRead) *pcbRead = read;
2385     if(pcbWritten) *pcbWritten = written;
2386 
2387     return hr;
2388 }
2389 
2390 HRESULT __RPC_STUB IStream_CopyTo_Stub(
2391     IStream* This,
2392     IStream *pstm,
2393     ULARGE_INTEGER cb,
2394     ULARGE_INTEGER *pcbRead,
2395     ULARGE_INTEGER *pcbWritten)
2396 {
2397     TRACE("(%p)->(%p, %s, %p, %p)\n", This, pstm, wine_dbgstr_longlong(cb.QuadPart), pcbRead, pcbWritten);
2398 
2399     return IStream_CopyTo(This, pstm, cb, pcbRead, pcbWritten);
2400 }
2401 
2402 HRESULT CALLBACK IEnumSTATSTG_Next_Proxy(
2403     IEnumSTATSTG* This,
2404     ULONG celt,
2405     STATSTG *rgelt,
2406     ULONG *pceltFetched)
2407 {
2408     ULONG fetched;
2409     TRACE("(%p)->(%d, %p, %p)\n", This, celt, rgelt, pceltFetched);
2410     if (!pceltFetched) pceltFetched = &fetched;
2411     return IEnumSTATSTG_RemoteNext_Proxy(This, celt, rgelt, pceltFetched);
2412 }
2413 
2414 HRESULT __RPC_STUB IEnumSTATSTG_Next_Stub(
2415     IEnumSTATSTG* This,
2416     ULONG celt,
2417     STATSTG *rgelt,
2418     ULONG *pceltFetched)
2419 {
2420     HRESULT hr;
2421     TRACE("(%p)->(%d, %p, %p)\n", This, celt, rgelt, pceltFetched);
2422     *pceltFetched = 0;
2423     hr = IEnumSTATSTG_Next(This, celt, rgelt, pceltFetched);
2424     if (hr == S_OK) *pceltFetched = celt;
2425     return hr;
2426 }
2427 
2428 HRESULT CALLBACK IStorage_OpenStream_Proxy(
2429     IStorage* This,
2430     LPCOLESTR pwcsName,
2431     void *reserved1,
2432     DWORD grfMode,
2433     DWORD reserved2,
2434     IStream **ppstm)
2435 {
2436     TRACE("(%p)->(%s, %p, %08x, %d %p)\n", This, debugstr_w(pwcsName), reserved1, grfMode, reserved2, ppstm);
2437     if(reserved1) WARN("reserved1 %p\n", reserved1);
2438 
2439     return IStorage_RemoteOpenStream_Proxy(This, pwcsName, 0, NULL, grfMode, reserved2, ppstm);
2440 }
2441 
2442 HRESULT __RPC_STUB IStorage_OpenStream_Stub(
2443     IStorage* This,
2444     LPCOLESTR pwcsName,
2445     ULONG cbReserved1,
2446     byte *reserved1,
2447     DWORD grfMode,
2448     DWORD reserved2,
2449     IStream **ppstm)
2450 {
2451     TRACE("(%p)->(%s, %d, %p, %08x, %d %p)\n", This, debugstr_w(pwcsName), cbReserved1, reserved1, grfMode, reserved2, ppstm);
2452     if(cbReserved1 || reserved1) WARN("cbReserved1 %d reserved1 %p\n", cbReserved1, reserved1);
2453 
2454     return IStorage_OpenStream(This, pwcsName, NULL, grfMode, reserved2, ppstm);
2455 }
2456 
2457 HRESULT CALLBACK IStorage_EnumElements_Proxy(
2458     IStorage* This,
2459     DWORD reserved1,
2460     void *reserved2,
2461     DWORD reserved3,
2462     IEnumSTATSTG **ppenum)
2463 {
2464     TRACE("(%p)->(%d, %p, %d, %p)\n", This, reserved1, reserved2, reserved3, ppenum);
2465     if(reserved2) WARN("reserved2 %p\n", reserved2);
2466 
2467     return IStorage_RemoteEnumElements_Proxy(This, reserved1, 0, NULL, reserved3, ppenum);
2468 }
2469 
2470 HRESULT __RPC_STUB IStorage_EnumElements_Stub(
2471     IStorage* This,
2472     DWORD reserved1,
2473     ULONG cbReserved2,
2474     byte *reserved2,
2475     DWORD reserved3,
2476     IEnumSTATSTG **ppenum)
2477 {
2478     TRACE("(%p)->(%d, %d, %p, %d, %p)\n", This, reserved1, cbReserved2, reserved2, reserved3, ppenum);
2479     if(cbReserved2 || reserved2) WARN("cbReserved2 %d reserved2 %p\n", cbReserved2, reserved2);
2480 
2481     return IStorage_EnumElements(This, reserved1, NULL, reserved3, ppenum);
2482 }
2483 
2484 HRESULT CALLBACK ILockBytes_ReadAt_Proxy(
2485     ILockBytes* This,
2486     ULARGE_INTEGER ulOffset,
2487     void *pv,
2488     ULONG cb,
2489     ULONG *pcbRead)
2490 {
2491     ULONG read;
2492     HRESULT hr;
2493 
2494     TRACE("(%p)->(%s, %p, %d, %p)\n", This, wine_dbgstr_longlong(ulOffset.QuadPart), pv, cb, pcbRead);
2495 
2496     hr = ILockBytes_RemoteReadAt_Proxy(This, ulOffset, pv, cb, &read);
2497     if(pcbRead) *pcbRead = read;
2498 
2499     return hr;
2500 }
2501 
2502 HRESULT __RPC_STUB ILockBytes_ReadAt_Stub(
2503     ILockBytes* This,
2504     ULARGE_INTEGER ulOffset,
2505     byte *pv,
2506     ULONG cb,
2507     ULONG *pcbRead)
2508 {
2509     TRACE("(%p)->(%s, %p, %d, %p)\n", This, wine_dbgstr_longlong(ulOffset.QuadPart), pv, cb, pcbRead);
2510     return ILockBytes_ReadAt(This, ulOffset, pv, cb, pcbRead);
2511 }
2512 
2513 HRESULT CALLBACK ILockBytes_WriteAt_Proxy(
2514     ILockBytes* This,
2515     ULARGE_INTEGER ulOffset,
2516     const void *pv,
2517     ULONG cb,
2518     ULONG *pcbWritten)
2519 {
2520     ULONG written;
2521     HRESULT hr;
2522 
2523     TRACE("(%p)->(%s, %p, %d, %p)\n", This, wine_dbgstr_longlong(ulOffset.QuadPart), pv, cb, pcbWritten);
2524 
2525     hr = ILockBytes_RemoteWriteAt_Proxy(This, ulOffset, pv, cb, &written);
2526     if(pcbWritten) *pcbWritten = written;
2527 
2528     return hr;
2529 }
2530 
2531 HRESULT __RPC_STUB ILockBytes_WriteAt_Stub(
2532     ILockBytes* This,
2533     ULARGE_INTEGER ulOffset,
2534     const byte *pv,
2535     ULONG cb,
2536     ULONG *pcbWritten)
2537 {
2538     TRACE("(%p)->(%s, %p, %d, %p)\n", This, wine_dbgstr_longlong(ulOffset.QuadPart), pv, cb, pcbWritten);
2539     return ILockBytes_WriteAt(This, ulOffset, pv, cb, pcbWritten);
2540 }
2541 
2542 HRESULT CALLBACK IFillLockBytes_FillAppend_Proxy(
2543     IFillLockBytes* This,
2544     const void *pv,
2545     ULONG cb,
2546     ULONG *pcbWritten)
2547 {
2548     ULONG written;
2549     HRESULT hr;
2550 
2551     TRACE("(%p)->(%p, %d, %p)\n", This, pv, cb, pcbWritten);
2552 
2553     hr = IFillLockBytes_RemoteFillAppend_Proxy(This, pv, cb, &written);
2554     if(pcbWritten) *pcbWritten = written;
2555 
2556     return hr;
2557 }
2558 
2559 HRESULT __RPC_STUB IFillLockBytes_FillAppend_Stub(
2560     IFillLockBytes* This,
2561     const byte *pv,
2562     ULONG cb,
2563     ULONG *pcbWritten)
2564 {
2565     TRACE("(%p)->(%p, %d, %p)\n", This, pv, cb, pcbWritten);
2566     return IFillLockBytes_FillAppend(This, pv, cb, pcbWritten);
2567 }
2568 
2569 HRESULT CALLBACK IFillLockBytes_FillAt_Proxy(
2570     IFillLockBytes* This,
2571     ULARGE_INTEGER ulOffset,
2572     const void *pv,
2573     ULONG cb,
2574     ULONG *pcbWritten)
2575 {
2576     ULONG written;
2577     HRESULT hr;
2578 
2579     TRACE("(%p)->(%s, %p, %d, %p)\n", This, wine_dbgstr_longlong(ulOffset.QuadPart), pv, cb, pcbWritten);
2580 
2581     hr = IFillLockBytes_RemoteFillAt_Proxy(This, ulOffset, pv, cb, &written);
2582     if(pcbWritten) *pcbWritten = written;
2583 
2584     return hr;
2585 }
2586 
2587 HRESULT __RPC_STUB IFillLockBytes_FillAt_Stub(
2588     IFillLockBytes* This,
2589     ULARGE_INTEGER ulOffset,
2590     const byte *pv,
2591     ULONG cb,
2592     ULONG *pcbWritten)
2593 {
2594     TRACE("(%p)->(%s, %p, %d, %p)\n", This, wine_dbgstr_longlong(ulOffset.QuadPart), pv, cb, pcbWritten);
2595     return IFillLockBytes_FillAt(This, ulOffset, pv, cb, pcbWritten);
2596 }
2597 
2598 HRESULT CALLBACK IEnumFORMATETC_Next_Proxy(
2599     IEnumFORMATETC* This,
2600     ULONG celt,
2601     FORMATETC *rgelt,
2602     ULONG *pceltFetched)
2603 {
2604     ULONG fetched;
2605     if (!pceltFetched) pceltFetched = &fetched;
2606     return IEnumFORMATETC_RemoteNext_Proxy(This, celt, rgelt, pceltFetched);
2607 }
2608 
2609 HRESULT __RPC_STUB IEnumFORMATETC_Next_Stub(
2610     IEnumFORMATETC* This,
2611     ULONG celt,
2612     FORMATETC *rgelt,
2613     ULONG *pceltFetched)
2614 {
2615     HRESULT hr;
2616     *pceltFetched = 0;
2617     hr = IEnumFORMATETC_Next(This, celt, rgelt, pceltFetched);
2618     if (hr == S_OK) *pceltFetched = celt;
2619     return hr;
2620 }
2621 
2622 HRESULT CALLBACK IEnumSTATDATA_Next_Proxy(
2623     IEnumSTATDATA* This,
2624     ULONG celt,
2625     STATDATA *rgelt,
2626     ULONG *pceltFetched)
2627 {
2628     ULONG fetched;
2629     TRACE("(%p)->(%d, %p, %p)\n", This, celt, rgelt, pceltFetched);
2630     if (!pceltFetched) pceltFetched = &fetched;
2631     return IEnumSTATDATA_RemoteNext_Proxy(This, celt, rgelt, pceltFetched);
2632 }
2633 
2634 HRESULT __RPC_STUB IEnumSTATDATA_Next_Stub(
2635     IEnumSTATDATA* This,
2636     ULONG celt,
2637     STATDATA *rgelt,
2638     ULONG *pceltFetched)
2639 {
2640     HRESULT hr;
2641     TRACE("(%p)->(%d, %p, %p)\n", This, celt, rgelt, pceltFetched);
2642     *pceltFetched = 0;
2643     hr = IEnumSTATDATA_Next(This, celt, rgelt, pceltFetched);
2644     if (hr == S_OK) *pceltFetched = celt;
2645     return hr;
2646 }
2647 
2648 void CALLBACK IAdviseSink_OnDataChange_Proxy(
2649     IAdviseSink* This,
2650     FORMATETC *pFormatetc,
2651     STGMEDIUM *pStgmed)
2652 {
2653     TRACE("(%p)->(%p, %p)\n", This, pFormatetc, pStgmed);
2654     IAdviseSink_RemoteOnDataChange_Proxy(This, pFormatetc, pStgmed);
2655 }
2656 
2657 HRESULT __RPC_STUB IAdviseSink_OnDataChange_Stub(
2658     IAdviseSink* This,
2659     FORMATETC *pFormatetc,
2660     ASYNC_STGMEDIUM *pStgmed)
2661 {
2662     TRACE("(%p)->(%p, %p)\n", This, pFormatetc, pStgmed);
2663     IAdviseSink_OnDataChange(This, pFormatetc, pStgmed);
2664     return S_OK;
2665 }
2666 
2667 void CALLBACK IAdviseSink_OnViewChange_Proxy(
2668     IAdviseSink* This,
2669     DWORD dwAspect,
2670     LONG lindex)
2671 {
2672     TRACE("(%p)->(%d, %d)\n", This, dwAspect, lindex);
2673     IAdviseSink_RemoteOnViewChange_Proxy(This, dwAspect, lindex);
2674 }
2675 
2676 HRESULT __RPC_STUB IAdviseSink_OnViewChange_Stub(
2677     IAdviseSink* This,
2678     DWORD dwAspect,
2679     LONG lindex)
2680 {
2681     TRACE("(%p)->(%d, %d)\n", This, dwAspect, lindex);
2682     IAdviseSink_OnViewChange(This, dwAspect, lindex);
2683     return S_OK;
2684 }
2685 
2686 void CALLBACK IAdviseSink_OnRename_Proxy(
2687     IAdviseSink* This,
2688     IMoniker *pmk)
2689 {
2690     TRACE("(%p)->(%p)\n", This, pmk);
2691     IAdviseSink_RemoteOnRename_Proxy(This, pmk);
2692 }
2693 
2694 HRESULT __RPC_STUB IAdviseSink_OnRename_Stub(
2695     IAdviseSink* This,
2696     IMoniker *pmk)
2697 {
2698     TRACE("(%p)->(%p)\n", This, pmk);
2699     IAdviseSink_OnRename(This, pmk);
2700     return S_OK;
2701 }
2702 
2703 void CALLBACK IAdviseSink_OnSave_Proxy(
2704     IAdviseSink* This)
2705 {
2706     TRACE("(%p)\n", This);
2707     IAdviseSink_RemoteOnSave_Proxy(This);
2708 }
2709 
2710 HRESULT __RPC_STUB IAdviseSink_OnSave_Stub(
2711     IAdviseSink* This)
2712 {
2713     TRACE("(%p)\n", This);
2714     IAdviseSink_OnSave(This);
2715     return S_OK;
2716 }
2717 
2718 void CALLBACK IAdviseSink_OnClose_Proxy(
2719     IAdviseSink* This)
2720 {
2721     TRACE("(%p)\n", This);
2722     IAdviseSink_RemoteOnClose_Proxy(This);
2723 }
2724 
2725 HRESULT __RPC_STUB IAdviseSink_OnClose_Stub(
2726     IAdviseSink* This)
2727 {
2728     TRACE("(%p)\n", This);
2729     IAdviseSink_OnClose(This);
2730     return S_OK;
2731 }
2732 
2733 void CALLBACK IAdviseSink2_OnLinkSrcChange_Proxy(
2734     IAdviseSink2* This,
2735     IMoniker *pmk)
2736 {
2737     TRACE("(%p)->(%p)\n", This, pmk);
2738     IAdviseSink2_RemoteOnLinkSrcChange_Proxy(This, pmk);
2739 }
2740 
2741 HRESULT __RPC_STUB IAdviseSink2_OnLinkSrcChange_Stub(
2742     IAdviseSink2* This,
2743     IMoniker *pmk)
2744 {
2745     TRACE("(%p)->(%p)\n", This, pmk);
2746     IAdviseSink2_OnLinkSrcChange(This, pmk);
2747     return S_OK;
2748 }
2749 
2750 HRESULT CALLBACK IDataObject_GetData_Proxy(
2751     IDataObject* This,
2752     FORMATETC *pformatetcIn,
2753     STGMEDIUM *pmedium)
2754 {
2755     TRACE("(%p)->(%p, %p)\n", This, pformatetcIn, pmedium);
2756     return IDataObject_RemoteGetData_Proxy(This, pformatetcIn, pmedium);
2757 }
2758 
2759 HRESULT __RPC_STUB IDataObject_GetData_Stub(
2760     IDataObject* This,
2761     FORMATETC *pformatetcIn,
2762     STGMEDIUM *pRemoteMedium)
2763 {
2764     TRACE("(%p)->(%p, %p)\n", This, pformatetcIn, pRemoteMedium);
2765     return IDataObject_GetData(This, pformatetcIn, pRemoteMedium);
2766 }
2767 
2768 HRESULT CALLBACK IDataObject_GetDataHere_Proxy(IDataObject *iface, FORMATETC *fmt, STGMEDIUM *med)
2769 {
2770     IUnknown *release;
2771     IStorage *stg = NULL;
2772     HRESULT hr;
2773 
2774     TRACE("(%p)->(%p, %p)\n", iface, fmt, med);
2775 
2776     if ((med->tymed & (TYMED_HGLOBAL | TYMED_FILE | TYMED_ISTREAM | TYMED_ISTORAGE)) == 0)
2777         return DV_E_TYMED;
2778     if (med->tymed != fmt->tymed)
2779         return DV_E_TYMED;
2780 
2781     release = med->pUnkForRelease;
2782     med->pUnkForRelease = NULL;
2783 
2784     if (med->tymed == TYMED_ISTREAM || med->tymed == TYMED_ISTORAGE)
2785     {
2786         stg = med->u.pstg; /* This may actually be a stream, but that's ok */
2787         if (stg) IStorage_AddRef( stg );
2788     }
2789 
2790     hr = IDataObject_RemoteGetDataHere_Proxy(iface, fmt, med);
2791 
2792     med->pUnkForRelease = release;
2793     if (stg)
2794     {
2795         if (med->u.pstg)
2796             IStorage_Release( med->u.pstg );
2797         med->u.pstg = stg;
2798     }
2799 
2800     return hr;
2801 }
2802 
2803 HRESULT __RPC_STUB IDataObject_GetDataHere_Stub(
2804     IDataObject* This,
2805     FORMATETC *pformatetc,
2806     STGMEDIUM *pRemoteMedium)
2807 {
2808     TRACE("(%p)->(%p, %p)\n", This, pformatetc, pRemoteMedium);
2809     return IDataObject_GetDataHere(This, pformatetc, pRemoteMedium);
2810 }
2811 
2812 HRESULT CALLBACK IDataObject_SetData_Proxy(
2813     IDataObject* This,
2814     FORMATETC *pformatetc,
2815     STGMEDIUM *pmedium,
2816     BOOL fRelease)
2817 {
2818     FIXME(":stub\n");
2819     return E_NOTIMPL;
2820 }
2821 
2822 HRESULT __RPC_STUB IDataObject_SetData_Stub(
2823     IDataObject* This,
2824     FORMATETC *pformatetc,
2825     FLAG_STGMEDIUM *pmedium,
2826     BOOL fRelease)
2827 {
2828     FIXME(":stub\n");
2829     return E_NOTIMPL;
2830 }
2831 
2832 /* call_as/local stubs for oleidl.idl */
2833 
2834 HRESULT CALLBACK IOleInPlaceActiveObject_TranslateAccelerator_Proxy(
2835     IOleInPlaceActiveObject* This,
2836     LPMSG lpmsg)
2837 {
2838     TRACE("(%p %p)\n", This, lpmsg);
2839     return IOleInPlaceActiveObject_RemoteTranslateAccelerator_Proxy(This);
2840 }
2841 
2842 HRESULT __RPC_STUB IOleInPlaceActiveObject_TranslateAccelerator_Stub(
2843     IOleInPlaceActiveObject* This)
2844 {
2845     TRACE("(%p)\n", This);
2846     return S_FALSE;
2847 }
2848 
2849 HRESULT CALLBACK IOleInPlaceActiveObject_ResizeBorder_Proxy(
2850     IOleInPlaceActiveObject* This,
2851     LPCRECT prcBorder,
2852     IOleInPlaceUIWindow *pUIWindow,
2853     BOOL fFrameWindow)
2854 {
2855     FIXME(":stub\n");
2856     return E_NOTIMPL;
2857 }
2858 
2859 HRESULT __RPC_STUB IOleInPlaceActiveObject_ResizeBorder_Stub(
2860     IOleInPlaceActiveObject* This,
2861     LPCRECT prcBorder,
2862     REFIID riid,
2863     IOleInPlaceUIWindow *pUIWindow,
2864     BOOL fFrameWindow)
2865 {
2866     FIXME(":stub\n");
2867     return E_NOTIMPL;
2868 }
2869 
2870 HRESULT CALLBACK IOleCache2_UpdateCache_Proxy(
2871     IOleCache2* This,
2872     LPDATAOBJECT pDataObject,
2873     DWORD grfUpdf,
2874     LPVOID pReserved)
2875 {
2876     TRACE("(%p, %p, 0x%08x, %p)\n", This, pDataObject, grfUpdf, pReserved);
2877     return IOleCache2_RemoteUpdateCache_Proxy(This, pDataObject, grfUpdf, (LONG_PTR)pReserved);
2878 }
2879 
2880 HRESULT __RPC_STUB IOleCache2_UpdateCache_Stub(
2881     IOleCache2* This,
2882     LPDATAOBJECT pDataObject,
2883     DWORD grfUpdf,
2884     LONG_PTR pReserved)
2885 {
2886     TRACE("(%p, %p, 0x%08x, %li)\n", This, pDataObject, grfUpdf, pReserved);
2887     return IOleCache2_UpdateCache(This, pDataObject, grfUpdf, (void*)pReserved);
2888 }
2889 
2890 HRESULT CALLBACK IEnumOLEVERB_Next_Proxy(
2891     IEnumOLEVERB* This,
2892     ULONG celt,
2893     LPOLEVERB rgelt,
2894     ULONG *pceltFetched)
2895 {
2896     ULONG fetched;
2897     TRACE("(%p)->(%d, %p, %p)\n", This, celt, rgelt, pceltFetched);
2898     if (!pceltFetched) pceltFetched = &fetched;
2899     return IEnumOLEVERB_RemoteNext_Proxy(This, celt, rgelt, pceltFetched);
2900 }
2901 
2902 HRESULT __RPC_STUB IEnumOLEVERB_Next_Stub(
2903     IEnumOLEVERB* This,
2904     ULONG celt,
2905     LPOLEVERB rgelt,
2906     ULONG *pceltFetched)
2907 {
2908     HRESULT hr;
2909     TRACE("(%p)->(%d, %p, %p)\n", This, celt, rgelt, pceltFetched);
2910     *pceltFetched = 0;
2911     hr = IEnumOLEVERB_Next(This, celt, rgelt, pceltFetched);
2912     if (hr == S_OK) *pceltFetched = celt;
2913     return hr;
2914 }
2915 
2916 HRESULT CALLBACK IViewObject_Draw_Proxy(
2917     IViewObject* This,
2918     DWORD dwDrawAspect,
2919     LONG lindex,
2920     void *pvAspect,
2921     DVTARGETDEVICE *ptd,
2922     HDC hdcTargetDev,
2923     HDC hdcDraw,
2924     LPCRECTL lprcBounds,
2925     LPCRECTL lprcWBounds,
2926     BOOL (STDMETHODCALLTYPE *pfnContinue)(ULONG_PTR dwContinue),
2927     ULONG_PTR dwContinue)
2928 {
2929     FIXME(":stub\n");
2930     return E_NOTIMPL;
2931 }
2932 
2933 HRESULT __RPC_STUB IViewObject_Draw_Stub(
2934     IViewObject* This,
2935     DWORD dwDrawAspect,
2936     LONG lindex,
2937     ULONG_PTR pvAspect,
2938     DVTARGETDEVICE *ptd,
2939     ULONG_PTR hdcTargetDev,
2940     ULONG_PTR hdcDraw,
2941     LPCRECTL lprcBounds,
2942     LPCRECTL lprcWBounds,
2943     IContinue *pContinue)
2944 {
2945     FIXME(":stub\n");
2946     return E_NOTIMPL;
2947 }
2948 
2949 HRESULT CALLBACK IViewObject_GetColorSet_Proxy(
2950     IViewObject* This,
2951     DWORD dwDrawAspect,
2952     LONG lindex,
2953     void *pvAspect,
2954     DVTARGETDEVICE *ptd,
2955     HDC hicTargetDev,
2956     LOGPALETTE **ppColorSet)
2957 {
2958     FIXME(":stub\n");
2959     return E_NOTIMPL;
2960 }
2961 
2962 HRESULT __RPC_STUB IViewObject_GetColorSet_Stub(
2963     IViewObject* This,
2964     DWORD dwDrawAspect,
2965     LONG lindex,
2966     ULONG_PTR pvAspect,
2967     DVTARGETDEVICE *ptd,
2968     ULONG_PTR hicTargetDev,
2969     LOGPALETTE **ppColorSet)
2970 {
2971     FIXME(":stub\n");
2972     return E_NOTIMPL;
2973 }
2974 
2975 HRESULT CALLBACK IViewObject_Freeze_Proxy(
2976     IViewObject* This,
2977     DWORD dwDrawAspect,
2978     LONG lindex,
2979     void *pvAspect,
2980     DWORD *pdwFreeze)
2981 {
2982     FIXME(":stub\n");
2983     return E_NOTIMPL;
2984 }
2985 
2986 HRESULT __RPC_STUB IViewObject_Freeze_Stub(
2987     IViewObject* This,
2988     DWORD dwDrawAspect,
2989     LONG lindex,
2990     ULONG_PTR pvAspect,
2991     DWORD *pdwFreeze)
2992 {
2993     FIXME(":stub\n");
2994     return E_NOTIMPL;
2995 }
2996 
2997 HRESULT CALLBACK IViewObject_GetAdvise_Proxy(
2998     IViewObject* This,
2999     DWORD *pAspects,
3000     DWORD *pAdvf,
3001     IAdviseSink **ppAdvSink)
3002 {
3003     FIXME(":stub\n");
3004     return E_NOTIMPL;
3005 }
3006 
3007 HRESULT __RPC_STUB IViewObject_GetAdvise_Stub(
3008     IViewObject* This,
3009     DWORD *pAspects,
3010     DWORD *pAdvf,
3011     IAdviseSink **ppAdvSink)
3012 {
3013     FIXME(":stub\n");
3014     return E_NOTIMPL;
3015 }
3016