mfplat: Add MFCreateAMMediaTypeFromMFMediaType stub.
[wine.git] / dlls / combase / usrmarshal.c
blob87513d335bf1f72c34aaac961d4922b7c60e815a
1 /*
2 * Marshaling Routines
4 * Copyright 2005 Robert Shearman
5 * Copyright 2009 Huw Davies
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #define COBJMACROS
23 #include "ole2.h"
25 #include "wine/debug.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(ole);
29 #define ALIGNED_LENGTH(_Len, _Align) (((_Len)+(_Align))&~(_Align))
30 #define ALIGNED_POINTER(_Ptr, _Align) ((LPVOID)ALIGNED_LENGTH((ULONG_PTR)(_Ptr), _Align))
31 #define ALIGN_LENGTH(_Len, _Align) _Len = ALIGNED_LENGTH(_Len, _Align)
32 #define ALIGN_POINTER(_Ptr, _Align) _Ptr = ALIGNED_POINTER(_Ptr, _Align)
34 static const char* debugstr_user_flags(ULONG *pFlags)
36 char buf[12];
37 const char* loword;
38 switch (LOWORD(*pFlags))
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;
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));
63 static ULONG handle_UserSize(ULONG *pFlags, ULONG StartingSize, HANDLE *handle)
65 if (LOWORD(*pFlags) == MSHCTX_DIFFERENTMACHINE)
67 ERR("can't remote a local handle\n");
68 RaiseException(RPC_S_INVALID_TAG, 0, 0, NULL);
69 return StartingSize;
72 ALIGN_LENGTH(StartingSize, 3);
73 return StartingSize + sizeof(RemotableHandle);
76 static unsigned char * handle_UserMarshal(ULONG *pFlags, unsigned char *pBuffer, HANDLE *handle)
78 RemotableHandle *remhandle;
79 if (LOWORD(*pFlags) == MSHCTX_DIFFERENTMACHINE)
81 ERR("can't remote a local handle\n");
82 RaiseException(RPC_S_INVALID_TAG, 0, 0, NULL);
83 return pBuffer;
86 ALIGN_POINTER(pBuffer, 3);
87 remhandle = (RemotableHandle *)pBuffer;
88 remhandle->fContext = WDT_INPROC_CALL;
89 remhandle->u.hInproc = (LONG_PTR)*handle;
90 return pBuffer + sizeof(RemotableHandle);
93 static unsigned char * handle_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, HANDLE *handle)
95 RemotableHandle *remhandle;
97 ALIGN_POINTER(pBuffer, 3);
98 remhandle = (RemotableHandle *)pBuffer;
99 if (remhandle->fContext != WDT_INPROC_CALL)
100 RaiseException(RPC_X_BAD_STUB_DATA, 0, 0, NULL);
101 *handle = (HANDLE)(LONG_PTR)remhandle->u.hInproc;
102 return pBuffer + sizeof(RemotableHandle);
105 static void handle_UserFree(ULONG *pFlags, HANDLE *handle)
107 /* nothing to do */
110 #define IMPL_WIREM_HANDLE(type) \
111 ULONG __RPC_USER type##_UserSize(ULONG *pFlags, ULONG StartingSize, type *handle) \
113 TRACE("%s, %lu, %p.\n", debugstr_user_flags(pFlags), StartingSize, handle); \
114 return handle_UserSize(pFlags, StartingSize, (HANDLE *)handle); \
117 unsigned char * __RPC_USER type##_UserMarshal(ULONG *pFlags, unsigned char *pBuffer, type *handle) \
119 TRACE("%s, %p, &%p.\n", debugstr_user_flags(pFlags), pBuffer, *handle); \
120 return handle_UserMarshal(pFlags, pBuffer, (HANDLE *)handle); \
123 unsigned char * __RPC_USER type##_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, type *handle) \
125 TRACE("%s, %p, %p.\n", debugstr_user_flags(pFlags), pBuffer, handle); \
126 return handle_UserUnmarshal(pFlags, pBuffer, (HANDLE *)handle); \
129 void __RPC_USER type##_UserFree(ULONG *pFlags, type *handle) \
131 TRACE("%s, &%p.\n", debugstr_user_flags(pFlags), *handle); \
132 handle_UserFree(pFlags, (HANDLE *)handle); \
135 IMPL_WIREM_HANDLE(HACCEL)
136 IMPL_WIREM_HANDLE(HBRUSH)
137 IMPL_WIREM_HANDLE(HDC)
138 IMPL_WIREM_HANDLE(HICON)
139 IMPL_WIREM_HANDLE(HMENU)
140 IMPL_WIREM_HANDLE(HWND)
142 /******************************************************************************
143 * CLIPFORMAT_UserSize (combase.@)
145 * Calculates the buffer size required to marshal a clip format.
147 * PARAMS
148 * pFlags [I] Flags. See notes.
149 * StartingSize [I] Starting size of the buffer. This value is added on to
150 * the buffer size required for the clip format.
151 * pCF [I] Clip format to size.
153 * RETURNS
154 * The buffer size required to marshal a clip format plus the starting size.
156 * NOTES
157 * Even though the function is documented to take a pointer to an unsigned
158 * long in pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
159 * the first parameter is an unsigned long.
160 * This function is only intended to be called by the RPC runtime.
162 ULONG __RPC_USER CLIPFORMAT_UserSize(ULONG *pFlags, ULONG size, CLIPFORMAT *pCF)
164 TRACE("%s, %lu, %p.\n", debugstr_user_flags(pFlags), size, pCF);
166 ALIGN_LENGTH(size, 3);
168 size += 8;
170 /* only need to marshal the name if it is not a pre-defined type and
171 * we are going remote */
172 if ((*pCF >= 0xc000) && (LOWORD(*pFlags) == MSHCTX_DIFFERENTMACHINE))
174 WCHAR format[255];
175 INT ret;
176 size += 3 * sizeof(UINT);
177 /* urg! this function is badly designed because it won't tell us how
178 * much space is needed without doing a dummy run of storing the
179 * name into a buffer */
180 ret = GetClipboardFormatNameW(*pCF, format, ARRAY_SIZE(format)-1);
181 if (!ret)
182 RaiseException(DV_E_CLIPFORMAT, 0, 0, NULL);
183 size += (ret + 1) * sizeof(WCHAR);
185 return size;
188 /******************************************************************************
189 * CLIPFORMAT_UserMarshal (combase.@)
191 * Marshals a clip format into a buffer.
193 * PARAMS
194 * pFlags [I] Flags. See notes.
195 * pBuffer [I] Buffer to marshal the clip format into.
196 * pCF [I] Clip format to marshal.
198 * RETURNS
199 * The end of the marshaled data in the buffer.
201 * NOTES
202 * Even though the function is documented to take a pointer to an unsigned
203 * long in pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
204 * the first parameter is an unsigned long.
205 * This function is only intended to be called by the RPC runtime.
207 unsigned char * __RPC_USER CLIPFORMAT_UserMarshal(ULONG *pFlags, unsigned char *pBuffer, CLIPFORMAT *pCF)
209 TRACE("%s, %p, &0x%04x.\n", debugstr_user_flags(pFlags), pBuffer, *pCF);
211 ALIGN_POINTER(pBuffer, 3);
213 /* only need to marshal the name if it is not a pre-defined type and
214 * we are going remote */
215 if ((*pCF >= 0xc000) && (LOWORD(*pFlags) == MSHCTX_DIFFERENTMACHINE))
217 WCHAR format[255];
218 UINT len;
220 *(DWORD *)pBuffer = WDT_REMOTE_CALL;
221 pBuffer += 4;
222 *(DWORD *)pBuffer = *pCF;
223 pBuffer += 4;
225 len = GetClipboardFormatNameW(*pCF, format, ARRAY_SIZE(format)-1);
226 if (!len)
227 RaiseException(DV_E_CLIPFORMAT, 0, 0, NULL);
228 len += 1;
229 *(UINT *)pBuffer = len;
230 pBuffer += sizeof(UINT);
231 *(UINT *)pBuffer = 0;
232 pBuffer += sizeof(UINT);
233 *(UINT *)pBuffer = len;
234 pBuffer += sizeof(UINT);
235 TRACE("marshaling format name %s\n", debugstr_w(format));
236 memcpy(pBuffer, format, len * sizeof(WCHAR));
237 pBuffer += len * sizeof(WCHAR);
239 else
241 *(DWORD *)pBuffer = WDT_INPROC_CALL;
242 pBuffer += 4;
243 *(DWORD *)pBuffer = *pCF;
244 pBuffer += 4;
247 return pBuffer;
250 /******************************************************************************
251 * CLIPFORMAT_UserUnmarshal (combase.@)
253 * Unmarshals a clip format from a buffer.
255 * PARAMS
256 * pFlags [I] Flags. See notes.
257 * pBuffer [I] Buffer to marshal the clip format from.
258 * pCF [O] Address that receive the unmarshaled clip format.
260 * RETURNS
261 * The end of the marshaled data in the buffer.
263 * NOTES
264 * Even though the function is documented to take a pointer to an unsigned
265 * long in pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
266 * the first parameter is an unsigned long.
267 * This function is only intended to be called by the RPC runtime.
269 unsigned char * __RPC_USER CLIPFORMAT_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, CLIPFORMAT *pCF)
271 LONG fContext;
273 TRACE("%s, %p, %p.\n", debugstr_user_flags(pFlags), pBuffer, pCF);
275 ALIGN_POINTER(pBuffer, 3);
277 fContext = *(DWORD *)pBuffer;
278 pBuffer += 4;
280 if (fContext == WDT_INPROC_CALL)
282 *pCF = *(CLIPFORMAT *)pBuffer;
283 pBuffer += 4;
285 else if (fContext == WDT_REMOTE_CALL)
287 CLIPFORMAT cf;
288 UINT len;
290 /* pointer ID for registered clip format string */
291 if (*(DWORD *)pBuffer == 0)
292 RaiseException(RPC_S_INVALID_BOUND, 0, 0, NULL);
293 pBuffer += 4;
295 len = *(UINT *)pBuffer;
296 pBuffer += sizeof(UINT);
297 if (*(UINT *)pBuffer != 0)
298 RaiseException(RPC_S_INVALID_BOUND, 0, 0, NULL);
299 pBuffer += sizeof(UINT);
300 if (*(UINT *)pBuffer != len)
301 RaiseException(RPC_S_INVALID_BOUND, 0, 0, NULL);
302 pBuffer += sizeof(UINT);
303 if (((WCHAR *)pBuffer)[len - 1] != '\0')
304 RaiseException(RPC_S_INVALID_BOUND, 0, 0, NULL);
305 TRACE("unmarshaling clip format %s\n", debugstr_w((LPCWSTR)pBuffer));
306 cf = RegisterClipboardFormatW((LPCWSTR)pBuffer);
307 pBuffer += len * sizeof(WCHAR);
308 if (!cf)
309 RaiseException(DV_E_CLIPFORMAT, 0, 0, NULL);
310 *pCF = cf;
312 else
313 /* code not really appropriate, but nearest I can find */
314 RaiseException(RPC_S_INVALID_TAG, 0, 0, NULL);
315 return pBuffer;
318 /******************************************************************************
319 * CLIPFORMAT_UserFree (combase.@)
321 * Frees an unmarshaled clip format.
323 * PARAMS
324 * pFlags [I] Flags. See notes.
325 * pCF [I] Clip format to free.
327 * RETURNS
328 * The end of the marshaled data in the buffer.
330 * NOTES
331 * Even though the function is documented to take a pointer to an unsigned
332 * long in pFlags, it actually takes a pointer to a USER_MARSHAL_CB
333 * structure, of which the first parameter is an unsigned long.
334 * This function is only intended to be called by the RPC runtime.
336 void __RPC_USER CLIPFORMAT_UserFree(ULONG *pFlags, CLIPFORMAT *pCF)
338 /* there is no inverse of the RegisterClipboardFormat function,
339 * so nothing to do */
342 /******************************************************************************
343 * HBITMAP_UserSize (combase.@)
345 * Calculates the buffer size required to marshal a bitmap.
347 * PARAMS
348 * pFlags [I] Flags. See notes.
349 * StartingSize [I] Starting size of the buffer. This value is added on to
350 * the buffer size required for the clip format.
351 * phBmp [I] Bitmap to size.
353 * RETURNS
354 * The buffer size required to marshal an bitmap plus the starting size.
356 * NOTES
357 * Even though the function is documented to take a pointer to a ULONG in
358 * pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
359 * the first parameter is a ULONG.
360 * This function is only intended to be called by the RPC runtime.
362 ULONG __RPC_USER HBITMAP_UserSize(ULONG *flags, ULONG size, HBITMAP *bmp)
364 TRACE("%s, %lu, %p.\n", debugstr_user_flags(flags), size, *bmp);
366 ALIGN_LENGTH(size, 3);
368 size += sizeof(ULONG);
369 if (LOWORD(*flags) == MSHCTX_INPROC)
370 size += sizeof(ULONG);
371 else
373 size += sizeof(ULONG);
375 if (*bmp)
377 size += sizeof(ULONG);
378 size += FIELD_OFFSET(userBITMAP, cbSize);
379 size += GetBitmapBits(*bmp, 0, NULL);
383 return size;
386 /******************************************************************************
387 * HBITMAP_UserMarshal (combase.@)
389 * Marshals a bitmap into a buffer.
391 * PARAMS
392 * pFlags [I] Flags. See notes.
393 * pBuffer [I] Buffer to marshal the clip format into.
394 * phBmp [I] Bitmap to marshal.
396 * RETURNS
397 * The end of the marshaled data in the buffer.
399 * NOTES
400 * Even though the function is documented to take a pointer to a ULONG in
401 * pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
402 * the first parameter is a ULONG.
403 * This function is only intended to be called by the RPC runtime.
405 unsigned char * __RPC_USER HBITMAP_UserMarshal(ULONG *flags, unsigned char *buffer, HBITMAP *bmp)
407 TRACE("(%s, %p, %p)\n", debugstr_user_flags(flags), buffer, *bmp);
409 ALIGN_POINTER(buffer, 3);
411 if (LOWORD(*flags) == MSHCTX_INPROC)
413 *(ULONG *)buffer = WDT_INPROC_CALL;
414 buffer += sizeof(ULONG);
415 *(ULONG *)buffer = (ULONG)(ULONG_PTR)*bmp;
416 buffer += sizeof(ULONG);
418 else
420 *(ULONG *)buffer = WDT_REMOTE_CALL;
421 buffer += sizeof(ULONG);
422 *(ULONG *)buffer = (ULONG)(ULONG_PTR)*bmp;
423 buffer += sizeof(ULONG);
425 if (*bmp)
427 static const ULONG header_size = FIELD_OFFSET(userBITMAP, cbSize);
428 BITMAP bitmap;
429 ULONG bitmap_size;
431 bitmap_size = GetBitmapBits(*bmp, 0, NULL);
432 *(ULONG *)buffer = bitmap_size;
433 buffer += sizeof(ULONG);
435 GetObjectW(*bmp, sizeof(BITMAP), &bitmap);
436 memcpy(buffer, &bitmap, header_size);
437 buffer += header_size;
439 GetBitmapBits(*bmp, bitmap_size, buffer);
440 buffer += bitmap_size;
443 return buffer;
446 /******************************************************************************
447 * HBITMAP_UserUnmarshal (combase.@)
449 * Unmarshals a bitmap from a buffer.
451 * PARAMS
452 * pFlags [I] Flags. See notes.
453 * pBuffer [I] Buffer to marshal the clip format from.
454 * phBmp [O] Address that receive the unmarshaled bitmap.
456 * RETURNS
457 * The end of the marshaled data in the buffer.
459 * NOTES
460 * Even though the function is documented to take a pointer to an ULONG in
461 * pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
462 * the first parameter is an ULONG.
463 * This function is only intended to be called by the RPC runtime.
465 unsigned char * __RPC_USER HBITMAP_UserUnmarshal(ULONG *flags, unsigned char *buffer, HBITMAP *bmp)
467 ULONG context;
469 TRACE("(%s, %p, %p)\n", debugstr_user_flags(flags), buffer, bmp);
471 ALIGN_POINTER(buffer, 3);
473 context = *(ULONG *)buffer;
474 buffer += sizeof(ULONG);
476 if (context == WDT_INPROC_CALL)
478 *bmp = *(HBITMAP *)buffer;
479 buffer += sizeof(*bmp);
481 else if (context == WDT_REMOTE_CALL)
483 ULONG handle = *(ULONG *)buffer;
484 buffer += sizeof(ULONG);
486 if (handle)
488 static const ULONG header_size = FIELD_OFFSET(userBITMAP, cbSize);
489 BITMAP bitmap;
490 ULONG bitmap_size;
491 unsigned char *bits;
493 bitmap_size = *(ULONG *)buffer;
494 buffer += sizeof(ULONG);
495 bits = malloc(bitmap_size);
497 memcpy(&bitmap, buffer, header_size);
498 buffer += header_size;
500 memcpy(bits, buffer, bitmap_size);
501 buffer += bitmap_size;
503 bitmap.bmBits = bits;
504 *bmp = CreateBitmapIndirect(&bitmap);
506 free(bits);
508 else
509 *bmp = NULL;
511 else
512 RaiseException(RPC_S_INVALID_TAG, 0, 0, NULL);
514 return buffer;
517 /******************************************************************************
518 * HBITMAP_UserFree (combase.@)
520 * Frees an unmarshaled bitmap.
522 * PARAMS
523 * pFlags [I] Flags. See notes.
524 * phBmp [I] Bitmap to free.
526 * RETURNS
527 * The end of the marshaled data in the buffer.
529 * NOTES
530 * Even though the function is documented to take a pointer to a ULONG in
531 * pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of
532 * which the first parameter is a ULONG.
533 * This function is only intended to be called by the RPC runtime.
535 void __RPC_USER HBITMAP_UserFree(ULONG *flags, HBITMAP *bmp)
537 TRACE("(%s, %p)\n", debugstr_user_flags(flags), *bmp);
539 if (LOWORD(*flags) != MSHCTX_INPROC)
540 DeleteObject(*bmp);
543 /******************************************************************************
544 * HPALETTE_UserSize (combase.@)
546 * Calculates the buffer size required to marshal a palette.
548 * PARAMS
549 * pFlags [I] Flags. See notes.
550 * StartingSize [I] Starting size of the buffer. This value is added on to
551 * the buffer size required for the clip format.
552 * phPal [I] Palette to size.
554 * RETURNS
555 * The buffer size required to marshal a palette plus the starting size.
557 * NOTES
558 * Even though the function is documented to take a pointer to a ULONG in
559 * pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
560 * the first parameter is a ULONG.
561 * This function is only intended to be called by the RPC runtime.
563 ULONG __RPC_USER HPALETTE_UserSize(ULONG *pFlags, ULONG StartingSize, HPALETTE *phPal)
565 FIXME(":stub\n");
566 return StartingSize;
569 /******************************************************************************
570 * HPALETTE_UserMarshal (combase.@)
572 * Marshals a palette into a buffer.
574 * PARAMS
575 * pFlags [I] Flags. See notes.
576 * pBuffer [I] Buffer to marshal the clip format into.
577 * phPal [I] Palette to marshal.
579 * RETURNS
580 * The end of the marshaled data in the buffer.
582 * NOTES
583 * Even though the function is documented to take a pointer to a ULONG in
584 * pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
585 * the first parameter is a ULONG.
586 * This function is only intended to be called by the RPC runtime.
588 unsigned char * __RPC_USER HPALETTE_UserMarshal(ULONG *pFlags, unsigned char *pBuffer, HPALETTE *phPal)
590 FIXME(":stub\n");
591 return pBuffer;
594 /******************************************************************************
595 * HPALETTE_UserUnmarshal (combase.@)
597 * Unmarshals a palette from a buffer.
599 * PARAMS
600 * pFlags [I] Flags. See notes.
601 * pBuffer [I] Buffer to marshal the clip format from.
602 * phPal [O] Address that receive the unmarshaled palette.
604 * RETURNS
605 * The end of the marshaled data in the buffer.
607 * NOTES
608 * Even though the function is documented to take a pointer to an ULONG in
609 * pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
610 * the first parameter is an ULONG.
611 * This function is only intended to be called by the RPC runtime.
613 unsigned char * __RPC_USER HPALETTE_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, HPALETTE *phPal)
615 FIXME(":stub\n");
616 return pBuffer;
619 /******************************************************************************
620 * HGLOBAL_UserSize (combase.@)
622 * Calculates the buffer size required to marshal an HGLOBAL.
624 * PARAMS
625 * pFlags [I] Flags. See notes.
626 * StartingSize [I] Starting size of the buffer. This value is added on to
627 * the buffer size required for the clip format.
628 * phGlobal [I] HGLOBAL to size.
630 * RETURNS
631 * The buffer size required to marshal an HGLOBAL plus the starting size.
633 * NOTES
634 * Even though the function is documented to take a pointer to a ULONG in
635 * pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
636 * the first parameter is a ULONG.
637 * This function is only intended to be called by the RPC runtime.
639 ULONG __RPC_USER HGLOBAL_UserSize(ULONG *pFlags, ULONG StartingSize, HGLOBAL *phGlobal)
641 ULONG size = StartingSize;
643 TRACE("%s, %lu, %p.\n", debugstr_user_flags(pFlags), StartingSize, phGlobal);
645 ALIGN_LENGTH(size, 3);
647 size += sizeof(ULONG);
649 if (LOWORD(*pFlags) == MSHCTX_INPROC)
650 size += sizeof(HGLOBAL);
651 else
653 size += sizeof(ULONG);
654 if (*phGlobal)
656 SIZE_T ret;
657 size += 3 * sizeof(ULONG);
658 ret = GlobalSize(*phGlobal);
659 size += (ULONG)ret;
663 return size;
666 /******************************************************************************
667 * HGLOBAL_UserMarshal (combase.@)
669 * Marshals an HGLOBAL into a buffer.
671 * PARAMS
672 * pFlags [I] Flags. See notes.
673 * pBuffer [I] Buffer to marshal the clip format into.
674 * phGlobal [I] HGLOBAL to marshal.
676 * RETURNS
677 * The end of the marshaled data in the buffer.
679 * NOTES
680 * Even though the function is documented to take a pointer to a ULONG in
681 * pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
682 * the first parameter is a ULONG.
683 * This function is only intended to be called by the RPC runtime.
685 unsigned char * __RPC_USER HGLOBAL_UserMarshal(ULONG *pFlags, unsigned char *pBuffer, HGLOBAL *phGlobal)
687 TRACE("%s, %p, &%p.\n", debugstr_user_flags(pFlags), pBuffer, *phGlobal);
689 ALIGN_POINTER(pBuffer, 3);
691 if (LOWORD(*pFlags) == MSHCTX_INPROC)
693 if (sizeof(*phGlobal) == 8)
694 *(ULONG *)pBuffer = WDT_INPROC64_CALL;
695 else
696 *(ULONG *)pBuffer = WDT_INPROC_CALL;
697 pBuffer += sizeof(ULONG);
698 *(HGLOBAL *)pBuffer = *phGlobal;
699 pBuffer += sizeof(HGLOBAL);
701 else
703 *(ULONG *)pBuffer = WDT_REMOTE_CALL;
704 pBuffer += sizeof(ULONG);
705 *(ULONG *)pBuffer = HandleToULong(*phGlobal);
706 pBuffer += sizeof(ULONG);
707 if (*phGlobal)
709 const unsigned char *memory;
710 SIZE_T size = GlobalSize(*phGlobal);
711 *(ULONG *)pBuffer = (ULONG)size;
712 pBuffer += sizeof(ULONG);
713 *(ULONG *)pBuffer = HandleToULong(*phGlobal);
714 pBuffer += sizeof(ULONG);
715 *(ULONG *)pBuffer = (ULONG)size;
716 pBuffer += sizeof(ULONG);
718 memory = GlobalLock(*phGlobal);
719 memcpy(pBuffer, memory, size);
720 pBuffer += size;
721 GlobalUnlock(*phGlobal);
725 return pBuffer;
728 /******************************************************************************
729 * HGLOBAL_UserUnmarshal (combase.@)
731 * Unmarshals an HGLOBAL from a buffer.
733 * PARAMS
734 * pFlags [I] Flags. See notes.
735 * pBuffer [I] Buffer to marshal the clip format from.
736 * phGlobal [O] Address that receive the unmarshaled HGLOBAL.
738 * RETURNS
739 * The end of the marshaled data in the buffer.
741 * NOTES
742 * Even though the function is documented to take a pointer to an ULONG in
743 * pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
744 * the first parameter is an ULONG.
745 * This function is only intended to be called by the RPC runtime.
747 unsigned char * __RPC_USER HGLOBAL_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, HGLOBAL *phGlobal)
749 ULONG fContext;
751 TRACE("%s, %p, &%p.\n", debugstr_user_flags(pFlags), pBuffer, *phGlobal);
753 ALIGN_POINTER(pBuffer, 3);
755 fContext = *(ULONG *)pBuffer;
756 pBuffer += sizeof(ULONG);
758 if (((fContext == WDT_INPROC_CALL) && (sizeof(*phGlobal) < 8)) ||
759 ((fContext == WDT_INPROC64_CALL) && (sizeof(*phGlobal) == 8)))
761 *phGlobal = *(HGLOBAL *)pBuffer;
762 pBuffer += sizeof(*phGlobal);
764 else if (fContext == WDT_REMOTE_CALL)
766 ULONG handle;
768 handle = *(ULONG *)pBuffer;
769 pBuffer += sizeof(ULONG);
771 if (handle)
773 ULONG size;
774 void *memory;
776 size = *(ULONG *)pBuffer;
777 pBuffer += sizeof(ULONG);
778 /* redundancy is bad - it means you have to check consistency like
779 * this: */
780 if (*(ULONG *)pBuffer != handle)
782 RaiseException(RPC_X_BAD_STUB_DATA, 0, 0, NULL);
783 return pBuffer;
785 pBuffer += sizeof(ULONG);
786 /* redundancy is bad - it means you have to check consistency like
787 * this: */
788 if (*(ULONG *)pBuffer != size)
790 RaiseException(RPC_X_BAD_STUB_DATA, 0, 0, NULL);
791 return pBuffer;
793 pBuffer += sizeof(ULONG);
795 /* FIXME: check size is not too big */
797 *phGlobal = GlobalAlloc(GMEM_MOVEABLE, size);
798 memory = GlobalLock(*phGlobal);
799 memcpy(memory, pBuffer, size);
800 pBuffer += size;
801 GlobalUnlock(*phGlobal);
803 else
804 *phGlobal = NULL;
806 else
807 RaiseException(RPC_S_INVALID_TAG, 0, 0, NULL);
809 return pBuffer;
812 /******************************************************************************
813 * HGLOBAL_UserFree (combase.@)
815 * Frees an unmarshaled HGLOBAL.
817 * PARAMS
818 * pFlags [I] Flags. See notes.
819 * phGlobal [I] HGLOBAL to free.
821 * RETURNS
822 * The end of the marshaled data in the buffer.
824 * NOTES
825 * Even though the function is documented to take a pointer to a ULONG in
826 * pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of
827 * which the first parameter is a ULONG.
828 * This function is only intended to be called by the RPC runtime.
830 void __RPC_USER HGLOBAL_UserFree(ULONG *pFlags, HGLOBAL *phGlobal)
832 TRACE("%s, &%p.\n", debugstr_user_flags(pFlags), *phGlobal);
834 if (LOWORD(*pFlags) != MSHCTX_INPROC && *phGlobal)
835 GlobalFree(*phGlobal);
838 /******************************************************************************
839 * HPALETTE_UserFree (combase.@)
841 * Frees an unmarshaled palette.
843 * PARAMS
844 * pFlags [I] Flags. See notes.
845 * phPal [I] Palette to free.
847 * RETURNS
848 * The end of the marshaled data in the buffer.
850 * NOTES
851 * Even though the function is documented to take a pointer to a ULONG in
852 * pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of
853 * which the first parameter is a ULONG.
854 * This function is only intended to be called by the RPC runtime.
856 void __RPC_USER HPALETTE_UserFree(ULONG *pFlags, HPALETTE *phPal)
858 FIXME(":stub\n");
861 /******************************************************************************
862 * WdtpInterfacePointer_UserSize (combase.@)
864 * Calculates the buffer size required to marshal an interface pointer.
866 * PARAMS
867 * pFlags [I] Flags. See notes.
868 * RealFlags [I] The MSHCTX to use when marshaling the interface.
869 * punk [I] Interface pointer to size.
870 * StartingSize [I] Starting size of the buffer. This value is added on to
871 * the buffer size required for the clip format.
872 * riid [I] ID of interface to size.
874 * RETURNS
875 * The buffer size required to marshal an interface pointer plus the starting size.
877 * NOTES
878 * Even though the function is documented to take a pointer to a ULONG in
879 * pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
880 * the first parameter is a ULONG.
882 ULONG __RPC_USER WdtpInterfacePointer_UserSize(ULONG *pFlags, ULONG RealFlags, ULONG StartingSize, IUnknown *punk, REFIID riid)
884 DWORD marshal_size = 0;
885 HRESULT hr;
887 TRACE("%s, %#lx, %lu, %p, %s.\n", debugstr_user_flags(pFlags), RealFlags, StartingSize, punk, debugstr_guid(riid));
889 hr = CoGetMarshalSizeMax(&marshal_size, riid, punk, LOWORD(RealFlags), NULL, MSHLFLAGS_NORMAL);
890 if (FAILED(hr)) return StartingSize;
892 ALIGN_LENGTH(StartingSize, 3);
893 StartingSize += 2 * sizeof(DWORD);
894 return StartingSize + marshal_size;
897 /******************************************************************************
898 * WdtpInterfacePointer_UserMarshal (combase.@)
900 * Marshals an interface pointer into a buffer.
902 * PARAMS
903 * pFlags [I] Flags. See notes.
904 * RealFlags [I] The MSHCTX to use when marshaling the interface.
905 * pBuffer [I] Buffer to marshal the clip format into.
906 * punk [I] Interface pointer to marshal.
907 * riid [I] ID of interface to marshal.
909 * RETURNS
910 * The end of the marshaled data in the buffer.
912 * NOTES
913 * Even though the function is documented to take a pointer to a ULONG in
914 * pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
915 * the first parameter is a ULONG.
917 unsigned char * WINAPI WdtpInterfacePointer_UserMarshal(ULONG *pFlags, ULONG RealFlags, unsigned char *pBuffer, IUnknown *punk, REFIID riid)
919 HGLOBAL h = GlobalAlloc(GMEM_MOVEABLE, 0);
920 IStream *stm;
921 DWORD size;
922 void *ptr;
924 TRACE("%s, %#lx, %p, &%p, %s.\n", debugstr_user_flags(pFlags), RealFlags, pBuffer, punk, debugstr_guid(riid));
926 if (!h) return NULL;
927 if (CreateStreamOnHGlobal(h, TRUE, &stm) != S_OK)
929 GlobalFree(h);
930 return NULL;
933 if (CoMarshalInterface(stm, riid, punk, LOWORD(RealFlags), NULL, MSHLFLAGS_NORMAL) != S_OK)
935 IStream_Release(stm);
936 return pBuffer;
939 ALIGN_POINTER(pBuffer, 3);
940 size = GlobalSize(h);
942 *(DWORD *)pBuffer = size;
943 pBuffer += sizeof(DWORD);
944 *(DWORD *)pBuffer = size;
945 pBuffer += sizeof(DWORD);
947 ptr = GlobalLock(h);
948 memcpy(pBuffer, ptr, size);
949 GlobalUnlock(h);
951 IStream_Release(stm);
952 return pBuffer + size;
955 /******************************************************************************
956 * WdtpInterfacePointer_UserUnmarshal (combase.@)
958 * Unmarshals an interface pointer from a buffer.
960 * PARAMS
961 * pFlags [I] Flags. See notes.
962 * pBuffer [I] Buffer to marshal the clip format from.
963 * ppunk [I/O] Address that receives the unmarshaled interface pointer.
964 * riid [I] ID of interface to unmarshal.
966 * RETURNS
967 * The end of the marshaled data in the buffer.
969 * NOTES
970 * Even though the function is documented to take a pointer to an ULONG in
971 * pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
972 * the first parameter is an ULONG.
974 unsigned char * WINAPI WdtpInterfacePointer_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, IUnknown **ppunk, REFIID riid)
976 HRESULT hr;
977 HGLOBAL h;
978 IStream *stm;
979 DWORD size;
980 void *ptr;
981 IUnknown *orig;
983 TRACE("%s, %p, %p, %s.\n", debugstr_user_flags(pFlags), pBuffer, ppunk, debugstr_guid(riid));
985 ALIGN_POINTER(pBuffer, 3);
987 size = *(DWORD *)pBuffer;
988 pBuffer += sizeof(DWORD);
989 if (size != *(DWORD *)pBuffer)
990 RaiseException(RPC_X_BAD_STUB_DATA, 0, 0, NULL);
992 pBuffer += sizeof(DWORD);
994 /* FIXME: sanity check on size */
996 h = GlobalAlloc(GMEM_MOVEABLE, size);
997 if (!h) RaiseException(RPC_X_NO_MEMORY, 0, 0, NULL);
999 if (CreateStreamOnHGlobal(h, TRUE, &stm) != S_OK)
1001 GlobalFree(h);
1002 RaiseException(RPC_X_NO_MEMORY, 0, 0, NULL);
1005 ptr = GlobalLock(h);
1006 memcpy(ptr, pBuffer, size);
1007 GlobalUnlock(h);
1009 orig = *ppunk;
1010 hr = CoUnmarshalInterface(stm, riid, (void**)ppunk);
1011 IStream_Release(stm);
1013 if (hr != S_OK) RaiseException(hr, 0, 0, NULL);
1015 if (orig) IUnknown_Release(orig);
1017 return pBuffer + size;
1020 /******************************************************************************
1021 * WdtpInterfacePointer_UserFree (combase.@)
1023 void WINAPI WdtpInterfacePointer_UserFree(IUnknown *punk)
1025 TRACE("%p.\n", punk);
1026 if (punk) IUnknown_Release(punk);