user32: Add current keyboard layout to thread data.
[wine.git] / dlls / combase / usrmarshal.c
blob48a6c2de4bed05a85306674041b8d1a3ac6a743a
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 #define NONAMELESSUNION
25 #include "ole2.h"
27 #include "wine/debug.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(ole);
31 #define ALIGNED_LENGTH(_Len, _Align) (((_Len)+(_Align))&~(_Align))
32 #define ALIGNED_POINTER(_Ptr, _Align) ((LPVOID)ALIGNED_LENGTH((ULONG_PTR)(_Ptr), _Align))
33 #define ALIGN_LENGTH(_Len, _Align) _Len = ALIGNED_LENGTH(_Len, _Align)
34 #define ALIGN_POINTER(_Ptr, _Align) _Ptr = ALIGNED_POINTER(_Ptr, _Align)
36 static const char* debugstr_user_flags(ULONG *pFlags)
38 char buf[12];
39 const char* loword;
40 switch (LOWORD(*pFlags))
42 case MSHCTX_LOCAL:
43 loword = "MSHCTX_LOCAL";
44 break;
45 case MSHCTX_NOSHAREDMEM:
46 loword = "MSHCTX_NOSHAREDMEM";
47 break;
48 case MSHCTX_DIFFERENTMACHINE:
49 loword = "MSHCTX_DIFFERENTMACHINE";
50 break;
51 case MSHCTX_INPROC:
52 loword = "MSHCTX_INPROC";
53 break;
54 default:
55 sprintf(buf, "%d", LOWORD(*pFlags));
56 loword=buf;
59 if (HIWORD(*pFlags) == NDR_LOCAL_DATA_REPRESENTATION)
60 return wine_dbg_sprintf("MAKELONG(%s, NDR_LOCAL_DATA_REPRESENTATION)", loword);
61 else
62 return wine_dbg_sprintf("MAKELONG(%s, 0x%04x)", loword, HIWORD(*pFlags));
65 static ULONG handle_UserSize(ULONG *pFlags, ULONG StartingSize, HANDLE *handle)
67 if (LOWORD(*pFlags) == MSHCTX_DIFFERENTMACHINE)
69 ERR("can't remote a local handle\n");
70 RaiseException(RPC_S_INVALID_TAG, 0, 0, NULL);
71 return StartingSize;
74 ALIGN_LENGTH(StartingSize, 3);
75 return StartingSize + sizeof(RemotableHandle);
78 static unsigned char * handle_UserMarshal(ULONG *pFlags, unsigned char *pBuffer, HANDLE *handle)
80 RemotableHandle *remhandle;
81 if (LOWORD(*pFlags) == MSHCTX_DIFFERENTMACHINE)
83 ERR("can't remote a local handle\n");
84 RaiseException(RPC_S_INVALID_TAG, 0, 0, NULL);
85 return pBuffer;
88 ALIGN_POINTER(pBuffer, 3);
89 remhandle = (RemotableHandle *)pBuffer;
90 remhandle->fContext = WDT_INPROC_CALL;
91 remhandle->u.hInproc = (LONG_PTR)*handle;
92 return pBuffer + sizeof(RemotableHandle);
95 static unsigned char * handle_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, HANDLE *handle)
97 RemotableHandle *remhandle;
99 ALIGN_POINTER(pBuffer, 3);
100 remhandle = (RemotableHandle *)pBuffer;
101 if (remhandle->fContext != WDT_INPROC_CALL)
102 RaiseException(RPC_X_BAD_STUB_DATA, 0, 0, NULL);
103 *handle = (HANDLE)(LONG_PTR)remhandle->u.hInproc;
104 return pBuffer + sizeof(RemotableHandle);
107 static void handle_UserFree(ULONG *pFlags, HANDLE *handle)
109 /* nothing to do */
112 #define IMPL_WIREM_HANDLE(type) \
113 ULONG __RPC_USER type##_UserSize(ULONG *pFlags, ULONG StartingSize, type *handle) \
115 TRACE("(%s, %d, %p\n", debugstr_user_flags(pFlags), StartingSize, handle); \
116 return handle_UserSize(pFlags, StartingSize, (HANDLE *)handle); \
119 unsigned char * __RPC_USER type##_UserMarshal(ULONG *pFlags, unsigned char *pBuffer, type *handle) \
121 TRACE("(%s, %p, &%p\n", debugstr_user_flags(pFlags), pBuffer, *handle); \
122 return handle_UserMarshal(pFlags, pBuffer, (HANDLE *)handle); \
125 unsigned char * __RPC_USER type##_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, type *handle) \
127 TRACE("(%s, %p, %p\n", debugstr_user_flags(pFlags), pBuffer, handle); \
128 return handle_UserUnmarshal(pFlags, pBuffer, (HANDLE *)handle); \
131 void __RPC_USER type##_UserFree(ULONG *pFlags, type *handle) \
133 TRACE("(%s, &%p\n", debugstr_user_flags(pFlags), *handle); \
134 handle_UserFree(pFlags, (HANDLE *)handle); \
137 IMPL_WIREM_HANDLE(HACCEL)
138 IMPL_WIREM_HANDLE(HBRUSH)
139 IMPL_WIREM_HANDLE(HDC)
140 IMPL_WIREM_HANDLE(HICON)
141 IMPL_WIREM_HANDLE(HMENU)
142 IMPL_WIREM_HANDLE(HWND)
144 /******************************************************************************
145 * CLIPFORMAT_UserSize (combase.@)
147 * Calculates the buffer size required to marshal a clip format.
149 * PARAMS
150 * pFlags [I] Flags. See notes.
151 * StartingSize [I] Starting size of the buffer. This value is added on to
152 * the buffer size required for the clip format.
153 * pCF [I] Clip format to size.
155 * RETURNS
156 * The buffer size required to marshal a clip format plus the starting size.
158 * NOTES
159 * Even though the function is documented to take a pointer to an unsigned
160 * long in pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
161 * the first parameter is an unsigned long.
162 * This function is only intended to be called by the RPC runtime.
164 ULONG __RPC_USER CLIPFORMAT_UserSize(ULONG *pFlags, ULONG size, CLIPFORMAT *pCF)
166 TRACE("%s, %u, %p\n", debugstr_user_flags(pFlags), size, pCF);
168 ALIGN_LENGTH(size, 3);
170 size += 8;
172 /* only need to marshal the name if it is not a pre-defined type and
173 * we are going remote */
174 if ((*pCF >= 0xc000) && (LOWORD(*pFlags) == MSHCTX_DIFFERENTMACHINE))
176 WCHAR format[255];
177 INT ret;
178 size += 3 * sizeof(UINT);
179 /* urg! this function is badly designed because it won't tell us how
180 * much space is needed without doing a dummy run of storing the
181 * name into a buffer */
182 ret = GetClipboardFormatNameW(*pCF, format, ARRAY_SIZE(format)-1);
183 if (!ret)
184 RaiseException(DV_E_CLIPFORMAT, 0, 0, NULL);
185 size += (ret + 1) * sizeof(WCHAR);
187 return size;
190 /******************************************************************************
191 * CLIPFORMAT_UserMarshal (combase.@)
193 * Marshals a clip format into a buffer.
195 * PARAMS
196 * pFlags [I] Flags. See notes.
197 * pBuffer [I] Buffer to marshal the clip format into.
198 * pCF [I] Clip format to marshal.
200 * RETURNS
201 * The end of the marshaled data in the buffer.
203 * NOTES
204 * Even though the function is documented to take a pointer to an unsigned
205 * long in pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
206 * the first parameter is an unsigned long.
207 * This function is only intended to be called by the RPC runtime.
209 unsigned char * __RPC_USER CLIPFORMAT_UserMarshal(ULONG *pFlags, unsigned char *pBuffer, CLIPFORMAT *pCF)
211 TRACE("%s, %p, &0x%04x.\n", debugstr_user_flags(pFlags), pBuffer, *pCF);
213 ALIGN_POINTER(pBuffer, 3);
215 /* only need to marshal the name if it is not a pre-defined type and
216 * we are going remote */
217 if ((*pCF >= 0xc000) && (LOWORD(*pFlags) == MSHCTX_DIFFERENTMACHINE))
219 WCHAR format[255];
220 UINT len;
222 *(DWORD *)pBuffer = WDT_REMOTE_CALL;
223 pBuffer += 4;
224 *(DWORD *)pBuffer = *pCF;
225 pBuffer += 4;
227 len = GetClipboardFormatNameW(*pCF, format, ARRAY_SIZE(format)-1);
228 if (!len)
229 RaiseException(DV_E_CLIPFORMAT, 0, 0, NULL);
230 len += 1;
231 *(UINT *)pBuffer = len;
232 pBuffer += sizeof(UINT);
233 *(UINT *)pBuffer = 0;
234 pBuffer += sizeof(UINT);
235 *(UINT *)pBuffer = len;
236 pBuffer += sizeof(UINT);
237 TRACE("marshaling format name %s\n", debugstr_w(format));
238 memcpy(pBuffer, format, len * sizeof(WCHAR));
239 pBuffer += len * sizeof(WCHAR);
241 else
243 *(DWORD *)pBuffer = WDT_INPROC_CALL;
244 pBuffer += 4;
245 *(DWORD *)pBuffer = *pCF;
246 pBuffer += 4;
249 return pBuffer;
252 /******************************************************************************
253 * CLIPFORMAT_UserUnmarshal (combase.@)
255 * Unmarshals a clip format from a buffer.
257 * PARAMS
258 * pFlags [I] Flags. See notes.
259 * pBuffer [I] Buffer to marshal the clip format from.
260 * pCF [O] Address that receive the unmarshaled clip format.
262 * RETURNS
263 * The end of the marshaled data in the buffer.
265 * NOTES
266 * Even though the function is documented to take a pointer to an unsigned
267 * long in pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
268 * the first parameter is an unsigned long.
269 * This function is only intended to be called by the RPC runtime.
271 unsigned char * __RPC_USER CLIPFORMAT_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, CLIPFORMAT *pCF)
273 LONG fContext;
275 TRACE("%s, %p, %p.\n", debugstr_user_flags(pFlags), pBuffer, pCF);
277 ALIGN_POINTER(pBuffer, 3);
279 fContext = *(DWORD *)pBuffer;
280 pBuffer += 4;
282 if (fContext == WDT_INPROC_CALL)
284 *pCF = *(CLIPFORMAT *)pBuffer;
285 pBuffer += 4;
287 else if (fContext == WDT_REMOTE_CALL)
289 CLIPFORMAT cf;
290 UINT len;
292 /* pointer ID for registered clip format string */
293 if (*(DWORD *)pBuffer == 0)
294 RaiseException(RPC_S_INVALID_BOUND, 0, 0, NULL);
295 pBuffer += 4;
297 len = *(UINT *)pBuffer;
298 pBuffer += sizeof(UINT);
299 if (*(UINT *)pBuffer != 0)
300 RaiseException(RPC_S_INVALID_BOUND, 0, 0, NULL);
301 pBuffer += sizeof(UINT);
302 if (*(UINT *)pBuffer != len)
303 RaiseException(RPC_S_INVALID_BOUND, 0, 0, NULL);
304 pBuffer += sizeof(UINT);
305 if (((WCHAR *)pBuffer)[len - 1] != '\0')
306 RaiseException(RPC_S_INVALID_BOUND, 0, 0, NULL);
307 TRACE("unmarshaling clip format %s\n", debugstr_w((LPCWSTR)pBuffer));
308 cf = RegisterClipboardFormatW((LPCWSTR)pBuffer);
309 pBuffer += len * sizeof(WCHAR);
310 if (!cf)
311 RaiseException(DV_E_CLIPFORMAT, 0, 0, NULL);
312 *pCF = cf;
314 else
315 /* code not really appropriate, but nearest I can find */
316 RaiseException(RPC_S_INVALID_TAG, 0, 0, NULL);
317 return pBuffer;
320 /******************************************************************************
321 * CLIPFORMAT_UserFree (combase.@)
323 * Frees an unmarshaled clip format.
325 * PARAMS
326 * pFlags [I] Flags. See notes.
327 * pCF [I] Clip format to free.
329 * RETURNS
330 * The end of the marshaled data in the buffer.
332 * NOTES
333 * Even though the function is documented to take a pointer to an unsigned
334 * long in pFlags, it actually takes a pointer to a USER_MARSHAL_CB
335 * structure, of which the first parameter is an unsigned long.
336 * This function is only intended to be called by the RPC runtime.
338 void __RPC_USER CLIPFORMAT_UserFree(ULONG *pFlags, CLIPFORMAT *pCF)
340 /* there is no inverse of the RegisterClipboardFormat function,
341 * so nothing to do */
344 /******************************************************************************
345 * HBITMAP_UserSize (combase.@)
347 * Calculates the buffer size required to marshal a bitmap.
349 * PARAMS
350 * pFlags [I] Flags. See notes.
351 * StartingSize [I] Starting size of the buffer. This value is added on to
352 * the buffer size required for the clip format.
353 * phBmp [I] Bitmap to size.
355 * RETURNS
356 * The buffer size required to marshal an bitmap plus the starting size.
358 * NOTES
359 * Even though the function is documented to take a pointer to a ULONG in
360 * pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
361 * the first parameter is a ULONG.
362 * This function is only intended to be called by the RPC runtime.
364 ULONG __RPC_USER HBITMAP_UserSize(ULONG *flags, ULONG size, HBITMAP *bmp)
366 TRACE("(%s, %d, %p)\n", debugstr_user_flags(flags), size, *bmp);
368 ALIGN_LENGTH(size, 3);
370 size += sizeof(ULONG);
371 if (LOWORD(*flags) == MSHCTX_INPROC)
372 size += sizeof(ULONG);
373 else
375 size += sizeof(ULONG);
377 if (*bmp)
379 size += sizeof(ULONG);
380 size += FIELD_OFFSET(userBITMAP, cbSize);
381 size += GetBitmapBits(*bmp, 0, NULL);
385 return size;
388 /******************************************************************************
389 * HBITMAP_UserMarshal (combase.@)
391 * Marshals a bitmap into a buffer.
393 * PARAMS
394 * pFlags [I] Flags. See notes.
395 * pBuffer [I] Buffer to marshal the clip format into.
396 * phBmp [I] Bitmap to marshal.
398 * RETURNS
399 * The end of the marshaled data in the buffer.
401 * NOTES
402 * Even though the function is documented to take a pointer to a ULONG in
403 * pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
404 * the first parameter is a ULONG.
405 * This function is only intended to be called by the RPC runtime.
407 unsigned char * __RPC_USER HBITMAP_UserMarshal(ULONG *flags, unsigned char *buffer, HBITMAP *bmp)
409 TRACE("(%s, %p, %p)\n", debugstr_user_flags(flags), buffer, *bmp);
411 ALIGN_POINTER(buffer, 3);
413 if (LOWORD(*flags) == MSHCTX_INPROC)
415 *(ULONG *)buffer = WDT_INPROC_CALL;
416 buffer += sizeof(ULONG);
417 *(ULONG *)buffer = (ULONG)(ULONG_PTR)*bmp;
418 buffer += sizeof(ULONG);
420 else
422 *(ULONG *)buffer = WDT_REMOTE_CALL;
423 buffer += sizeof(ULONG);
424 *(ULONG *)buffer = (ULONG)(ULONG_PTR)*bmp;
425 buffer += sizeof(ULONG);
427 if (*bmp)
429 static const ULONG header_size = FIELD_OFFSET(userBITMAP, cbSize);
430 BITMAP bitmap;
431 ULONG bitmap_size;
433 bitmap_size = GetBitmapBits(*bmp, 0, NULL);
434 *(ULONG *)buffer = bitmap_size;
435 buffer += sizeof(ULONG);
437 GetObjectW(*bmp, sizeof(BITMAP), &bitmap);
438 memcpy(buffer, &bitmap, header_size);
439 buffer += header_size;
441 GetBitmapBits(*bmp, bitmap_size, buffer);
442 buffer += bitmap_size;
445 return buffer;
448 /******************************************************************************
449 * HBITMAP_UserUnmarshal (combase.@)
451 * Unmarshals a bitmap from a buffer.
453 * PARAMS
454 * pFlags [I] Flags. See notes.
455 * pBuffer [I] Buffer to marshal the clip format from.
456 * phBmp [O] Address that receive the unmarshaled bitmap.
458 * RETURNS
459 * The end of the marshaled data in the buffer.
461 * NOTES
462 * Even though the function is documented to take a pointer to an ULONG in
463 * pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
464 * the first parameter is an ULONG.
465 * This function is only intended to be called by the RPC runtime.
467 unsigned char * __RPC_USER HBITMAP_UserUnmarshal(ULONG *flags, unsigned char *buffer, HBITMAP *bmp)
469 ULONG context;
471 TRACE("(%s, %p, %p)\n", debugstr_user_flags(flags), buffer, bmp);
473 ALIGN_POINTER(buffer, 3);
475 context = *(ULONG *)buffer;
476 buffer += sizeof(ULONG);
478 if (context == WDT_INPROC_CALL)
480 *bmp = *(HBITMAP *)buffer;
481 buffer += sizeof(*bmp);
483 else if (context == WDT_REMOTE_CALL)
485 ULONG handle = *(ULONG *)buffer;
486 buffer += sizeof(ULONG);
488 if (handle)
490 static const ULONG header_size = FIELD_OFFSET(userBITMAP, cbSize);
491 BITMAP bitmap;
492 ULONG bitmap_size;
493 unsigned char *bits;
495 bitmap_size = *(ULONG *)buffer;
496 buffer += sizeof(ULONG);
497 bits = HeapAlloc(GetProcessHeap(), 0, bitmap_size);
499 memcpy(&bitmap, buffer, header_size);
500 buffer += header_size;
502 memcpy(bits, buffer, bitmap_size);
503 buffer += bitmap_size;
505 bitmap.bmBits = bits;
506 *bmp = CreateBitmapIndirect(&bitmap);
508 HeapFree(GetProcessHeap(), 0, bits);
510 else
511 *bmp = NULL;
513 else
514 RaiseException(RPC_S_INVALID_TAG, 0, 0, NULL);
516 return buffer;
519 /******************************************************************************
520 * HBITMAP_UserFree (combase.@)
522 * Frees an unmarshaled bitmap.
524 * PARAMS
525 * pFlags [I] Flags. See notes.
526 * phBmp [I] Bitmap to free.
528 * RETURNS
529 * The end of the marshaled data in the buffer.
531 * NOTES
532 * Even though the function is documented to take a pointer to a ULONG in
533 * pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of
534 * which the first parameter is a ULONG.
535 * This function is only intended to be called by the RPC runtime.
537 void __RPC_USER HBITMAP_UserFree(ULONG *flags, HBITMAP *bmp)
539 TRACE("(%s, %p)\n", debugstr_user_flags(flags), *bmp);
541 if (LOWORD(*flags) != MSHCTX_INPROC)
542 DeleteObject(*bmp);
545 /******************************************************************************
546 * HPALETTE_UserSize (combase.@)
548 * Calculates the buffer size required to marshal a palette.
550 * PARAMS
551 * pFlags [I] Flags. See notes.
552 * StartingSize [I] Starting size of the buffer. This value is added on to
553 * the buffer size required for the clip format.
554 * phPal [I] Palette to size.
556 * RETURNS
557 * The buffer size required to marshal a palette plus the starting size.
559 * NOTES
560 * Even though the function is documented to take a pointer to a ULONG in
561 * pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
562 * the first parameter is a ULONG.
563 * This function is only intended to be called by the RPC runtime.
565 ULONG __RPC_USER HPALETTE_UserSize(ULONG *pFlags, ULONG StartingSize, HPALETTE *phPal)
567 FIXME(":stub\n");
568 return StartingSize;
571 /******************************************************************************
572 * HPALETTE_UserMarshal (combase.@)
574 * Marshals a palette into a buffer.
576 * PARAMS
577 * pFlags [I] Flags. See notes.
578 * pBuffer [I] Buffer to marshal the clip format into.
579 * phPal [I] Palette to marshal.
581 * RETURNS
582 * The end of the marshaled data in the buffer.
584 * NOTES
585 * Even though the function is documented to take a pointer to a ULONG in
586 * pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
587 * the first parameter is a ULONG.
588 * This function is only intended to be called by the RPC runtime.
590 unsigned char * __RPC_USER HPALETTE_UserMarshal(ULONG *pFlags, unsigned char *pBuffer, HPALETTE *phPal)
592 FIXME(":stub\n");
593 return pBuffer;
596 /******************************************************************************
597 * HPALETTE_UserUnmarshal (combase.@)
599 * Unmarshals a palette from a buffer.
601 * PARAMS
602 * pFlags [I] Flags. See notes.
603 * pBuffer [I] Buffer to marshal the clip format from.
604 * phPal [O] Address that receive the unmarshaled palette.
606 * RETURNS
607 * The end of the marshaled data in the buffer.
609 * NOTES
610 * Even though the function is documented to take a pointer to an ULONG in
611 * pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
612 * the first parameter is an ULONG.
613 * This function is only intended to be called by the RPC runtime.
615 unsigned char * __RPC_USER HPALETTE_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, HPALETTE *phPal)
617 FIXME(":stub\n");
618 return pBuffer;
621 /******************************************************************************
622 * HGLOBAL_UserSize (combase.@)
624 * Calculates the buffer size required to marshal an HGLOBAL.
626 * PARAMS
627 * pFlags [I] Flags. See notes.
628 * StartingSize [I] Starting size of the buffer. This value is added on to
629 * the buffer size required for the clip format.
630 * phGlobal [I] HGLOBAL to size.
632 * RETURNS
633 * The buffer size required to marshal an HGLOBAL plus the starting size.
635 * NOTES
636 * Even though the function is documented to take a pointer to a ULONG in
637 * pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
638 * the first parameter is a ULONG.
639 * This function is only intended to be called by the RPC runtime.
641 ULONG __RPC_USER HGLOBAL_UserSize(ULONG *pFlags, ULONG StartingSize, HGLOBAL *phGlobal)
643 ULONG size = StartingSize;
645 TRACE("%s, %u, %p.\n", debugstr_user_flags(pFlags), StartingSize, phGlobal);
647 ALIGN_LENGTH(size, 3);
649 size += sizeof(ULONG);
651 if (LOWORD(*pFlags) == MSHCTX_INPROC)
652 size += sizeof(HGLOBAL);
653 else
655 size += sizeof(ULONG);
656 if (*phGlobal)
658 SIZE_T ret;
659 size += 3 * sizeof(ULONG);
660 ret = GlobalSize(*phGlobal);
661 size += (ULONG)ret;
665 return size;
668 /******************************************************************************
669 * HGLOBAL_UserMarshal (combase.@)
671 * Marshals an HGLOBAL into a buffer.
673 * PARAMS
674 * pFlags [I] Flags. See notes.
675 * pBuffer [I] Buffer to marshal the clip format into.
676 * phGlobal [I] HGLOBAL to marshal.
678 * RETURNS
679 * The end of the marshaled data in the buffer.
681 * NOTES
682 * Even though the function is documented to take a pointer to a ULONG in
683 * pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
684 * the first parameter is a ULONG.
685 * This function is only intended to be called by the RPC runtime.
687 unsigned char * __RPC_USER HGLOBAL_UserMarshal(ULONG *pFlags, unsigned char *pBuffer, HGLOBAL *phGlobal)
689 TRACE("%s, %p, &%p.\n", debugstr_user_flags(pFlags), pBuffer, *phGlobal);
691 ALIGN_POINTER(pBuffer, 3);
693 if (LOWORD(*pFlags) == MSHCTX_INPROC)
695 if (sizeof(*phGlobal) == 8)
696 *(ULONG *)pBuffer = WDT_INPROC64_CALL;
697 else
698 *(ULONG *)pBuffer = WDT_INPROC_CALL;
699 pBuffer += sizeof(ULONG);
700 *(HGLOBAL *)pBuffer = *phGlobal;
701 pBuffer += sizeof(HGLOBAL);
703 else
705 *(ULONG *)pBuffer = WDT_REMOTE_CALL;
706 pBuffer += sizeof(ULONG);
707 *(ULONG *)pBuffer = HandleToULong(*phGlobal);
708 pBuffer += sizeof(ULONG);
709 if (*phGlobal)
711 const unsigned char *memory;
712 SIZE_T size = GlobalSize(*phGlobal);
713 *(ULONG *)pBuffer = (ULONG)size;
714 pBuffer += sizeof(ULONG);
715 *(ULONG *)pBuffer = HandleToULong(*phGlobal);
716 pBuffer += sizeof(ULONG);
717 *(ULONG *)pBuffer = (ULONG)size;
718 pBuffer += sizeof(ULONG);
720 memory = GlobalLock(*phGlobal);
721 memcpy(pBuffer, memory, size);
722 pBuffer += size;
723 GlobalUnlock(*phGlobal);
727 return pBuffer;
730 /******************************************************************************
731 * HGLOBAL_UserUnmarshal (combase.@)
733 * Unmarshals an HGLOBAL from a buffer.
735 * PARAMS
736 * pFlags [I] Flags. See notes.
737 * pBuffer [I] Buffer to marshal the clip format from.
738 * phGlobal [O] Address that receive the unmarshaled HGLOBAL.
740 * RETURNS
741 * The end of the marshaled data in the buffer.
743 * NOTES
744 * Even though the function is documented to take a pointer to an ULONG in
745 * pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
746 * the first parameter is an ULONG.
747 * This function is only intended to be called by the RPC runtime.
749 unsigned char * __RPC_USER HGLOBAL_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, HGLOBAL *phGlobal)
751 ULONG fContext;
753 TRACE("%s, %p, &%p.\n", debugstr_user_flags(pFlags), pBuffer, *phGlobal);
755 ALIGN_POINTER(pBuffer, 3);
757 fContext = *(ULONG *)pBuffer;
758 pBuffer += sizeof(ULONG);
760 if (((fContext == WDT_INPROC_CALL) && (sizeof(*phGlobal) < 8)) ||
761 ((fContext == WDT_INPROC64_CALL) && (sizeof(*phGlobal) == 8)))
763 *phGlobal = *(HGLOBAL *)pBuffer;
764 pBuffer += sizeof(*phGlobal);
766 else if (fContext == WDT_REMOTE_CALL)
768 ULONG handle;
770 handle = *(ULONG *)pBuffer;
771 pBuffer += sizeof(ULONG);
773 if (handle)
775 ULONG size;
776 void *memory;
778 size = *(ULONG *)pBuffer;
779 pBuffer += sizeof(ULONG);
780 /* redundancy is bad - it means you have to check consistency like
781 * this: */
782 if (*(ULONG *)pBuffer != handle)
784 RaiseException(RPC_X_BAD_STUB_DATA, 0, 0, NULL);
785 return pBuffer;
787 pBuffer += sizeof(ULONG);
788 /* redundancy is bad - it means you have to check consistency like
789 * this: */
790 if (*(ULONG *)pBuffer != size)
792 RaiseException(RPC_X_BAD_STUB_DATA, 0, 0, NULL);
793 return pBuffer;
795 pBuffer += sizeof(ULONG);
797 /* FIXME: check size is not too big */
799 *phGlobal = GlobalAlloc(GMEM_MOVEABLE, size);
800 memory = GlobalLock(*phGlobal);
801 memcpy(memory, pBuffer, size);
802 pBuffer += size;
803 GlobalUnlock(*phGlobal);
805 else
806 *phGlobal = NULL;
808 else
809 RaiseException(RPC_S_INVALID_TAG, 0, 0, NULL);
811 return pBuffer;
814 /******************************************************************************
815 * HGLOBAL_UserFree (combase.@)
817 * Frees an unmarshaled HGLOBAL.
819 * PARAMS
820 * pFlags [I] Flags. See notes.
821 * phGlobal [I] HGLOBAL to free.
823 * RETURNS
824 * The end of the marshaled data in the buffer.
826 * NOTES
827 * Even though the function is documented to take a pointer to a ULONG in
828 * pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of
829 * which the first parameter is a ULONG.
830 * This function is only intended to be called by the RPC runtime.
832 void __RPC_USER HGLOBAL_UserFree(ULONG *pFlags, HGLOBAL *phGlobal)
834 TRACE("%s, &%p.\n", debugstr_user_flags(pFlags), *phGlobal);
836 if (LOWORD(*pFlags) != MSHCTX_INPROC && *phGlobal)
837 GlobalFree(*phGlobal);
840 /******************************************************************************
841 * HPALETTE_UserFree (combase.@)
843 * Frees an unmarshaled palette.
845 * PARAMS
846 * pFlags [I] Flags. See notes.
847 * phPal [I] Palette to free.
849 * RETURNS
850 * The end of the marshaled data in the buffer.
852 * NOTES
853 * Even though the function is documented to take a pointer to a ULONG in
854 * pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of
855 * which the first parameter is a ULONG.
856 * This function is only intended to be called by the RPC runtime.
858 void __RPC_USER HPALETTE_UserFree(ULONG *pFlags, HPALETTE *phPal)
860 FIXME(":stub\n");
863 /******************************************************************************
864 * WdtpInterfacePointer_UserSize (combase.@)
866 * Calculates the buffer size required to marshal an interface pointer.
868 * PARAMS
869 * pFlags [I] Flags. See notes.
870 * RealFlags [I] The MSHCTX to use when marshaling the interface.
871 * punk [I] Interface pointer to size.
872 * StartingSize [I] Starting size of the buffer. This value is added on to
873 * the buffer size required for the clip format.
874 * riid [I] ID of interface to size.
876 * RETURNS
877 * The buffer size required to marshal an interface pointer plus the starting size.
879 * NOTES
880 * Even though the function is documented to take a pointer to a ULONG in
881 * pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
882 * the first parameter is a ULONG.
884 ULONG __RPC_USER WdtpInterfacePointer_UserSize(ULONG *pFlags, ULONG RealFlags, ULONG StartingSize, IUnknown *punk, REFIID riid)
886 DWORD marshal_size = 0;
887 HRESULT hr;
889 TRACE("%s, %#x, %u, %p, %s.\n", debugstr_user_flags(pFlags), RealFlags, StartingSize, punk, debugstr_guid(riid));
891 hr = CoGetMarshalSizeMax(&marshal_size, riid, punk, LOWORD(RealFlags), NULL, MSHLFLAGS_NORMAL);
892 if (FAILED(hr)) return StartingSize;
894 ALIGN_LENGTH(StartingSize, 3);
895 StartingSize += 2 * sizeof(DWORD);
896 return StartingSize + marshal_size;
899 /******************************************************************************
900 * WdtpInterfacePointer_UserMarshal (combase.@)
902 * Marshals an interface pointer into a buffer.
904 * PARAMS
905 * pFlags [I] Flags. See notes.
906 * RealFlags [I] The MSHCTX to use when marshaling the interface.
907 * pBuffer [I] Buffer to marshal the clip format into.
908 * punk [I] Interface pointer to marshal.
909 * riid [I] ID of interface to marshal.
911 * RETURNS
912 * The end of the marshaled data in the buffer.
914 * NOTES
915 * Even though the function is documented to take a pointer to a ULONG in
916 * pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
917 * the first parameter is a ULONG.
919 unsigned char * WINAPI WdtpInterfacePointer_UserMarshal(ULONG *pFlags, ULONG RealFlags, unsigned char *pBuffer, IUnknown *punk, REFIID riid)
921 HGLOBAL h = GlobalAlloc(GMEM_MOVEABLE, 0);
922 IStream *stm;
923 DWORD size;
924 void *ptr;
926 TRACE("%s, %#x, %p, &%p, %s.\n", debugstr_user_flags(pFlags), RealFlags, pBuffer, punk, debugstr_guid(riid));
928 if (!h) return NULL;
929 if (CreateStreamOnHGlobal(h, TRUE, &stm) != S_OK)
931 GlobalFree(h);
932 return NULL;
935 if (CoMarshalInterface(stm, riid, punk, LOWORD(RealFlags), NULL, MSHLFLAGS_NORMAL) != S_OK)
937 IStream_Release(stm);
938 return pBuffer;
941 ALIGN_POINTER(pBuffer, 3);
942 size = GlobalSize(h);
944 *(DWORD *)pBuffer = size;
945 pBuffer += sizeof(DWORD);
946 *(DWORD *)pBuffer = size;
947 pBuffer += sizeof(DWORD);
949 ptr = GlobalLock(h);
950 memcpy(pBuffer, ptr, size);
951 GlobalUnlock(h);
953 IStream_Release(stm);
954 return pBuffer + size;
957 /******************************************************************************
958 * WdtpInterfacePointer_UserUnmarshal (combase.@)
960 * Unmarshals an interface pointer from a buffer.
962 * PARAMS
963 * pFlags [I] Flags. See notes.
964 * pBuffer [I] Buffer to marshal the clip format from.
965 * ppunk [I/O] Address that receives the unmarshaled interface pointer.
966 * riid [I] ID of interface to unmarshal.
968 * RETURNS
969 * The end of the marshaled data in the buffer.
971 * NOTES
972 * Even though the function is documented to take a pointer to an ULONG in
973 * pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
974 * the first parameter is an ULONG.
976 unsigned char * WINAPI WdtpInterfacePointer_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, IUnknown **ppunk, REFIID riid)
978 HRESULT hr;
979 HGLOBAL h;
980 IStream *stm;
981 DWORD size;
982 void *ptr;
983 IUnknown *orig;
985 TRACE("%s, %p, %p, %s.\n", debugstr_user_flags(pFlags), pBuffer, ppunk, debugstr_guid(riid));
987 ALIGN_POINTER(pBuffer, 3);
989 size = *(DWORD *)pBuffer;
990 pBuffer += sizeof(DWORD);
991 if (size != *(DWORD *)pBuffer)
992 RaiseException(RPC_X_BAD_STUB_DATA, 0, 0, NULL);
994 pBuffer += sizeof(DWORD);
996 /* FIXME: sanity check on size */
998 h = GlobalAlloc(GMEM_MOVEABLE, size);
999 if (!h) RaiseException(RPC_X_NO_MEMORY, 0, 0, NULL);
1001 if (CreateStreamOnHGlobal(h, TRUE, &stm) != S_OK)
1003 GlobalFree(h);
1004 RaiseException(RPC_X_NO_MEMORY, 0, 0, NULL);
1007 ptr = GlobalLock(h);
1008 memcpy(ptr, pBuffer, size);
1009 GlobalUnlock(h);
1011 orig = *ppunk;
1012 hr = CoUnmarshalInterface(stm, riid, (void**)ppunk);
1013 IStream_Release(stm);
1015 if (hr != S_OK) RaiseException(hr, 0, 0, NULL);
1017 if (orig) IUnknown_Release(orig);
1019 return pBuffer + size;
1022 /******************************************************************************
1023 * WdtpInterfacePointer_UserFree (combase.@)
1025 void WINAPI WdtpInterfacePointer_UserFree(IUnknown *punk)
1027 TRACE("%p.\n", punk);
1028 if (punk) IUnknown_Release(punk);