Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/dlls/combase/usrmarshal.c
4389 views
1
/*
2
* Marshaling Routines
3
*
4
* Copyright 2005 Robert Shearman
5
* Copyright 2009 Huw Davies
6
*
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.
11
*
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.
16
*
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
20
*/
21
22
#define COBJMACROS
23
#include "ole2.h"
24
25
#include "winstring.h"
26
#include "wine/debug.h"
27
28
WINE_DEFAULT_DEBUG_CHANNEL(ole);
29
30
#define ALIGNED_LENGTH(_Len, _Align) (((_Len)+(_Align))&~(_Align))
31
#define ALIGNED_POINTER(_Ptr, _Align) ((LPVOID)ALIGNED_LENGTH((ULONG_PTR)(_Ptr), _Align))
32
#define ALIGN_LENGTH(_Len, _Align) _Len = ALIGNED_LENGTH(_Len, _Align)
33
#define ALIGN_POINTER(_Ptr, _Align) _Ptr = ALIGNED_POINTER(_Ptr, _Align)
34
35
static const char* debugstr_user_flags(ULONG *pFlags)
36
{
37
char buf[12];
38
const char* loword;
39
switch (LOWORD(*pFlags))
40
{
41
case MSHCTX_LOCAL:
42
loword = "MSHCTX_LOCAL";
43
break;
44
case MSHCTX_NOSHAREDMEM:
45
loword = "MSHCTX_NOSHAREDMEM";
46
break;
47
case MSHCTX_DIFFERENTMACHINE:
48
loword = "MSHCTX_DIFFERENTMACHINE";
49
break;
50
case MSHCTX_INPROC:
51
loword = "MSHCTX_INPROC";
52
break;
53
default:
54
sprintf(buf, "%d", LOWORD(*pFlags));
55
loword=buf;
56
}
57
58
if (HIWORD(*pFlags) == NDR_LOCAL_DATA_REPRESENTATION)
59
return wine_dbg_sprintf("MAKELONG(%s, NDR_LOCAL_DATA_REPRESENTATION)", loword);
60
else
61
return wine_dbg_sprintf("MAKELONG(%s, 0x%04x)", loword, HIWORD(*pFlags));
62
}
63
64
static ULONG handle_UserSize(ULONG *pFlags, ULONG StartingSize, HANDLE *handle)
65
{
66
if (LOWORD(*pFlags) == MSHCTX_DIFFERENTMACHINE)
67
{
68
ERR("can't remote a local handle\n");
69
RaiseException(RPC_S_INVALID_TAG, 0, 0, NULL);
70
return StartingSize;
71
}
72
73
ALIGN_LENGTH(StartingSize, 3);
74
return StartingSize + sizeof(RemotableHandle);
75
}
76
77
static unsigned char * handle_UserMarshal(ULONG *pFlags, unsigned char *pBuffer, HANDLE *handle)
78
{
79
RemotableHandle *remhandle;
80
if (LOWORD(*pFlags) == MSHCTX_DIFFERENTMACHINE)
81
{
82
ERR("can't remote a local handle\n");
83
RaiseException(RPC_S_INVALID_TAG, 0, 0, NULL);
84
return pBuffer;
85
}
86
87
ALIGN_POINTER(pBuffer, 3);
88
remhandle = (RemotableHandle *)pBuffer;
89
remhandle->fContext = WDT_INPROC_CALL;
90
remhandle->u.hInproc = (LONG_PTR)*handle;
91
return pBuffer + sizeof(RemotableHandle);
92
}
93
94
static unsigned char * handle_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, HANDLE *handle)
95
{
96
RemotableHandle *remhandle;
97
98
ALIGN_POINTER(pBuffer, 3);
99
remhandle = (RemotableHandle *)pBuffer;
100
if (remhandle->fContext != WDT_INPROC_CALL)
101
RaiseException(RPC_X_BAD_STUB_DATA, 0, 0, NULL);
102
*handle = (HANDLE)(LONG_PTR)remhandle->u.hInproc;
103
return pBuffer + sizeof(RemotableHandle);
104
}
105
106
static void handle_UserFree(ULONG *pFlags, HANDLE *handle)
107
{
108
/* nothing to do */
109
}
110
111
#define IMPL_WIREM_HANDLE(type) \
112
ULONG __RPC_USER type##_UserSize(ULONG *pFlags, ULONG StartingSize, type *handle) \
113
{ \
114
TRACE("%s, %lu, %p.\n", debugstr_user_flags(pFlags), StartingSize, handle); \
115
return handle_UserSize(pFlags, StartingSize, (HANDLE *)handle); \
116
} \
117
\
118
unsigned char * __RPC_USER type##_UserMarshal(ULONG *pFlags, unsigned char *pBuffer, type *handle) \
119
{ \
120
TRACE("%s, %p, &%p.\n", debugstr_user_flags(pFlags), pBuffer, *handle); \
121
return handle_UserMarshal(pFlags, pBuffer, (HANDLE *)handle); \
122
} \
123
\
124
unsigned char * __RPC_USER type##_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, type *handle) \
125
{ \
126
TRACE("%s, %p, %p.\n", debugstr_user_flags(pFlags), pBuffer, handle); \
127
return handle_UserUnmarshal(pFlags, pBuffer, (HANDLE *)handle); \
128
} \
129
\
130
void __RPC_USER type##_UserFree(ULONG *pFlags, type *handle) \
131
{ \
132
TRACE("%s, &%p.\n", debugstr_user_flags(pFlags), *handle); \
133
handle_UserFree(pFlags, (HANDLE *)handle); \
134
}
135
136
IMPL_WIREM_HANDLE(HACCEL)
137
IMPL_WIREM_HANDLE(HBRUSH)
138
IMPL_WIREM_HANDLE(HDC)
139
IMPL_WIREM_HANDLE(HICON)
140
IMPL_WIREM_HANDLE(HMENU)
141
IMPL_WIREM_HANDLE(HWND)
142
143
/******************************************************************************
144
* CLIPFORMAT_UserSize (combase.@)
145
*
146
* Calculates the buffer size required to marshal a clip format.
147
*
148
* PARAMS
149
* pFlags [I] Flags. See notes.
150
* StartingSize [I] Starting size of the buffer. This value is added on to
151
* the buffer size required for the clip format.
152
* pCF [I] Clip format to size.
153
*
154
* RETURNS
155
* The buffer size required to marshal a clip format plus the starting size.
156
*
157
* NOTES
158
* Even though the function is documented to take a pointer to an unsigned
159
* long in pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
160
* the first parameter is an unsigned long.
161
* This function is only intended to be called by the RPC runtime.
162
*/
163
ULONG __RPC_USER CLIPFORMAT_UserSize(ULONG *pFlags, ULONG size, CLIPFORMAT *pCF)
164
{
165
TRACE("%s, %lu, %p.\n", debugstr_user_flags(pFlags), size, pCF);
166
167
ALIGN_LENGTH(size, 3);
168
169
size += 8;
170
171
/* only need to marshal the name if it is not a pre-defined type and
172
* we are going remote */
173
if ((*pCF >= 0xc000) && (LOWORD(*pFlags) == MSHCTX_DIFFERENTMACHINE))
174
{
175
WCHAR format[255];
176
INT ret;
177
size += 3 * sizeof(UINT);
178
/* urg! this function is badly designed because it won't tell us how
179
* much space is needed without doing a dummy run of storing the
180
* name into a buffer */
181
ret = GetClipboardFormatNameW(*pCF, format, ARRAY_SIZE(format)-1);
182
if (!ret)
183
RaiseException(DV_E_CLIPFORMAT, 0, 0, NULL);
184
size += (ret + 1) * sizeof(WCHAR);
185
}
186
return size;
187
}
188
189
/******************************************************************************
190
* CLIPFORMAT_UserMarshal (combase.@)
191
*
192
* Marshals a clip format into a buffer.
193
*
194
* PARAMS
195
* pFlags [I] Flags. See notes.
196
* pBuffer [I] Buffer to marshal the clip format into.
197
* pCF [I] Clip format to marshal.
198
*
199
* RETURNS
200
* The end of the marshaled data in the buffer.
201
*
202
* NOTES
203
* Even though the function is documented to take a pointer to an unsigned
204
* long in pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
205
* the first parameter is an unsigned long.
206
* This function is only intended to be called by the RPC runtime.
207
*/
208
unsigned char * __RPC_USER CLIPFORMAT_UserMarshal(ULONG *pFlags, unsigned char *pBuffer, CLIPFORMAT *pCF)
209
{
210
TRACE("%s, %p, &0x%04x.\n", debugstr_user_flags(pFlags), pBuffer, *pCF);
211
212
ALIGN_POINTER(pBuffer, 3);
213
214
/* only need to marshal the name if it is not a pre-defined type and
215
* we are going remote */
216
if ((*pCF >= 0xc000) && (LOWORD(*pFlags) == MSHCTX_DIFFERENTMACHINE))
217
{
218
WCHAR format[255];
219
UINT len;
220
221
*(DWORD *)pBuffer = WDT_REMOTE_CALL;
222
pBuffer += 4;
223
*(DWORD *)pBuffer = *pCF;
224
pBuffer += 4;
225
226
len = GetClipboardFormatNameW(*pCF, format, ARRAY_SIZE(format)-1);
227
if (!len)
228
RaiseException(DV_E_CLIPFORMAT, 0, 0, NULL);
229
len += 1;
230
*(UINT *)pBuffer = len;
231
pBuffer += sizeof(UINT);
232
*(UINT *)pBuffer = 0;
233
pBuffer += sizeof(UINT);
234
*(UINT *)pBuffer = len;
235
pBuffer += sizeof(UINT);
236
TRACE("marshaling format name %s\n", debugstr_w(format));
237
memcpy(pBuffer, format, len * sizeof(WCHAR));
238
pBuffer += len * sizeof(WCHAR);
239
}
240
else
241
{
242
*(DWORD *)pBuffer = WDT_INPROC_CALL;
243
pBuffer += 4;
244
*(DWORD *)pBuffer = *pCF;
245
pBuffer += 4;
246
}
247
248
return pBuffer;
249
}
250
251
/******************************************************************************
252
* CLIPFORMAT_UserUnmarshal (combase.@)
253
*
254
* Unmarshals a clip format from a buffer.
255
*
256
* PARAMS
257
* pFlags [I] Flags. See notes.
258
* pBuffer [I] Buffer to marshal the clip format from.
259
* pCF [O] Address that receive the unmarshaled clip format.
260
*
261
* RETURNS
262
* The end of the marshaled data in the buffer.
263
*
264
* NOTES
265
* Even though the function is documented to take a pointer to an unsigned
266
* long in pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
267
* the first parameter is an unsigned long.
268
* This function is only intended to be called by the RPC runtime.
269
*/
270
unsigned char * __RPC_USER CLIPFORMAT_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, CLIPFORMAT *pCF)
271
{
272
LONG fContext;
273
274
TRACE("%s, %p, %p.\n", debugstr_user_flags(pFlags), pBuffer, pCF);
275
276
ALIGN_POINTER(pBuffer, 3);
277
278
fContext = *(DWORD *)pBuffer;
279
pBuffer += 4;
280
281
if (fContext == WDT_INPROC_CALL)
282
{
283
*pCF = *(CLIPFORMAT *)pBuffer;
284
pBuffer += 4;
285
}
286
else if (fContext == WDT_REMOTE_CALL)
287
{
288
CLIPFORMAT cf;
289
UINT len;
290
291
/* pointer ID for registered clip format string */
292
if (*(DWORD *)pBuffer == 0)
293
RaiseException(RPC_S_INVALID_BOUND, 0, 0, NULL);
294
pBuffer += 4;
295
296
len = *(UINT *)pBuffer;
297
pBuffer += sizeof(UINT);
298
if (*(UINT *)pBuffer != 0)
299
RaiseException(RPC_S_INVALID_BOUND, 0, 0, NULL);
300
pBuffer += sizeof(UINT);
301
if (*(UINT *)pBuffer != len)
302
RaiseException(RPC_S_INVALID_BOUND, 0, 0, NULL);
303
pBuffer += sizeof(UINT);
304
if (((WCHAR *)pBuffer)[len - 1] != '\0')
305
RaiseException(RPC_S_INVALID_BOUND, 0, 0, NULL);
306
TRACE("unmarshaling clip format %s\n", debugstr_w((LPCWSTR)pBuffer));
307
cf = RegisterClipboardFormatW((LPCWSTR)pBuffer);
308
pBuffer += len * sizeof(WCHAR);
309
if (!cf)
310
RaiseException(DV_E_CLIPFORMAT, 0, 0, NULL);
311
*pCF = cf;
312
}
313
else
314
/* code not really appropriate, but nearest I can find */
315
RaiseException(RPC_S_INVALID_TAG, 0, 0, NULL);
316
return pBuffer;
317
}
318
319
/******************************************************************************
320
* CLIPFORMAT_UserFree (combase.@)
321
*
322
* Frees an unmarshaled clip format.
323
*
324
* PARAMS
325
* pFlags [I] Flags. See notes.
326
* pCF [I] Clip format to free.
327
*
328
* RETURNS
329
* The end of the marshaled data in the buffer.
330
*
331
* NOTES
332
* Even though the function is documented to take a pointer to an unsigned
333
* long in pFlags, it actually takes a pointer to a USER_MARSHAL_CB
334
* structure, of which the first parameter is an unsigned long.
335
* This function is only intended to be called by the RPC runtime.
336
*/
337
void __RPC_USER CLIPFORMAT_UserFree(ULONG *pFlags, CLIPFORMAT *pCF)
338
{
339
/* there is no inverse of the RegisterClipboardFormat function,
340
* so nothing to do */
341
}
342
343
/******************************************************************************
344
* HBITMAP_UserSize (combase.@)
345
*
346
* Calculates the buffer size required to marshal a bitmap.
347
*
348
* PARAMS
349
* pFlags [I] Flags. See notes.
350
* StartingSize [I] Starting size of the buffer. This value is added on to
351
* the buffer size required for the clip format.
352
* phBmp [I] Bitmap to size.
353
*
354
* RETURNS
355
* The buffer size required to marshal an bitmap plus the starting size.
356
*
357
* NOTES
358
* Even though the function is documented to take a pointer to a ULONG in
359
* pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
360
* the first parameter is a ULONG.
361
* This function is only intended to be called by the RPC runtime.
362
*/
363
ULONG __RPC_USER HBITMAP_UserSize(ULONG *flags, ULONG size, HBITMAP *bmp)
364
{
365
TRACE("%s, %lu, %p.\n", debugstr_user_flags(flags), size, *bmp);
366
367
ALIGN_LENGTH(size, 3);
368
369
size += sizeof(ULONG);
370
if (LOWORD(*flags) == MSHCTX_INPROC)
371
size += sizeof(ULONG);
372
else
373
{
374
size += sizeof(ULONG);
375
376
if (*bmp)
377
{
378
size += sizeof(ULONG);
379
size += FIELD_OFFSET(userBITMAP, cbSize);
380
size += GetBitmapBits(*bmp, 0, NULL);
381
}
382
}
383
384
return size;
385
}
386
387
/******************************************************************************
388
* HBITMAP_UserMarshal (combase.@)
389
*
390
* Marshals a bitmap into a buffer.
391
*
392
* PARAMS
393
* pFlags [I] Flags. See notes.
394
* pBuffer [I] Buffer to marshal the clip format into.
395
* phBmp [I] Bitmap to marshal.
396
*
397
* RETURNS
398
* The end of the marshaled data in the buffer.
399
*
400
* NOTES
401
* Even though the function is documented to take a pointer to a ULONG in
402
* pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
403
* the first parameter is a ULONG.
404
* This function is only intended to be called by the RPC runtime.
405
*/
406
unsigned char * __RPC_USER HBITMAP_UserMarshal(ULONG *flags, unsigned char *buffer, HBITMAP *bmp)
407
{
408
TRACE("(%s, %p, %p)\n", debugstr_user_flags(flags), buffer, *bmp);
409
410
ALIGN_POINTER(buffer, 3);
411
412
if (LOWORD(*flags) == MSHCTX_INPROC)
413
{
414
*(ULONG *)buffer = WDT_INPROC_CALL;
415
buffer += sizeof(ULONG);
416
*(ULONG *)buffer = (ULONG)(ULONG_PTR)*bmp;
417
buffer += sizeof(ULONG);
418
}
419
else
420
{
421
*(ULONG *)buffer = WDT_REMOTE_CALL;
422
buffer += sizeof(ULONG);
423
*(ULONG *)buffer = (ULONG)(ULONG_PTR)*bmp;
424
buffer += sizeof(ULONG);
425
426
if (*bmp)
427
{
428
static const ULONG header_size = FIELD_OFFSET(userBITMAP, cbSize);
429
BITMAP bitmap;
430
ULONG bitmap_size;
431
432
bitmap_size = GetBitmapBits(*bmp, 0, NULL);
433
*(ULONG *)buffer = bitmap_size;
434
buffer += sizeof(ULONG);
435
436
GetObjectW(*bmp, sizeof(BITMAP), &bitmap);
437
memcpy(buffer, &bitmap, header_size);
438
buffer += header_size;
439
440
GetBitmapBits(*bmp, bitmap_size, buffer);
441
buffer += bitmap_size;
442
}
443
}
444
return buffer;
445
}
446
447
/******************************************************************************
448
* HBITMAP_UserUnmarshal (combase.@)
449
*
450
* Unmarshals a bitmap from a buffer.
451
*
452
* PARAMS
453
* pFlags [I] Flags. See notes.
454
* pBuffer [I] Buffer to marshal the clip format from.
455
* phBmp [O] Address that receive the unmarshaled bitmap.
456
*
457
* RETURNS
458
* The end of the marshaled data in the buffer.
459
*
460
* NOTES
461
* Even though the function is documented to take a pointer to an ULONG in
462
* pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
463
* the first parameter is an ULONG.
464
* This function is only intended to be called by the RPC runtime.
465
*/
466
unsigned char * __RPC_USER HBITMAP_UserUnmarshal(ULONG *flags, unsigned char *buffer, HBITMAP *bmp)
467
{
468
ULONG context;
469
470
TRACE("(%s, %p, %p)\n", debugstr_user_flags(flags), buffer, bmp);
471
472
ALIGN_POINTER(buffer, 3);
473
474
context = *(ULONG *)buffer;
475
buffer += sizeof(ULONG);
476
477
if (context == WDT_INPROC_CALL)
478
{
479
*bmp = *(HBITMAP *)buffer;
480
buffer += sizeof(*bmp);
481
}
482
else if (context == WDT_REMOTE_CALL)
483
{
484
ULONG handle = *(ULONG *)buffer;
485
buffer += sizeof(ULONG);
486
487
if (handle)
488
{
489
static const ULONG header_size = FIELD_OFFSET(userBITMAP, cbSize);
490
BITMAP bitmap;
491
ULONG bitmap_size;
492
unsigned char *bits;
493
494
bitmap_size = *(ULONG *)buffer;
495
buffer += sizeof(ULONG);
496
bits = malloc(bitmap_size);
497
498
memcpy(&bitmap, buffer, header_size);
499
buffer += header_size;
500
501
memcpy(bits, buffer, bitmap_size);
502
buffer += bitmap_size;
503
504
bitmap.bmBits = bits;
505
*bmp = CreateBitmapIndirect(&bitmap);
506
507
free(bits);
508
}
509
else
510
*bmp = NULL;
511
}
512
else
513
RaiseException(RPC_S_INVALID_TAG, 0, 0, NULL);
514
515
return buffer;
516
}
517
518
/******************************************************************************
519
* HBITMAP_UserFree (combase.@)
520
*
521
* Frees an unmarshaled bitmap.
522
*
523
* PARAMS
524
* pFlags [I] Flags. See notes.
525
* phBmp [I] Bitmap to free.
526
*
527
* RETURNS
528
* The end of the marshaled data in the buffer.
529
*
530
* NOTES
531
* Even though the function is documented to take a pointer to a ULONG in
532
* pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of
533
* which the first parameter is a ULONG.
534
* This function is only intended to be called by the RPC runtime.
535
*/
536
void __RPC_USER HBITMAP_UserFree(ULONG *flags, HBITMAP *bmp)
537
{
538
TRACE("(%s, %p)\n", debugstr_user_flags(flags), *bmp);
539
540
if (LOWORD(*flags) != MSHCTX_INPROC)
541
DeleteObject(*bmp);
542
}
543
544
/******************************************************************************
545
* HPALETTE_UserSize (combase.@)
546
*
547
* Calculates the buffer size required to marshal a palette.
548
*
549
* PARAMS
550
* pFlags [I] Flags. See notes.
551
* StartingSize [I] Starting size of the buffer. This value is added on to
552
* the buffer size required for the clip format.
553
* phPal [I] Palette to size.
554
*
555
* RETURNS
556
* The buffer size required to marshal a palette plus the starting size.
557
*
558
* NOTES
559
* Even though the function is documented to take a pointer to a ULONG in
560
* pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
561
* the first parameter is a ULONG.
562
* This function is only intended to be called by the RPC runtime.
563
*/
564
ULONG __RPC_USER HPALETTE_UserSize(ULONG *pFlags, ULONG StartingSize, HPALETTE *phPal)
565
{
566
FIXME(":stub\n");
567
return StartingSize;
568
}
569
570
/******************************************************************************
571
* HPALETTE_UserMarshal (combase.@)
572
*
573
* Marshals a palette into a buffer.
574
*
575
* PARAMS
576
* pFlags [I] Flags. See notes.
577
* pBuffer [I] Buffer to marshal the clip format into.
578
* phPal [I] Palette to marshal.
579
*
580
* RETURNS
581
* The end of the marshaled data in the buffer.
582
*
583
* NOTES
584
* Even though the function is documented to take a pointer to a ULONG in
585
* pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
586
* the first parameter is a ULONG.
587
* This function is only intended to be called by the RPC runtime.
588
*/
589
unsigned char * __RPC_USER HPALETTE_UserMarshal(ULONG *pFlags, unsigned char *pBuffer, HPALETTE *phPal)
590
{
591
FIXME(":stub\n");
592
return pBuffer;
593
}
594
595
/******************************************************************************
596
* HPALETTE_UserUnmarshal (combase.@)
597
*
598
* Unmarshals a palette from a buffer.
599
*
600
* PARAMS
601
* pFlags [I] Flags. See notes.
602
* pBuffer [I] Buffer to marshal the clip format from.
603
* phPal [O] Address that receive the unmarshaled palette.
604
*
605
* RETURNS
606
* The end of the marshaled data in the buffer.
607
*
608
* NOTES
609
* Even though the function is documented to take a pointer to an ULONG in
610
* pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
611
* the first parameter is an ULONG.
612
* This function is only intended to be called by the RPC runtime.
613
*/
614
unsigned char * __RPC_USER HPALETTE_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, HPALETTE *phPal)
615
{
616
FIXME(":stub\n");
617
return pBuffer;
618
}
619
620
/******************************************************************************
621
* HGLOBAL_UserSize (combase.@)
622
*
623
* Calculates the buffer size required to marshal an HGLOBAL.
624
*
625
* PARAMS
626
* pFlags [I] Flags. See notes.
627
* StartingSize [I] Starting size of the buffer. This value is added on to
628
* the buffer size required for the clip format.
629
* phGlobal [I] HGLOBAL to size.
630
*
631
* RETURNS
632
* The buffer size required to marshal an HGLOBAL plus the starting size.
633
*
634
* NOTES
635
* Even though the function is documented to take a pointer to a ULONG in
636
* pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
637
* the first parameter is a ULONG.
638
* This function is only intended to be called by the RPC runtime.
639
*/
640
ULONG __RPC_USER HGLOBAL_UserSize(ULONG *pFlags, ULONG StartingSize, HGLOBAL *phGlobal)
641
{
642
ULONG size = StartingSize;
643
644
TRACE("%s, %lu, %p.\n", debugstr_user_flags(pFlags), StartingSize, phGlobal);
645
646
ALIGN_LENGTH(size, 3);
647
648
size += sizeof(ULONG);
649
650
if (LOWORD(*pFlags) == MSHCTX_INPROC)
651
size += sizeof(HGLOBAL);
652
else
653
{
654
size += sizeof(ULONG);
655
if (*phGlobal)
656
{
657
SIZE_T ret;
658
size += 3 * sizeof(ULONG);
659
ret = GlobalSize(*phGlobal);
660
size += (ULONG)ret;
661
}
662
}
663
664
return size;
665
}
666
667
/******************************************************************************
668
* HGLOBAL_UserMarshal (combase.@)
669
*
670
* Marshals an HGLOBAL into a buffer.
671
*
672
* PARAMS
673
* pFlags [I] Flags. See notes.
674
* pBuffer [I] Buffer to marshal the clip format into.
675
* phGlobal [I] HGLOBAL to marshal.
676
*
677
* RETURNS
678
* The end of the marshaled data in the buffer.
679
*
680
* NOTES
681
* Even though the function is documented to take a pointer to a ULONG in
682
* pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
683
* the first parameter is a ULONG.
684
* This function is only intended to be called by the RPC runtime.
685
*/
686
unsigned char * __RPC_USER HGLOBAL_UserMarshal(ULONG *pFlags, unsigned char *pBuffer, HGLOBAL *phGlobal)
687
{
688
TRACE("%s, %p, &%p.\n", debugstr_user_flags(pFlags), pBuffer, *phGlobal);
689
690
ALIGN_POINTER(pBuffer, 3);
691
692
if (LOWORD(*pFlags) == MSHCTX_INPROC)
693
{
694
if (sizeof(*phGlobal) == 8)
695
*(ULONG *)pBuffer = WDT_INPROC64_CALL;
696
else
697
*(ULONG *)pBuffer = WDT_INPROC_CALL;
698
pBuffer += sizeof(ULONG);
699
*(HGLOBAL *)pBuffer = *phGlobal;
700
pBuffer += sizeof(HGLOBAL);
701
}
702
else
703
{
704
*(ULONG *)pBuffer = WDT_REMOTE_CALL;
705
pBuffer += sizeof(ULONG);
706
*(ULONG *)pBuffer = HandleToULong(*phGlobal);
707
pBuffer += sizeof(ULONG);
708
if (*phGlobal)
709
{
710
const unsigned char *memory;
711
SIZE_T size = GlobalSize(*phGlobal);
712
*(ULONG *)pBuffer = (ULONG)size;
713
pBuffer += sizeof(ULONG);
714
*(ULONG *)pBuffer = HandleToULong(*phGlobal);
715
pBuffer += sizeof(ULONG);
716
*(ULONG *)pBuffer = (ULONG)size;
717
pBuffer += sizeof(ULONG);
718
719
memory = GlobalLock(*phGlobal);
720
memcpy(pBuffer, memory, size);
721
pBuffer += size;
722
GlobalUnlock(*phGlobal);
723
}
724
}
725
726
return pBuffer;
727
}
728
729
/******************************************************************************
730
* HGLOBAL_UserUnmarshal (combase.@)
731
*
732
* Unmarshals an HGLOBAL from a buffer.
733
*
734
* PARAMS
735
* pFlags [I] Flags. See notes.
736
* pBuffer [I] Buffer to marshal the clip format from.
737
* phGlobal [O] Address that receive the unmarshaled HGLOBAL.
738
*
739
* RETURNS
740
* The end of the marshaled data in the buffer.
741
*
742
* NOTES
743
* Even though the function is documented to take a pointer to an ULONG in
744
* pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
745
* the first parameter is an ULONG.
746
* This function is only intended to be called by the RPC runtime.
747
*/
748
unsigned char * __RPC_USER HGLOBAL_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, HGLOBAL *phGlobal)
749
{
750
ULONG fContext;
751
752
TRACE("%s, %p, &%p.\n", debugstr_user_flags(pFlags), pBuffer, *phGlobal);
753
754
ALIGN_POINTER(pBuffer, 3);
755
756
fContext = *(ULONG *)pBuffer;
757
pBuffer += sizeof(ULONG);
758
759
if (((fContext == WDT_INPROC_CALL) && (sizeof(*phGlobal) < 8)) ||
760
((fContext == WDT_INPROC64_CALL) && (sizeof(*phGlobal) == 8)))
761
{
762
*phGlobal = *(HGLOBAL *)pBuffer;
763
pBuffer += sizeof(*phGlobal);
764
}
765
else if (fContext == WDT_REMOTE_CALL)
766
{
767
ULONG handle;
768
769
handle = *(ULONG *)pBuffer;
770
pBuffer += sizeof(ULONG);
771
772
if (handle)
773
{
774
ULONG size;
775
void *memory;
776
777
size = *(ULONG *)pBuffer;
778
pBuffer += sizeof(ULONG);
779
/* redundancy is bad - it means you have to check consistency like
780
* this: */
781
if (*(ULONG *)pBuffer != handle)
782
{
783
RaiseException(RPC_X_BAD_STUB_DATA, 0, 0, NULL);
784
return pBuffer;
785
}
786
pBuffer += sizeof(ULONG);
787
/* redundancy is bad - it means you have to check consistency like
788
* this: */
789
if (*(ULONG *)pBuffer != size)
790
{
791
RaiseException(RPC_X_BAD_STUB_DATA, 0, 0, NULL);
792
return pBuffer;
793
}
794
pBuffer += sizeof(ULONG);
795
796
/* FIXME: check size is not too big */
797
798
*phGlobal = GlobalAlloc(GMEM_MOVEABLE, size);
799
memory = GlobalLock(*phGlobal);
800
memcpy(memory, pBuffer, size);
801
pBuffer += size;
802
GlobalUnlock(*phGlobal);
803
}
804
else
805
*phGlobal = NULL;
806
}
807
else
808
RaiseException(RPC_S_INVALID_TAG, 0, 0, NULL);
809
810
return pBuffer;
811
}
812
813
/******************************************************************************
814
* HGLOBAL_UserFree (combase.@)
815
*
816
* Frees an unmarshaled HGLOBAL.
817
*
818
* PARAMS
819
* pFlags [I] Flags. See notes.
820
* phGlobal [I] HGLOBAL to free.
821
*
822
* RETURNS
823
* The end of the marshaled data in the buffer.
824
*
825
* NOTES
826
* Even though the function is documented to take a pointer to a ULONG in
827
* pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of
828
* which the first parameter is a ULONG.
829
* This function is only intended to be called by the RPC runtime.
830
*/
831
void __RPC_USER HGLOBAL_UserFree(ULONG *pFlags, HGLOBAL *phGlobal)
832
{
833
TRACE("%s, &%p.\n", debugstr_user_flags(pFlags), *phGlobal);
834
835
if (LOWORD(*pFlags) != MSHCTX_INPROC && *phGlobal)
836
GlobalFree(*phGlobal);
837
}
838
839
/******************************************************************************
840
* HPALETTE_UserFree (combase.@)
841
*
842
* Frees an unmarshaled palette.
843
*
844
* PARAMS
845
* pFlags [I] Flags. See notes.
846
* phPal [I] Palette to free.
847
*
848
* RETURNS
849
* The end of the marshaled data in the buffer.
850
*
851
* NOTES
852
* Even though the function is documented to take a pointer to a ULONG in
853
* pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of
854
* which the first parameter is a ULONG.
855
* This function is only intended to be called by the RPC runtime.
856
*/
857
void __RPC_USER HPALETTE_UserFree(ULONG *pFlags, HPALETTE *phPal)
858
{
859
FIXME(":stub\n");
860
}
861
862
/******************************************************************************
863
* WdtpInterfacePointer_UserSize (combase.@)
864
*
865
* Calculates the buffer size required to marshal an interface pointer.
866
*
867
* PARAMS
868
* pFlags [I] Flags. See notes.
869
* RealFlags [I] The MSHCTX to use when marshaling the interface.
870
* punk [I] Interface pointer to size.
871
* StartingSize [I] Starting size of the buffer. This value is added on to
872
* the buffer size required for the clip format.
873
* riid [I] ID of interface to size.
874
*
875
* RETURNS
876
* The buffer size required to marshal an interface pointer plus the starting size.
877
*
878
* NOTES
879
* Even though the function is documented to take a pointer to a ULONG in
880
* pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
881
* the first parameter is a ULONG.
882
*/
883
ULONG __RPC_USER WdtpInterfacePointer_UserSize(ULONG *pFlags, ULONG RealFlags, ULONG StartingSize, IUnknown *punk, REFIID riid)
884
{
885
DWORD marshal_size = 0;
886
HRESULT hr;
887
888
TRACE("%s, %#lx, %lu, %p, %s.\n", debugstr_user_flags(pFlags), RealFlags, StartingSize, punk, debugstr_guid(riid));
889
890
hr = CoGetMarshalSizeMax(&marshal_size, riid, punk, LOWORD(RealFlags), NULL, MSHLFLAGS_NORMAL);
891
if (FAILED(hr)) return StartingSize;
892
893
ALIGN_LENGTH(StartingSize, 3);
894
StartingSize += 2 * sizeof(DWORD);
895
return StartingSize + marshal_size;
896
}
897
898
/******************************************************************************
899
* WdtpInterfacePointer_UserMarshal (combase.@)
900
*
901
* Marshals an interface pointer into a buffer.
902
*
903
* PARAMS
904
* pFlags [I] Flags. See notes.
905
* RealFlags [I] The MSHCTX to use when marshaling the interface.
906
* pBuffer [I] Buffer to marshal the clip format into.
907
* punk [I] Interface pointer to marshal.
908
* riid [I] ID of interface to marshal.
909
*
910
* RETURNS
911
* The end of the marshaled data in the buffer.
912
*
913
* NOTES
914
* Even though the function is documented to take a pointer to a ULONG in
915
* pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
916
* the first parameter is a ULONG.
917
*/
918
unsigned char * WINAPI WdtpInterfacePointer_UserMarshal(ULONG *pFlags, ULONG RealFlags, unsigned char *pBuffer, IUnknown *punk, REFIID riid)
919
{
920
HGLOBAL h = GlobalAlloc(GMEM_MOVEABLE, 0);
921
IStream *stm;
922
DWORD size;
923
void *ptr;
924
925
TRACE("%s, %#lx, %p, &%p, %s.\n", debugstr_user_flags(pFlags), RealFlags, pBuffer, punk, debugstr_guid(riid));
926
927
if (!h) return NULL;
928
if (CreateStreamOnHGlobal(h, TRUE, &stm) != S_OK)
929
{
930
GlobalFree(h);
931
return NULL;
932
}
933
934
if (CoMarshalInterface(stm, riid, punk, LOWORD(RealFlags), NULL, MSHLFLAGS_NORMAL) != S_OK)
935
{
936
IStream_Release(stm);
937
return pBuffer;
938
}
939
940
ALIGN_POINTER(pBuffer, 3);
941
size = GlobalSize(h);
942
943
*(DWORD *)pBuffer = size;
944
pBuffer += sizeof(DWORD);
945
*(DWORD *)pBuffer = size;
946
pBuffer += sizeof(DWORD);
947
948
ptr = GlobalLock(h);
949
memcpy(pBuffer, ptr, size);
950
GlobalUnlock(h);
951
952
IStream_Release(stm);
953
return pBuffer + size;
954
}
955
956
/******************************************************************************
957
* WdtpInterfacePointer_UserUnmarshal (combase.@)
958
*
959
* Unmarshals an interface pointer from a buffer.
960
*
961
* PARAMS
962
* pFlags [I] Flags. See notes.
963
* pBuffer [I] Buffer to marshal the clip format from.
964
* ppunk [I/O] Address that receives the unmarshaled interface pointer.
965
* riid [I] ID of interface to unmarshal.
966
*
967
* RETURNS
968
* The end of the marshaled data in the buffer.
969
*
970
* NOTES
971
* Even though the function is documented to take a pointer to an ULONG in
972
* pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
973
* the first parameter is an ULONG.
974
*/
975
unsigned char * WINAPI WdtpInterfacePointer_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, IUnknown **ppunk, REFIID riid)
976
{
977
HRESULT hr;
978
HGLOBAL h;
979
IStream *stm;
980
DWORD size;
981
void *ptr;
982
IUnknown *orig;
983
984
TRACE("%s, %p, %p, %s.\n", debugstr_user_flags(pFlags), pBuffer, ppunk, debugstr_guid(riid));
985
986
ALIGN_POINTER(pBuffer, 3);
987
988
size = *(DWORD *)pBuffer;
989
pBuffer += sizeof(DWORD);
990
if (size != *(DWORD *)pBuffer)
991
RaiseException(RPC_X_BAD_STUB_DATA, 0, 0, NULL);
992
993
pBuffer += sizeof(DWORD);
994
995
/* FIXME: sanity check on size */
996
997
h = GlobalAlloc(GMEM_MOVEABLE, size);
998
if (!h) RaiseException(RPC_X_NO_MEMORY, 0, 0, NULL);
999
1000
if (CreateStreamOnHGlobal(h, TRUE, &stm) != S_OK)
1001
{
1002
GlobalFree(h);
1003
RaiseException(RPC_X_NO_MEMORY, 0, 0, NULL);
1004
}
1005
1006
ptr = GlobalLock(h);
1007
memcpy(ptr, pBuffer, size);
1008
GlobalUnlock(h);
1009
1010
orig = *ppunk;
1011
hr = CoUnmarshalInterface(stm, riid, (void**)ppunk);
1012
IStream_Release(stm);
1013
1014
if (hr != S_OK) RaiseException(hr, 0, 0, NULL);
1015
1016
if (orig) IUnknown_Release(orig);
1017
1018
return pBuffer + size;
1019
}
1020
1021
/******************************************************************************
1022
* WdtpInterfacePointer_UserFree (combase.@)
1023
*/
1024
void WINAPI WdtpInterfacePointer_UserFree(IUnknown *punk)
1025
{
1026
TRACE("%p.\n", punk);
1027
if (punk) IUnknown_Release(punk);
1028
}
1029
1030
struct hstring_wire_inproc
1031
{
1032
ULONG context;
1033
HSTRING str;
1034
};
1035
1036
struct hstring_wire_local
1037
{
1038
ULONG context;
1039
ULONG size;
1040
WCHAR data[1];
1041
};
1042
1043
/******************************************************************************
1044
* HSTRING_UserSize (combase.@)
1045
*/
1046
ULONG __RPC_USER HSTRING_UserSize(ULONG *flags, ULONG size, HSTRING *str)
1047
{
1048
TRACE("%s, %lu, %s.\n", debugstr_user_flags(flags), size, debugstr_hstring(*str));
1049
1050
ALIGN_LENGTH(size, 7);
1051
if (LOWORD(*flags) == MSHCTX_INPROC)
1052
size += sizeof(struct hstring_wire_inproc);
1053
else
1054
size += offsetof(struct hstring_wire_local, data[WindowsGetStringLen(*str)]);
1055
return size;
1056
}
1057
1058
/******************************************************************************
1059
* HSTRING_UserMarshal (combase.@)
1060
*/
1061
BYTE * __RPC_USER HSTRING_UserMarshal(ULONG *flags, BYTE *buf, HSTRING *str)
1062
{
1063
const ULONG context = sizeof(*str) == 8 ? WDT_INPROC64_CALL : WDT_INPROC_CALL;
1064
1065
TRACE("%s, %p, %s.\n", debugstr_user_flags(flags), buf, debugstr_hstring(*str));
1066
1067
if (LOWORD(*flags) == MSHCTX_DIFFERENTMACHINE)
1068
{
1069
FIXME("MSHCTX_DIFFERENTMACHINE is not supported yet.\n");
1070
RpcRaiseException(RPC_S_INVALID_TAG);
1071
}
1072
1073
if (LOWORD(*flags) == MSHCTX_INPROC)
1074
{
1075
struct hstring_wire_inproc *wire = ALIGNED_POINTER(buf, 7);
1076
1077
wire->context = context;
1078
WindowsDuplicateString(*str, &wire->str);
1079
buf = (BYTE *)(wire + 1);
1080
}
1081
else
1082
{
1083
struct hstring_wire_local *wire = ALIGNED_POINTER(buf, 7);
1084
const WCHAR *str_buf;
1085
UINT32 len;
1086
1087
wire->context = context;
1088
str_buf = WindowsGetStringRawBuffer(*str, &len);
1089
wire->size = len * sizeof(WCHAR);
1090
memcpy(wire->data, str_buf, wire->size);
1091
buf = (BYTE *)&wire->data[len];
1092
}
1093
1094
return buf;
1095
}
1096
1097
/******************************************************************************
1098
* HSTRING_UserUnmarshal (combase.@)
1099
*/
1100
BYTE * __RPC_USER HSTRING_UserUnmarshal(ULONG *flags, BYTE *buf, HSTRING *str)
1101
{
1102
TRACE("%p, %p, %p\n", debugstr_user_flags(flags), buf, str);
1103
1104
if (LOWORD(*flags) == MSHCTX_INPROC)
1105
{
1106
const struct hstring_wire_inproc *wire = ALIGNED_POINTER(buf, 7);
1107
1108
*str = wire->str;
1109
TRACE("str=%s\n", debugstr_hstring(*str));
1110
buf = (BYTE *)(wire + 1);
1111
}
1112
else
1113
{
1114
const struct hstring_wire_local *wire = ALIGNED_POINTER(buf, 7);
1115
UINT32 len;
1116
HRESULT hr;
1117
1118
len = wire->size / sizeof(WCHAR);
1119
hr = WindowsCreateString(wire->data, len, str);
1120
if (FAILED(hr))
1121
RpcRaiseException(RPC_S_OUT_OF_MEMORY);
1122
buf = (BYTE *)&wire->data[len];
1123
}
1124
1125
return buf;
1126
}
1127
1128
/******************************************************************************
1129
* HSTRING_UserFree (combase.@)
1130
*/
1131
void __RPC_USER HSTRING_UserFree(ULONG *flags, HSTRING *str)
1132
{
1133
TRACE("%s, %s.\n", debugstr_user_flags(flags), debugstr_hstring(*str));
1134
1135
if (LOWORD(*flags) == MSHCTX_INPROC)
1136
WindowsDeleteString(*str);
1137
}
1138
1139