ReactOS 0.4.17-dev-357-ga8f14ff
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
33typedef struct
34{
35 IUnknown IUnknown_iface;
36 ULONG refs;
38
39static const IUnknownVtbl HeapUnknown_Vtbl;
40
41static inline SF_TYPE get_union_type(SAFEARRAY *psa)
42{
43 VARTYPE vt;
44 HRESULT hr;
45
47 if (FAILED(hr))
48 {
49 if(psa->fFeatures & FADF_VARIANT) return SF_VARIANT;
50
51 switch(psa->cbElements)
52 {
53 case 1: vt = VT_I1; break;
54 case 2: vt = VT_I2; break;
55 case 4: vt = VT_I4; break;
56 case 8: vt = VT_I8; break;
57 default: return 0;
58 }
59 }
60
61 if (psa->fFeatures & FADF_HAVEIID)
62 return SF_HAVEIID;
63
64 switch (vt)
65 {
66 case VT_I1:
67 case VT_UI1: return SF_I1;
68 case VT_BOOL:
69 case VT_I2:
70 case VT_UI2: return SF_I2;
71 case VT_INT:
72 case VT_UINT:
73 case VT_I4:
74 case VT_UI4:
75 case VT_R4: return SF_I4;
76 case VT_DATE:
77 case VT_CY:
78 case VT_R8:
79 case VT_I8:
80 case VT_UI8: return SF_I8;
81 case VT_INT_PTR:
82 case VT_UINT_PTR: return (sizeof(UINT_PTR) == 4 ? SF_I4 : SF_I8);
83 case VT_BSTR: return SF_BSTR;
84 case VT_DISPATCH: return SF_DISPATCH;
85 case VT_VARIANT: return SF_VARIANT;
86 case VT_UNKNOWN: return SF_UNKNOWN;
87 /* Note: Return a non-zero size to indicate vt is valid. The actual size
88 * of a UDT is taken from the result of IRecordInfo_GetSize().
89 */
90 case VT_RECORD: return SF_RECORD;
91 default: return SF_ERROR;
92 }
93}
94
96{
97 const SAFEARRAYBOUND* psab = psa->rgsabound;
98 USHORT cCount = psa->cDims;
99 ULONG ulNumCells = 1;
100
101 while (cCount--)
102 {
103 if (!psab->cElements)
104 return 0;
105 ulNumCells *= psab->cElements;
106 psab++;
107 }
108 return ulNumCells;
109}
110
111static DWORD elem_wire_size(LPSAFEARRAY lpsa, SF_TYPE sftype)
112{
113 switch (sftype)
114 {
115 case SF_HAVEIID:
116 case SF_UNKNOWN:
117 case SF_DISPATCH:
118 case SF_BSTR:
119 return sizeof(DWORD);
120
121 default:
122 return lpsa->cbElements;
123 }
124}
125
126static void check_safearray(void *buffer, LPSAFEARRAY lpsa)
127{
128 unsigned char *wiresa = buffer;
129 const SAFEARRAYBOUND *bounds;
130 VARTYPE vt;
131 SF_TYPE sftype;
132 ULONG cell_count;
133 int i;
134
135 if(!lpsa)
136 {
137 ok(*(DWORD *)wiresa == 0, "wiresa + 0x0 should be NULL instead of 0x%08lx\n", *(DWORD *)wiresa);
138 return;
139 }
140
141 /* If FADF_HAVEIID is set, VT will be 0. */
142 if((lpsa->fFeatures & FADF_HAVEIID) || FAILED(SafeArrayGetVartype(lpsa, &vt)))
143 vt = 0;
144
145 sftype = get_union_type(lpsa);
146 cell_count = get_cell_count(lpsa);
147
148 ok(*(DWORD *)wiresa, "wiresa + 0x0 should be non-NULL instead of 0x%08lx\n", *(DWORD *)wiresa); /* win2k: this is lpsa. winxp: this is 0x00000001 */
149 wiresa += sizeof(DWORD);
150 ok(*(DWORD *)wiresa == lpsa->cDims, "wiresa + 0x4 should be lpsa->cDims instead of 0x%08lx\n", *(DWORD *)wiresa);
151 wiresa += sizeof(DWORD);
152 ok(*(WORD *)wiresa == lpsa->cDims, "wiresa + 0x8 should be lpsa->cDims instead of 0x%04x\n", *(WORD *)wiresa);
153 wiresa += sizeof(WORD);
154 ok(*(WORD *)wiresa == lpsa->fFeatures, "wiresa + 0xa should be lpsa->fFeatures instead of 0x%08x\n", *(WORD *)wiresa);
155 wiresa += sizeof(WORD);
156 ok(*(DWORD *)wiresa == elem_wire_size(lpsa, sftype), "wiresa + 0xc should be 0x%08lx instead of 0x%08lx\n", elem_wire_size(lpsa, sftype), *(DWORD *)wiresa);
157 wiresa += sizeof(DWORD);
158 ok(*(WORD *)wiresa == lpsa->cLocks, "wiresa + 0x10 should be lpsa->cLocks instead of 0x%04x\n", *(WORD *)wiresa);
159 wiresa += sizeof(WORD);
160 ok(*(WORD *)wiresa == vt, "wiresa + 0x12 should be %04x instead of 0x%04x\n", vt, *(WORD *)wiresa);
161 wiresa += sizeof(WORD);
162 ok(*(DWORD *)wiresa == sftype, "wiresa + 0x14 should be %08lx instead of 0x%08lx\n", (DWORD)sftype, *(DWORD *)wiresa);
163 wiresa += sizeof(DWORD);
164 ok(*(DWORD *)wiresa == cell_count, "wiresa + 0x18 should be %lu instead of %lu\n", cell_count, *(DWORD *)wiresa);
165 wiresa += sizeof(DWORD);
166 ok(*(DWORD *)wiresa, "wiresa + 0x1c should be non-zero instead of 0x%08lx\n", *(DWORD *)wiresa);
167 wiresa += sizeof(DWORD);
168 if(sftype == SF_HAVEIID)
169 {
170 GUID guid;
171 SafeArrayGetIID(lpsa, &guid);
172 ok(IsEqualGUID(&guid, wiresa), "guid mismatch\n");
173 wiresa += sizeof(GUID);
174 }
175
176 /* bounds are marshaled in natural dimensions order */
177 bounds = (SAFEARRAYBOUND*)wiresa;
178 for(i=0; i<lpsa->cDims; i++)
179 {
180 ok(memcmp(bounds, &lpsa->rgsabound[lpsa->cDims-i-1], sizeof(SAFEARRAYBOUND)) == 0,
181 "bounds mismatch for dimension %d, got (%ld,%ld), expected (%ld,%ld)\n", i,
182 bounds->lLbound, bounds->cElements, lpsa->rgsabound[lpsa->cDims-i-1].lLbound,
183 lpsa->rgsabound[lpsa->cDims-i-1].cElements);
184 bounds++;
185 }
186
187 wiresa += sizeof(lpsa->rgsabound[0]) * lpsa->cDims;
188
189 ok(*(DWORD *)wiresa == cell_count, "wiresa + 0x28 should be %lu instead of %lu\n", cell_count, *(DWORD*)wiresa);
190 wiresa += sizeof(DWORD);
191 /* elements are now pointed to by wiresa */
192}
193
195{
196 ok(0, "unexpected user_allocate call\n");
197 return CoTaskMemAlloc(size);
198}
199
200static void WINAPI user_free(void *p)
201{
202 ok(0, "unexpected user_free call\n");
204}
205
207 PMIDL_STUB_MESSAGE stub_msg,
208 PRPC_MESSAGE rpc_msg, unsigned char *buffer,
209 unsigned int size, MSHCTX context)
210{
211 memset(rpc_msg, 0, sizeof(*rpc_msg));
212 rpc_msg->Buffer = buffer;
213 rpc_msg->BufferLength = size;
214
215 memset(stub_msg, 0, sizeof(*stub_msg));
216 stub_msg->RpcMsg = rpc_msg;
217 stub_msg->Buffer = buffer;
218 stub_msg->pfnAllocate = user_allocate;
219 stub_msg->pfnFree = user_free;
220
221 memset(umcb, 0, sizeof(*umcb));
223 umcb->pStubMsg = stub_msg;
226}
227
229{
230 HeapUnknown *heap_unknown[10];
231 unsigned char *buffer, *next;
232 ULONG size, expected, size2;
233 LPSAFEARRAY lpsa;
234 LPSAFEARRAY lpsa2 = NULL;
235 SAFEARRAYBOUND sab[2];
237 MIDL_STUB_MESSAGE stub_msg;
238 USER_MARSHAL_CB umcb;
239 HRESULT hr;
240 VARTYPE vt, vt2;
241 OLECHAR *values[10];
242 int expected_bstr_size;
243 int i;
244 LONG indices[1];
245
246 sab[0].lLbound = 5;
247 sab[0].cElements = 10;
248
249 lpsa = SafeArrayCreate(VT_I2, 1, sab);
250 *(DWORD *)lpsa->pvData = 0xcafebabe;
251
252 lpsa->cLocks = 7;
253 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
254 size = LPSAFEARRAY_UserSize(&umcb.Flags, 1, &lpsa);
255 expected = (44 + 1 + sizeof(ULONG) - 1) & ~(sizeof(ULONG) - 1);
256 expected += sab[0].cElements * sizeof(USHORT);
257 ok(size == expected || size == expected + 12, /* win64 */
258 "size should be %lu bytes, not %lu\n", expected, size);
259 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
260 size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
261 expected = 44 + sab[0].cElements * sizeof(USHORT);
262 ok(size == expected || size == expected + 12, /* win64 */
263 "size should be %lu bytes, not %lu\n", expected, size);
265 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
266 next = LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
267 ok(next - buffer == expected, "Marshaled %lu bytes, expected %lu\n", (ULONG) (next - buffer), expected);
268 ok(lpsa->cLocks == 7, "got lock count %lu\n", lpsa->cLocks);
269
270 check_safearray(buffer, lpsa);
271
272 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
273 LPSAFEARRAY_UserUnmarshal(&umcb.Flags, buffer, &lpsa2);
274 ok(lpsa2 != NULL, "LPSAFEARRAY didn't unmarshal\n");
275 SafeArrayGetVartype(lpsa, &vt);
276 SafeArrayGetVartype(lpsa2, &vt2);
277 ok(vt == vt2, "vts differ %x %x\n", vt, vt2);
278 ok(lpsa2->cLocks == 0, "got lock count %lu, expected 0\n", lpsa2->cLocks);
279 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
280 LPSAFEARRAY_UserFree(&umcb.Flags, &lpsa2);
281 ok(!lpsa2, "lpsa2 was not set to 0 by LPSAFEARRAY_UserFree\n");
283 lpsa->cLocks = 0;
284 hr = SafeArrayDestroy(lpsa);
285 ok(hr == S_OK, "got 0x%08lx\n", hr);
286
287 /* use two dimensions */
288 sab[0].lLbound = 5;
289 sab[0].cElements = 10;
290 sab[1].lLbound = 1;
291 sab[1].cElements = 2;
292
293 lpsa = SafeArrayCreate(VT_I2, 2, sab);
294 *(DWORD *)lpsa->pvData = 0xcafebabe;
295
296 lpsa->cLocks = 7;
297 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
298 size = LPSAFEARRAY_UserSize(&umcb.Flags, 1, &lpsa);
299 expected = (44 + 1 + +sizeof(SAFEARRAYBOUND) + sizeof(ULONG) - 1) & ~(sizeof(ULONG) - 1);
300 expected += max(sab[0].cElements, sab[1].cElements) * lpsa->cDims * sizeof(USHORT);
301 ok(size == expected || size == expected + 12, /* win64 */
302 "size should be %lu bytes, not %lu\n", expected, size);
303 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
304 size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
305 expected = 52 + max(sab[0].cElements, sab[1].cElements) * lpsa->cDims * sizeof(USHORT);
306 ok(size == expected || size == expected + 12, /* win64 */
307 "size should be %lu bytes, not %lu\n", expected, size);
309 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
310 next = LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
311 ok(next - buffer == expected, "Marshaled %lu bytes, expected %lu\n", (ULONG) (next - buffer), expected);
312 ok(lpsa->cLocks == 7, "got lock count %lu\n", lpsa->cLocks);
313
314 check_safearray(buffer, lpsa);
315
316 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
317 LPSAFEARRAY_UserUnmarshal(&umcb.Flags, buffer, &lpsa2);
318 ok(lpsa2 != NULL, "LPSAFEARRAY didn't unmarshal\n");
319 SafeArrayGetVartype(lpsa, &vt);
320 SafeArrayGetVartype(lpsa2, &vt2);
321 ok(vt == vt2, "vts differ %x %x\n", vt, vt2);
322 ok(lpsa2->cLocks == 0, "got lock count %lu, expected 0\n", lpsa2->cLocks);
323 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
324 LPSAFEARRAY_UserFree(&umcb.Flags, &lpsa2);
326 lpsa->cLocks = 0;
327 hr = SafeArrayDestroy(lpsa);
328 ok(hr == S_OK, "got 0x%08lx\n", hr);
329
330 /* test NULL safe array */
331 lpsa = NULL;
332
333 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
334 size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
335 expected = 4;
336 ok(size == expected, "size should be 4 bytes, not %ld\n", size);
338 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
339 next = LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
340 ok(next - buffer == expected, "Marshaled %lu bytes, expected %lu\n", (ULONG) (next - buffer), expected);
341 check_safearray(buffer, lpsa);
342
343 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
344 LPSAFEARRAY_UserUnmarshal(&umcb.Flags, buffer, &lpsa2);
345 ok(lpsa2 == NULL, "NULL LPSAFEARRAY didn't unmarshal\n");
346 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
347 LPSAFEARRAY_UserFree(&umcb.Flags, &lpsa2);
349
350 sab[0].lLbound = 5;
351 sab[0].cElements = 10;
352
353 lpsa = SafeArrayCreate(VT_R8, 1, sab);
354 *(double *)lpsa->pvData = 3.1415;
355
356 lpsa->cLocks = 7;
357 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
358 size = LPSAFEARRAY_UserSize(&umcb.Flags, 1, &lpsa);
359 expected = (44 + 1 + (sizeof(double) - 1)) & ~(sizeof(double) - 1);
360 expected += sab[0].cElements * sizeof(double);
361 ok(size == expected || size == expected + 16, /* win64 */
362 "size should be %lu bytes, not %lu\n", expected, size);
363 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
364 expected = (44 + (sizeof(double) - 1)) & ~(sizeof(double) - 1);
365 expected += sab[0].cElements * sizeof(double);
366 size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
367 ok(size == expected || size == expected + 8, /* win64 */
368 "size should be %lu bytes, not %lu\n", expected, size);
370 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
371 next = LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
372 ok(next - buffer == expected || broken(next - buffer + sizeof(DWORD) == expected),
373 "Marshaled %lu bytes, expected %lu\n", (ULONG) (next - buffer), expected);
374
375 check_safearray(buffer, lpsa);
376
378 lpsa->cLocks = 0;
379 hr = SafeArrayDestroy(lpsa);
380 ok(hr == S_OK, "got 0x%08lx\n", hr);
381
382 /* VARTYPE-less arrays can be marshaled if cbElements is 1,2,4 or 8 as type SF_In */
383 hr = SafeArrayAllocDescriptor(1, &lpsa);
384 ok(hr == S_OK, "saad failed %08lx\n", hr);
385 lpsa->cbElements = 8;
386 lpsa->rgsabound[0].lLbound = 2;
387 lpsa->rgsabound[0].cElements = 48;
388 hr = SafeArrayAllocData(lpsa);
389 ok(hr == S_OK, "saad failed %08lx\n", hr);
390 hr = SafeArrayGetVartype(lpsa, &vt);
391 ok(hr == E_INVALIDARG, "ret %08lx\n", hr);
392
393 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
394 size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
395 expected = (44 + lpsa->cbElements - 1) & ~(lpsa->cbElements - 1);
396 expected += lpsa->cbElements * lpsa->rgsabound[0].cElements;
397 ok(size == expected || size == expected + 8, /* win64 */
398 "size should be %lu bytes, not %lu\n", expected, size);
400 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
401 next = LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
402 ok(next - buffer == expected || broken(next - buffer + sizeof(DWORD) == expected),
403 "Marshaled %lu bytes, expected %lu\n", (ULONG) (next - buffer), expected);
404 check_safearray(buffer, lpsa);
406 hr = SafeArrayDestroyData(lpsa);
407 ok(hr == S_OK, "got 0x%08lx\n", hr);
409 ok(hr == S_OK, "got 0x%08lx\n", hr);
410
411 /* Test an array of VT_BSTR */
412 sab[0].lLbound = 3;
413 sab[0].cElements = ARRAY_SIZE(values);
414
415 lpsa = SafeArrayCreate(VT_BSTR, 1, sab);
416 expected_bstr_size = 0;
417 for (i = 0; i < sab[0].cElements; i++)
418 {
419 int j;
420 WCHAR buf[128];
421 for (j = 0; j <= i; j++)
422 buf[j] = 'a' + j;
423 buf[j] = 0;
424 indices[0] = i + sab[0].lLbound;
427 ok(hr == S_OK, "Failed to put bstr element hr 0x%lx\n", hr);
428 expected_bstr_size += (j * sizeof(WCHAR)) + (3 * sizeof(DWORD));
429 if (i % 2 == 0) /* Account for DWORD padding. Works so long as cElements is even */
430 expected_bstr_size += sizeof(WCHAR);
431 }
432
433 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
434 size = LPSAFEARRAY_UserSize(&umcb.Flags, 1, &lpsa);
435 expected = 44 + (sab[0].cElements * sizeof(DWORD)) + expected_bstr_size;
437 ok(size == expected + sizeof(DWORD) || size == (expected + sizeof(DWORD) + 12 /* win64 */),
438 "size should be %lu bytes, not %lu\n", expected + (ULONG) sizeof(DWORD), size);
439 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
440 size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
442 ok(size == expected || size == (expected + 12 /* win64 */),
443 "size should be %lu bytes, not %lu\n", expected, size);
445 memset(buffer, 0xcc, size);
446 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
447 next = LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
449 ok(next - buffer == expected, "Marshaled %lu bytes, expected %lu\n", (ULONG) (next - buffer), expected);
450
451 check_safearray(buffer, lpsa);
452
453 lpsa2 = NULL;
454 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
455 next = LPSAFEARRAY_UserUnmarshal(&umcb.Flags, buffer, &lpsa2);
457 ok(next - buffer == expected, "Marshaled %lu bytes, expected %lu\n", (ULONG) (next - buffer), expected);
458 ok(lpsa2 != NULL, "LPSAFEARRAY didn't unmarshal, result %p\n", next);
459
460 for (i = 0; i < ARRAY_SIZE(values); i++)
461 {
462 BSTR gotvalue = NULL;
463
464 if (lpsa2)
465 {
466 indices[0] = i + sab[0].lLbound;
467 hr = SafeArrayGetElement(lpsa2, indices, &gotvalue);
468 ok(hr == S_OK, "Failed to get bstr element at hres 0x%lx\n", hr);
469 if (hr == S_OK)
470 {
471 ok(VarBstrCmp(values[i], gotvalue, 0, 0) == VARCMP_EQ, "String %d does not match\n", i);
472 SysFreeString(gotvalue);
473 }
474 }
475
477 }
478
479 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
480 LPSAFEARRAY_UserFree(&umcb.Flags, &lpsa2);
481
483 hr = SafeArrayDestroy(lpsa);
484 ok(hr == S_OK, "got 0x%08lx\n", hr);
485
486 /* VARTYPE-less arrays with FADF_VARIANT */
487 hr = SafeArrayAllocDescriptor(1, &lpsa);
488 ok(hr == S_OK, "saad failed %08lx\n", hr);
489 lpsa->cbElements = sizeof(VARIANT);
490 lpsa->fFeatures = FADF_VARIANT;
491 lpsa->rgsabound[0].lLbound = 2;
492 lpsa->rgsabound[0].cElements = 48;
493 hr = SafeArrayAllocData(lpsa);
494 ok(hr == S_OK, "saad failed %08lx\n", hr);
495 hr = SafeArrayGetVartype(lpsa, &vt);
496 ok(hr == E_INVALIDARG, "ret %08lx\n", hr);
497
498 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
499 size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
500 expected = 44 + 28 * lpsa->rgsabound[0].cElements;
502 ok(size == expected || size == expected + 8, /* win64 */
503 "size should be %lu bytes, not %lu\n", expected, size);
505 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
506 next = LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
508 ok(next - buffer == expected || broken(next - buffer + sizeof(DWORD) == expected),
509 "Marshaled %lu bytes, expected %lu\n", (ULONG) (next - buffer), expected);
510 lpsa->cbElements = 16; /* VARIANT wire size */
511 check_safearray(buffer, lpsa);
513 hr = SafeArrayDestroyData(lpsa);
514 ok(hr == S_OK, "got 0x%08lx\n", hr);
516 ok(hr == S_OK, "got 0x%08lx\n", hr);
517
518 /* Test an array of VT_UNKNOWN */
519 sab[0].lLbound = 3;
520 sab[0].cElements = ARRAY_SIZE(heap_unknown);
521
522 lpsa = SafeArrayCreate(VT_UNKNOWN, 1, sab);
523
524 /*
525 * Calculate approximate expected size. Sizes are different between Windows
526 * versions, so this should calculate the smallest size that seems sane.
527 */
528 expected = 60;
529 for (i = 0; i < sab[0].cElements; i++)
530 {
531 HeapUnknown *unk;
532 VARIANT v;
533
534 unk = HeapAlloc(GetProcessHeap(), 0, sizeof(*unk));
535 unk->IUnknown_iface.lpVtbl = &HeapUnknown_Vtbl;
536 unk->refs = 1;
537
538 indices[0] = i + sab[0].lLbound;
539 heap_unknown[i] = unk;
540 hr = SafeArrayPutElement(lpsa, indices, &heap_unknown[i]->IUnknown_iface);
541 ok(hr == S_OK, "Failed to put unknown element hr 0x%lx\n", hr);
542 ok(unk->refs == 2, "VT_UNKNOWN safearray elem %d, refcount %ld\n", i, unk->refs);
543
544 V_VT(&v) = VT_UNKNOWN;
545 V_UNKNOWN(&v) = &unk->IUnknown_iface;
546 expected += VARIANT_UserSize(&umcb.Flags, 0, &v) - 20;
547 }
548
549 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
550 size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
551 ok(size >= expected || size >= (expected + 12 ),
552 "size should be at least %lu bytes, not %lu\n", expected, size);
553
554 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
555 size2 = LPSAFEARRAY_UserSize(&umcb.Flags, 1, &lpsa);
556 ok(size2 == (size + sizeof(DWORD)) || size2 == (size + sizeof(DWORD) + 12),
557 "size should be %lu bytes, not %lu\n", size + (ULONG) sizeof(DWORD), size2);
558
560 memset(buffer, 0xcc, size);
561 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
562 next = LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
563 ok((next - buffer) <= size, "Marshaled %lu bytes, expected at most %lu\n", (ULONG) (next - buffer), size);
564 check_safearray(buffer, lpsa);
566 ok(heap_unknown[0]->refs == 3, "Unexpected refcount %ld\n", heap_unknown[0]->refs);
567
568 lpsa2 = NULL;
569 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
570 next = LPSAFEARRAY_UserUnmarshal(&umcb.Flags, buffer, &lpsa2);
571 ok((next - buffer) <= size, "Marshaled %lu bytes, expected at most %lu\n", (ULONG) (next - buffer), size);
572 ok(lpsa2 != NULL, "LPSAFEARRAY didn't unmarshal, result %p\n", next);
573
574 for (i = 0; i < ARRAY_SIZE(heap_unknown); i++)
575 {
576 IUnknown *gotvalue = NULL;
577
578 if (lpsa2)
579 {
580 indices[0] = i + sab[0].lLbound;
581 hr = SafeArrayGetElement(lpsa2, indices, &gotvalue);
582 ok(hr == S_OK, "Failed to get unk element at %d, hres 0x%lx\n", i, hr);
583 if (hr == S_OK)
584 {
585 ok(gotvalue == &heap_unknown[i]->IUnknown_iface, "Interface %d mismatch, expected %p, got %p\n",
586 i, &heap_unknown[i]->IUnknown_iface, gotvalue);
587 IUnknown_Release(gotvalue);
588 }
589 }
590 }
591
592 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
593 LPSAFEARRAY_UserFree(&umcb.Flags, &lpsa2);
594
595 /* Set one of the elements to NULL, see how this effects size. */
596 indices[0] = 3 + sab[0].lLbound;
598 ok(hr == S_OK, "Failed to put unknown element hr 0x%lx\n", hr);
599
600 expected = 60;
601 for (i = 0; i < sab[0].cElements; i++)
602 {
603 VARIANT v;
604
605 V_VT(&v) = VT_UNKNOWN;
606 V_UNKNOWN(&v) = (i != 3) ? &heap_unknown[i]->IUnknown_iface : NULL;
607 expected += VARIANT_UserSize(&umcb.Flags, 0, &v) - 20;
608 }
609
610 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
611 size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
612 ok(size >= expected || size >= (expected + 12 ),
613 "size should be at least %lu bytes, not %lu\n", expected, size);
614
615 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
616 size2 = LPSAFEARRAY_UserSize(&umcb.Flags, 1, &lpsa);
617 ok(size2 == (size + sizeof(DWORD)) || size2 == (size + sizeof(DWORD) + 12),
618 "size should be %lu bytes, not %lu\n", size + (ULONG) sizeof(DWORD), size2);
619
621 memset(buffer, 0xcc, size);
622 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
623 next = LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
624 ok((next - buffer) <= expected, "Marshaled %lu bytes, expected at most %lu bytes\n", (ULONG) (next - buffer), expected);
625 check_safearray(buffer, lpsa);
626
627 lpsa2 = NULL;
628 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
629 next = LPSAFEARRAY_UserUnmarshal(&umcb.Flags, buffer, &lpsa2);
630 ok((next - buffer) <= expected, "Marshaled %lu bytes, expected at most %lu bytes\n", (ULONG) (next - buffer), expected);
631 ok(lpsa2 != NULL, "LPSAFEARRAY didn't unmarshal, result %p\n", next);
632
633 for (i = 0; i < ARRAY_SIZE(heap_unknown); i++)
634 {
635 IUnknown *gotvalue = NULL;
636
637 if (lpsa2)
638 {
639 indices[0] = i + sab[0].lLbound;
640 hr = SafeArrayGetElement(lpsa2, indices, &gotvalue);
641 ok(hr == S_OK, "Failed to get unk element at %d, hres 0x%lx\n", i, hr);
642 if (hr == S_OK)
643 {
644 /* Our NULL interface. */
645 if (i == 3)
646 ok(gotvalue == NULL, "Interface %d expected NULL, got %p\n", i, gotvalue);
647 else
648 {
649 ok(gotvalue == &heap_unknown[i]->IUnknown_iface, "Interface %d mismatch, expected %p, got %p\n",
650 i, &heap_unknown[i]->IUnknown_iface, gotvalue);
651 IUnknown_Release(gotvalue);
652 }
653 }
654 }
655 IUnknown_Release(&heap_unknown[i]->IUnknown_iface);
656 }
657
658 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
659 LPSAFEARRAY_UserFree(&umcb.Flags, &lpsa2);
660
661 ok(heap_unknown[0]->refs == 1, "Unexpected refcount %ld\n", heap_unknown[0]->refs);
662
663 hr = SafeArrayDestroy(lpsa);
664 ok(hr == S_OK, "got 0x%08lx\n", hr);
665}
666
667static void check_bstr(void *buffer, BSTR b)
668{
669 DWORD *wireb = buffer;
671
672 ok(*wireb == (len + 1) / 2, "wv[0] %08lx\n", *wireb);
673 wireb++;
674 if(b)
675 ok(*wireb == len, "wv[1] %08lx\n", *wireb);
676 else
677 ok(*wireb == 0xffffffff, "wv[1] %08lx\n", *wireb);
678 wireb++;
679 ok(*wireb == (len + 1) / 2, "wv[2] %08lx\n", *wireb);
680 if(len)
681 {
682 wireb++;
683 ok(!memcmp(wireb, b, (len + 1) & ~1), "strings differ\n");
684 }
685 return;
686}
687
688static void test_marshal_BSTR(void)
689{
690 ULONG size;
692 MIDL_STUB_MESSAGE stub_msg;
693 USER_MARSHAL_CB umcb;
694 unsigned char *buffer, *next;
695 BSTR b, b2;
696 WCHAR str[] = {'m','a','r','s','h','a','l',' ','t','e','s','t','1',0};
697 DWORD len;
698
700 len = SysStringLen(b);
701 ok(len == 13, "get %ld\n", len);
702
703 /* BSTRs are DWORD aligned */
704
705 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
706 size = BSTR_UserSize(&umcb.Flags, 1, &b);
707 ok(size == 42, "size %ld\n", size);
708
709 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
710 size = BSTR_UserSize(&umcb.Flags, 0, &b);
711 ok(size == 38, "size %ld\n", size);
712
714 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
715 next = BSTR_UserMarshal(&umcb.Flags, buffer, &b);
716 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
718
719 b2 = NULL;
720 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
722 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
723 ok(b2 != NULL, "BSTR didn't unmarshal\n");
724 ok(!memcmp(b, b2, (len + 1) * 2), "strings differ\n");
725 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
726 BSTR_UserFree(&umcb.Flags, &b2);
727
730
731 b = NULL;
732 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
733 size = BSTR_UserSize(&umcb.Flags, 0, &b);
734 ok(size == 12, "size %ld\n", size);
735
737 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
738 next = BSTR_UserMarshal(&umcb.Flags, buffer, &b);
739 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
740
742 b2 = NULL;
743 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
745 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
746 ok(b2 == NULL, "NULL BSTR didn't unmarshal\n");
747 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
748 BSTR_UserFree(&umcb.Flags, &b2);
750
751 b = SysAllocStringByteLen("abc", 3);
752 *(((char*)b) + 3) = 'd';
753 len = SysStringLen(b);
754 ok(len == 1, "get %ld\n", len);
756 ok(len == 3, "get %ld\n", len);
757
758 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
759 size = BSTR_UserSize(&umcb.Flags, 0, &b);
760 ok(size == 16, "size %ld\n", size);
761
763 memset(buffer, 0xcc, size);
764 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
765 next = BSTR_UserMarshal(&umcb.Flags, buffer, &b);
766 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
768 ok(buffer[15] == 'd', "buffer[15] %02x\n", buffer[15]);
769
770 b2 = NULL;
771 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
773 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
774 ok(b2 != NULL, "BSTR didn't unmarshal\n");
775 ok(!memcmp(b, b2, len), "strings differ\n");
776 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
777 BSTR_UserFree(&umcb.Flags, &b2);
780
781 b = SysAllocStringByteLen("", 0);
782 len = SysStringLen(b);
783 ok(len == 0, "get %ld\n", len);
785 ok(len == 0, "get %ld\n", len);
786
787 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
788 size = BSTR_UserSize(&umcb.Flags, 0, &b);
789 ok(size == 12, "size %ld\n", size);
790
792 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
793 next = BSTR_UserMarshal(&umcb.Flags, buffer, &b);
794 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
796
797 b2 = NULL;
798 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
800 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
801 ok(b2 != NULL, "NULL LPSAFEARRAY didn't unmarshal\n");
803 ok(len == 0, "byte len %ld\n", len);
804 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
805 BSTR_UserFree(&umcb.Flags, &b2);
808}
809
811{
812 return CONTAINING_RECORD(iface, HeapUnknown, IUnknown_iface);
813}
814
816{
818 {
819 IUnknown_AddRef(iface);
820 *ppv = iface;
821 return S_OK;
822 }
823 *ppv = NULL;
824 return E_NOINTERFACE;
825}
826
828{
830 return InterlockedIncrement((LONG*)&This->refs);
831}
832
834{
836 ULONG refs = InterlockedDecrement((LONG*)&This->refs);
837 if (!refs) HeapFree(GetProcessHeap(), 0, This);
838 return refs;
839}
840
841static const IUnknownVtbl HeapUnknown_Vtbl =
842{
846};
847
848typedef struct
849{
850 DWORD clSize;
851 DWORD rpcReserved;
852 USHORT vt;
853 USHORT wReserved1;
854 USHORT wReserved2;
855 USHORT wReserved3;
856 DWORD switch_is;
858
860{
861 const variant_wire_t *header = (const variant_wire_t*)wirev;
862 DWORD switch_is;
863
864 ok(header->clSize == (size + 7) >> 3, "wv[0] %08lx, expected %08lx\n", header->clSize, (size + 7) >> 3);
865 ok(header->rpcReserved == 0, "wv[1] %08lx\n", header->rpcReserved);
866 ok(header->vt == V_VT(v), "vt %04x expected %04x\n", header->vt, V_VT(v));
867#ifdef __REACTOS__
868 ok(header->wReserved1 == v->n1.n2.wReserved1, "res1 %04x expected %04x\n", header->wReserved1, v->n1.n2.wReserved1);
869 ok(header->wReserved2 == v->n1.n2.wReserved2, "res2 %04x expected %04x\n", header->wReserved2, v->n1.n2.wReserved2);
870 ok(header->wReserved3 == v->n1.n2.wReserved3, "res3 %04x expected %04x\n", header->wReserved3, v->n1.n2.wReserved3);
871#else
872 ok(header->wReserved1 == v->wReserved1, "res1 %04x expected %04x\n", header->wReserved1, v->wReserved1);
873 ok(header->wReserved2 == v->wReserved2, "res2 %04x expected %04x\n", header->wReserved2, v->wReserved2);
874 ok(header->wReserved3 == v->wReserved3, "res3 %04x expected %04x\n", header->wReserved3, v->wReserved3);
875#endif
876
877 switch_is = V_VT(v);
878 if(switch_is & VT_ARRAY)
879 switch_is &= ~VT_TYPEMASK;
880 ok(header->switch_is == switch_is, "switch_is %08lx expected %08lx\n", header->switch_is, switch_is);
881
882 return (DWORD*)((unsigned char*)wirev + sizeof(variant_wire_t));
883}
884
885/* Win9x and WinME don't always align as needed. Variants have
886 * an alignment of 8.
887 */
888static void *alloc_aligned(SIZE_T size, void **buf)
889{
890 *buf = HeapAlloc(GetProcessHeap(), 0, size + 7);
891 return (void *)(((UINT_PTR)*buf + 7) & ~7);
892}
893
894static void test_marshal_VARIANT(void)
895{
896 VARIANT v, v2, v3;
897 MIDL_STUB_MESSAGE stubMsg = { 0 };
898 RPC_MESSAGE rpcMsg = { 0 };
899 USER_MARSHAL_CB umcb = { 0 };
900 unsigned char *buffer, *next;
902 void *oldbuffer;
903 SIZE_T size;
904 ULONG ul;
905 short s;
906 double d;
907 void *mem;
908 DWORD *wirev;
909 BSTR b, b2;
910 WCHAR str[] = {'m','a','r','s','h','a','l',' ','t','e','s','t',0};
911 SAFEARRAYBOUND sab;
912 LPSAFEARRAY lpsa, lpsa2, lpsa_copy;
913 DECIMAL dec, dec2;
914 HeapUnknown *heap_unknown;
916 HRESULT hr;
917 LONG bound, bound2;
918 VARTYPE vt, vt2;
919 IUnknown *unk;
920
921 hr = CoGetMalloc(MEMCTX_TASK, &allocator);
922 ok(hr == S_OK, "got hr %#lx\n", hr);
923 ok(!!allocator, "got allocator %p\n", allocator);
924
925 stubMsg.RpcMsg = &rpcMsg;
926
927 umcb.Flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
928 umcb.pStubMsg = &stubMsg;
929 umcb.pReserve = NULL;
932
933 /*** I1 ***/
934 VariantInit(&v);
935 V_VT(&v) = VT_I1;
936 V_I1(&v) = 0x12;
937
938 /* check_variant_header tests wReserved[123], so initialize to unique values.
939 * (Could probably also do this by setting the variant to a known DECIMAL.)
940 */
941#ifdef __REACTOS__
942 v.n1.n2.wReserved1 = 0x1234;
943 v.n1.n2.wReserved2 = 0x5678;
944 v.n1.n2.wReserved3 = 0x9abc;
945#else
946 v.wReserved1 = 0x1234;
947 v.wReserved2 = 0x5678;
948 v.wReserved3 = 0x9abc;
949#endif
950
951 /* Variants have an alignment of 8 */
952 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 1, &v);
953 ok(stubMsg.BufferLength == 29, "size %ld\n", stubMsg.BufferLength);
954
955 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
956 ok(stubMsg.BufferLength == 21, "size %ld\n", stubMsg.BufferLength);
957
958 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
959 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
961 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
962 wirev = (DWORD*)buffer;
963
964 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength);
965 ok(*(char*)wirev == V_I1(&v), "wv[5] %08lx\n", *wirev);
966 VariantInit(&v2);
967 stubMsg.Buffer = buffer;
969 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
970 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
971 ok(V_I1(&v) == V_I1(&v2), "got i1 %x expect %x\n", V_I1(&v), V_I1(&v2));
972
973 VARIANT_UserFree(&umcb.Flags, &v2);
974 HeapFree(GetProcessHeap(), 0, oldbuffer);
975
976 /*** I2 ***/
977 VariantInit(&v);
978 V_VT(&v) = VT_I2;
979 V_I2(&v) = 0x1234;
980
981 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
982 ok(stubMsg.BufferLength == 22, "size %ld\n", stubMsg.BufferLength);
983
984 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
985 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
987 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
988 wirev = (DWORD*)buffer;
989
990 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength);
991 ok(*(short*)wirev == V_I2(&v), "wv[5] %08lx\n", *wirev);
992 VariantInit(&v2);
993 stubMsg.Buffer = buffer;
995 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
996 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
997 ok(V_I2(&v) == V_I2(&v2), "got i2 %x expect %x\n", V_I2(&v), V_I2(&v2));
998
999 VARIANT_UserFree(&umcb.Flags, &v2);
1000 HeapFree(GetProcessHeap(), 0, oldbuffer);
1001
1002 /*** I2 BYREF ***/
1003 VariantInit(&v);
1004 V_VT(&v) = VT_I2 | VT_BYREF;
1005 s = 0x1234;
1006 V_I2REF(&v) = &s;
1007
1008 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1009 ok(stubMsg.BufferLength == 26, "size %ld\n", stubMsg.BufferLength);
1010
1011 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1012 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1014 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1015 wirev = (DWORD*)buffer;
1016
1017 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength);
1018 ok(*wirev == 0x4, "wv[5] %08lx\n", *wirev);
1019 wirev++;
1020 ok(*(short*)wirev == s, "wv[6] %08lx\n", *wirev);
1021 VariantInit(&v2);
1022 V_VT(&v2) = VT_I2 | VT_BYREF;
1023 V_BYREF(&v2) = mem = CoTaskMemAlloc(sizeof(V_I2(&v2)));
1024 stubMsg.Buffer = buffer;
1026 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1027 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1028 ok(V_BYREF(&v2) == mem, "didn't reuse existing memory\n");
1029 ok(*V_I2REF(&v) == *V_I2REF(&v2), "got i2 ref %x expect ui4 ref %x\n", *V_I2REF(&v), *V_I2REF(&v2));
1030
1031 VARIANT_UserFree(&umcb.Flags, &v2);
1032 HeapFree(GetProcessHeap(), 0, oldbuffer);
1033
1034 /*** I4 ***/
1035 VariantInit(&v);
1036 V_VT(&v) = VT_I4;
1037 V_I4(&v) = 0x1234;
1038
1039 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1040 ok(stubMsg.BufferLength == 24, "size %ld\n", stubMsg.BufferLength);
1041
1042 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1043 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1045 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1046 wirev = (DWORD*)buffer;
1047
1048 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength);
1049 ok(*wirev == V_I4(&v), "wv[5] %08lx\n", *wirev);
1050
1051 VariantInit(&v2);
1052 stubMsg.Buffer = buffer;
1054 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1055 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1056 ok(V_I4(&v) == V_I4(&v2), "got i4 %lx expect %lx\n", V_I4(&v), V_I4(&v2));
1057
1058 VARIANT_UserFree(&umcb.Flags, &v2);
1059 HeapFree(GetProcessHeap(), 0, oldbuffer);
1060
1061 /*** UI4 ***/
1062 VariantInit(&v);
1063 V_VT(&v) = VT_UI4;
1064 V_UI4(&v) = 0x1234;
1065
1066 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1067 ok(stubMsg.BufferLength == 24, "size %ld\n", stubMsg.BufferLength);
1068
1069 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1070 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1072 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1073 wirev = (DWORD*)buffer;
1074
1075 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength);
1076 ok(*wirev == 0x1234, "wv[5] %08lx\n", *wirev);
1077 VariantInit(&v2);
1078 stubMsg.Buffer = buffer;
1080 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1081 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1082 ok(V_UI4(&v) == V_UI4(&v2), "got ui4 %lx expect %lx\n", V_UI4(&v), V_UI4(&v2));
1083
1084 VARIANT_UserFree(&umcb.Flags, &v2);
1085 HeapFree(GetProcessHeap(), 0, oldbuffer);
1086
1087 /*** UI4 BYREF ***/
1088 VariantInit(&v);
1089 V_VT(&v) = VT_UI4 | VT_BYREF;
1090 ul = 0x1234;
1091 V_UI4REF(&v) = &ul;
1092
1093 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1094 ok(stubMsg.BufferLength == 28, "size %ld\n", stubMsg.BufferLength);
1095
1096 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1097 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1099 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1100 wirev = (DWORD*)buffer;
1101
1102 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength);
1103 ok(*wirev == 0x4, "wv[5] %08lx\n", *wirev);
1104 wirev++;
1105 ok(*wirev == ul, "wv[6] %08lx\n", *wirev);
1106
1107 VariantInit(&v2);
1108 stubMsg.Buffer = buffer;
1110 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1111 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1112 ok(*V_UI4REF(&v) == *V_UI4REF(&v2), "got ui4 ref %lx expect ui4 ref %lx\n", *V_UI4REF(&v), *V_UI4REF(&v2));
1113 size = IMalloc_GetSize(allocator, V_BYREF(&v2));
1114 ok(size == sizeof(V_UI4(&v2)), "got size %#Ix\n", size);
1115 VARIANT_UserFree(&umcb.Flags, &v2);
1116 HeapFree(GetProcessHeap(), 0, oldbuffer);
1117
1118 /*** I8 ***/
1119 VariantInit(&v);
1120 V_VT(&v) = VT_I8;
1121 V_I8(&v) = (LONGLONG)1000000 * 1000000;
1122
1123 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1124 ok(stubMsg.BufferLength == 32, "size %ld\n", stubMsg.BufferLength);
1125
1126 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1127 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1128 memset(buffer, 0xcc, stubMsg.BufferLength);
1130 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1131 wirev = (DWORD*)buffer;
1132
1133 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength);
1134 ok(*wirev == 0xcccccccc, "wv[5] %08lx\n", *wirev); /* pad */
1135 wirev++;
1136 ok(*(LONGLONG *)wirev == V_I8(&v), "wv[6] %s\n", wine_dbgstr_longlong(*(LONGLONG *)wirev));
1137 VariantInit(&v2);
1138 stubMsg.Buffer = buffer;
1140 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1141 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1142 ok(V_I8(&v) == V_I8(&v2), "got i8 %s expect %s\n",
1144
1145 VARIANT_UserFree(&umcb.Flags, &v2);
1146 HeapFree(GetProcessHeap(), 0, oldbuffer);
1147
1148 /*** R4 ***/
1149 VariantInit(&v);
1150 V_VT(&v) = VT_R4;
1151 V_R8(&v) = 3.1415;
1152
1153 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1154 ok(stubMsg.BufferLength == 24, "size %ld\n", stubMsg.BufferLength);
1155
1156 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1157 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1159 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1160 wirev = (DWORD*)buffer;
1161
1162 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength);
1163 ok(*(float*)wirev == V_R4(&v), "wv[5] %08lx\n", *wirev);
1164 VariantInit(&v2);
1165 stubMsg.Buffer = buffer;
1167 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1168 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1169 ok(V_R4(&v) == V_R4(&v2), "got r4 %f expect %f\n", V_R4(&v), V_R4(&v2));
1170
1171 VARIANT_UserFree(&umcb.Flags, &v2);
1172 HeapFree(GetProcessHeap(), 0, oldbuffer);
1173
1174 /*** R8 ***/
1175 VariantInit(&v);
1176 V_VT(&v) = VT_R8;
1177 V_R8(&v) = 3.1415;
1178
1179 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1180 ok(stubMsg.BufferLength == 32, "size %ld\n", stubMsg.BufferLength);
1181
1182 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1183 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1184 memset(buffer, 0xcc, stubMsg.BufferLength);
1186 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1187 wirev = (DWORD*)buffer;
1188
1189 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength);
1190 ok(*wirev == 0xcccccccc, "wv[5] %08lx\n", *wirev); /* pad */
1191 wirev++;
1192 ok(*(double*)wirev == V_R8(&v), "wv[6] %08lx, wv[7] %08lx\n", *wirev, *(wirev+1));
1193 VariantInit(&v2);
1194 stubMsg.Buffer = buffer;
1196 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1197 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1198 ok(V_R8(&v) == V_R8(&v2), "got r8 %f expect %f\n", V_R8(&v), V_R8(&v2));
1199
1200 VARIANT_UserFree(&umcb.Flags, &v2);
1201 HeapFree(GetProcessHeap(), 0, oldbuffer);
1202
1203 /*** R8 BYREF ***/
1204 VariantInit(&v);
1205 V_VT(&v) = VT_R8 | VT_BYREF;
1206 d = 3.1415;
1207 V_R8REF(&v) = &d;
1208
1209 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1210 ok(stubMsg.BufferLength == 32, "size %ld\n", stubMsg.BufferLength);
1211
1212 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1213 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1215 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1216 wirev = (DWORD*)buffer;
1217
1218 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength);
1219 ok(*wirev == 8, "wv[5] %08lx\n", *wirev);
1220 wirev++;
1221 ok(*(double*)wirev == d, "wv[6] %08lx wv[7] %08lx\n", *wirev, *(wirev+1));
1222 VariantInit(&v2);
1223 stubMsg.Buffer = buffer;
1225 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1226 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1227 ok(*V_R8REF(&v) == *V_R8REF(&v2), "got r8 ref %f expect %f\n", *V_R8REF(&v), *V_R8REF(&v2));
1228 size = IMalloc_GetSize(allocator, V_BYREF(&v2));
1229 ok(size == sizeof(V_R8(&v2)), "got size %#Ix\n", size);
1230 VARIANT_UserFree(&umcb.Flags, &v2);
1231 HeapFree(GetProcessHeap(), 0, oldbuffer);
1232
1233 /*** VARIANT_BOOL ***/
1234 VariantInit(&v);
1235 V_VT(&v) = VT_BOOL;
1236 V_BOOL(&v) = 0x1234;
1237
1238 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1239 ok(stubMsg.BufferLength == 22, "size %ld\n", stubMsg.BufferLength);
1240
1241 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1242 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1244 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1245 wirev = (DWORD*)buffer;
1246
1247 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength);
1248 ok(*(short*)wirev == V_BOOL(&v), "wv[5] %04x\n", *(WORD*)wirev);
1249 VariantInit(&v2);
1250 stubMsg.Buffer = buffer;
1252 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1253 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1254 ok(V_BOOL(&v) == V_BOOL(&v2), "got bool %x expect %x\n", V_BOOL(&v), V_BOOL(&v2));
1255
1256 VARIANT_UserFree(&umcb.Flags, &v2);
1257 HeapFree(GetProcessHeap(), 0, oldbuffer);
1258
1259 /*** DECIMAL ***/
1260 VarDecFromI4(0x12345678, &dec);
1261 dec.wReserved = 0xfedc; /* Also initialize reserved field, as we check it later */
1262 VariantInit(&v);
1263 V_DECIMAL(&v) = dec;
1264 V_VT(&v) = VT_DECIMAL;
1265
1266 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1267 ok(stubMsg.BufferLength == 40, "size %ld\n", stubMsg.BufferLength);
1268
1269 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1270 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1271 memset(buffer, 0xcc, stubMsg.BufferLength);
1273 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1274 wirev = (DWORD*)buffer;
1275
1276 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength);
1277 ok(*wirev == 0xcccccccc, "wirev[5] %08lx\n", *wirev); /* pad */
1278 wirev++;
1279 dec2 = dec;
1280 dec2.wReserved = VT_DECIMAL;
1281 ok(!memcmp(wirev, &dec2, sizeof(dec2)), "wirev[6] %08lx wirev[7] %08lx wirev[8] %08lx wirev[9] %08lx\n",
1282 *wirev, *(wirev + 1), *(wirev + 2), *(wirev + 3));
1283 VariantInit(&v2);
1284 stubMsg.Buffer = buffer;
1286 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1287 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1288 ok(!memcmp(&V_DECIMAL(&v), & V_DECIMAL(&v2), sizeof(DECIMAL)), "decimals differ\n");
1289
1290 VARIANT_UserFree(&umcb.Flags, &v2);
1291 HeapFree(GetProcessHeap(), 0, oldbuffer);
1292
1293 /*** DECIMAL BYREF ***/
1294 VariantInit(&v);
1295 V_VT(&v) = VT_DECIMAL | VT_BYREF;
1296 V_DECIMALREF(&v) = &dec;
1297
1298 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1299 ok(stubMsg.BufferLength == 40, "size %ld\n", stubMsg.BufferLength);
1300
1301 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1302 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1304 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1305 wirev = (DWORD*)buffer;
1306
1307 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength);
1308 ok(*wirev == 16, "wv[5] %08lx\n", *wirev);
1309 wirev++;
1310 ok(!memcmp(wirev, &dec, sizeof(dec)), "wirev[6] %08lx wirev[7] %08lx wirev[8] %08lx wirev[9] %08lx\n", *wirev, *(wirev + 1), *(wirev + 2), *(wirev + 3));
1311 VariantInit(&v2);
1312 /* check_variant_header tests wReserved[123], so initialize to unique values.
1313 * (Could probably also do this by setting the variant to a known DECIMAL.)
1314 */
1315#ifdef __REACTOS__
1316 v2.n1.n2.wReserved1 = 0x0123;
1317 v2.n1.n2.wReserved2 = 0x4567;
1318 v2.n1.n2.wReserved3 = 0x89ab;
1319#else
1320 v2.wReserved1 = 0x0123;
1321 v2.wReserved2 = 0x4567;
1322 v2.wReserved3 = 0x89ab;
1323#endif
1324
1325 stubMsg.Buffer = buffer;
1327 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1328 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1329 ok(!memcmp(V_DECIMALREF(&v), V_DECIMALREF(&v2), sizeof(DECIMAL)), "decimals differ\n");
1330 size = IMalloc_GetSize(allocator, V_BYREF(&v2));
1331 ok(size == sizeof(V_DECIMAL(&v2)), "got size %#Ix\n", size);
1332 VARIANT_UserFree(&umcb.Flags, &v2);
1333 HeapFree(GetProcessHeap(), 0, oldbuffer);
1334
1335 /*** EMPTY ***/
1336 VariantInit(&v);
1337 V_VT(&v) = VT_EMPTY;
1338
1339 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1340 ok(stubMsg.BufferLength == 20, "size %ld\n", stubMsg.BufferLength);
1341
1342 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1343 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1345 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1346 wirev = (DWORD*)buffer;
1347
1348 check_variant_header(wirev, &v, stubMsg.BufferLength);
1349 VariantInit(&v2);
1350 stubMsg.Buffer = buffer;
1352 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1353 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1354
1355 VARIANT_UserFree(&umcb.Flags, &v2);
1356 HeapFree(GetProcessHeap(), 0, oldbuffer);
1357
1358 /*** NULL ***/
1359 VariantInit(&v);
1360 V_VT(&v) = VT_NULL;
1361
1362 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1363 ok(stubMsg.BufferLength == 20, "size %ld\n", stubMsg.BufferLength);
1364
1365 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1366 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1368 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1369 wirev = (DWORD*)buffer;
1370
1371 check_variant_header(wirev, &v, stubMsg.BufferLength);
1372 VariantInit(&v2);
1373 stubMsg.Buffer = buffer;
1375 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1376 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1377
1378 VARIANT_UserFree(&umcb.Flags, &v2);
1379 HeapFree(GetProcessHeap(), 0, oldbuffer);
1380
1381 /*** BSTR ***/
1382 b = SysAllocString(str);
1383 VariantInit(&v);
1384 V_VT(&v) = VT_BSTR;
1385 V_BSTR(&v) = b;
1386
1387 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1388 ok(stubMsg.BufferLength == 60, "size %ld\n", stubMsg.BufferLength);
1389 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1390 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1392 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1393 wirev = (DWORD*)buffer;
1394
1395 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength);
1396 ok(*wirev, "wv[5] %08lx\n", *wirev); /* win2k: this is b. winxp: this is (char*)b + 1 */
1397 wirev++;
1398 check_bstr(wirev, V_BSTR(&v));
1399 VariantInit(&v2);
1400 stubMsg.Buffer = buffer;
1402 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1403 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1404 ok(SysStringByteLen(V_BSTR(&v)) == SysStringByteLen(V_BSTR(&v2)), "bstr string lens differ\n");
1405 ok(!memcmp(V_BSTR(&v), V_BSTR(&v2), SysStringByteLen(V_BSTR(&v))), "bstrs differ\n");
1406
1407 VARIANT_UserFree(&umcb.Flags, &v2);
1408 HeapFree(GetProcessHeap(), 0, oldbuffer);
1409
1410 /*** BSTR BYREF ***/
1411 VariantInit(&v);
1412 V_VT(&v) = VT_BSTR | VT_BYREF;
1413 V_BSTRREF(&v) = &b;
1414
1415 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1416 ok(stubMsg.BufferLength == 64, "size %ld\n", stubMsg.BufferLength);
1417 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1418 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1420 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1421 wirev = (DWORD*)buffer;
1422
1423 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength);
1424 ok(*wirev == 0x4, "wv[5] %08lx\n", *wirev);
1425 wirev++;
1426 ok(*wirev, "wv[6] %08lx\n", *wirev); /* win2k: this is b. winxp: this is (char*)b + 1 */
1427 wirev++;
1428 check_bstr(wirev, b);
1430 b2[0] = 0;
1431 V_VT(&v2) = VT_BSTR | VT_BYREF;
1432 V_BSTRREF(&v2) = &b2;
1433 mem = b2;
1434 VariantInit(&v2);
1435 stubMsg.Buffer = buffer;
1437 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1438 ok(mem == b2, "BSTR should be reused\n");
1439 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1440 ok(SysStringByteLen(*V_BSTRREF(&v)) == SysStringByteLen(*V_BSTRREF(&v2)), "bstr string lens differ\n");
1441 ok(!memcmp(*V_BSTRREF(&v), *V_BSTRREF(&v2), SysStringByteLen(*V_BSTRREF(&v))), "bstrs differ\n");
1442 size = IMalloc_GetSize(allocator, V_BYREF(&v2));
1443 ok(size == sizeof(V_BSTR(&v2)), "got size %#Ix\n", size);
1445 HeapFree(GetProcessHeap(), 0, oldbuffer);
1447
1448 /*** ARRAY ***/
1449 sab.lLbound = 5;
1450 sab.cElements = 10;
1451
1452 lpsa = SafeArrayCreate(VT_R8, 1, &sab);
1453 *(DWORD *)lpsa->pvData = 0xcafebabe;
1454 *((DWORD *)lpsa->pvData + 1) = 0xdeadbeef;
1455
1456 VariantInit(&v);
1457 V_VT(&v) = VT_UI4 | VT_ARRAY;
1458 V_ARRAY(&v) = lpsa;
1459
1460 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1461 expected = 152;
1462 ok(stubMsg.BufferLength == expected || stubMsg.BufferLength == expected + 8, /* win64 */
1463 "size %lu instead of %lu\n", stubMsg.BufferLength, expected);
1464 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1465 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1467 ok(next == buffer + expected, "got %p expect %p\n", next, buffer + expected);
1468 wirev = (DWORD*)buffer;
1469
1470 wirev = check_variant_header(wirev, &v, expected);
1471 ok(*wirev, "wv[5] %08lx\n", *wirev); /* win2k: this is lpsa. winxp: this is (char*)lpsa + 1 */
1472 wirev++;
1473 check_safearray(wirev, lpsa);
1474 VariantInit(&v2);
1475 stubMsg.Buffer = buffer;
1477 ok(next == buffer + expected, "got %p expect %p\n", next, buffer + expected);
1478 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1479 ok(SafeArrayGetDim(V_ARRAY(&v)) == SafeArrayGetDim(V_ARRAY(&v2)), "array dims differ\n");
1480 SafeArrayGetLBound(V_ARRAY(&v), 1, &bound);
1481 SafeArrayGetLBound(V_ARRAY(&v2), 1, &bound2);
1482 ok(bound == bound2, "array lbounds differ\n");
1483 SafeArrayGetUBound(V_ARRAY(&v), 1, &bound);
1484 SafeArrayGetUBound(V_ARRAY(&v2), 1, &bound2);
1485 ok(bound == bound2, "array ubounds differ\n");
1488 ok(vt == vt2, "array vts differ %x %x\n", vt, vt2);
1489 VARIANT_UserFree(&umcb.Flags, &v2);
1490 HeapFree(GetProcessHeap(), 0, oldbuffer);
1491
1492 /*** ARRAY BYREF ***/
1493 VariantInit(&v);
1494 V_VT(&v) = VT_UI4 | VT_ARRAY | VT_BYREF;
1495 V_ARRAYREF(&v) = &lpsa;
1496
1497 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1498 expected = 152;
1499 ok(stubMsg.BufferLength == expected || stubMsg.BufferLength == expected + 16, /* win64 */
1500 "size %lu instead of %lu\n", stubMsg.BufferLength, expected);
1501 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1502 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1504 ok(next == buffer + expected, "got %p expect %p\n", next, buffer + expected);
1505 wirev = (DWORD*)buffer;
1506
1507 wirev = check_variant_header(wirev, &v, expected);
1508 ok(*wirev == 4, "wv[5] %08lx\n", *wirev);
1509 wirev++;
1510 ok(*wirev, "wv[6] %08lx\n", *wirev); /* win2k: this is lpsa. winxp: this is (char*)lpsa + 1 */
1511 wirev++;
1512 check_safearray(wirev, lpsa);
1513 VariantInit(&v2);
1514 stubMsg.Buffer = buffer;
1516 ok(next == buffer + expected, "got %p expect %p\n", next, buffer + expected);
1517 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1518 ok(SafeArrayGetDim(*V_ARRAYREF(&v)) == SafeArrayGetDim(*V_ARRAYREF(&v2)), "array dims differ\n");
1519 SafeArrayGetLBound(*V_ARRAYREF(&v), 1, &bound);
1520 SafeArrayGetLBound(*V_ARRAYREF(&v2), 1, &bound2);
1521 ok(bound == bound2, "array lbounds differ\n");
1522 SafeArrayGetUBound(*V_ARRAYREF(&v), 1, &bound);
1523 SafeArrayGetUBound(*V_ARRAYREF(&v2), 1, &bound2);
1524 ok(bound == bound2, "array ubounds differ\n");
1527 ok(vt == vt2, "array vts differ %x %x\n", vt, vt2);
1528 size = IMalloc_GetSize(allocator, V_BYREF(&v2));
1529 ok(size == sizeof(V_ARRAY(&v2)), "got size %#Ix\n", size);
1530 VARIANT_UserFree(&umcb.Flags, &v2);
1531 HeapFree(GetProcessHeap(), 0, oldbuffer);
1532
1533 /*** ARRAY BYREF ***/
1534 VariantInit(&v);
1535 V_VT(&v) = VT_UI4 | VT_ARRAY | VT_BYREF;
1536 V_ARRAYREF(&v) = &lpsa;
1537 lpsa->fFeatures |= FADF_STATIC;
1538
1539 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1540 expected = 152;
1541 ok(stubMsg.BufferLength == expected || stubMsg.BufferLength == expected + 16, /* win64 */
1542 "size %lu instead of %lu\n", stubMsg.BufferLength, expected);
1543 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1544 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1546 ok(next == buffer + expected, "got %p expect %p\n", next, buffer + expected);
1547 wirev = (DWORD*)buffer;
1548
1549 wirev = check_variant_header(wirev, &v, expected);
1550 ok(*wirev == 4, "wv[5] %08lx\n", *wirev);
1551 wirev++;
1552 ok(*wirev, "wv[6] %08lx\n", *wirev); /* win2k: this is lpsa. winxp: this is (char*)lpsa + 1 */
1553 wirev++;
1554 check_safearray(wirev, lpsa);
1555 lpsa_copy = lpsa2 = SafeArrayCreate(VT_I8, 1, &sab);
1556 /* set FADF_STATIC feature to make sure lpsa2->pvData pointer changes if new data buffer is allocated */
1557 lpsa2->fFeatures |= FADF_STATIC;
1558 mem = lpsa2->pvData;
1559 V_VT(&v2) = VT_UI4 | VT_ARRAY | VT_BYREF;
1560 V_ARRAYREF(&v2) = &lpsa2;
1561 stubMsg.Buffer = buffer;
1563 ok(next == buffer + expected, "got %p expect %p\n", next, buffer + expected);
1564 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1565 ok(lpsa2 == lpsa_copy, "safearray should be reused\n");
1566 ok(mem == lpsa2->pvData, "safearray data should be reused\n");
1567 ok(SafeArrayGetDim(*V_ARRAYREF(&v)) == SafeArrayGetDim(*V_ARRAYREF(&v2)), "array dims differ\n");
1568 SafeArrayGetLBound(*V_ARRAYREF(&v), 1, &bound);
1569 SafeArrayGetLBound(*V_ARRAYREF(&v2), 1, &bound2);
1570 ok(bound == bound2, "array lbounds differ\n");
1571 SafeArrayGetUBound(*V_ARRAYREF(&v), 1, &bound);
1572 SafeArrayGetUBound(*V_ARRAYREF(&v2), 1, &bound2);
1573 ok(bound == bound2, "array ubounds differ\n");
1576 ok(vt == vt2, "array vts differ %x %x\n", vt, vt2);
1577 lpsa2->fFeatures &= ~FADF_STATIC;
1579 ok(hr == S_OK, "got 0x%08lx\n", hr);
1580 HeapFree(GetProcessHeap(), 0, oldbuffer);
1581 lpsa->fFeatures &= ~FADF_STATIC;
1582 hr = SafeArrayDestroy(lpsa);
1583 ok(hr == S_OK, "got 0x%08lx\n", hr);
1584
1585 /*** VARIANT BYREF ***/
1586 VariantInit(&v);
1587 VariantInit(&v2);
1588 V_VT(&v2) = VT_R8;
1589 V_R8(&v2) = 3.1415;
1590 V_VT(&v) = VT_VARIANT | VT_BYREF;
1591 V_VARIANTREF(&v) = &v2;
1592
1593 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1594 ok(stubMsg.BufferLength == 64, "size %ld\n", stubMsg.BufferLength);
1595 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1596 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1597 memset(buffer, 0xcc, stubMsg.BufferLength);
1599 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1600 wirev = (DWORD*)buffer;
1601 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength);
1602
1603 ok(*wirev == sizeof(VARIANT), "wv[5] %08lx\n", *wirev);
1604 wirev++;
1605 ok(*wirev == ('U' | 's' << 8 | 'e' << 16 | 'r' << 24), "wv[6] %08lx\n", *wirev); /* 'User' */
1606 wirev++;
1607 ok(*wirev == 0xcccccccc, "wv[7] %08lx\n", *wirev); /* pad */
1608 wirev++;
1609 wirev = check_variant_header(wirev, &v2, stubMsg.BufferLength - 32);
1610 ok(*wirev == 0xcccccccc, "wv[13] %08lx\n", *wirev); /* pad for VT_R8 */
1611 wirev++;
1612 ok(*(double*)wirev == V_R8(&v2), "wv[6] %08lx wv[7] %08lx\n", *wirev, *(wirev+1));
1613 VariantInit(&v3);
1614 stubMsg.Buffer = buffer;
1616 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1617 ok(V_VT(&v) == V_VT(&v3), "got vt %d expect %d\n", V_VT(&v), V_VT(&v3));
1618 ok(V_VT(V_VARIANTREF(&v)) == V_VT(V_VARIANTREF(&v3)), "vts differ %x %x\n",
1620 ok(V_R8(V_VARIANTREF(&v)) == V_R8(V_VARIANTREF(&v3)), "r8s differ\n");
1621 size = IMalloc_GetSize(allocator, V_BYREF(&v3));
1622 ok(size == sizeof(*V_VARIANTREF(&v3)), "got size %#Ix\n", size);
1623 VARIANT_UserFree(&umcb.Flags, &v3);
1624 HeapFree(GetProcessHeap(), 0, oldbuffer);
1625
1626 /*** UNKNOWN ***/
1627 heap_unknown = HeapAlloc(GetProcessHeap(), 0, sizeof(*heap_unknown));
1628 heap_unknown->IUnknown_iface.lpVtbl = &HeapUnknown_Vtbl;
1629 heap_unknown->refs = 1;
1630 VariantInit(&v);
1631 VariantInit(&v2);
1632 V_VT(&v) = VT_UNKNOWN;
1633 V_UNKNOWN(&v) = &heap_unknown->IUnknown_iface;
1634
1635 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1636 ok(stubMsg.BufferLength > 40, "size %ld\n", stubMsg.BufferLength);
1637 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1638 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1639 memset(buffer, 0xcc, stubMsg.BufferLength);
1641 todo_wine
1642 ok(heap_unknown->refs == 2, "got refcount %ld\n", heap_unknown->refs);
1643 wirev = (DWORD*)buffer;
1644 wirev = check_variant_header(wirev, &v, next - buffer);
1645
1646 todo_wine_if( *wirev == (DWORD)(DWORD_PTR)V_UNKNOWN(&v) /* win9x */)
1647 ok(*wirev == (DWORD)(DWORD_PTR)V_UNKNOWN(&v) + 1, "wv[5] %08lx\n", *wirev);
1648 wirev++;
1649 ok(*wirev == next - buffer - 0x20, "wv[6] %08lx\n", *wirev);
1650 wirev++;
1651 ok(*wirev == next - buffer - 0x20, "wv[7] %08lx\n", *wirev);
1652 wirev++;
1653 ok(*wirev == 0x574f454d, "wv[8] %08lx\n", *wirev);
1654 VariantInit(&v3);
1655 V_VT(&v3) = VT_UNKNOWN;
1656 V_UNKNOWN(&v3) = &heap_unknown->IUnknown_iface;
1657 IUnknown_AddRef(V_UNKNOWN(&v3));
1658 stubMsg.Buffer = buffer;
1659 todo_wine
1660 ok(heap_unknown->refs == 3, "got refcount %ld\n", heap_unknown->refs);
1662 ok(V_VT(&v) == V_VT(&v3), "got vt %d expect %d\n", V_VT(&v), V_VT(&v3));
1663 ok(V_UNKNOWN(&v) == V_UNKNOWN(&v3), "got %p expect %p\n", V_UNKNOWN(&v), V_UNKNOWN(&v3));
1664 VARIANT_UserFree(&umcb.Flags, &v3);
1665 ok(heap_unknown->refs == 1, "%ld refcounts of IUnknown leaked\n", heap_unknown->refs - 1);
1666 IUnknown_Release(&heap_unknown->IUnknown_iface);
1667 HeapFree(GetProcessHeap(), 0, oldbuffer);
1668
1669 /*** NULL UNKNOWN ***/
1670 VariantInit(&v);
1671 V_VT(&v) = VT_UNKNOWN;
1672 V_UNKNOWN(&v) = NULL;
1673
1674 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1675 ok(stubMsg.BufferLength >= 24, "size %ld\n", stubMsg.BufferLength);
1676 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1677 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1678 memset(buffer, 0xcc, stubMsg.BufferLength);
1680 wirev = (DWORD*)buffer;
1681 wirev = check_variant_header(wirev, &v, next - buffer);
1682 ok(*wirev == 0, "wv[5] %08lx\n", *wirev);
1683
1684 VariantInit(&v2);
1685 stubMsg.Buffer = buffer;
1687 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1688 ok(V_UNKNOWN(&v2) == NULL, "got %p expect NULL\n", V_UNKNOWN(&v2));
1689 VARIANT_UserFree(&umcb.Flags, &v2);
1690 HeapFree(GetProcessHeap(), 0, oldbuffer);
1691
1692 /*** UNKNOWN BYREF ***/
1693 heap_unknown = HeapAlloc(GetProcessHeap(), 0, sizeof(*heap_unknown));
1694 heap_unknown->IUnknown_iface.lpVtbl = &HeapUnknown_Vtbl;
1695 heap_unknown->refs = 1;
1696 VariantInit(&v);
1697 VariantInit(&v2);
1698 V_VT(&v) = VT_UNKNOWN | VT_BYREF;
1699 V_UNKNOWNREF(&v) = (IUnknown **)&heap_unknown;
1700
1701 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1702 ok(stubMsg.BufferLength >= 44, "size %ld\n", stubMsg.BufferLength);
1703 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1704 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1705 memset(buffer, 0xcc, stubMsg.BufferLength);
1706 ok(heap_unknown->refs == 1, "got refcount %ld\n", heap_unknown->refs);
1708 todo_wine
1709 ok(heap_unknown->refs == 2, "got refcount %ld\n", heap_unknown->refs);
1710 wirev = (DWORD*)buffer;
1711 wirev = check_variant_header(wirev, &v, next - buffer);
1712
1713 ok(*wirev == 4, "wv[5] %08lx\n", *wirev);
1714 wirev++;
1715 todo_wine_if( *wirev == (DWORD)(DWORD_PTR)heap_unknown /* win9x */)
1716 ok(*wirev == (DWORD)(DWORD_PTR)heap_unknown + 1, "wv[6] %08lx\n", *wirev);
1717 wirev++;
1718 ok(*wirev == next - buffer - 0x24, "wv[7] %08lx\n", *wirev);
1719 wirev++;
1720 ok(*wirev == next - buffer - 0x24, "wv[8] %08lx\n", *wirev);
1721 wirev++;
1722 ok(*wirev == 0x574f454d, "wv[9] %08lx\n", *wirev);
1723
1724 VariantInit(&v3);
1725 V_VT(&v3) = VT_UNKNOWN;
1726 V_UNKNOWN(&v3) = &heap_unknown->IUnknown_iface;
1727 IUnknown_AddRef(V_UNKNOWN(&v3));
1728 stubMsg.Buffer = buffer;
1730 ok(heap_unknown->refs == 2, "got refcount %ld\n", heap_unknown->refs);
1731 ok(V_VT(&v) == V_VT(&v3), "got vt %d expect %d\n", V_VT(&v), V_VT(&v3));
1732 ok(*V_UNKNOWNREF(&v) == *V_UNKNOWNREF(&v3), "got %p expect %p\n", *V_UNKNOWNREF(&v), *V_UNKNOWNREF(&v3));
1733 size = IMalloc_GetSize(allocator, V_BYREF(&v3));
1734 ok(size == sizeof(V_BSTR(&v3)), "got size %#Ix\n", size);
1735 VARIANT_UserFree(&umcb.Flags, &v3);
1736 ok(heap_unknown->refs == 1, "%ld refcounts of IUnknown leaked\n", heap_unknown->refs - 1);
1737 IUnknown_Release(&heap_unknown->IUnknown_iface);
1738 HeapFree(GetProcessHeap(), 0, oldbuffer);
1739
1740 unk = NULL;
1741 VariantInit(&v);
1742 V_VT(&v) = VT_UNKNOWN | VT_BYREF;
1743 V_UNKNOWNREF(&v) = &unk;
1744
1745 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1746 ok(stubMsg.BufferLength >= 28, "size %ld\n", stubMsg.BufferLength);
1747 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1748 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1749 memset(buffer, 0xcc, stubMsg.BufferLength);
1751 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1752 wirev = (DWORD*)buffer;
1753 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength);
1754
1755 ok(*wirev == 4, "wv[5] %08lx\n", *wirev);
1756
1757 VariantInit(&v2);
1758 stubMsg.Buffer = buffer;
1760 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1761 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v2), V_VT(&v));
1762 ok(!*V_UNKNOWNREF(&v2), "got %p expect NULL\n", *V_UNKNOWNREF(&v2));
1763 size = IMalloc_GetSize(allocator, V_BYREF(&v2));
1764 ok(size == sizeof(V_BSTR(&v2)), "got size %#Ix\n", size);
1765 VARIANT_UserFree(&umcb.Flags, &v2);
1766 HeapFree(GetProcessHeap(), 0, oldbuffer);
1767
1768 IMalloc_Release(allocator);
1769}
1770
1771
1772START_TEST(usrmarshal)
1773{
1775
1779
1781}
ios_base &_STLP_CALL dec(ios_base &__s)
Definition: _ios_base.h:321
#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
HRESULT hr
Definition: delayimp.cpp:582
#define NULL
Definition: types.h:112
void WINAPI DECLSPEC_HOTPATCH CoUninitialize(void)
Definition: combase.c:2842
void *WINAPI CoTaskMemAlloc(SIZE_T size)
Definition: malloc.c:381
void WINAPI CoTaskMemFree(void *ptr)
Definition: malloc.c:389
HRESULT WINAPI CoGetMalloc(DWORD context, IMalloc **imalloc)
Definition: malloc.c:365
#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
GUID guid
Definition: version.c:147
static REFPROPVARIANT PROPVAR_CHANGE_FLAGS VARTYPE vt
Definition: suminfo.c:91
_ACRTIMP int __cdecl memcmp(const void *, const void *, size_t)
Definition: string.c:2807
HRESULT WINAPI CoInitialize(LPVOID lpReserved)
Definition: compobj.c:531
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 short WORD
Definition: ntddk_ex.h:93
unsigned long DWORD
Definition: ntddk_ex.h:95
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
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
#define todo_wine_if(is_todo)
Definition: minitest.h:81
#define todo_wine
Definition: minitest.h:80
static CRYPT_DATA_BLOB b2[]
Definition: msg.c:538
BOOL expected
Definition: store.c:2000
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 void test_marshal_BSTR(void)
Definition: usrmarshal.c:688
static SF_TYPE get_union_type(SAFEARRAY *psa)
Definition: usrmarshal.c:41
static void * alloc_aligned(SIZE_T size, void **buf)
Definition: usrmarshal.c:888
static void test_marshal_LPSAFEARRAY(void)
Definition: usrmarshal.c:228
static void check_bstr(void *buffer, BSTR b)
Definition: usrmarshal.c:667
static void check_safearray(void *buffer, LPSAFEARRAY lpsa)
Definition: usrmarshal.c:126
static ULONG WINAPI HeapUnknown_AddRef(IUnknown *iface)
Definition: usrmarshal.c:827
static DWORD * check_variant_header(DWORD *wirev, VARIANT *v, ULONG size)
Definition: usrmarshal.c:859
static ULONG WINAPI HeapUnknown_Release(IUnknown *iface)
Definition: usrmarshal.c:833
static ULONG get_cell_count(const SAFEARRAY *psa)
Definition: usrmarshal.c:95
static HRESULT WINAPI HeapUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
Definition: usrmarshal.c:815
static const IUnknownVtbl HeapUnknown_Vtbl
Definition: usrmarshal.c:39
static void test_marshal_VARIANT(void)
Definition: usrmarshal.c:894
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
short WCHAR
Definition: pedump.c:58
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:68
@ USER_MARSHAL_CB_BUFFER_SIZE
Definition: rpcndr.h:307
@ USER_MARSHAL_CB_UNMARSHALL
Definition: rpcndr.h:309
#define USER_MARSHAL_CB_SIGNATURE
Definition: rpcndr.h:301
#define memset(x, y, z)
Definition: compat.h:39
IUnknown IUnknown_iface
Definition: marshal.c:2847
ULONG refs
Definition: marshal.c:2848
unsigned char * Buffer
Definition: rpcndr.h:186
ULONG BufferLength
Definition: rpcndr.h:190
unsigned char * BufferEnd
Definition: rpcndr.h:188
PRPC_MESSAGE RpcMsg
Definition: rpcndr.h:185
unsigned char * BufferStart
Definition: rpcndr.h:187
unsigned int BufferLength
Definition: rpcdcep.h:41
void * Buffer
Definition: rpcdcep.h:40
USER_MARSHAL_CB_TYPE CBType
Definition: rpcndr.h:319
PFORMAT_STRING pReserve
Definition: rpcndr.h:317
ULONG Signature
Definition: rpcndr.h:318
PMIDL_STUB_MESSAGE pStubMsg
Definition: rpcndr.h:316
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 WINAPI
Definition: msvc.h:6
#define E_NOINTERFACE
Definition: winerror.h:3479