ReactOS 0.4.16-dev-1311-g81a4d83
usrmarshal.c
Go to the documentation of this file.
1/*
2 * Marshaling Tests
3 *
4 * Copyright 2004 Robert Shearman
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21#define COBJMACROS
22#define CONST_VTABLE
23
24#include <stdarg.h>
25
26#include "windef.h"
27#include "winbase.h"
28#include "objbase.h"
29#include "propidl.h" /* for LPSAFEARRAY_User* routines */
30
31#include "wine/test.h"
32
33#if (__STDC__ && !defined(_FORCENAMELESSUNION)) || defined(NONAMELESSUNION)
34# define V_U2(A) ((A)->n1.n2)
35#else
36# define V_U2(A) (*(A))
37#endif
38
39#ifdef __REACTOS__
40typedef struct
41{
42 IUnknown IUnknown_iface;
43 ULONG refs;
45
46static const IUnknownVtbl HeapUnknown_Vtbl;
47#endif
48
49static HRESULT (WINAPI *pSafeArrayGetIID)(SAFEARRAY*,GUID*);
50static HRESULT (WINAPI *pSafeArrayGetVartype)(SAFEARRAY*,VARTYPE*);
51static HRESULT (WINAPI *pVarBstrCmp)(BSTR,BSTR,LCID,ULONG);
52
53static inline SF_TYPE get_union_type(SAFEARRAY *psa)
54{
55 VARTYPE vt;
56 HRESULT hr;
57
58 hr = pSafeArrayGetVartype(psa, &vt);
59 if (FAILED(hr))
60 {
61 if(psa->fFeatures & FADF_VARIANT) return SF_VARIANT;
62
63 switch(psa->cbElements)
64 {
65 case 1: vt = VT_I1; break;
66 case 2: vt = VT_I2; break;
67 case 4: vt = VT_I4; break;
68 case 8: vt = VT_I8; break;
69 default: return 0;
70 }
71 }
72
73 if (psa->fFeatures & FADF_HAVEIID)
74 return SF_HAVEIID;
75
76 switch (vt)
77 {
78 case VT_I1:
79 case VT_UI1: return SF_I1;
80 case VT_BOOL:
81 case VT_I2:
82 case VT_UI2: return SF_I2;
83 case VT_INT:
84 case VT_UINT:
85 case VT_I4:
86 case VT_UI4:
87 case VT_R4: return SF_I4;
88 case VT_DATE:
89 case VT_CY:
90 case VT_R8:
91 case VT_I8:
92 case VT_UI8: return SF_I8;
93 case VT_INT_PTR:
94 case VT_UINT_PTR: return (sizeof(UINT_PTR) == 4 ? SF_I4 : SF_I8);
95 case VT_BSTR: return SF_BSTR;
96 case VT_DISPATCH: return SF_DISPATCH;
97 case VT_VARIANT: return SF_VARIANT;
98 case VT_UNKNOWN: return SF_UNKNOWN;
99 /* Note: Return a non-zero size to indicate vt is valid. The actual size
100 * of a UDT is taken from the result of IRecordInfo_GetSize().
101 */
102 case VT_RECORD: return SF_RECORD;
103 default: return SF_ERROR;
104 }
105}
106
108{
109 const SAFEARRAYBOUND* psab = psa->rgsabound;
110 USHORT cCount = psa->cDims;
111 ULONG ulNumCells = 1;
112
113 while (cCount--)
114 {
115 if (!psab->cElements)
116 return 0;
117 ulNumCells *= psab->cElements;
118 psab++;
119 }
120 return ulNumCells;
121}
122
123static DWORD elem_wire_size(LPSAFEARRAY lpsa, SF_TYPE sftype)
124{
125#ifdef __REACTOS__
126 switch (sftype)
127 {
128 case SF_HAVEIID:
129 case SF_UNKNOWN:
130 case SF_DISPATCH:
131 case SF_BSTR:
132#else
133 if (sftype == SF_BSTR)
134#endif
135 return sizeof(DWORD);
136#ifdef __REACTOS__
137
138 default:
139#else
140 else
141#endif
142 return lpsa->cbElements;
143#ifdef __REACTOS__
144 }
145#endif
146}
147
148static void check_safearray(void *buffer, LPSAFEARRAY lpsa)
149{
150 unsigned char *wiresa = buffer;
151 const SAFEARRAYBOUND *bounds;
152 VARTYPE vt;
153 SF_TYPE sftype;
154 ULONG cell_count;
155 int i;
156
157 if(!lpsa)
158 {
159 ok(*(DWORD *)wiresa == 0, "wiresa + 0x0 should be NULL instead of 0x%08x\n", *(DWORD *)wiresa);
160 return;
161 }
162
163 if (!pSafeArrayGetVartype || !pSafeArrayGetIID)
164 return;
165
166#ifdef __REACTOS__
167 /* If FADF_HAVEIID is set, VT will be 0. */
168 if((lpsa->fFeatures & FADF_HAVEIID) || FAILED(SafeArrayGetVartype(lpsa, &vt)))
169#else
170 if(FAILED(pSafeArrayGetVartype(lpsa, &vt)))
171#endif
172 vt = 0;
173
174 sftype = get_union_type(lpsa);
175 cell_count = get_cell_count(lpsa);
176
177 ok(*(DWORD *)wiresa, "wiresa + 0x0 should be non-NULL instead of 0x%08x\n", *(DWORD *)wiresa); /* win2k: this is lpsa. winxp: this is 0x00000001 */
178 wiresa += sizeof(DWORD);
179 ok(*(DWORD *)wiresa == lpsa->cDims, "wiresa + 0x4 should be lpsa->cDims instead of 0x%08x\n", *(DWORD *)wiresa);
180 wiresa += sizeof(DWORD);
181 ok(*(WORD *)wiresa == lpsa->cDims, "wiresa + 0x8 should be lpsa->cDims instead of 0x%04x\n", *(WORD *)wiresa);
182 wiresa += sizeof(WORD);
183 ok(*(WORD *)wiresa == lpsa->fFeatures, "wiresa + 0xa should be lpsa->fFeatures instead of 0x%08x\n", *(WORD *)wiresa);
184 wiresa += sizeof(WORD);
185 ok(*(DWORD *)wiresa == elem_wire_size(lpsa, sftype), "wiresa + 0xc should be 0x%08x instead of 0x%08x\n", elem_wire_size(lpsa, sftype), *(DWORD *)wiresa);
186 wiresa += sizeof(DWORD);
187 ok(*(WORD *)wiresa == lpsa->cLocks, "wiresa + 0x10 should be lpsa->cLocks instead of 0x%04x\n", *(WORD *)wiresa);
188 wiresa += sizeof(WORD);
189 ok(*(WORD *)wiresa == vt, "wiresa + 0x12 should be %04x instead of 0x%04x\n", vt, *(WORD *)wiresa);
190 wiresa += sizeof(WORD);
191 ok(*(DWORD *)wiresa == sftype, "wiresa + 0x14 should be %08x instead of 0x%08x\n", (DWORD)sftype, *(DWORD *)wiresa);
192 wiresa += sizeof(DWORD);
193 ok(*(DWORD *)wiresa == cell_count, "wiresa + 0x18 should be %u instead of %u\n", cell_count, *(DWORD *)wiresa);
194 wiresa += sizeof(DWORD);
195 ok(*(DWORD *)wiresa, "wiresa + 0x1c should be non-zero instead of 0x%08x\n", *(DWORD *)wiresa);
196 wiresa += sizeof(DWORD);
197 if(sftype == SF_HAVEIID)
198 {
199 GUID guid;
200 pSafeArrayGetIID(lpsa, &guid);
201 ok(IsEqualGUID(&guid, wiresa), "guid mismatch\n");
202 wiresa += sizeof(GUID);
203 }
204
205 /* bounds are marshaled in natural dimensions order */
206 bounds = (SAFEARRAYBOUND*)wiresa;
207 for(i=0; i<lpsa->cDims; i++)
208 {
209 ok(memcmp(bounds, &lpsa->rgsabound[lpsa->cDims-i-1], sizeof(SAFEARRAYBOUND)) == 0,
210 "bounds mismatch for dimension %d, got (%d,%d), expected (%d,%d)\n", i,
211 bounds->lLbound, bounds->cElements, lpsa->rgsabound[lpsa->cDims-i-1].lLbound,
212 lpsa->rgsabound[lpsa->cDims-i-1].cElements);
213 bounds++;
214 }
215
216 wiresa += sizeof(lpsa->rgsabound[0]) * lpsa->cDims;
217
218 ok(*(DWORD *)wiresa == cell_count, "wiresa + 0x28 should be %u instead of %u\n", cell_count, *(DWORD*)wiresa);
219 wiresa += sizeof(DWORD);
220 /* elements are now pointed to by wiresa */
221}
222
224{
225 ok(0, "unexpected user_allocate call\n");
226 return CoTaskMemAlloc(size);
227}
228
229static void WINAPI user_free(void *p)
230{
231 ok(0, "unexpected user_free call\n");
233}
234
236 PMIDL_STUB_MESSAGE stub_msg,
237 PRPC_MESSAGE rpc_msg, unsigned char *buffer,
238 unsigned int size, MSHCTX context)
239{
240 memset(rpc_msg, 0, sizeof(*rpc_msg));
241 rpc_msg->Buffer = buffer;
242 rpc_msg->BufferLength = size;
243
244 memset(stub_msg, 0, sizeof(*stub_msg));
245 stub_msg->RpcMsg = rpc_msg;
246 stub_msg->Buffer = buffer;
247 stub_msg->pfnAllocate = user_allocate;
248 stub_msg->pfnFree = user_free;
249
250 memset(umcb, 0, sizeof(*umcb));
252 umcb->pStubMsg = stub_msg;
255}
256
258{
259#ifdef __REACTOS__
260 HeapUnknown *heap_unknown[10];
261#endif
262 unsigned char *buffer, *next;
263#ifdef __REACTOS__
264 ULONG size, expected, size2;
265#else
267#endif
268 LPSAFEARRAY lpsa;
269 LPSAFEARRAY lpsa2 = NULL;
270 SAFEARRAYBOUND sab[2];
272 MIDL_STUB_MESSAGE stub_msg;
273 USER_MARSHAL_CB umcb;
274 HRESULT hr;
275 VARTYPE vt, vt2;
276 OLECHAR *values[10];
277 int expected_bstr_size;
278 int i;
279 LONG indices[1];
280
281 sab[0].lLbound = 5;
282 sab[0].cElements = 10;
283
284 lpsa = SafeArrayCreate(VT_I2, 1, sab);
285 *(DWORD *)lpsa->pvData = 0xcafebabe;
286
287 lpsa->cLocks = 7;
288 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
289 size = LPSAFEARRAY_UserSize(&umcb.Flags, 1, &lpsa);
290 expected = (44 + 1 + sizeof(ULONG) - 1) & ~(sizeof(ULONG) - 1);
291 expected += sab[0].cElements * sizeof(USHORT);
292 ok(size == expected || size == expected + 12, /* win64 */
293 "size should be %u bytes, not %u\n", expected, size);
294 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
295 size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
296 expected = 44 + sab[0].cElements * sizeof(USHORT);
297 ok(size == expected || size == expected + 12, /* win64 */
298 "size should be %u bytes, not %u\n", expected, size);
300 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
301 next = LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
302 ok(next - buffer == expected, "Marshaled %u bytes, expected %u\n", (ULONG) (next - buffer), expected);
303 ok(lpsa->cLocks == 7, "got lock count %u\n", lpsa->cLocks);
304
305 check_safearray(buffer, lpsa);
306
307 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
308 LPSAFEARRAY_UserUnmarshal(&umcb.Flags, buffer, &lpsa2);
309 ok(lpsa2 != NULL, "LPSAFEARRAY didn't unmarshal\n");
310 if (pSafeArrayGetVartype)
311 {
312 pSafeArrayGetVartype(lpsa, &vt);
313 pSafeArrayGetVartype(lpsa2, &vt2);
314 ok(vt == vt2, "vts differ %x %x\n", vt, vt2);
315 }
316 ok(lpsa2->cLocks == 0, "got lock count %u, expected 0\n", lpsa2->cLocks);
317 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
318 LPSAFEARRAY_UserFree(&umcb.Flags, &lpsa2);
319 ok(!lpsa2, "lpsa2 was not set to 0 by LPSAFEARRAY_UserFree\n");
321 lpsa->cLocks = 0;
322 hr = SafeArrayDestroy(lpsa);
323 ok(hr == S_OK, "got 0x%08x\n", hr);
324
325 /* use two dimensions */
326 sab[0].lLbound = 5;
327 sab[0].cElements = 10;
328 sab[1].lLbound = 1;
329 sab[1].cElements = 2;
330
331 lpsa = SafeArrayCreate(VT_I2, 2, sab);
332 *(DWORD *)lpsa->pvData = 0xcafebabe;
333
334 lpsa->cLocks = 7;
335 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
336 size = LPSAFEARRAY_UserSize(&umcb.Flags, 1, &lpsa);
337 expected = (44 + 1 + +sizeof(SAFEARRAYBOUND) + sizeof(ULONG) - 1) & ~(sizeof(ULONG) - 1);
338 expected += max(sab[0].cElements, sab[1].cElements) * lpsa->cDims * sizeof(USHORT);
339 ok(size == expected || size == expected + 12, /* win64 */
340 "size should be %u bytes, not %u\n", expected, size);
341 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
342 size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
343 expected = 52 + max(sab[0].cElements, sab[1].cElements) * lpsa->cDims * sizeof(USHORT);
344 ok(size == expected || size == expected + 12, /* win64 */
345 "size should be %u bytes, not %u\n", expected, size);
347 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
348 next = LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
349 ok(next - buffer == expected, "Marshaled %u bytes, expected %u\n", (ULONG) (next - buffer), expected);
350 ok(lpsa->cLocks == 7, "got lock count %u\n", lpsa->cLocks);
351
352 check_safearray(buffer, lpsa);
353
354 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
355 LPSAFEARRAY_UserUnmarshal(&umcb.Flags, buffer, &lpsa2);
356 ok(lpsa2 != NULL, "LPSAFEARRAY didn't unmarshal\n");
357 if (pSafeArrayGetVartype)
358 {
359 pSafeArrayGetVartype(lpsa, &vt);
360 pSafeArrayGetVartype(lpsa2, &vt2);
361 ok(vt == vt2, "vts differ %x %x\n", vt, vt2);
362 }
363 ok(lpsa2->cLocks == 0, "got lock count %u, expected 0\n", lpsa2->cLocks);
364 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
365 LPSAFEARRAY_UserFree(&umcb.Flags, &lpsa2);
367 lpsa->cLocks = 0;
368 hr = SafeArrayDestroy(lpsa);
369 ok(hr == S_OK, "got 0x%08x\n", hr);
370
371 /* test NULL safe array */
372 lpsa = NULL;
373
374 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
375 size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
376 expected = 4;
377 ok(size == expected, "size should be 4 bytes, not %d\n", size);
379 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
380 next = LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
381 ok(next - buffer == expected, "Marshaled %u bytes, expected %u\n", (ULONG) (next - buffer), expected);
382 check_safearray(buffer, lpsa);
383
384 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
385 LPSAFEARRAY_UserUnmarshal(&umcb.Flags, buffer, &lpsa2);
386 ok(lpsa2 == NULL, "NULL LPSAFEARRAY didn't unmarshal\n");
387 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
388 LPSAFEARRAY_UserFree(&umcb.Flags, &lpsa2);
390
391 sab[0].lLbound = 5;
392 sab[0].cElements = 10;
393
394 lpsa = SafeArrayCreate(VT_R8, 1, sab);
395 *(double *)lpsa->pvData = 3.1415;
396
397 lpsa->cLocks = 7;
398 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
399 size = LPSAFEARRAY_UserSize(&umcb.Flags, 1, &lpsa);
400 expected = (44 + 1 + (sizeof(double) - 1)) & ~(sizeof(double) - 1);
401 expected += sab[0].cElements * sizeof(double);
402 ok(size == expected || size == expected + 16, /* win64 */
403 "size should be %u bytes, not %u\n", expected, size);
404 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
405 expected = (44 + (sizeof(double) - 1)) & ~(sizeof(double) - 1);
406 expected += sab[0].cElements * sizeof(double);
407 size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
408 ok(size == expected || size == expected + 8, /* win64 */
409 "size should be %u bytes, not %u\n", expected, size);
411 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
412 next = LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
413 ok(next - buffer == expected || broken(next - buffer + sizeof(DWORD) == expected),
414 "Marshaled %u bytes, expected %u\n", (ULONG) (next - buffer), expected);
415
416 check_safearray(buffer, lpsa);
417
419 lpsa->cLocks = 0;
420 hr = SafeArrayDestroy(lpsa);
421 ok(hr == S_OK, "got 0x%08x\n", hr);
422
423 /* VARTYPE-less arrays can be marshaled if cbElements is 1,2,4 or 8 as type SF_In */
424 hr = SafeArrayAllocDescriptor(1, &lpsa);
425 ok(hr == S_OK, "saad failed %08x\n", hr);
426 lpsa->cbElements = 8;
427 lpsa->rgsabound[0].lLbound = 2;
428 lpsa->rgsabound[0].cElements = 48;
429 hr = SafeArrayAllocData(lpsa);
430 ok(hr == S_OK, "saad failed %08x\n", hr);
431
432 if (pSafeArrayGetVartype)
433 {
434 hr = pSafeArrayGetVartype(lpsa, &vt);
435 ok(hr == E_INVALIDARG, "ret %08x\n", hr);
436 }
437
438 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
439 size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
440 expected = (44 + lpsa->cbElements - 1) & ~(lpsa->cbElements - 1);
441 expected += lpsa->cbElements * lpsa->rgsabound[0].cElements;
442 ok(size == expected || size == expected + 8, /* win64 */
443 "size should be %u bytes, not %u\n", expected, size);
445 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
446 next = LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
447 ok(next - buffer == expected || broken(next - buffer + sizeof(DWORD) == expected),
448 "Marshaled %u bytes, expected %u\n", (ULONG) (next - buffer), expected);
449 check_safearray(buffer, lpsa);
451 hr = SafeArrayDestroyData(lpsa);
452 ok(hr == S_OK, "got 0x%08x\n", hr);
454 ok(hr == S_OK, "got 0x%08x\n", hr);
455
456 /* Test an array of VT_BSTR */
457 sab[0].lLbound = 3;
458 sab[0].cElements = ARRAY_SIZE(values);
459
460 lpsa = SafeArrayCreate(VT_BSTR, 1, sab);
461 expected_bstr_size = 0;
462 for (i = 0; i < sab[0].cElements; i++)
463 {
464 int j;
465 WCHAR buf[128];
466 for (j = 0; j <= i; j++)
467 buf[j] = 'a' + j;
468 buf[j] = 0;
469 indices[0] = i + sab[0].lLbound;
472 ok(hr == S_OK, "Failed to put bstr element hr 0x%x\n", hr);
473 expected_bstr_size += (j * sizeof(WCHAR)) + (3 * sizeof(DWORD));
474 if (i % 2 == 0) /* Account for DWORD padding. Works so long as cElements is even */
475 expected_bstr_size += sizeof(WCHAR);
476 }
477
478 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
479 size = LPSAFEARRAY_UserSize(&umcb.Flags, 1, &lpsa);
480 expected = 44 + (sab[0].cElements * sizeof(DWORD)) + expected_bstr_size;
482 ok(size == expected + sizeof(DWORD) || size == (expected + sizeof(DWORD) + 12 /* win64 */),
483 "size should be %u bytes, not %u\n", expected + (ULONG) sizeof(DWORD), size);
484 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
485 size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
487 ok(size == expected || size == (expected + 12 /* win64 */),
488 "size should be %u bytes, not %u\n", expected, size);
490 memset(buffer, 0xcc, size);
491 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
492 next = LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
494 ok(next - buffer == expected, "Marshaled %u bytes, expected %u\n", (ULONG) (next - buffer), expected);
495
496 check_safearray(buffer, lpsa);
497
498 lpsa2 = NULL;
499 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
500 next = LPSAFEARRAY_UserUnmarshal(&umcb.Flags, buffer, &lpsa2);
502 ok(next - buffer == expected, "Marshaled %u bytes, expected %u\n", (ULONG) (next - buffer), expected);
503 ok(lpsa2 != NULL, "LPSAFEARRAY didn't unmarshal, result %p\n", next);
504
505 for (i = 0; i < ARRAY_SIZE(values); i++)
506 {
507 BSTR gotvalue = NULL;
508
509 if (lpsa2)
510 {
511 indices[0] = i + sab[0].lLbound;
512 hr = SafeArrayGetElement(lpsa2, indices, &gotvalue);
513 ok(hr == S_OK, "Failed to get bstr element at hres 0x%x\n", hr);
514 if (hr == S_OK)
515 {
516 if (pVarBstrCmp)
517 ok(pVarBstrCmp(values[i], gotvalue, 0, 0) == VARCMP_EQ, "String %d does not match\n", i);
518 SysFreeString(gotvalue);
519 }
520 }
521
523 }
524
525 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
526 LPSAFEARRAY_UserFree(&umcb.Flags, &lpsa2);
527
529 hr = SafeArrayDestroy(lpsa);
530 ok(hr == S_OK, "got 0x%08x\n", hr);
531
532 /* VARTYPE-less arrays with FADF_VARIANT */
533 hr = SafeArrayAllocDescriptor(1, &lpsa);
534 ok(hr == S_OK, "saad failed %08x\n", hr);
535 lpsa->cbElements = sizeof(VARIANT);
536 lpsa->fFeatures = FADF_VARIANT;
537 lpsa->rgsabound[0].lLbound = 2;
538 lpsa->rgsabound[0].cElements = 48;
539 hr = SafeArrayAllocData(lpsa);
540 ok(hr == S_OK, "saad failed %08x\n", hr);
541
542 if (pSafeArrayGetVartype)
543 {
544 hr = pSafeArrayGetVartype(lpsa, &vt);
545 ok(hr == E_INVALIDARG, "ret %08x\n", hr);
546 }
547
548 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
549 size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
550 expected = 44 + 28 * lpsa->rgsabound[0].cElements;
552 ok(size == expected || size == expected + 8, /* win64 */
553 "size should be %u bytes, not %u\n", expected, size);
555 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
556 next = LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
558 ok(next - buffer == expected || broken(next - buffer + sizeof(DWORD) == expected),
559 "Marshaled %u bytes, expected %u\n", (ULONG) (next - buffer), expected);
560 lpsa->cbElements = 16; /* VARIANT wire size */
561 check_safearray(buffer, lpsa);
563 hr = SafeArrayDestroyData(lpsa);
564 ok(hr == S_OK, "got 0x%08x\n", hr);
566 ok(hr == S_OK, "got 0x%08x\n", hr);
567
568#ifdef __REACTOS__
569 /* Test an array of VT_UNKNOWN */
570 sab[0].lLbound = 3;
571 sab[0].cElements = ARRAY_SIZE(heap_unknown);
572
573 lpsa = SafeArrayCreate(VT_UNKNOWN, 1, sab);
574
575 /*
576 * Calculate approximate expected size. Sizes are different between Windows
577 * versions, so this should calculate the smallest size that seems sane.
578 */
579 expected = 60;
580 for (i = 0; i < sab[0].cElements; i++)
581 {
582 HeapUnknown *unk;
583 VARIANT v;
584
585 unk = HeapAlloc(GetProcessHeap(), 0, sizeof(*unk));
586 unk->IUnknown_iface.lpVtbl = &HeapUnknown_Vtbl;
587 unk->refs = 1;
588
589 indices[0] = i + sab[0].lLbound;
590 heap_unknown[i] = unk;
591 hr = SafeArrayPutElement(lpsa, indices, &heap_unknown[i]->IUnknown_iface);
592 ok(hr == S_OK, "Failed to put unknown element hr 0x%x\n", hr);
593 ok(unk->refs == 2, "VT_UNKNOWN safearray elem %d, refcount %d\n", i, unk->refs);
594
595 V_VT(&v) = VT_UNKNOWN;
596 V_UNKNOWN(&v) = &unk->IUnknown_iface;
597 expected += VARIANT_UserSize(&umcb.Flags, 0, &v) - 20;
598 }
599
600 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
601 size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
602 ok(size >= expected || size >= (expected + 12 ),
603 "size should be at least %u bytes, not %u\n", expected, size);
604
605 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
606 size2 = LPSAFEARRAY_UserSize(&umcb.Flags, 1, &lpsa);
607 ok(size2 == (size + sizeof(DWORD)) || size2 == (size + sizeof(DWORD) + 12),
608 "size should be %u bytes, not %u\n", size + (ULONG) sizeof(DWORD), size2);
609
611 memset(buffer, 0xcc, size);
612 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
613 next = LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
614 ok((next - buffer) <= size, "Marshaled %u bytes, expected at most %u\n", (ULONG) (next - buffer), size);
615 check_safearray(buffer, lpsa);
617 ok(heap_unknown[0]->refs == 3, "Unexpected refcount %d\n", heap_unknown[0]->refs);
618
619 lpsa2 = NULL;
620 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
621 next = LPSAFEARRAY_UserUnmarshal(&umcb.Flags, buffer, &lpsa2);
622 ok((next - buffer) <= size, "Marshaled %u bytes, expected at most %u\n", (ULONG) (next - buffer), size);
623 ok(lpsa2 != NULL, "LPSAFEARRAY didn't unmarshal, result %p\n", next);
624
625 for (i = 0; i < ARRAY_SIZE(heap_unknown); i++)
626 {
627 IUnknown *gotvalue = NULL;
628
629 if (lpsa2)
630 {
631 indices[0] = i + sab[0].lLbound;
632 hr = SafeArrayGetElement(lpsa2, indices, &gotvalue);
633 ok(hr == S_OK, "Failed to get unk element at %d, hres 0x%x\n", i, hr);
634 if (hr == S_OK)
635 {
636 ok(gotvalue == &heap_unknown[i]->IUnknown_iface, "Interface %d mismatch, expected %p, got %p\n",
637 i, &heap_unknown[i]->IUnknown_iface, gotvalue);
638 IUnknown_Release(gotvalue);
639 }
640 }
641 }
642
643 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
644 LPSAFEARRAY_UserFree(&umcb.Flags, &lpsa2);
645
646 /* Set one of the elements to NULL, see how this effects size. */
647 indices[0] = 3 + sab[0].lLbound;
649 ok(hr == S_OK, "Failed to put unknown element hr 0x%x\n", hr);
650
651 expected = 60;
652 for (i = 0; i < sab[0].cElements; i++)
653 {
654 VARIANT v;
655
656 V_VT(&v) = VT_UNKNOWN;
657 V_UNKNOWN(&v) = (i != 3) ? &heap_unknown[i]->IUnknown_iface : NULL;
658 expected += VARIANT_UserSize(&umcb.Flags, 0, &v) - 20;
659 }
660
661 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
662 size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
663 ok(size >= expected || size >= (expected + 12 ),
664 "size should be at least %u bytes, not %u\n", expected, size);
665
666 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
667 size2 = LPSAFEARRAY_UserSize(&umcb.Flags, 1, &lpsa);
668 ok(size2 == (size + sizeof(DWORD)) || size2 == (size + sizeof(DWORD) + 12),
669 "size should be %u bytes, not %u\n", size + (ULONG) sizeof(DWORD), size2);
670
672 memset(buffer, 0xcc, size);
673 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
674 next = LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
675 ok((next - buffer) <= expected, "Marshaled %u bytes, expected at most %u bytes\n", (ULONG) (next - buffer), expected);
676 check_safearray(buffer, lpsa);
677
678 lpsa2 = NULL;
679 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
680 next = LPSAFEARRAY_UserUnmarshal(&umcb.Flags, buffer, &lpsa2);
681 ok((next - buffer) <= expected, "Marshaled %u bytes, expected at most %u bytes\n", (ULONG) (next - buffer), expected);
682 ok(lpsa2 != NULL, "LPSAFEARRAY didn't unmarshal, result %p\n", next);
683
684 for (i = 0; i < ARRAY_SIZE(heap_unknown); i++)
685 {
686 IUnknown *gotvalue = NULL;
687
688 if (lpsa2)
689 {
690 indices[0] = i + sab[0].lLbound;
691 hr = SafeArrayGetElement(lpsa2, indices, &gotvalue);
692 ok(hr == S_OK, "Failed to get unk element at %d, hres 0x%x\n", i, hr);
693 if (hr == S_OK)
694 {
695 /* Our NULL interface. */
696 if (i == 3)
697 ok(gotvalue == NULL, "Interface %d expected NULL, got %p\n", i, gotvalue);
698 else
699 {
700 ok(gotvalue == &heap_unknown[i]->IUnknown_iface, "Interface %d mismatch, expected %p, got %p\n",
701 i, &heap_unknown[i]->IUnknown_iface, gotvalue);
702 IUnknown_Release(gotvalue);
703 }
704 }
705 }
706 IUnknown_Release(&heap_unknown[i]->IUnknown_iface);
707 }
708
709 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
710 LPSAFEARRAY_UserFree(&umcb.Flags, &lpsa2);
711
712 ok(heap_unknown[0]->refs == 1, "Unexpected refcount %d\n", heap_unknown[0]->refs);
713
714 hr = SafeArrayDestroy(lpsa);
715 ok(hr == S_OK, "got 0x%08x\n", hr);
716#endif
717}
718
719static void check_bstr(void *buffer, BSTR b)
720{
721 DWORD *wireb = buffer;
723
724 ok(*wireb == (len + 1) / 2, "wv[0] %08x\n", *wireb);
725 wireb++;
726 if(b)
727 ok(*wireb == len, "wv[1] %08x\n", *wireb);
728 else
729 ok(*wireb == 0xffffffff, "wv[1] %08x\n", *wireb);
730 wireb++;
731 ok(*wireb == (len + 1) / 2, "wv[2] %08x\n", *wireb);
732 if(len)
733 {
734 wireb++;
735 ok(!memcmp(wireb, b, (len + 1) & ~1), "strings differ\n");
736 }
737 return;
738}
739
740static void test_marshal_BSTR(void)
741{
742 ULONG size;
744 MIDL_STUB_MESSAGE stub_msg;
745 USER_MARSHAL_CB umcb;
746 unsigned char *buffer, *next;
747 BSTR b, b2;
748 WCHAR str[] = {'m','a','r','s','h','a','l',' ','t','e','s','t','1',0};
749 DWORD len;
750
752 len = SysStringLen(b);
753 ok(len == 13, "get %d\n", len);
754
755 /* BSTRs are DWORD aligned */
756
757 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
758 size = BSTR_UserSize(&umcb.Flags, 1, &b);
759 ok(size == 42, "size %d\n", size);
760
761 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
762 size = BSTR_UserSize(&umcb.Flags, 0, &b);
763 ok(size == 38, "size %d\n", size);
764
766 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
767 next = BSTR_UserMarshal(&umcb.Flags, buffer, &b);
768 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
770
771 b2 = NULL;
772 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
774 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
775 ok(b2 != NULL, "BSTR didn't unmarshal\n");
776 ok(!memcmp(b, b2, (len + 1) * 2), "strings differ\n");
777 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
778 BSTR_UserFree(&umcb.Flags, &b2);
779
782
783 b = NULL;
784 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
785 size = BSTR_UserSize(&umcb.Flags, 0, &b);
786 ok(size == 12, "size %d\n", size);
787
789 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
790 next = BSTR_UserMarshal(&umcb.Flags, buffer, &b);
791 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
792
794 b2 = NULL;
795 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
797 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
798 ok(b2 == NULL, "NULL BSTR didn't unmarshal\n");
799 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
800 BSTR_UserFree(&umcb.Flags, &b2);
802
803 b = SysAllocStringByteLen("abc", 3);
804 *(((char*)b) + 3) = 'd';
805 len = SysStringLen(b);
806 ok(len == 1, "get %d\n", len);
808 ok(len == 3, "get %d\n", len);
809
810 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
811 size = BSTR_UserSize(&umcb.Flags, 0, &b);
812 ok(size == 16, "size %d\n", size);
813
815 memset(buffer, 0xcc, size);
816 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
817 next = BSTR_UserMarshal(&umcb.Flags, buffer, &b);
818 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
820 ok(buffer[15] == 'd', "buffer[15] %02x\n", buffer[15]);
821
822 b2 = NULL;
823 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
825 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
826 ok(b2 != NULL, "BSTR didn't unmarshal\n");
827 ok(!memcmp(b, b2, len), "strings differ\n");
828 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
829 BSTR_UserFree(&umcb.Flags, &b2);
832
833 b = SysAllocStringByteLen("", 0);
834 len = SysStringLen(b);
835 ok(len == 0, "get %d\n", len);
837 ok(len == 0, "get %d\n", len);
838
839 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
840 size = BSTR_UserSize(&umcb.Flags, 0, &b);
841 ok(size == 12, "size %d\n", size);
842
844 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
845 next = BSTR_UserMarshal(&umcb.Flags, buffer, &b);
846 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
848
849 b2 = NULL;
850 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
852 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
853 ok(b2 != NULL, "NULL LPSAFEARRAY didn't unmarshal\n");
855 ok(len == 0, "byte len %d\n", len);
856 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
857 BSTR_UserFree(&umcb.Flags, &b2);
860}
861
862#ifndef __REACTOS__
863typedef struct
864{
865 IUnknown IUnknown_iface;
866 ULONG refs;
868#endif
869
871{
872 return CONTAINING_RECORD(iface, HeapUnknown, IUnknown_iface);
873}
874
876{
878 {
879 IUnknown_AddRef(iface);
880 *ppv = iface;
881 return S_OK;
882 }
883 *ppv = NULL;
884 return E_NOINTERFACE;
885}
886
888{
890 return InterlockedIncrement((LONG*)&This->refs);
891}
892
894{
896 ULONG refs = InterlockedDecrement((LONG*)&This->refs);
897 if (!refs) HeapFree(GetProcessHeap(), 0, This);
898 return refs;
899}
900
901static const IUnknownVtbl HeapUnknown_Vtbl =
902{
906};
907
908typedef struct
909{
910 DWORD clSize;
911 DWORD rpcReserved;
912 USHORT vt;
913 USHORT wReserved1;
914 USHORT wReserved2;
915 USHORT wReserved3;
916 DWORD switch_is;
918
920{
921 const variant_wire_t *header = (const variant_wire_t*)wirev;
922 DWORD switch_is;
923
924 ok(header->clSize == (size + 7) >> 3, "wv[0] %08x, expected %08x\n", header->clSize, (size + 7) >> 3);
925 ok(header->rpcReserved == 0, "wv[1] %08x\n", header->rpcReserved);
926 ok(header->vt == V_VT(v), "vt %04x expected %04x\n", header->vt, V_VT(v));
927 ok(header->wReserved1 == V_U2(v).wReserved1, "res1 %04x expected %04x\n", header->wReserved1, V_U2(v).wReserved1);
928 ok(header->wReserved2 == V_U2(v).wReserved2, "res2 %04x expected %04x\n", header->wReserved2, V_U2(v).wReserved2);
929 ok(header->wReserved3 == V_U2(v).wReserved3, "res3 %04x expected %04x\n", header->wReserved3, V_U2(v).wReserved3);
930
931 switch_is = V_VT(v);
932 if(switch_is & VT_ARRAY)
933 switch_is &= ~VT_TYPEMASK;
934 ok(header->switch_is == switch_is, "switch_is %08x expected %08x\n", header->switch_is, switch_is);
935
936 return (DWORD*)((unsigned char*)wirev + sizeof(variant_wire_t));
937}
938
939/* Win9x and WinME don't always align as needed. Variants have
940 * an alignment of 8.
941 */
942static void *alloc_aligned(SIZE_T size, void **buf)
943{
944 *buf = HeapAlloc(GetProcessHeap(), 0, size + 7);
945 return (void *)(((UINT_PTR)*buf + 7) & ~7);
946}
947
948static void test_marshal_VARIANT(void)
949{
950 VARIANT v, v2, v3;
951 MIDL_STUB_MESSAGE stubMsg = { 0 };
952 RPC_MESSAGE rpcMsg = { 0 };
953 USER_MARSHAL_CB umcb = { 0 };
954 unsigned char *buffer, *next;
955 void *oldbuffer;
956 ULONG ul;
957 short s;
958 double d;
959 void *mem;
960 DWORD *wirev;
961 BSTR b, b2;
962 WCHAR str[] = {'m','a','r','s','h','a','l',' ','t','e','s','t',0};
963 SAFEARRAYBOUND sab;
964 LPSAFEARRAY lpsa, lpsa2, lpsa_copy;
965 DECIMAL dec, dec2;
966 HeapUnknown *heap_unknown;
968 HRESULT hr;
969 LONG bound, bound2;
970 VARTYPE vt, vt2;
971 IUnknown *unk;
972
973 stubMsg.RpcMsg = &rpcMsg;
974
975 umcb.Flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
976 umcb.pStubMsg = &stubMsg;
977 umcb.pReserve = NULL;
980
981 /*** I1 ***/
982 VariantInit(&v);
983 V_VT(&v) = VT_I1;
984 V_I1(&v) = 0x12;
985
986 /* check_variant_header tests wReserved[123], so initialize to unique values.
987 * (Could probably also do this by setting the variant to a known DECIMAL.)
988 */
989 V_U2(&v).wReserved1 = 0x1234;
990 V_U2(&v).wReserved2 = 0x5678;
991 V_U2(&v).wReserved3 = 0x9abc;
992
993 /* Variants have an alignment of 8 */
994 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 1, &v);
995 ok(stubMsg.BufferLength == 29, "size %d\n", stubMsg.BufferLength);
996
997 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
998 ok(stubMsg.BufferLength == 21, "size %d\n", stubMsg.BufferLength);
999
1000 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1001 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1003 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1004 wirev = (DWORD*)buffer;
1005
1006 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength);
1007 ok(*(char*)wirev == V_I1(&v), "wv[5] %08x\n", *wirev);
1008 VariantInit(&v2);
1009 stubMsg.Buffer = buffer;
1011 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1012 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1013 ok(V_I1(&v) == V_I1(&v2), "got i1 %x expect %x\n", V_I1(&v), V_I1(&v2));
1014
1015 VARIANT_UserFree(&umcb.Flags, &v2);
1016 HeapFree(GetProcessHeap(), 0, oldbuffer);
1017
1018 /*** I2 ***/
1019 VariantInit(&v);
1020 V_VT(&v) = VT_I2;
1021 V_I2(&v) = 0x1234;
1022
1023 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1024 ok(stubMsg.BufferLength == 22, "size %d\n", stubMsg.BufferLength);
1025
1026 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1027 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1029 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1030 wirev = (DWORD*)buffer;
1031
1032 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength);
1033 ok(*(short*)wirev == V_I2(&v), "wv[5] %08x\n", *wirev);
1034 VariantInit(&v2);
1035 stubMsg.Buffer = buffer;
1037 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1038 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1039 ok(V_I2(&v) == V_I2(&v2), "got i2 %x expect %x\n", V_I2(&v), V_I2(&v2));
1040
1041 VARIANT_UserFree(&umcb.Flags, &v2);
1042 HeapFree(GetProcessHeap(), 0, oldbuffer);
1043
1044 /*** I2 BYREF ***/
1045 VariantInit(&v);
1046 V_VT(&v) = VT_I2 | VT_BYREF;
1047 s = 0x1234;
1048 V_I2REF(&v) = &s;
1049
1050 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1051 ok(stubMsg.BufferLength == 26, "size %d\n", stubMsg.BufferLength);
1052
1053 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1054 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1056 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1057 wirev = (DWORD*)buffer;
1058
1059 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength);
1060 ok(*wirev == 0x4, "wv[5] %08x\n", *wirev);
1061 wirev++;
1062 ok(*(short*)wirev == s, "wv[6] %08x\n", *wirev);
1063 VariantInit(&v2);
1064 V_VT(&v2) = VT_I2 | VT_BYREF;
1065 V_BYREF(&v2) = mem = CoTaskMemAlloc(sizeof(V_I2(&v2)));
1066 stubMsg.Buffer = buffer;
1068 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1069 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1070 ok(V_BYREF(&v2) == mem, "didn't reuse existing memory\n");
1071 ok(*V_I2REF(&v) == *V_I2REF(&v2), "got i2 ref %x expect ui4 ref %x\n", *V_I2REF(&v), *V_I2REF(&v2));
1072
1073 VARIANT_UserFree(&umcb.Flags, &v2);
1074 HeapFree(GetProcessHeap(), 0, oldbuffer);
1075
1076 /*** I4 ***/
1077 VariantInit(&v);
1078 V_VT(&v) = VT_I4;
1079 V_I4(&v) = 0x1234;
1080
1081 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1082 ok(stubMsg.BufferLength == 24, "size %d\n", stubMsg.BufferLength);
1083
1084 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1085 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1087 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1088 wirev = (DWORD*)buffer;
1089
1090 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength);
1091 ok(*wirev == V_I4(&v), "wv[5] %08x\n", *wirev);
1092
1093 VariantInit(&v2);
1094 stubMsg.Buffer = buffer;
1096 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1097 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1098 ok(V_I4(&v) == V_I4(&v2), "got i4 %x expect %x\n", V_I4(&v), V_I4(&v2));
1099
1100 VARIANT_UserFree(&umcb.Flags, &v2);
1101 HeapFree(GetProcessHeap(), 0, oldbuffer);
1102
1103 /*** UI4 ***/
1104 VariantInit(&v);
1105 V_VT(&v) = VT_UI4;
1106 V_UI4(&v) = 0x1234;
1107
1108 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1109 ok(stubMsg.BufferLength == 24, "size %d\n", stubMsg.BufferLength);
1110
1111 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1112 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1114 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1115 wirev = (DWORD*)buffer;
1116
1117 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength);
1118 ok(*wirev == 0x1234, "wv[5] %08x\n", *wirev);
1119 VariantInit(&v2);
1120 stubMsg.Buffer = buffer;
1122 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1123 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1124 ok(V_UI4(&v) == V_UI4(&v2), "got ui4 %x expect %x\n", V_UI4(&v), V_UI4(&v2));
1125
1126 VARIANT_UserFree(&umcb.Flags, &v2);
1127 HeapFree(GetProcessHeap(), 0, oldbuffer);
1128
1129 /*** UI4 BYREF ***/
1130 VariantInit(&v);
1131 V_VT(&v) = VT_UI4 | VT_BYREF;
1132 ul = 0x1234;
1133 V_UI4REF(&v) = &ul;
1134
1135 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1136 ok(stubMsg.BufferLength == 28, "size %d\n", stubMsg.BufferLength);
1137
1138 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1139 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1141 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1142 wirev = (DWORD*)buffer;
1143
1144 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength);
1145 ok(*wirev == 0x4, "wv[5] %08x\n", *wirev);
1146 wirev++;
1147 ok(*wirev == ul, "wv[6] %08x\n", *wirev);
1148
1149 VariantInit(&v2);
1150 stubMsg.Buffer = buffer;
1152 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1153 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1154 ok(*V_UI4REF(&v) == *V_UI4REF(&v2), "got ui4 ref %x expect ui4 ref %x\n", *V_UI4REF(&v), *V_UI4REF(&v2));
1155
1156 VARIANT_UserFree(&umcb.Flags, &v2);
1157 HeapFree(GetProcessHeap(), 0, oldbuffer);
1158
1159 /*** I8 ***/
1160 VariantInit(&v);
1161 V_VT(&v) = VT_I8;
1162 V_I8(&v) = (LONGLONG)1000000 * 1000000;
1163
1164 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1165 ok(stubMsg.BufferLength == 32, "size %d\n", stubMsg.BufferLength);
1166
1167 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1168 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1169 memset(buffer, 0xcc, stubMsg.BufferLength);
1171 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1172 wirev = (DWORD*)buffer;
1173
1174 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength);
1175 ok(*wirev == 0xcccccccc, "wv[5] %08x\n", *wirev); /* pad */
1176 wirev++;
1177 ok(*(LONGLONG *)wirev == V_I8(&v), "wv[6] %s\n", wine_dbgstr_longlong(*(LONGLONG *)wirev));
1178 VariantInit(&v2);
1179 stubMsg.Buffer = buffer;
1181 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1182 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1183 ok(V_I8(&v) == V_I8(&v2), "got i8 %s expect %s\n",
1185
1186 VARIANT_UserFree(&umcb.Flags, &v2);
1187 HeapFree(GetProcessHeap(), 0, oldbuffer);
1188
1189 /*** R4 ***/
1190 VariantInit(&v);
1191 V_VT(&v) = VT_R4;
1192 V_R8(&v) = 3.1415;
1193
1194 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1195 ok(stubMsg.BufferLength == 24, "size %d\n", stubMsg.BufferLength);
1196
1197 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1198 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1200 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1201 wirev = (DWORD*)buffer;
1202
1203 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength);
1204 ok(*(float*)wirev == V_R4(&v), "wv[5] %08x\n", *wirev);
1205 VariantInit(&v2);
1206 stubMsg.Buffer = buffer;
1208 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1209 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1210 ok(V_R4(&v) == V_R4(&v2), "got r4 %f expect %f\n", V_R4(&v), V_R4(&v2));
1211
1212 VARIANT_UserFree(&umcb.Flags, &v2);
1213 HeapFree(GetProcessHeap(), 0, oldbuffer);
1214
1215 /*** R8 ***/
1216 VariantInit(&v);
1217 V_VT(&v) = VT_R8;
1218 V_R8(&v) = 3.1415;
1219
1220 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1221 ok(stubMsg.BufferLength == 32, "size %d\n", stubMsg.BufferLength);
1222
1223 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1224 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1225 memset(buffer, 0xcc, stubMsg.BufferLength);
1227 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1228 wirev = (DWORD*)buffer;
1229
1230 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength);
1231 ok(*wirev == 0xcccccccc, "wv[5] %08x\n", *wirev); /* pad */
1232 wirev++;
1233 ok(*(double*)wirev == V_R8(&v), "wv[6] %08x, wv[7] %08x\n", *wirev, *(wirev+1));
1234 VariantInit(&v2);
1235 stubMsg.Buffer = buffer;
1237 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1238 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1239 ok(V_R8(&v) == V_R8(&v2), "got r8 %f expect %f\n", V_R8(&v), V_R8(&v2));
1240
1241 VARIANT_UserFree(&umcb.Flags, &v2);
1242 HeapFree(GetProcessHeap(), 0, oldbuffer);
1243
1244 /*** R8 BYREF ***/
1245 VariantInit(&v);
1246 V_VT(&v) = VT_R8 | VT_BYREF;
1247 d = 3.1415;
1248 V_R8REF(&v) = &d;
1249
1250 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1251 ok(stubMsg.BufferLength == 32, "size %d\n", stubMsg.BufferLength);
1252
1253 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1254 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1256 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1257 wirev = (DWORD*)buffer;
1258
1259 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength);
1260 ok(*wirev == 8, "wv[5] %08x\n", *wirev);
1261 wirev++;
1262 ok(*(double*)wirev == d, "wv[6] %08x wv[7] %08x\n", *wirev, *(wirev+1));
1263 VariantInit(&v2);
1264 stubMsg.Buffer = buffer;
1266 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1267 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1268 ok(*V_R8REF(&v) == *V_R8REF(&v2), "got r8 ref %f expect %f\n", *V_R8REF(&v), *V_R8REF(&v2));
1269
1270 VARIANT_UserFree(&umcb.Flags, &v2);
1271 HeapFree(GetProcessHeap(), 0, oldbuffer);
1272
1273 /*** VARIANT_BOOL ***/
1274 VariantInit(&v);
1275 V_VT(&v) = VT_BOOL;
1276 V_BOOL(&v) = 0x1234;
1277
1278 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1279 ok(stubMsg.BufferLength == 22, "size %d\n", stubMsg.BufferLength);
1280
1281 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1282 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1284 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1285 wirev = (DWORD*)buffer;
1286
1287 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength);
1288 ok(*(short*)wirev == V_BOOL(&v), "wv[5] %04x\n", *(WORD*)wirev);
1289 VariantInit(&v2);
1290 stubMsg.Buffer = buffer;
1292 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1293 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1294 ok(V_BOOL(&v) == V_BOOL(&v2), "got bool %x expect %x\n", V_BOOL(&v), V_BOOL(&v2));
1295
1296 VARIANT_UserFree(&umcb.Flags, &v2);
1297 HeapFree(GetProcessHeap(), 0, oldbuffer);
1298
1299 /*** DECIMAL ***/
1300 VarDecFromI4(0x12345678, &dec);
1301 dec.wReserved = 0xfedc; /* Also initialize reserved field, as we check it later */
1302 VariantInit(&v);
1303 V_DECIMAL(&v) = dec;
1304 V_VT(&v) = VT_DECIMAL;
1305
1306 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1307 ok(stubMsg.BufferLength == 40, "size %d\n", stubMsg.BufferLength);
1308
1309 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1310 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1311 memset(buffer, 0xcc, stubMsg.BufferLength);
1313 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1314 wirev = (DWORD*)buffer;
1315
1316 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength);
1317 ok(*wirev == 0xcccccccc, "wirev[5] %08x\n", *wirev); /* pad */
1318 wirev++;
1319 dec2 = dec;
1320 dec2.wReserved = VT_DECIMAL;
1321 ok(!memcmp(wirev, &dec2, sizeof(dec2)), "wirev[6] %08x wirev[7] %08x wirev[8] %08x wirev[9] %08x\n",
1322 *wirev, *(wirev + 1), *(wirev + 2), *(wirev + 3));
1323 VariantInit(&v2);
1324 stubMsg.Buffer = buffer;
1326 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1327 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1328 ok(!memcmp(&V_DECIMAL(&v), & V_DECIMAL(&v2), sizeof(DECIMAL)), "decimals differ\n");
1329
1330 VARIANT_UserFree(&umcb.Flags, &v2);
1331 HeapFree(GetProcessHeap(), 0, oldbuffer);
1332
1333 /*** DECIMAL BYREF ***/
1334 VariantInit(&v);
1335 V_VT(&v) = VT_DECIMAL | VT_BYREF;
1336 V_DECIMALREF(&v) = &dec;
1337
1338 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1339 ok(stubMsg.BufferLength == 40, "size %d\n", stubMsg.BufferLength);
1340
1341 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1342 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1344 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1345 wirev = (DWORD*)buffer;
1346
1347 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength);
1348 ok(*wirev == 16, "wv[5] %08x\n", *wirev);
1349 wirev++;
1350 ok(!memcmp(wirev, &dec, sizeof(dec)), "wirev[6] %08x wirev[7] %08x wirev[8] %08x wirev[9] %08x\n", *wirev, *(wirev + 1), *(wirev + 2), *(wirev + 3));
1351 VariantInit(&v2);
1352 /* check_variant_header tests wReserved[123], so initialize to unique values.
1353 * (Could probably also do this by setting the variant to a known DECIMAL.)
1354 */
1355 V_U2(&v2).wReserved1 = 0x0123;
1356 V_U2(&v2).wReserved2 = 0x4567;
1357 V_U2(&v2).wReserved3 = 0x89ab;
1358
1359 stubMsg.Buffer = buffer;
1361 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1362 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1363 ok(!memcmp(V_DECIMALREF(&v), V_DECIMALREF(&v2), sizeof(DECIMAL)), "decimals differ\n");
1364
1365 VARIANT_UserFree(&umcb.Flags, &v2);
1366 HeapFree(GetProcessHeap(), 0, oldbuffer);
1367
1368 /*** EMPTY ***/
1369 VariantInit(&v);
1370 V_VT(&v) = VT_EMPTY;
1371
1372 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1373 ok(stubMsg.BufferLength == 20, "size %d\n", stubMsg.BufferLength);
1374
1375 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1376 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1378 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1379 wirev = (DWORD*)buffer;
1380
1381 check_variant_header(wirev, &v, stubMsg.BufferLength);
1382 VariantInit(&v2);
1383 stubMsg.Buffer = buffer;
1385 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1386 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1387
1388 VARIANT_UserFree(&umcb.Flags, &v2);
1389 HeapFree(GetProcessHeap(), 0, oldbuffer);
1390
1391 /*** NULL ***/
1392 VariantInit(&v);
1393 V_VT(&v) = VT_NULL;
1394
1395 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1396 ok(stubMsg.BufferLength == 20, "size %d\n", stubMsg.BufferLength);
1397
1398 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1399 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1401 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1402 wirev = (DWORD*)buffer;
1403
1404 check_variant_header(wirev, &v, stubMsg.BufferLength);
1405 VariantInit(&v2);
1406 stubMsg.Buffer = buffer;
1408 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1409 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1410
1411 VARIANT_UserFree(&umcb.Flags, &v2);
1412 HeapFree(GetProcessHeap(), 0, oldbuffer);
1413
1414 /*** BSTR ***/
1415 b = SysAllocString(str);
1416 VariantInit(&v);
1417 V_VT(&v) = VT_BSTR;
1418 V_BSTR(&v) = b;
1419
1420 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1421 ok(stubMsg.BufferLength == 60, "size %d\n", stubMsg.BufferLength);
1422 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1423 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1425 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1426 wirev = (DWORD*)buffer;
1427
1428 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength);
1429 ok(*wirev, "wv[5] %08x\n", *wirev); /* win2k: this is b. winxp: this is (char*)b + 1 */
1430 wirev++;
1431 check_bstr(wirev, V_BSTR(&v));
1432 VariantInit(&v2);
1433 stubMsg.Buffer = buffer;
1435 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1436 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1437 ok(SysStringByteLen(V_BSTR(&v)) == SysStringByteLen(V_BSTR(&v2)), "bstr string lens differ\n");
1438 ok(!memcmp(V_BSTR(&v), V_BSTR(&v2), SysStringByteLen(V_BSTR(&v))), "bstrs differ\n");
1439
1440 VARIANT_UserFree(&umcb.Flags, &v2);
1441 HeapFree(GetProcessHeap(), 0, oldbuffer);
1442
1443 /*** BSTR BYREF ***/
1444 VariantInit(&v);
1445 V_VT(&v) = VT_BSTR | VT_BYREF;
1446 V_BSTRREF(&v) = &b;
1447
1448 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1449 ok(stubMsg.BufferLength == 64, "size %d\n", stubMsg.BufferLength);
1450 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1451 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1453 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1454 wirev = (DWORD*)buffer;
1455
1456 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength);
1457 ok(*wirev == 0x4, "wv[5] %08x\n", *wirev);
1458 wirev++;
1459 ok(*wirev, "wv[6] %08x\n", *wirev); /* win2k: this is b. winxp: this is (char*)b + 1 */
1460 wirev++;
1461 check_bstr(wirev, b);
1463 b2[0] = 0;
1464 V_VT(&v2) = VT_BSTR | VT_BYREF;
1465 V_BSTRREF(&v2) = &b2;
1466 mem = b2;
1467 VariantInit(&v2);
1468 stubMsg.Buffer = buffer;
1470 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1471 ok(mem == b2, "BSTR should be reused\n");
1472 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1473 ok(SysStringByteLen(*V_BSTRREF(&v)) == SysStringByteLen(*V_BSTRREF(&v2)), "bstr string lens differ\n");
1474 ok(!memcmp(*V_BSTRREF(&v), *V_BSTRREF(&v2), SysStringByteLen(*V_BSTRREF(&v))), "bstrs differ\n");
1475
1477 HeapFree(GetProcessHeap(), 0, oldbuffer);
1479
1480 /*** ARRAY ***/
1481 sab.lLbound = 5;
1482 sab.cElements = 10;
1483
1484 lpsa = SafeArrayCreate(VT_R8, 1, &sab);
1485 *(DWORD *)lpsa->pvData = 0xcafebabe;
1486 *((DWORD *)lpsa->pvData + 1) = 0xdeadbeef;
1487
1488 VariantInit(&v);
1489 V_VT(&v) = VT_UI4 | VT_ARRAY;
1490 V_ARRAY(&v) = lpsa;
1491
1492 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1493 expected = 152;
1494 ok(stubMsg.BufferLength == expected || stubMsg.BufferLength == expected + 8, /* win64 */
1495 "size %u instead of %u\n", stubMsg.BufferLength, expected);
1496 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1497 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1499 ok(next == buffer + expected, "got %p expect %p\n", next, buffer + expected);
1500 wirev = (DWORD*)buffer;
1501
1502 wirev = check_variant_header(wirev, &v, expected);
1503 ok(*wirev, "wv[5] %08x\n", *wirev); /* win2k: this is lpsa. winxp: this is (char*)lpsa + 1 */
1504 wirev++;
1505 check_safearray(wirev, lpsa);
1506 VariantInit(&v2);
1507 stubMsg.Buffer = buffer;
1509 ok(next == buffer + expected, "got %p expect %p\n", next, buffer + expected);
1510 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1511 ok(SafeArrayGetDim(V_ARRAY(&v)) == SafeArrayGetDim(V_ARRAY(&v2)), "array dims differ\n");
1512 SafeArrayGetLBound(V_ARRAY(&v), 1, &bound);
1513 SafeArrayGetLBound(V_ARRAY(&v2), 1, &bound2);
1514 ok(bound == bound2, "array lbounds differ\n");
1515 SafeArrayGetUBound(V_ARRAY(&v), 1, &bound);
1516 SafeArrayGetUBound(V_ARRAY(&v2), 1, &bound2);
1517 ok(bound == bound2, "array ubounds differ\n");
1518 if (pSafeArrayGetVartype)
1519 {
1520 pSafeArrayGetVartype(V_ARRAY(&v), &vt);
1521 pSafeArrayGetVartype(V_ARRAY(&v2), &vt2);
1522 ok(vt == vt2, "array vts differ %x %x\n", vt, vt2);
1523 }
1524 VARIANT_UserFree(&umcb.Flags, &v2);
1525 HeapFree(GetProcessHeap(), 0, oldbuffer);
1526
1527 /*** ARRAY BYREF ***/
1528 VariantInit(&v);
1529 V_VT(&v) = VT_UI4 | VT_ARRAY | VT_BYREF;
1530 V_ARRAYREF(&v) = &lpsa;
1531
1532 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1533 expected = 152;
1534 ok(stubMsg.BufferLength == expected || stubMsg.BufferLength == expected + 16, /* win64 */
1535 "size %u instead of %u\n", stubMsg.BufferLength, expected);
1536 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1537 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1539 ok(next == buffer + expected, "got %p expect %p\n", next, buffer + expected);
1540 wirev = (DWORD*)buffer;
1541
1542 wirev = check_variant_header(wirev, &v, expected);
1543 ok(*wirev == 4, "wv[5] %08x\n", *wirev);
1544 wirev++;
1545 ok(*wirev, "wv[6] %08x\n", *wirev); /* win2k: this is lpsa. winxp: this is (char*)lpsa + 1 */
1546 wirev++;
1547 check_safearray(wirev, lpsa);
1548 VariantInit(&v2);
1549 stubMsg.Buffer = buffer;
1551 ok(next == buffer + expected, "got %p expect %p\n", next, buffer + expected);
1552 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1553 ok(SafeArrayGetDim(*V_ARRAYREF(&v)) == SafeArrayGetDim(*V_ARRAYREF(&v2)), "array dims differ\n");
1554 SafeArrayGetLBound(*V_ARRAYREF(&v), 1, &bound);
1555 SafeArrayGetLBound(*V_ARRAYREF(&v2), 1, &bound2);
1556 ok(bound == bound2, "array lbounds differ\n");
1557 SafeArrayGetUBound(*V_ARRAYREF(&v), 1, &bound);
1558 SafeArrayGetUBound(*V_ARRAYREF(&v2), 1, &bound2);
1559 ok(bound == bound2, "array ubounds differ\n");
1560 if (pSafeArrayGetVartype)
1561 {
1562 pSafeArrayGetVartype(*V_ARRAYREF(&v), &vt);
1563 pSafeArrayGetVartype(*V_ARRAYREF(&v2), &vt2);
1564 ok(vt == vt2, "array vts differ %x %x\n", vt, vt2);
1565 }
1566 VARIANT_UserFree(&umcb.Flags, &v2);
1567 HeapFree(GetProcessHeap(), 0, oldbuffer);
1568
1569 /*** ARRAY BYREF ***/
1570 VariantInit(&v);
1571 V_VT(&v) = VT_UI4 | VT_ARRAY | VT_BYREF;
1572 V_ARRAYREF(&v) = &lpsa;
1573 lpsa->fFeatures |= FADF_STATIC;
1574
1575 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1576 expected = 152;
1577 ok(stubMsg.BufferLength == expected || stubMsg.BufferLength == expected + 16, /* win64 */
1578 "size %u instead of %u\n", stubMsg.BufferLength, expected);
1579 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1580 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1582 ok(next == buffer + expected, "got %p expect %p\n", next, buffer + expected);
1583 wirev = (DWORD*)buffer;
1584
1585 wirev = check_variant_header(wirev, &v, expected);
1586 ok(*wirev == 4, "wv[5] %08x\n", *wirev);
1587 wirev++;
1588 ok(*wirev, "wv[6] %08x\n", *wirev); /* win2k: this is lpsa. winxp: this is (char*)lpsa + 1 */
1589 wirev++;
1590 check_safearray(wirev, lpsa);
1591 lpsa_copy = lpsa2 = SafeArrayCreate(VT_I8, 1, &sab);
1592 /* set FADF_STATIC feature to make sure lpsa2->pvData pointer changes if new data buffer is allocated */
1593 lpsa2->fFeatures |= FADF_STATIC;
1594 mem = lpsa2->pvData;
1595 V_VT(&v2) = VT_UI4 | VT_ARRAY | VT_BYREF;
1596 V_ARRAYREF(&v2) = &lpsa2;
1597 stubMsg.Buffer = buffer;
1599 ok(next == buffer + expected, "got %p expect %p\n", next, buffer + expected);
1600 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1601 ok(lpsa2 == lpsa_copy, "safearray should be reused\n");
1602 ok(mem == lpsa2->pvData, "safearray data should be reused\n");
1603 ok(SafeArrayGetDim(*V_ARRAYREF(&v)) == SafeArrayGetDim(*V_ARRAYREF(&v2)), "array dims differ\n");
1604 SafeArrayGetLBound(*V_ARRAYREF(&v), 1, &bound);
1605 SafeArrayGetLBound(*V_ARRAYREF(&v2), 1, &bound2);
1606 ok(bound == bound2, "array lbounds differ\n");
1607 SafeArrayGetUBound(*V_ARRAYREF(&v), 1, &bound);
1608 SafeArrayGetUBound(*V_ARRAYREF(&v2), 1, &bound2);
1609 ok(bound == bound2, "array ubounds differ\n");
1610 if (pSafeArrayGetVartype)
1611 {
1612 pSafeArrayGetVartype(*V_ARRAYREF(&v), &vt);
1613 pSafeArrayGetVartype(*V_ARRAYREF(&v2), &vt2);
1614 ok(vt == vt2, "array vts differ %x %x\n", vt, vt2);
1615 }
1616 lpsa2->fFeatures &= ~FADF_STATIC;
1618 ok(hr == S_OK, "got 0x%08x\n", hr);
1619 HeapFree(GetProcessHeap(), 0, oldbuffer);
1620 lpsa->fFeatures &= ~FADF_STATIC;
1621 hr = SafeArrayDestroy(lpsa);
1622 ok(hr == S_OK, "got 0x%08x\n", hr);
1623
1624 /*** VARIANT BYREF ***/
1625 VariantInit(&v);
1626 VariantInit(&v2);
1627 V_VT(&v2) = VT_R8;
1628 V_R8(&v2) = 3.1415;
1629 V_VT(&v) = VT_VARIANT | VT_BYREF;
1630 V_VARIANTREF(&v) = &v2;
1631
1632 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1633 ok(stubMsg.BufferLength == 64, "size %d\n", stubMsg.BufferLength);
1634 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1635 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1636 memset(buffer, 0xcc, stubMsg.BufferLength);
1638 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1639 wirev = (DWORD*)buffer;
1640 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength);
1641
1642 ok(*wirev == sizeof(VARIANT), "wv[5] %08x\n", *wirev);
1643 wirev++;
1644 ok(*wirev == ('U' | 's' << 8 | 'e' << 16 | 'r' << 24), "wv[6] %08x\n", *wirev); /* 'User' */
1645 wirev++;
1646 ok(*wirev == 0xcccccccc, "wv[7] %08x\n", *wirev); /* pad */
1647 wirev++;
1648 wirev = check_variant_header(wirev, &v2, stubMsg.BufferLength - 32);
1649 ok(*wirev == 0xcccccccc, "wv[13] %08x\n", *wirev); /* pad for VT_R8 */
1650 wirev++;
1651 ok(*(double*)wirev == V_R8(&v2), "wv[6] %08x wv[7] %08x\n", *wirev, *(wirev+1));
1652 VariantInit(&v3);
1653 stubMsg.Buffer = buffer;
1655 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1656 ok(V_VT(&v) == V_VT(&v3), "got vt %d expect %d\n", V_VT(&v), V_VT(&v3));
1657 ok(V_VT(V_VARIANTREF(&v)) == V_VT(V_VARIANTREF(&v3)), "vts differ %x %x\n",
1659 ok(V_R8(V_VARIANTREF(&v)) == V_R8(V_VARIANTREF(&v3)), "r8s differ\n");
1660 VARIANT_UserFree(&umcb.Flags, &v3);
1661 HeapFree(GetProcessHeap(), 0, oldbuffer);
1662
1663 /*** UNKNOWN ***/
1664 heap_unknown = HeapAlloc(GetProcessHeap(), 0, sizeof(*heap_unknown));
1665 heap_unknown->IUnknown_iface.lpVtbl = &HeapUnknown_Vtbl;
1666 heap_unknown->refs = 1;
1667 VariantInit(&v);
1668 VariantInit(&v2);
1669 V_VT(&v) = VT_UNKNOWN;
1670 V_UNKNOWN(&v) = &heap_unknown->IUnknown_iface;
1671
1672 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1673 ok(stubMsg.BufferLength > 40, "size %d\n", stubMsg.BufferLength);
1674 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1675 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1676 memset(buffer, 0xcc, stubMsg.BufferLength);
1679 ok(heap_unknown->refs == 2, "got refcount %d\n", heap_unknown->refs);
1680 wirev = (DWORD*)buffer;
1681 wirev = check_variant_header(wirev, &v, next - buffer);
1682
1683 ok(*wirev == (DWORD_PTR)V_UNKNOWN(&v) /* Win9x */ ||
1684 *wirev == (DWORD_PTR)V_UNKNOWN(&v) + 1 /* NT */, "wv[5] %08x\n", *wirev);
1685 wirev++;
1686 ok(*wirev == next - buffer - 0x20, "wv[6] %08x\n", *wirev);
1687 wirev++;
1688 ok(*wirev == next - buffer - 0x20, "wv[7] %08x\n", *wirev);
1689 wirev++;
1690 ok(*wirev == 0x574f454d, "wv[8] %08x\n", *wirev);
1691 VariantInit(&v3);
1692 V_VT(&v3) = VT_UNKNOWN;
1693 V_UNKNOWN(&v3) = &heap_unknown->IUnknown_iface;
1694 IUnknown_AddRef(V_UNKNOWN(&v3));
1695 stubMsg.Buffer = buffer;
1697 ok(heap_unknown->refs == 3, "got refcount %d\n", heap_unknown->refs);
1699 ok(V_VT(&v) == V_VT(&v3), "got vt %d expect %d\n", V_VT(&v), V_VT(&v3));
1700 ok(V_UNKNOWN(&v) == V_UNKNOWN(&v3), "got %p expect %p\n", V_UNKNOWN(&v), V_UNKNOWN(&v3));
1701 VARIANT_UserFree(&umcb.Flags, &v3);
1702 ok(heap_unknown->refs == 1, "%d refcounts of IUnknown leaked\n", heap_unknown->refs - 1);
1703 IUnknown_Release(&heap_unknown->IUnknown_iface);
1704 HeapFree(GetProcessHeap(), 0, oldbuffer);
1705
1706 /*** NULL UNKNOWN ***/
1707 VariantInit(&v);
1708 V_VT(&v) = VT_UNKNOWN;
1709 V_UNKNOWN(&v) = NULL;
1710
1711 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1712 ok(stubMsg.BufferLength >= 24, "size %d\n", stubMsg.BufferLength);
1713 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1714 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1715 memset(buffer, 0xcc, stubMsg.BufferLength);
1717 wirev = (DWORD*)buffer;
1718 wirev = check_variant_header(wirev, &v, next - buffer);
1719 ok(*wirev == 0, "wv[5] %08x\n", *wirev);
1720
1721 VariantInit(&v2);
1722 stubMsg.Buffer = buffer;
1724 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1725 ok(V_UNKNOWN(&v2) == NULL, "got %p expect NULL\n", V_UNKNOWN(&v2));
1726 VARIANT_UserFree(&umcb.Flags, &v2);
1727 HeapFree(GetProcessHeap(), 0, oldbuffer);
1728
1729 /*** UNKNOWN BYREF ***/
1730 heap_unknown = HeapAlloc(GetProcessHeap(), 0, sizeof(*heap_unknown));
1731 heap_unknown->IUnknown_iface.lpVtbl = &HeapUnknown_Vtbl;
1732 heap_unknown->refs = 1;
1733 VariantInit(&v);
1734 VariantInit(&v2);
1735 V_VT(&v) = VT_UNKNOWN | VT_BYREF;
1736 V_UNKNOWNREF(&v) = (IUnknown **)&heap_unknown;
1737
1738 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1739 ok(stubMsg.BufferLength >= 44, "size %d\n", stubMsg.BufferLength);
1740 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1741 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1742 memset(buffer, 0xcc, stubMsg.BufferLength);
1743 ok(heap_unknown->refs == 1, "got refcount %d\n", heap_unknown->refs);
1746 ok(heap_unknown->refs == 2, "got refcount %d\n", heap_unknown->refs);
1747 wirev = (DWORD*)buffer;
1748 wirev = check_variant_header(wirev, &v, next - buffer);
1749
1750 ok(*wirev == 4, "wv[5] %08x\n", *wirev);
1751 wirev++;
1752 ok(*wirev == (DWORD_PTR)heap_unknown /* Win9x, Win2000 */ ||
1753 *wirev == (DWORD_PTR)heap_unknown + 1 /* XP */, "wv[6] %08x\n", *wirev);
1754 wirev++;
1755 ok(*wirev == next - buffer - 0x24, "wv[7] %08x\n", *wirev);
1756 wirev++;
1757 ok(*wirev == next - buffer - 0x24, "wv[8] %08x\n", *wirev);
1758 wirev++;
1759 ok(*wirev == 0x574f454d, "wv[9] %08x\n", *wirev);
1760
1761 VariantInit(&v3);
1762 V_VT(&v3) = VT_UNKNOWN;
1763 V_UNKNOWN(&v3) = &heap_unknown->IUnknown_iface;
1764 IUnknown_AddRef(V_UNKNOWN(&v3));
1765 stubMsg.Buffer = buffer;
1767 ok(heap_unknown->refs == 2, "got refcount %d\n", heap_unknown->refs);
1768 ok(V_VT(&v) == V_VT(&v3), "got vt %d expect %d\n", V_VT(&v), V_VT(&v3));
1769 ok(*V_UNKNOWNREF(&v) == *V_UNKNOWNREF(&v3), "got %p expect %p\n", *V_UNKNOWNREF(&v), *V_UNKNOWNREF(&v3));
1770 VARIANT_UserFree(&umcb.Flags, &v3);
1771 ok(heap_unknown->refs == 1, "%d refcounts of IUnknown leaked\n", heap_unknown->refs - 1);
1772 IUnknown_Release(&heap_unknown->IUnknown_iface);
1773 HeapFree(GetProcessHeap(), 0, oldbuffer);
1774
1775 unk = NULL;
1776 VariantInit(&v);
1777 V_VT(&v) = VT_UNKNOWN | VT_BYREF;
1778 V_UNKNOWNREF(&v) = &unk;
1779
1780 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1781 ok(stubMsg.BufferLength >= 28, "size %d\n", stubMsg.BufferLength);
1782 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1783 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1784 memset(buffer, 0xcc, stubMsg.BufferLength);
1786 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1787 wirev = (DWORD*)buffer;
1788 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength);
1789
1790 ok(*wirev == 4, "wv[5] %08x\n", *wirev);
1791
1792 VariantInit(&v2);
1793 stubMsg.Buffer = buffer;
1795 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1796 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v2), V_VT(&v));
1797 ok(!*V_UNKNOWNREF(&v2), "got %p expect NULL\n", *V_UNKNOWNREF(&v2));
1798 VARIANT_UserFree(&umcb.Flags, &v2);
1799 HeapFree(GetProcessHeap(), 0, oldbuffer);
1800}
1801
1802
1803START_TEST(usrmarshal)
1804{
1805 HANDLE hOleaut32 = GetModuleHandleA("oleaut32.dll");
1806#define GETPTR(func) p##func = (void*)GetProcAddress(hOleaut32, #func)
1810#undef GETPTR
1811
1812 if (!pSafeArrayGetIID || !pSafeArrayGetVartype)
1813 win_skip("SafeArrayGetIID and/or SafeArrayGetVartype is not available, some tests will be skipped\n");
1814
1816
1820
1822}
ios_base &_STLP_CALL dec(ios_base &__s)
Definition: _ios_base.h:321
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
#define ok(value,...)
Definition: atltest.h:57
#define broken(x)
Definition: atltest.h:178
#define START_TEST(x)
Definition: atltest.h:75
#define ARRAY_SIZE(A)
Definition: main.h:20
const GUID IID_IUnknown
#define E_INVALIDARG
Definition: ddrawi.h:101
#define NULL
Definition: types.h:112
#define GetProcessHeap()
Definition: compat.h:736
struct tagVARIANT VARIANT
Definition: compat.h:2377
#define HeapAlloc
Definition: compat.h:733
WCHAR OLECHAR
Definition: compat.h:2292
struct tagSAFEARRAYBOUND SAFEARRAYBOUND
static __inline const char * wine_dbgstr_longlong(ULONGLONG ll)
Definition: compat.h:49
OLECHAR * BSTR
Definition: compat.h:2293
unsigned short VARTYPE
Definition: compat.h:2254
#define HeapFree(x, y, z)
Definition: compat.h:735
@ VT_UI8
Definition: compat.h:2315
@ VT_BSTR
Definition: compat.h:2303
@ VT_INT
Definition: compat.h:2316
@ VT_R4
Definition: compat.h:2299
@ VT_UINT_PTR
Definition: compat.h:2328
@ VT_NULL
Definition: compat.h:2296
@ VT_UNKNOWN
Definition: compat.h:2308
@ VT_BYREF
Definition: compat.h:2342
@ VT_UI2
Definition: compat.h:2312
@ VT_DECIMAL
Definition: compat.h:2309
@ VT_ARRAY
Definition: compat.h:2341
@ VT_R8
Definition: compat.h:2300
@ VT_CY
Definition: compat.h:2301
@ VT_VARIANT
Definition: compat.h:2307
@ VT_I8
Definition: compat.h:2314
@ VT_I1
Definition: compat.h:2310
@ VT_I4
Definition: compat.h:2298
@ VT_INT_PTR
Definition: compat.h:2327
@ VT_DATE
Definition: compat.h:2302
@ VT_BOOL
Definition: compat.h:2306
@ VT_I2
Definition: compat.h:2297
@ VT_UI4
Definition: compat.h:2313
@ VT_UINT
Definition: compat.h:2317
@ VT_EMPTY
Definition: compat.h:2295
@ VT_RECORD
Definition: compat.h:2326
@ VT_DISPATCH
Definition: compat.h:2304
@ VT_UI1
Definition: compat.h:2311
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:812
GUID guid
Definition: version.c:147
static REFPROPVARIANT PROPVAR_CHANGE_FLAGS VARTYPE vt
Definition: suminfo.c:91
HRESULT WINAPI CoInitialize(LPVOID lpReserved)
Definition: compobj.c:1964
void WINAPI DECLSPEC_HOTPATCH CoUninitialize(void)
Definition: compobj.c:2067
HRESULT WINAPI SafeArrayGetUBound(SAFEARRAY *psa, UINT nDim, LONG *plUbound)
Definition: safearray.c:1033
HRESULT WINAPI SafeArrayDestroyDescriptor(SAFEARRAY *psa)
Definition: safearray.c:755
HRESULT WINAPI SafeArrayGetElement(SAFEARRAY *psa, LONG *rgIndices, void *pvData)
Definition: safearray.c:947
UINT WINAPI SafeArrayGetDim(SAFEARRAY *psa)
Definition: safearray.c:1094
HRESULT WINAPI SafeArrayGetIID(SAFEARRAY *psa, GUID *pGuid)
Definition: safearray.c:1670
HRESULT WINAPI SafeArrayGetLBound(SAFEARRAY *psa, UINT nDim, LONG *plLbound)
Definition: safearray.c:1066
HRESULT WINAPI SafeArrayDestroyData(SAFEARRAY *psa)
Definition: safearray.c:1256
HRESULT WINAPI SafeArrayAllocDescriptor(UINT cDims, SAFEARRAY **ppsaOut)
Definition: safearray.c:476
HRESULT WINAPI SafeArrayDestroy(SAFEARRAY *psa)
Definition: safearray.c:1347
SAFEARRAY *WINAPI SafeArrayCreate(VARTYPE vt, UINT cDims, SAFEARRAYBOUND *rgsabound)
Definition: safearray.c:600
HRESULT WINAPI SafeArrayAllocData(SAFEARRAY *psa)
Definition: safearray.c:557
HRESULT WINAPI SafeArrayGetVartype(SAFEARRAY *psa, VARTYPE *pvt)
Definition: safearray.c:1534
HRESULT WINAPI SafeArrayPutElement(SAFEARRAY *psa, LONG *rgIndices, void *pvData)
Definition: safearray.c:864
void WINAPI VARIANT_UserFree(ULONG *pFlags, VARIANT *pvar)
Definition: usrmarshal.c:679
unsigned char *WINAPI LPSAFEARRAY_UserMarshal(ULONG *pFlags, unsigned char *Buffer, LPSAFEARRAY *ppsa)
Definition: usrmarshal.c:972
void WINAPI BSTR_UserFree(ULONG *pFlags, BSTR *pstr)
Definition: usrmarshal.c:189
unsigned char *WINAPI VARIANT_UserUnmarshal(ULONG *pFlags, unsigned char *Buffer, VARIANT *pvar)
Definition: usrmarshal.c:534
ULONG WINAPI LPSAFEARRAY_UserSize(ULONG *pFlags, ULONG StartingSize, LPSAFEARRAY *ppsa)
Definition: usrmarshal.c:864
ULONG WINAPI BSTR_UserSize(ULONG *pFlags, ULONG Start, BSTR *pstr)
Definition: usrmarshal.c:136
unsigned char *WINAPI VARIANT_UserMarshal(ULONG *pFlags, unsigned char *Buffer, VARIANT *pvar)
Definition: usrmarshal.c:420
ULONG WINAPI VARIANT_UserSize(ULONG *pFlags, ULONG Start, VARIANT *pvar)
Definition: usrmarshal.c:397
unsigned char *WINAPI LPSAFEARRAY_UserUnmarshal(ULONG *pFlags, unsigned char *Buffer, LPSAFEARRAY *ppsa)
Definition: usrmarshal.c:1124
static DWORD elem_wire_size(LPSAFEARRAY lpsa, SF_TYPE sftype)
Definition: usrmarshal.c:798
void WINAPI LPSAFEARRAY_UserFree(ULONG *pFlags, LPSAFEARRAY *ppsa)
Definition: usrmarshal.c:1308
unsigned char *WINAPI BSTR_UserMarshal(ULONG *pFlags, unsigned char *Buffer, BSTR *pstr)
Definition: usrmarshal.c:146
unsigned char *WINAPI BSTR_UserUnmarshal(ULONG *pFlags, unsigned char *Buffer, BSTR *pstr)
Definition: usrmarshal.c:168
HRESULT WINAPI VarBstrCmp(BSTR pbstrLeft, BSTR pbstrRight, LCID lcid, DWORD dwFlags)
Definition: vartype.c:7158
HRESULT WINAPI VarDecFromI4(LONG lIn, DECIMAL *pDecOut)
Definition: vartype.c:4131
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
const GLdouble * v
Definition: gl.h:2040
GLdouble s
Definition: gl.h:2039
GLuint GLuint GLsizei GLenum const GLvoid * indices
Definition: gl.h:1545
GLuint buffer
Definition: glext.h:5915
GLsizeiptr size
Definition: glext.h:5919
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLboolean GLenum GLenum GLvoid * values
Definition: glext.h:5666
GLfloat GLfloat p
Definition: glext.h:8902
GLfloat GLfloat GLfloat GLfloat v3
Definition: glext.h:6064
GLenum GLsizei len
Definition: glext.h:6722
GLfloat GLfloat GLfloat v2
Definition: glext.h:6063
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
VOID WINAPI CoTaskMemFree(LPVOID ptr)
Definition: ifs.c:442
LPVOID WINAPI CoTaskMemAlloc(SIZE_T size)
Definition: ifs.c:426
REFIID riid
Definition: atlbase.h:39
REFIID LPVOID * ppv
Definition: atlbase.h:39
#define S_OK
Definition: intsafe.h:52
#define FAILED(hr)
Definition: intsafe.h:51
#define d
Definition: ke_i.h:81
#define b
Definition: ke_i.h:79
static CRYPT_DATA_BLOB b2[]
Definition: msg.c:582
BOOL expected
Definition: store.c:2063
#define todo_wine
Definition: custom.c:89
static const char mbstate_t *static wchar_t const char mbstate_t *static const wchar_t int *static double
Definition: string.c:91
static void WINAPI user_free(void *p)
Definition: usrmarshal.c:60
static TestUnknown * impl_from_IUnknown(IUnknown *iface)
Definition: usrmarshal.c:582
static void init_user_marshal_cb(USER_MARSHAL_CB *umcb, PMIDL_STUB_MESSAGE stub_msg, PRPC_MESSAGE rpc_msg, unsigned char *buffer, unsigned int size, MSHCTX context)
Definition: usrmarshal.c:66
static void *WINAPI user_allocate(SIZE_T size)
Definition: usrmarshal.c:53
static HMODULE hOleaut32
Definition: olefont.c:50
static void test_marshal_BSTR(void)
Definition: usrmarshal.c:740
static SF_TYPE get_union_type(SAFEARRAY *psa)
Definition: usrmarshal.c:53
static void * alloc_aligned(SIZE_T size, void **buf)
Definition: usrmarshal.c:942
static void test_marshal_LPSAFEARRAY(void)
Definition: usrmarshal.c:257
static void check_bstr(void *buffer, BSTR b)
Definition: usrmarshal.c:719
static void check_safearray(void *buffer, LPSAFEARRAY lpsa)
Definition: usrmarshal.c:148
#define GETPTR(func)
static ULONG WINAPI HeapUnknown_AddRef(IUnknown *iface)
Definition: usrmarshal.c:887
static DWORD * check_variant_header(DWORD *wirev, VARIANT *v, ULONG size)
Definition: usrmarshal.c:919
static ULONG WINAPI HeapUnknown_Release(IUnknown *iface)
Definition: usrmarshal.c:893
#define V_U2(A)
Definition: usrmarshal.c:36
static ULONG get_cell_count(const SAFEARRAY *psa)
Definition: usrmarshal.c:107
static HRESULT WINAPI HeapUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
Definition: usrmarshal.c:875
static void test_marshal_VARIANT(void)
Definition: usrmarshal.c:948
static GUID *static VARTYPE *static LCID
Definition: usrmarshal.c:51
static const IUnknownVtbl HeapUnknown_Vtbl
Definition: usrmarshal.c:901
static SCRIPT_CACHE SCRIPT_ANALYSIS * psa
Definition: usp10.c:64
unsigned __int3264 UINT_PTR
Definition: mstsclib_h.h:274
#define DWORD
Definition: nt_native.h:44
UINT WINAPI SysStringByteLen(BSTR str)
Definition: oleaut.c:215
BSTR WINAPI SysAllocString(LPCOLESTR str)
Definition: oleaut.c:238
UINT WINAPI SysStringLen(BSTR str)
Definition: oleaut.c:196
void WINAPI DECLSPEC_HOTPATCH SysFreeString(BSTR str)
Definition: oleaut.c:271
BSTR WINAPI DECLSPEC_HOTPATCH SysAllocStringByteLen(LPCSTR str, UINT len)
Definition: oleaut.c:428
#define V_I8(A)
Definition: oleauto.h:249
#define V_BOOL(A)
Definition: oleauto.h:224
#define V_ARRAY(A)
Definition: oleauto.h:222
#define V_ARRAYREF(A)
Definition: oleauto.h:223
#define V_BSTRREF(A)
Definition: oleauto.h:227
#define V_UNKNOWN(A)
Definition: oleauto.h:281
#define V_UI4REF(A)
Definition: oleauto.h:271
#define VARCMP_EQ
Definition: oleauto.h:658
#define V_UNKNOWNREF(A)
Definition: oleauto.h:282
#define V_I1(A)
Definition: oleauto.h:243
#define V_VARIANTREF(A)
Definition: oleauto.h:283
#define V_VT(A)
Definition: oleauto.h:211
#define V_BSTR(A)
Definition: oleauto.h:226
#define V_BYREF(A)
Definition: oleauto.h:228
#define V_I4(A)
Definition: oleauto.h:247
#define V_R4(A)
Definition: oleauto.h:260
#define V_DECIMAL(A)
Definition: oleauto.h:236
#define V_UI4(A)
Definition: oleauto.h:270
#define V_R8(A)
Definition: oleauto.h:262
#define V_I2REF(A)
Definition: oleauto.h:246
#define V_DECIMALREF(A)
Definition: oleauto.h:238
#define V_R8REF(A)
Definition: oleauto.h:263
#define V_I2(A)
Definition: oleauto.h:245
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
#define IsEqualGUID(rguid1, rguid2)
Definition: guiddef.h:147
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:95
#define REFIID
Definition: guiddef.h:118
static unsigned __int64 next
Definition: rand_nt.c:6
const WCHAR * str
#define NDR_LOCAL_DATA_REPRESENTATION
Definition: rpcndr.h:107
@ USER_MARSHAL_CB_BUFFER_SIZE
Definition: rpcndr.h:324
@ USER_MARSHAL_CB_UNMARSHALL
Definition: rpcndr.h:326
#define USER_MARSHAL_CB_SIGNATURE
Definition: rpcndr.h:318
#define win_skip
Definition: test.h:164
#define memset(x, y, z)
Definition: compat.h:39
HRESULT hr
Definition: shlfolder.c:183
IUnknown IUnknown_iface
Definition: marshal.c:2780
ULONG refs
Definition: marshal.c:2781
unsigned char * Buffer
Definition: rpcndr.h:203
ULONG BufferLength
Definition: rpcndr.h:207
unsigned char * BufferEnd
Definition: rpcndr.h:205
PRPC_MESSAGE RpcMsg
Definition: rpcndr.h:202
unsigned char * BufferStart
Definition: rpcndr.h:204
unsigned int BufferLength
Definition: rpcdcep.h:41
void * Buffer
Definition: rpcdcep.h:40
USER_MARSHAL_CB_TYPE CBType
Definition: rpcndr.h:336
PFORMAT_STRING pReserve
Definition: rpcndr.h:334
ULONG Signature
Definition: rpcndr.h:335
PMIDL_STUB_MESSAGE pStubMsg
Definition: rpcndr.h:333
Definition: http.c:7252
Definition: mem.c:349
USHORT wReserved
Definition: compat.h:2268
USHORT fFeatures
Definition: compat.h:2356
SAFEARRAYBOUND rgsabound[1]
Definition: compat.h:2360
ULONG cLocks
Definition: compat.h:2358
USHORT cDims
Definition: compat.h:2355
PVOID pvData
Definition: compat.h:2359
ULONG cbElements
Definition: compat.h:2357
#define max(a, b)
Definition: svc.c:63
uint32_t DWORD_PTR
Definition: typedefs.h:65
int64_t LONGLONG
Definition: typedefs.h:68
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define MAKELONG(a, b)
Definition: typedefs.h:249
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
void WINAPI VariantInit(VARIANTARG *pVarg)
Definition: variant.c:568
#define HRESULT
Definition: msvc.h:7
#define WINAPI
Definition: msvc.h:6
#define E_NOINTERFACE
Definition: winerror.h:2364
__wchar_t WCHAR
Definition: xmlstorage.h:180