[OLEAUT32_WINETEST] Sync with Wine Staging 1.7.47. CORE-9924
[reactos.git] / rostests / winetests / oleaut32 / usrmarshal.c
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 WIN32_NO_STATUS
22 #define _INC_WINDOWS
23 #define COM_NO_WINDOWS_H
24
25 #define COBJMACROS
26 #define CONST_VTABLE
27
28 #include <stdarg.h>
29
30 #include <windef.h>
31 #include <winbase.h>
32 #include <ole2.h>
33 //#include "objbase.h"
34 //#include "propidl.h" /* for LPSAFEARRAY_User* routines */
35
36 #include <wine/test.h>
37
38 #if (__STDC__ && !defined(_FORCENAMELESSUNION)) || defined(NONAMELESSUNION)
39 # define V_U2(A) ((A)->n1.n2)
40 #else
41 # define V_U2(A) (*(A))
42 #endif
43
44 static HRESULT (WINAPI *pSafeArrayGetIID)(SAFEARRAY*,GUID*);
45 static HRESULT (WINAPI *pSafeArrayGetVartype)(SAFEARRAY*,VARTYPE*);
46 static HRESULT (WINAPI *pVarBstrCmp)(BSTR,BSTR,LCID,ULONG);
47
48 static inline SF_TYPE get_union_type(SAFEARRAY *psa)
49 {
50 VARTYPE vt;
51 HRESULT hr;
52
53 hr = pSafeArrayGetVartype(psa, &vt);
54 if (FAILED(hr))
55 {
56 if(psa->fFeatures & FADF_VARIANT) return SF_VARIANT;
57
58 switch(psa->cbElements)
59 {
60 case 1: vt = VT_I1; break;
61 case 2: vt = VT_I2; break;
62 case 4: vt = VT_I4; break;
63 case 8: vt = VT_I8; break;
64 default: return 0;
65 }
66 }
67
68 if (psa->fFeatures & FADF_HAVEIID)
69 return SF_HAVEIID;
70
71 switch (vt)
72 {
73 case VT_I1:
74 case VT_UI1: return SF_I1;
75 case VT_BOOL:
76 case VT_I2:
77 case VT_UI2: return SF_I2;
78 case VT_INT:
79 case VT_UINT:
80 case VT_I4:
81 case VT_UI4:
82 case VT_R4: return SF_I4;
83 case VT_DATE:
84 case VT_CY:
85 case VT_R8:
86 case VT_I8:
87 case VT_UI8: return SF_I8;
88 case VT_INT_PTR:
89 case VT_UINT_PTR: return (sizeof(UINT_PTR) == 4 ? SF_I4 : SF_I8);
90 case VT_BSTR: return SF_BSTR;
91 case VT_DISPATCH: return SF_DISPATCH;
92 case VT_VARIANT: return SF_VARIANT;
93 case VT_UNKNOWN: return SF_UNKNOWN;
94 /* Note: Return a non-zero size to indicate vt is valid. The actual size
95 * of a UDT is taken from the result of IRecordInfo_GetSize().
96 */
97 case VT_RECORD: return SF_RECORD;
98 default: return SF_ERROR;
99 }
100 }
101
102 static ULONG get_cell_count(const SAFEARRAY *psa)
103 {
104 const SAFEARRAYBOUND* psab = psa->rgsabound;
105 USHORT cCount = psa->cDims;
106 ULONG ulNumCells = 1;
107
108 while (cCount--)
109 {
110 if (!psab->cElements)
111 return 0;
112 ulNumCells *= psab->cElements;
113 psab++;
114 }
115 return ulNumCells;
116 }
117
118 static DWORD elem_wire_size(LPSAFEARRAY lpsa, SF_TYPE sftype)
119 {
120 if (sftype == SF_BSTR)
121 return sizeof(DWORD);
122 else
123 return lpsa->cbElements;
124 }
125
126 static 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%08x\n", *(DWORD *)wiresa);
138 return;
139 }
140
141 if (!pSafeArrayGetVartype || !pSafeArrayGetIID)
142 return;
143
144 if(FAILED(pSafeArrayGetVartype(lpsa, &vt)))
145 vt = 0;
146
147 sftype = get_union_type(lpsa);
148 cell_count = get_cell_count(lpsa);
149
150 ok(*(DWORD *)wiresa, "wiresa + 0x0 should be non-NULL instead of 0x%08x\n", *(DWORD *)wiresa); /* win2k: this is lpsa. winxp: this is 0x00000001 */
151 wiresa += sizeof(DWORD);
152 ok(*(DWORD *)wiresa == lpsa->cDims, "wiresa + 0x4 should be lpsa->cDims instead of 0x%08x\n", *(DWORD *)wiresa);
153 wiresa += sizeof(DWORD);
154 ok(*(WORD *)wiresa == lpsa->cDims, "wiresa + 0x8 should be lpsa->cDims instead of 0x%04x\n", *(WORD *)wiresa);
155 wiresa += sizeof(WORD);
156 ok(*(WORD *)wiresa == lpsa->fFeatures, "wiresa + 0xa should be lpsa->fFeatures instead of 0x%08x\n", *(WORD *)wiresa);
157 wiresa += sizeof(WORD);
158 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);
159 wiresa += sizeof(DWORD);
160 ok(*(WORD *)wiresa == lpsa->cLocks, "wiresa + 0x10 should be lpsa->cLocks instead of 0x%04x\n", *(WORD *)wiresa);
161 wiresa += sizeof(WORD);
162 ok(*(WORD *)wiresa == vt, "wiresa + 0x12 should be %04x instead of 0x%04x\n", vt, *(WORD *)wiresa);
163 wiresa += sizeof(WORD);
164 ok(*(DWORD *)wiresa == sftype, "wiresa + 0x14 should be %08x instead of 0x%08x\n", (DWORD)sftype, *(DWORD *)wiresa);
165 wiresa += sizeof(DWORD);
166 ok(*(DWORD *)wiresa == cell_count, "wiresa + 0x18 should be %u instead of %u\n", cell_count, *(DWORD *)wiresa);
167 wiresa += sizeof(DWORD);
168 ok(*(DWORD *)wiresa, "wiresa + 0x1c should be non-zero instead of 0x%08x\n", *(DWORD *)wiresa);
169 wiresa += sizeof(DWORD);
170 if(sftype == SF_HAVEIID)
171 {
172 GUID guid;
173 pSafeArrayGetIID(lpsa, &guid);
174 ok(IsEqualGUID(&guid, wiresa), "guid mismatch\n");
175 wiresa += sizeof(GUID);
176 }
177
178 /* bounds are marshaled in natural dimensions order */
179 bounds = (SAFEARRAYBOUND*)wiresa;
180 for(i=0; i<lpsa->cDims; i++)
181 {
182 ok(memcmp(bounds, &lpsa->rgsabound[lpsa->cDims-i-1], sizeof(SAFEARRAYBOUND)) == 0,
183 "bounds mismatch for dimension %d, got (%d,%d), expected (%d,%d)\n", i,
184 bounds->lLbound, bounds->cElements, lpsa->rgsabound[lpsa->cDims-i-1].lLbound,
185 lpsa->rgsabound[lpsa->cDims-i-1].cElements);
186 bounds++;
187 }
188
189 wiresa += sizeof(lpsa->rgsabound[0]) * lpsa->cDims;
190
191 ok(*(DWORD *)wiresa == cell_count, "wiresa + 0x28 should be %u instead of %u\n", cell_count, *(DWORD*)wiresa);
192 wiresa += sizeof(DWORD);
193 /* elements are now pointed to by wiresa */
194 }
195
196 static void * WINAPI user_allocate(SIZE_T size)
197 {
198 ok(0, "unexpected user_allocate call\n");
199 return CoTaskMemAlloc(size);
200 }
201
202 static void WINAPI user_free(void *p)
203 {
204 ok(0, "unexpected user_free call\n");
205 CoTaskMemFree(p);
206 }
207
208 static void init_user_marshal_cb(USER_MARSHAL_CB *umcb,
209 PMIDL_STUB_MESSAGE stub_msg,
210 PRPC_MESSAGE rpc_msg, unsigned char *buffer,
211 unsigned int size, MSHCTX context)
212 {
213 memset(rpc_msg, 0, sizeof(*rpc_msg));
214 rpc_msg->Buffer = buffer;
215 rpc_msg->BufferLength = size;
216
217 memset(stub_msg, 0, sizeof(*stub_msg));
218 stub_msg->RpcMsg = rpc_msg;
219 stub_msg->Buffer = buffer;
220 stub_msg->pfnAllocate = user_allocate;
221 stub_msg->pfnFree = user_free;
222
223 memset(umcb, 0, sizeof(*umcb));
224 umcb->Flags = MAKELONG(context, NDR_LOCAL_DATA_REPRESENTATION);
225 umcb->pStubMsg = stub_msg;
226 umcb->Signature = USER_MARSHAL_CB_SIGNATURE;
227 umcb->CBType = buffer ? USER_MARSHAL_CB_UNMARSHALL : USER_MARSHAL_CB_BUFFER_SIZE;
228 }
229
230 static void test_marshal_LPSAFEARRAY(void)
231 {
232 unsigned char *buffer, *next;
233 ULONG size, expected;
234 LPSAFEARRAY lpsa;
235 LPSAFEARRAY lpsa2 = NULL;
236 SAFEARRAYBOUND sab[2];
237 RPC_MESSAGE rpc_msg;
238 MIDL_STUB_MESSAGE stub_msg;
239 USER_MARSHAL_CB umcb;
240 HRESULT hr;
241 VARTYPE vt, vt2;
242 OLECHAR *values[10];
243 int expected_bstr_size;
244 int i;
245 LONG indices[1];
246
247 sab[0].lLbound = 5;
248 sab[0].cElements = 10;
249
250 lpsa = SafeArrayCreate(VT_I2, 1, sab);
251 *(DWORD *)lpsa->pvData = 0xcafebabe;
252
253 lpsa->cLocks = 7;
254 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
255 size = LPSAFEARRAY_UserSize(&umcb.Flags, 1, &lpsa);
256 expected = (44 + 1 + sizeof(ULONG) - 1) & ~(sizeof(ULONG) - 1);
257 expected += sab[0].cElements * sizeof(USHORT);
258 ok(size == expected || size == expected + 12, /* win64 */
259 "size should be %u bytes, not %u\n", expected, size);
260 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
261 size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
262 expected = 44 + sab[0].cElements * sizeof(USHORT);
263 ok(size == expected || size == expected + 12, /* win64 */
264 "size should be %u bytes, not %u\n", expected, size);
265 buffer = HeapAlloc(GetProcessHeap(), 0, size);
266 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
267 next = LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
268 ok(next - buffer == expected, "Marshaled %u bytes, expected %u\n", (ULONG) (next - buffer), expected);
269 ok(lpsa->cLocks == 7, "got lock count %u\n", lpsa->cLocks);
270
271 check_safearray(buffer, lpsa);
272
273 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
274 LPSAFEARRAY_UserUnmarshal(&umcb.Flags, buffer, &lpsa2);
275 ok(lpsa2 != NULL, "LPSAFEARRAY didn't unmarshal\n");
276 if (pSafeArrayGetVartype)
277 {
278 pSafeArrayGetVartype(lpsa, &vt);
279 pSafeArrayGetVartype(lpsa2, &vt2);
280 ok(vt == vt2, "vts differ %x %x\n", vt, vt2);
281 }
282 ok(lpsa2->cLocks == 0, "got lock count %u, expected 0\n", lpsa2->cLocks);
283 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
284 LPSAFEARRAY_UserFree(&umcb.Flags, &lpsa2);
285 HeapFree(GetProcessHeap(), 0, buffer);
286 lpsa->cLocks = 0;
287 hr = SafeArrayDestroy(lpsa);
288 ok(hr == S_OK, "got 0x%08x\n", hr);
289
290 /* use two dimensions */
291 sab[0].lLbound = 5;
292 sab[0].cElements = 10;
293 sab[1].lLbound = 1;
294 sab[1].cElements = 2;
295
296 lpsa = SafeArrayCreate(VT_I2, 2, sab);
297 *(DWORD *)lpsa->pvData = 0xcafebabe;
298
299 lpsa->cLocks = 7;
300 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
301 size = LPSAFEARRAY_UserSize(&umcb.Flags, 1, &lpsa);
302 expected = (44 + 1 + +sizeof(SAFEARRAYBOUND) + sizeof(ULONG) - 1) & ~(sizeof(ULONG) - 1);
303 expected += max(sab[0].cElements, sab[1].cElements) * lpsa->cDims * sizeof(USHORT);
304 ok(size == expected || size == expected + 12, /* win64 */
305 "size should be %u bytes, not %u\n", expected, size);
306 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
307 size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
308 expected = 52 + max(sab[0].cElements, sab[1].cElements) * lpsa->cDims * sizeof(USHORT);
309 ok(size == expected || size == expected + 12, /* win64 */
310 "size should be %u bytes, not %u\n", expected, size);
311 buffer = HeapAlloc(GetProcessHeap(), 0, size);
312 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
313 next = LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
314 ok(next - buffer == expected, "Marshaled %u bytes, expected %u\n", (ULONG) (next - buffer), expected);
315 ok(lpsa->cLocks == 7, "got lock count %u\n", lpsa->cLocks);
316
317 check_safearray(buffer, lpsa);
318
319 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
320 LPSAFEARRAY_UserUnmarshal(&umcb.Flags, buffer, &lpsa2);
321 ok(lpsa2 != NULL, "LPSAFEARRAY didn't unmarshal\n");
322 if (pSafeArrayGetVartype)
323 {
324 pSafeArrayGetVartype(lpsa, &vt);
325 pSafeArrayGetVartype(lpsa2, &vt2);
326 ok(vt == vt2, "vts differ %x %x\n", vt, vt2);
327 }
328 ok(lpsa2->cLocks == 0, "got lock count %u, expected 0\n", lpsa2->cLocks);
329 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
330 LPSAFEARRAY_UserFree(&umcb.Flags, &lpsa2);
331 HeapFree(GetProcessHeap(), 0, buffer);
332 lpsa->cLocks = 0;
333 hr = SafeArrayDestroy(lpsa);
334 ok(hr == S_OK, "got 0x%08x\n", hr);
335
336 /* test NULL safe array */
337 lpsa = NULL;
338
339 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
340 size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
341 expected = 4;
342 ok(size == expected, "size should be 4 bytes, not %d\n", size);
343 buffer = HeapAlloc(GetProcessHeap(), 0, size);
344 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
345 next = LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
346 ok(next - buffer == expected, "Marshaled %u bytes, expected %u\n", (ULONG) (next - buffer), expected);
347 check_safearray(buffer, lpsa);
348
349 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
350 LPSAFEARRAY_UserUnmarshal(&umcb.Flags, buffer, &lpsa2);
351 ok(lpsa2 == NULL, "NULL LPSAFEARRAY didn't unmarshal\n");
352 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
353 LPSAFEARRAY_UserFree(&umcb.Flags, &lpsa2);
354 HeapFree(GetProcessHeap(), 0, buffer);
355
356 sab[0].lLbound = 5;
357 sab[0].cElements = 10;
358
359 lpsa = SafeArrayCreate(VT_R8, 1, sab);
360 *(double *)lpsa->pvData = 3.1415;
361
362 lpsa->cLocks = 7;
363 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
364 size = LPSAFEARRAY_UserSize(&umcb.Flags, 1, &lpsa);
365 expected = (44 + 1 + (sizeof(double) - 1)) & ~(sizeof(double) - 1);
366 expected += sab[0].cElements * sizeof(double);
367 ok(size == expected || size == expected + 16, /* win64 */
368 "size should be %u bytes, not %u\n", expected, size);
369 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
370 expected = (44 + (sizeof(double) - 1)) & ~(sizeof(double) - 1);
371 expected += sab[0].cElements * sizeof(double);
372 size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
373 ok(size == expected || size == expected + 8, /* win64 */
374 "size should be %u bytes, not %u\n", expected, size);
375 buffer = HeapAlloc(GetProcessHeap(), 0, size);
376 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
377 next = LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
378 ok(next - buffer == expected || broken(next - buffer + sizeof(DWORD) == expected),
379 "Marshaled %u bytes, expected %u\n", (ULONG) (next - buffer), expected);
380
381 check_safearray(buffer, lpsa);
382
383 HeapFree(GetProcessHeap(), 0, buffer);
384 lpsa->cLocks = 0;
385 hr = SafeArrayDestroy(lpsa);
386 ok(hr == S_OK, "got 0x%08x\n", hr);
387
388 /* VARTYPE-less arrays can be marshaled if cbElements is 1,2,4 or 8 as type SF_In */
389 hr = SafeArrayAllocDescriptor(1, &lpsa);
390 ok(hr == S_OK, "saad failed %08x\n", hr);
391 lpsa->cbElements = 8;
392 lpsa->rgsabound[0].lLbound = 2;
393 lpsa->rgsabound[0].cElements = 48;
394 hr = SafeArrayAllocData(lpsa);
395 ok(hr == S_OK, "saad failed %08x\n", hr);
396
397 if (pSafeArrayGetVartype)
398 {
399 hr = pSafeArrayGetVartype(lpsa, &vt);
400 ok(hr == E_INVALIDARG, "ret %08x\n", hr);
401 }
402
403 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
404 size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
405 expected = (44 + lpsa->cbElements - 1) & ~(lpsa->cbElements - 1);
406 expected += lpsa->cbElements * lpsa->rgsabound[0].cElements;
407 ok(size == expected || size == expected + 8, /* win64 */
408 "size should be %u bytes, not %u\n", expected, size);
409 buffer = HeapAlloc(GetProcessHeap(), 0, size);
410 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
411 next = LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
412 ok(next - buffer == expected || broken(next - buffer + sizeof(DWORD) == expected),
413 "Marshaled %u bytes, expected %u\n", (ULONG) (next - buffer), expected);
414 check_safearray(buffer, lpsa);
415 HeapFree(GetProcessHeap(), 0, buffer);
416 hr = SafeArrayDestroyData(lpsa);
417 ok(hr == S_OK, "got 0x%08x\n", hr);
418 hr = SafeArrayDestroyDescriptor(lpsa);
419 ok(hr == S_OK, "got 0x%08x\n", hr);
420
421 /* Test an array of VT_BSTR */
422 sab[0].lLbound = 3;
423 sab[0].cElements = sizeof(values) / sizeof(values[0]);
424
425 lpsa = SafeArrayCreate(VT_BSTR, 1, sab);
426 expected_bstr_size = 0;
427 for (i = 0; i < sab[0].cElements; i++)
428 {
429 int j;
430 WCHAR buf[128];
431 for (j = 0; j <= i; j++)
432 buf[j] = 'a' + j;
433 buf[j] = 0;
434 indices[0] = i + sab[0].lLbound;
435 values[i] = SysAllocString(buf);
436 hr = SafeArrayPutElement(lpsa, indices, values[i]);
437 ok(hr == S_OK, "Failed to put bstr element hr 0x%x\n", hr);
438 expected_bstr_size += (j * sizeof(WCHAR)) + (3 * sizeof(DWORD));
439 if (i % 2 == 0) /* Account for DWORD padding. Works so long as cElements is even */
440 expected_bstr_size += sizeof(WCHAR);
441 }
442
443 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
444 size = LPSAFEARRAY_UserSize(&umcb.Flags, 1, &lpsa);
445 expected = 44 + (sab[0].cElements * sizeof(DWORD)) + expected_bstr_size;
446 todo_wine
447 ok(size == expected + sizeof(DWORD) || size == (expected + sizeof(DWORD) + 12 /* win64 */),
448 "size should be %u bytes, not %u\n", expected + (ULONG) sizeof(DWORD), size);
449 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
450 size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
451 todo_wine
452 ok(size == expected || size == (expected + 12 /* win64 */),
453 "size should be %u bytes, not %u\n", expected, size);
454 buffer = HeapAlloc(GetProcessHeap(), 0, size);
455 memset(buffer, 0xcc, size);
456 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
457 next = LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
458 todo_wine
459 ok(next - buffer == expected, "Marshaled %u bytes, expected %u\n", (ULONG) (next - buffer), expected);
460
461 check_safearray(buffer, lpsa);
462
463 lpsa2 = NULL;
464 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
465 next = LPSAFEARRAY_UserUnmarshal(&umcb.Flags, buffer, &lpsa2);
466 todo_wine
467 ok(next - buffer == expected, "Marshaled %u bytes, expected %u\n", (ULONG) (next - buffer), expected);
468 ok(lpsa2 != NULL, "LPSAFEARRAY didn't unmarshal, result %p\n", next);
469
470 for (i = 0; i < sizeof(values) / sizeof(values[0]); i++)
471 {
472 BSTR gotvalue = NULL;
473
474 if (lpsa2)
475 {
476 indices[0] = i + sab[0].lLbound;
477 hr = SafeArrayGetElement(lpsa2, indices, &gotvalue);
478 ok(hr == S_OK, "Failed to get bstr element at hres 0x%x\n", hr);
479 if (hr == S_OK)
480 {
481 if (pVarBstrCmp)
482 ok(pVarBstrCmp(values[i], gotvalue, 0, 0) == VARCMP_EQ, "String %d does not match\n", i);
483 SysFreeString(gotvalue);
484 }
485 }
486
487 SysFreeString(values[i]);
488 }
489
490 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
491 LPSAFEARRAY_UserFree(&umcb.Flags, &lpsa2);
492
493 HeapFree(GetProcessHeap(), 0, buffer);
494 hr = SafeArrayDestroy(lpsa);
495 ok(hr == S_OK, "got 0x%08x\n", hr);
496
497 /* VARTYPE-less arrays with FADF_VARIANT */
498 hr = SafeArrayAllocDescriptor(1, &lpsa);
499 ok(hr == S_OK, "saad failed %08x\n", hr);
500 lpsa->cbElements = sizeof(VARIANT);
501 lpsa->fFeatures = FADF_VARIANT;
502 lpsa->rgsabound[0].lLbound = 2;
503 lpsa->rgsabound[0].cElements = 48;
504 hr = SafeArrayAllocData(lpsa);
505 ok(hr == S_OK, "saad failed %08x\n", hr);
506
507 if (pSafeArrayGetVartype)
508 {
509 hr = pSafeArrayGetVartype(lpsa, &vt);
510 ok(hr == E_INVALIDARG, "ret %08x\n", hr);
511 }
512
513 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
514 size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
515 expected = 44 + 28 * lpsa->rgsabound[0].cElements;
516 todo_wine
517 ok(size == expected || size == expected + 8, /* win64 */
518 "size should be %u bytes, not %u\n", expected, size);
519 buffer = HeapAlloc(GetProcessHeap(), 0, size);
520 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
521 next = LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
522 todo_wine
523 ok(next - buffer == expected || broken(next - buffer + sizeof(DWORD) == expected),
524 "Marshaled %u bytes, expected %u\n", (ULONG) (next - buffer), expected);
525 lpsa->cbElements = 16; /* VARIANT wire size */
526 check_safearray(buffer, lpsa);
527 HeapFree(GetProcessHeap(), 0, buffer);
528 hr = SafeArrayDestroyData(lpsa);
529 ok(hr == S_OK, "got 0x%08x\n", hr);
530 hr = SafeArrayDestroyDescriptor(lpsa);
531 ok(hr == S_OK, "got 0x%08x\n", hr);
532 }
533
534 static void check_bstr(void *buffer, BSTR b)
535 {
536 DWORD *wireb = buffer;
537 DWORD len = SysStringByteLen(b);
538
539 ok(*wireb == (len + 1) / 2, "wv[0] %08x\n", *wireb);
540 wireb++;
541 if(b)
542 ok(*wireb == len, "wv[1] %08x\n", *wireb);
543 else
544 ok(*wireb == 0xffffffff, "wv[1] %08x\n", *wireb);
545 wireb++;
546 ok(*wireb == (len + 1) / 2, "wv[2] %08x\n", *wireb);
547 if(len)
548 {
549 wireb++;
550 ok(!memcmp(wireb, b, (len + 1) & ~1), "strings differ\n");
551 }
552 return;
553 }
554
555 static void test_marshal_BSTR(void)
556 {
557 ULONG size;
558 RPC_MESSAGE rpc_msg;
559 MIDL_STUB_MESSAGE stub_msg;
560 USER_MARSHAL_CB umcb;
561 unsigned char *buffer, *next;
562 BSTR b, b2;
563 WCHAR str[] = {'m','a','r','s','h','a','l',' ','t','e','s','t','1',0};
564 DWORD len;
565
566 b = SysAllocString(str);
567 len = SysStringLen(b);
568 ok(len == 13, "get %d\n", len);
569
570 /* BSTRs are DWORD aligned */
571
572 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
573 size = BSTR_UserSize(&umcb.Flags, 1, &b);
574 ok(size == 42, "size %d\n", size);
575
576 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
577 size = BSTR_UserSize(&umcb.Flags, 0, &b);
578 ok(size == 38, "size %d\n", size);
579
580 buffer = HeapAlloc(GetProcessHeap(), 0, size);
581 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
582 next = BSTR_UserMarshal(&umcb.Flags, buffer, &b);
583 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
584 check_bstr(buffer, b);
585
586 b2 = NULL;
587 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
588 next = BSTR_UserUnmarshal(&umcb.Flags, buffer, &b2);
589 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
590 ok(b2 != NULL, "BSTR didn't unmarshal\n");
591 ok(!memcmp(b, b2, (len + 1) * 2), "strings differ\n");
592 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
593 BSTR_UserFree(&umcb.Flags, &b2);
594
595 HeapFree(GetProcessHeap(), 0, buffer);
596 SysFreeString(b);
597
598 b = NULL;
599 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
600 size = BSTR_UserSize(&umcb.Flags, 0, &b);
601 ok(size == 12, "size %d\n", size);
602
603 buffer = HeapAlloc(GetProcessHeap(), 0, size);
604 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
605 next = BSTR_UserMarshal(&umcb.Flags, buffer, &b);
606 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
607
608 check_bstr(buffer, b);
609 b2 = NULL;
610 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
611 next = BSTR_UserUnmarshal(&umcb.Flags, buffer, &b2);
612 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
613 ok(b2 == NULL, "NULL BSTR didn't unmarshal\n");
614 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
615 BSTR_UserFree(&umcb.Flags, &b2);
616 HeapFree(GetProcessHeap(), 0, buffer);
617
618 b = SysAllocStringByteLen("abc", 3);
619 *(((char*)b) + 3) = 'd';
620 len = SysStringLen(b);
621 ok(len == 1, "get %d\n", len);
622 len = SysStringByteLen(b);
623 ok(len == 3, "get %d\n", len);
624
625 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
626 size = BSTR_UserSize(&umcb.Flags, 0, &b);
627 ok(size == 16, "size %d\n", size);
628
629 buffer = HeapAlloc(GetProcessHeap(), 0, size);
630 memset(buffer, 0xcc, size);
631 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
632 next = BSTR_UserMarshal(&umcb.Flags, buffer, &b);
633 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
634 check_bstr(buffer, b);
635 ok(buffer[15] == 'd', "buffer[15] %02x\n", buffer[15]);
636
637 b2 = NULL;
638 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
639 next = BSTR_UserUnmarshal(&umcb.Flags, buffer, &b2);
640 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
641 ok(b2 != NULL, "BSTR didn't unmarshal\n");
642 ok(!memcmp(b, b2, len), "strings differ\n");
643 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
644 BSTR_UserFree(&umcb.Flags, &b2);
645 HeapFree(GetProcessHeap(), 0, buffer);
646 SysFreeString(b);
647
648 b = SysAllocStringByteLen("", 0);
649 len = SysStringLen(b);
650 ok(len == 0, "get %d\n", len);
651 len = SysStringByteLen(b);
652 ok(len == 0, "get %d\n", len);
653
654 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
655 size = BSTR_UserSize(&umcb.Flags, 0, &b);
656 ok(size == 12, "size %d\n", size);
657
658 buffer = HeapAlloc(GetProcessHeap(), 0, size);
659 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
660 next = BSTR_UserMarshal(&umcb.Flags, buffer, &b);
661 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
662 check_bstr(buffer, b);
663
664 b2 = NULL;
665 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
666 next = BSTR_UserUnmarshal(&umcb.Flags, buffer, &b2);
667 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
668 ok(b2 != NULL, "NULL LPSAFEARRAY didn't unmarshal\n");
669 len = SysStringByteLen(b2);
670 ok(len == 0, "byte len %d\n", len);
671 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
672 BSTR_UserFree(&umcb.Flags, &b2);
673 HeapFree(GetProcessHeap(), 0, buffer);
674 SysFreeString(b);
675 }
676
677 typedef struct
678 {
679 IUnknown IUnknown_iface;
680 ULONG refs;
681 } HeapUnknown;
682
683 static inline HeapUnknown *impl_from_IUnknown(IUnknown *iface)
684 {
685 return CONTAINING_RECORD(iface, HeapUnknown, IUnknown_iface);
686 }
687
688 static HRESULT WINAPI HeapUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
689 {
690 if (IsEqualIID(riid, &IID_IUnknown))
691 {
692 IUnknown_AddRef(iface);
693 *ppv = iface;
694 return S_OK;
695 }
696 *ppv = NULL;
697 return E_NOINTERFACE;
698 }
699
700 static ULONG WINAPI HeapUnknown_AddRef(IUnknown *iface)
701 {
702 HeapUnknown *This = impl_from_IUnknown(iface);
703 return InterlockedIncrement((LONG*)&This->refs);
704 }
705
706 static ULONG WINAPI HeapUnknown_Release(IUnknown *iface)
707 {
708 HeapUnknown *This = impl_from_IUnknown(iface);
709 ULONG refs = InterlockedDecrement((LONG*)&This->refs);
710 if (!refs) HeapFree(GetProcessHeap(), 0, This);
711 return refs;
712 }
713
714 static const IUnknownVtbl HeapUnknown_Vtbl =
715 {
716 HeapUnknown_QueryInterface,
717 HeapUnknown_AddRef,
718 HeapUnknown_Release
719 };
720
721 typedef struct
722 {
723 DWORD clSize;
724 DWORD rpcReserved;
725 USHORT vt;
726 USHORT wReserved1;
727 USHORT wReserved2;
728 USHORT wReserved3;
729 DWORD switch_is;
730 } variant_wire_t;
731
732 static DWORD *check_variant_header(DWORD *wirev, VARIANT *v, ULONG size)
733 {
734 const variant_wire_t *header = (const variant_wire_t*)wirev;
735 DWORD switch_is;
736
737 ok(header->clSize == (size + 7) >> 3, "wv[0] %08x, expected %08x\n", header->clSize, (size + 7) >> 3);
738 ok(header->rpcReserved == 0, "wv[1] %08x\n", header->rpcReserved);
739 ok(header->vt == V_VT(v), "vt %04x expected %04x\n", header->vt, V_VT(v));
740 ok(header->wReserved1 == V_U2(v).wReserved1, "res1 %04x expected %04x\n", header->wReserved1, V_U2(v).wReserved1);
741 ok(header->wReserved2 == V_U2(v).wReserved2, "res2 %04x expected %04x\n", header->wReserved2, V_U2(v).wReserved2);
742 ok(header->wReserved3 == V_U2(v).wReserved3, "res3 %04x expected %04x\n", header->wReserved3, V_U2(v).wReserved3);
743
744 switch_is = V_VT(v);
745 if(switch_is & VT_ARRAY)
746 switch_is &= ~VT_TYPEMASK;
747 ok(header->switch_is == switch_is, "switch_is %08x expected %08x\n", header->switch_is, switch_is);
748
749 return (DWORD*)((unsigned char*)wirev + sizeof(variant_wire_t));
750 }
751
752 /* Win9x and WinME don't always align as needed. Variants have
753 * an alignment of 8.
754 */
755 static void *alloc_aligned(SIZE_T size, void **buf)
756 {
757 *buf = HeapAlloc(GetProcessHeap(), 0, size + 7);
758 return (void *)(((UINT_PTR)*buf + 7) & ~7);
759 }
760
761 static void test_marshal_VARIANT(void)
762 {
763 VARIANT v, v2, v3;
764 MIDL_STUB_MESSAGE stubMsg = { 0 };
765 RPC_MESSAGE rpcMsg = { 0 };
766 USER_MARSHAL_CB umcb = { 0 };
767 unsigned char *buffer, *next;
768 void *oldbuffer;
769 ULONG ul;
770 short s;
771 double d;
772 void *mem;
773 DWORD *wirev;
774 BSTR b;
775 WCHAR str[] = {'m','a','r','s','h','a','l',' ','t','e','s','t',0};
776 SAFEARRAYBOUND sab;
777 LPSAFEARRAY lpsa;
778 DECIMAL dec, dec2;
779 HeapUnknown *heap_unknown;
780 DWORD expected;
781 HRESULT hr;
782 LONG bound, bound2;
783 VARTYPE vt, vt2;
784
785 stubMsg.RpcMsg = &rpcMsg;
786
787 umcb.Flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
788 umcb.pStubMsg = &stubMsg;
789 umcb.pReserve = NULL;
790 umcb.Signature = USER_MARSHAL_CB_SIGNATURE;
791 umcb.CBType = USER_MARSHAL_CB_UNMARSHALL;
792
793 /*** I1 ***/
794 VariantInit(&v);
795 V_VT(&v) = VT_I1;
796 V_I1(&v) = 0x12;
797
798 /* check_variant_header tests wReserved[123], so initialize to unique values.
799 * (Could probably also do this by setting the variant to a known DECIMAL.)
800 */
801 V_U2(&v).wReserved1 = 0x1234;
802 V_U2(&v).wReserved2 = 0x5678;
803 V_U2(&v).wReserved3 = 0x9abc;
804
805 /* Variants have an alignment of 8 */
806 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 1, &v);
807 ok(stubMsg.BufferLength == 29, "size %d\n", stubMsg.BufferLength);
808
809 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
810 ok(stubMsg.BufferLength == 21, "size %d\n", stubMsg.BufferLength);
811
812 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
813 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
814 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
815 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
816 wirev = (DWORD*)buffer;
817
818 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength);
819 ok(*(char*)wirev == V_I1(&v), "wv[5] %08x\n", *wirev);
820 VariantInit(&v2);
821 stubMsg.Buffer = buffer;
822 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
823 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
824 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
825 ok(V_I1(&v) == V_I1(&v2), "got i1 %x expect %x\n", V_I1(&v), V_I1(&v2));
826
827 VARIANT_UserFree(&umcb.Flags, &v2);
828 HeapFree(GetProcessHeap(), 0, oldbuffer);
829
830 /*** I2 ***/
831 VariantInit(&v);
832 V_VT(&v) = VT_I2;
833 V_I2(&v) = 0x1234;
834
835 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
836 ok(stubMsg.BufferLength == 22, "size %d\n", stubMsg.BufferLength);
837
838 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
839 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
840 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
841 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
842 wirev = (DWORD*)buffer;
843
844 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength);
845 ok(*(short*)wirev == V_I2(&v), "wv[5] %08x\n", *wirev);
846 VariantInit(&v2);
847 stubMsg.Buffer = buffer;
848 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
849 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
850 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
851 ok(V_I2(&v) == V_I2(&v2), "got i2 %x expect %x\n", V_I2(&v), V_I2(&v2));
852
853 VARIANT_UserFree(&umcb.Flags, &v2);
854 HeapFree(GetProcessHeap(), 0, oldbuffer);
855
856 /*** I2 BYREF ***/
857 VariantInit(&v);
858 V_VT(&v) = VT_I2 | VT_BYREF;
859 s = 0x1234;
860 V_I2REF(&v) = &s;
861
862 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
863 ok(stubMsg.BufferLength == 26, "size %d\n", stubMsg.BufferLength);
864
865 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
866 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
867 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
868 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
869 wirev = (DWORD*)buffer;
870
871 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength);
872 ok(*wirev == 0x4, "wv[5] %08x\n", *wirev);
873 wirev++;
874 ok(*(short*)wirev == s, "wv[6] %08x\n", *wirev);
875 VariantInit(&v2);
876 V_VT(&v2) = VT_I2 | VT_BYREF;
877 V_BYREF(&v2) = mem = CoTaskMemAlloc(sizeof(V_I2(&v2)));
878 stubMsg.Buffer = buffer;
879 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
880 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
881 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
882 ok(V_BYREF(&v2) == mem, "didn't reuse existing memory\n");
883 ok(*V_I2REF(&v) == *V_I2REF(&v2), "got i2 ref %x expect ui4 ref %x\n", *V_I2REF(&v), *V_I2REF(&v2));
884
885 VARIANT_UserFree(&umcb.Flags, &v2);
886 HeapFree(GetProcessHeap(), 0, oldbuffer);
887
888 /*** I4 ***/
889 VariantInit(&v);
890 V_VT(&v) = VT_I4;
891 V_I4(&v) = 0x1234;
892
893 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
894 ok(stubMsg.BufferLength == 24, "size %d\n", stubMsg.BufferLength);
895
896 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
897 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
898 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
899 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
900 wirev = (DWORD*)buffer;
901
902 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength);
903 ok(*wirev == V_I4(&v), "wv[5] %08x\n", *wirev);
904
905 VariantInit(&v2);
906 stubMsg.Buffer = buffer;
907 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
908 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
909 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
910 ok(V_I4(&v) == V_I4(&v2), "got i4 %x expect %x\n", V_I4(&v), V_I4(&v2));
911
912 VARIANT_UserFree(&umcb.Flags, &v2);
913 HeapFree(GetProcessHeap(), 0, oldbuffer);
914
915 /*** UI4 ***/
916 VariantInit(&v);
917 V_VT(&v) = VT_UI4;
918 V_UI4(&v) = 0x1234;
919
920 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
921 ok(stubMsg.BufferLength == 24, "size %d\n", stubMsg.BufferLength);
922
923 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
924 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
925 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
926 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
927 wirev = (DWORD*)buffer;
928
929 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength);
930 ok(*wirev == 0x1234, "wv[5] %08x\n", *wirev);
931 VariantInit(&v2);
932 stubMsg.Buffer = buffer;
933 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
934 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
935 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
936 ok(V_UI4(&v) == V_UI4(&v2), "got ui4 %x expect %x\n", V_UI4(&v), V_UI4(&v2));
937
938 VARIANT_UserFree(&umcb.Flags, &v2);
939 HeapFree(GetProcessHeap(), 0, oldbuffer);
940
941 /*** UI4 BYREF ***/
942 VariantInit(&v);
943 V_VT(&v) = VT_UI4 | VT_BYREF;
944 ul = 0x1234;
945 V_UI4REF(&v) = &ul;
946
947 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
948 ok(stubMsg.BufferLength == 28, "size %d\n", stubMsg.BufferLength);
949
950 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
951 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
952 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
953 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
954 wirev = (DWORD*)buffer;
955
956 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength);
957 ok(*wirev == 0x4, "wv[5] %08x\n", *wirev);
958 wirev++;
959 ok(*wirev == ul, "wv[6] %08x\n", *wirev);
960
961 VariantInit(&v2);
962 stubMsg.Buffer = buffer;
963 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
964 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
965 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
966 ok(*V_UI4REF(&v) == *V_UI4REF(&v2), "got ui4 ref %x expect ui4 ref %x\n", *V_UI4REF(&v), *V_UI4REF(&v2));
967
968 VARIANT_UserFree(&umcb.Flags, &v2);
969 HeapFree(GetProcessHeap(), 0, oldbuffer);
970
971 /*** R4 ***/
972 VariantInit(&v);
973 V_VT(&v) = VT_R4;
974 V_R8(&v) = 3.1415;
975
976 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
977 ok(stubMsg.BufferLength == 24, "size %d\n", stubMsg.BufferLength);
978
979 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
980 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
981 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
982 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
983 wirev = (DWORD*)buffer;
984
985 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength);
986 ok(*(float*)wirev == V_R4(&v), "wv[5] %08x\n", *wirev);
987 VariantInit(&v2);
988 stubMsg.Buffer = buffer;
989 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
990 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
991 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
992 ok(V_R4(&v) == V_R4(&v2), "got r4 %f expect %f\n", V_R4(&v), V_R4(&v2));
993
994 VARIANT_UserFree(&umcb.Flags, &v2);
995 HeapFree(GetProcessHeap(), 0, oldbuffer);
996
997 /*** R8 ***/
998 VariantInit(&v);
999 V_VT(&v) = VT_R8;
1000 V_R8(&v) = 3.1415;
1001
1002 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1003 ok(stubMsg.BufferLength == 32, "size %d\n", stubMsg.BufferLength);
1004
1005 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1006 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1007 memset(buffer, 0xcc, stubMsg.BufferLength);
1008 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1009 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1010 wirev = (DWORD*)buffer;
1011
1012 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength);
1013 ok(*wirev == 0xcccccccc, "wv[5] %08x\n", *wirev); /* pad */
1014 wirev++;
1015 ok(*(double*)wirev == V_R8(&v), "wv[6] %08x, wv[7] %08x\n", *wirev, *(wirev+1));
1016 VariantInit(&v2);
1017 stubMsg.Buffer = buffer;
1018 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1019 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1020 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1021 ok(V_R8(&v) == V_R8(&v2), "got r8 %f expect %f\n", V_R8(&v), V_R8(&v2));
1022
1023 VARIANT_UserFree(&umcb.Flags, &v2);
1024 HeapFree(GetProcessHeap(), 0, oldbuffer);
1025
1026 /*** R8 BYREF ***/
1027 VariantInit(&v);
1028 V_VT(&v) = VT_R8 | VT_BYREF;
1029 d = 3.1415;
1030 V_R8REF(&v) = &d;
1031
1032 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1033 ok(stubMsg.BufferLength == 32, "size %d\n", stubMsg.BufferLength);
1034
1035 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1036 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1037 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1038 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1039 wirev = (DWORD*)buffer;
1040
1041 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength);
1042 ok(*wirev == 8, "wv[5] %08x\n", *wirev);
1043 wirev++;
1044 ok(*(double*)wirev == d, "wv[6] %08x wv[7] %08x\n", *wirev, *(wirev+1));
1045 VariantInit(&v2);
1046 stubMsg.Buffer = buffer;
1047 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1048 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1049 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1050 ok(*V_R8REF(&v) == *V_R8REF(&v2), "got r8 ref %f expect %f\n", *V_R8REF(&v), *V_R8REF(&v2));
1051
1052 VARIANT_UserFree(&umcb.Flags, &v2);
1053 HeapFree(GetProcessHeap(), 0, oldbuffer);
1054
1055 /*** VARIANT_BOOL ***/
1056 VariantInit(&v);
1057 V_VT(&v) = VT_BOOL;
1058 V_BOOL(&v) = 0x1234;
1059
1060 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1061 ok(stubMsg.BufferLength == 22, "size %d\n", stubMsg.BufferLength);
1062
1063 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1064 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1065 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1066 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1067 wirev = (DWORD*)buffer;
1068
1069 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength);
1070 ok(*(short*)wirev == V_BOOL(&v), "wv[5] %04x\n", *(WORD*)wirev);
1071 VariantInit(&v2);
1072 stubMsg.Buffer = buffer;
1073 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1074 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1075 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1076 ok(V_BOOL(&v) == V_BOOL(&v2), "got bool %x expect %x\n", V_BOOL(&v), V_BOOL(&v2));
1077
1078 VARIANT_UserFree(&umcb.Flags, &v2);
1079 HeapFree(GetProcessHeap(), 0, oldbuffer);
1080
1081 /*** DECIMAL ***/
1082 VarDecFromI4(0x12345678, &dec);
1083 dec.wReserved = 0xfedc; /* Also initialize reserved field, as we check it later */
1084 VariantInit(&v);
1085 V_DECIMAL(&v) = dec;
1086 V_VT(&v) = VT_DECIMAL;
1087
1088 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1089 ok(stubMsg.BufferLength == 40, "size %d\n", stubMsg.BufferLength);
1090
1091 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1092 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1093 memset(buffer, 0xcc, stubMsg.BufferLength);
1094 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1095 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1096 wirev = (DWORD*)buffer;
1097
1098 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength);
1099 ok(*wirev == 0xcccccccc, "wirev[5] %08x\n", *wirev); /* pad */
1100 wirev++;
1101 dec2 = dec;
1102 dec2.wReserved = VT_DECIMAL;
1103 ok(!memcmp(wirev, &dec2, sizeof(dec2)), "wirev[6] %08x wirev[7] %08x wirev[8] %08x wirev[9] %08x\n",
1104 *wirev, *(wirev + 1), *(wirev + 2), *(wirev + 3));
1105 VariantInit(&v2);
1106 stubMsg.Buffer = buffer;
1107 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1108 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1109 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1110 ok(!memcmp(&V_DECIMAL(&v), & V_DECIMAL(&v2), sizeof(DECIMAL)), "decimals differ\n");
1111
1112 VARIANT_UserFree(&umcb.Flags, &v2);
1113 HeapFree(GetProcessHeap(), 0, oldbuffer);
1114
1115 /*** DECIMAL BYREF ***/
1116 VariantInit(&v);
1117 V_VT(&v) = VT_DECIMAL | VT_BYREF;
1118 V_DECIMALREF(&v) = &dec;
1119
1120 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1121 ok(stubMsg.BufferLength == 40, "size %d\n", stubMsg.BufferLength);
1122
1123 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1124 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1125 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1126 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1127 wirev = (DWORD*)buffer;
1128
1129 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength);
1130 ok(*wirev == 16, "wv[5] %08x\n", *wirev);
1131 wirev++;
1132 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));
1133 VariantInit(&v2);
1134 /* check_variant_header tests wReserved[123], so initialize to unique values.
1135 * (Could probably also do this by setting the variant to a known DECIMAL.)
1136 */
1137 V_U2(&v2).wReserved1 = 0x0123;
1138 V_U2(&v2).wReserved2 = 0x4567;
1139 V_U2(&v2).wReserved3 = 0x89ab;
1140
1141 stubMsg.Buffer = buffer;
1142 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1143 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1144 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1145 ok(!memcmp(V_DECIMALREF(&v), V_DECIMALREF(&v2), sizeof(DECIMAL)), "decimals differ\n");
1146
1147 VARIANT_UserFree(&umcb.Flags, &v2);
1148 HeapFree(GetProcessHeap(), 0, oldbuffer);
1149
1150 /*** EMPTY ***/
1151 VariantInit(&v);
1152 V_VT(&v) = VT_EMPTY;
1153
1154 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1155 ok(stubMsg.BufferLength == 20, "size %d\n", stubMsg.BufferLength);
1156
1157 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1158 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1159 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1160 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1161 wirev = (DWORD*)buffer;
1162
1163 check_variant_header(wirev, &v, stubMsg.BufferLength);
1164 VariantInit(&v2);
1165 stubMsg.Buffer = buffer;
1166 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
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
1170 VARIANT_UserFree(&umcb.Flags, &v2);
1171 HeapFree(GetProcessHeap(), 0, oldbuffer);
1172
1173 /*** NULL ***/
1174 VariantInit(&v);
1175 V_VT(&v) = VT_NULL;
1176
1177 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1178 ok(stubMsg.BufferLength == 20, "size %d\n", stubMsg.BufferLength);
1179
1180 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1181 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1182 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1183 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1184 wirev = (DWORD*)buffer;
1185
1186 check_variant_header(wirev, &v, stubMsg.BufferLength);
1187 VariantInit(&v2);
1188 stubMsg.Buffer = buffer;
1189 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1190 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1191 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1192
1193 VARIANT_UserFree(&umcb.Flags, &v2);
1194 HeapFree(GetProcessHeap(), 0, oldbuffer);
1195
1196 /*** BSTR ***/
1197 b = SysAllocString(str);
1198 VariantInit(&v);
1199 V_VT(&v) = VT_BSTR;
1200 V_BSTR(&v) = b;
1201
1202 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1203 ok(stubMsg.BufferLength == 60, "size %d\n", stubMsg.BufferLength);
1204 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1205 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1206 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1207 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1208 wirev = (DWORD*)buffer;
1209
1210 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength);
1211 ok(*wirev, "wv[5] %08x\n", *wirev); /* win2k: this is b. winxp: this is (char*)b + 1 */
1212 wirev++;
1213 check_bstr(wirev, V_BSTR(&v));
1214 VariantInit(&v2);
1215 stubMsg.Buffer = buffer;
1216 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1217 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1218 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1219 ok(SysStringByteLen(V_BSTR(&v)) == SysStringByteLen(V_BSTR(&v2)), "bstr string lens differ\n");
1220 ok(!memcmp(V_BSTR(&v), V_BSTR(&v2), SysStringByteLen(V_BSTR(&v))), "bstrs differ\n");
1221
1222 VARIANT_UserFree(&umcb.Flags, &v2);
1223 HeapFree(GetProcessHeap(), 0, oldbuffer);
1224
1225 /*** BSTR BYREF ***/
1226 VariantInit(&v);
1227 V_VT(&v) = VT_BSTR | VT_BYREF;
1228 V_BSTRREF(&v) = &b;
1229
1230 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1231 ok(stubMsg.BufferLength == 64, "size %d\n", stubMsg.BufferLength);
1232 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1233 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1234 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1235 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1236 wirev = (DWORD*)buffer;
1237
1238 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength);
1239 ok(*wirev == 0x4, "wv[5] %08x\n", *wirev);
1240 wirev++;
1241 ok(*wirev, "wv[6] %08x\n", *wirev); /* win2k: this is b. winxp: this is (char*)b + 1 */
1242 wirev++;
1243 check_bstr(wirev, b);
1244 VariantInit(&v2);
1245 stubMsg.Buffer = buffer;
1246 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1247 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1248 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1249 ok(SysStringByteLen(*V_BSTRREF(&v)) == SysStringByteLen(*V_BSTRREF(&v2)), "bstr string lens differ\n");
1250 ok(!memcmp(*V_BSTRREF(&v), *V_BSTRREF(&v2), SysStringByteLen(*V_BSTRREF(&v))), "bstrs differ\n");
1251
1252 VARIANT_UserFree(&umcb.Flags, &v2);
1253 HeapFree(GetProcessHeap(), 0, oldbuffer);
1254 SysFreeString(b);
1255
1256 /*** ARRAY ***/
1257 sab.lLbound = 5;
1258 sab.cElements = 10;
1259
1260 lpsa = SafeArrayCreate(VT_R8, 1, &sab);
1261 *(DWORD *)lpsa->pvData = 0xcafebabe;
1262 *((DWORD *)lpsa->pvData + 1) = 0xdeadbeef;
1263
1264 VariantInit(&v);
1265 V_VT(&v) = VT_UI4 | VT_ARRAY;
1266 V_ARRAY(&v) = lpsa;
1267
1268 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1269 expected = 152;
1270 ok(stubMsg.BufferLength == expected || stubMsg.BufferLength == expected + 8, /* win64 */
1271 "size %u instead of %u\n", stubMsg.BufferLength, expected);
1272 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1273 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1274 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1275 ok(next == buffer + expected, "got %p expect %p\n", next, buffer + expected);
1276 wirev = (DWORD*)buffer;
1277
1278 wirev = check_variant_header(wirev, &v, expected);
1279 ok(*wirev, "wv[5] %08x\n", *wirev); /* win2k: this is lpsa. winxp: this is (char*)lpsa + 1 */
1280 wirev++;
1281 check_safearray(wirev, lpsa);
1282 VariantInit(&v2);
1283 stubMsg.Buffer = buffer;
1284 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1285 ok(next == buffer + expected, "got %p expect %p\n", next, buffer + expected);
1286 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1287 ok(SafeArrayGetDim(V_ARRAY(&v)) == SafeArrayGetDim(V_ARRAY(&v2)), "array dims differ\n");
1288 SafeArrayGetLBound(V_ARRAY(&v), 1, &bound);
1289 SafeArrayGetLBound(V_ARRAY(&v2), 1, &bound2);
1290 ok(bound == bound2, "array lbounds differ\n");
1291 SafeArrayGetUBound(V_ARRAY(&v), 1, &bound);
1292 SafeArrayGetUBound(V_ARRAY(&v2), 1, &bound2);
1293 ok(bound == bound2, "array ubounds differ\n");
1294 if (pSafeArrayGetVartype)
1295 {
1296 pSafeArrayGetVartype(V_ARRAY(&v), &vt);
1297 pSafeArrayGetVartype(V_ARRAY(&v2), &vt2);
1298 ok(vt == vt2, "array vts differ %x %x\n", vt, vt2);
1299 }
1300 VARIANT_UserFree(&umcb.Flags, &v2);
1301 HeapFree(GetProcessHeap(), 0, oldbuffer);
1302
1303 /*** ARRAY BYREF ***/
1304 VariantInit(&v);
1305 V_VT(&v) = VT_UI4 | VT_ARRAY | VT_BYREF;
1306 V_ARRAYREF(&v) = &lpsa;
1307
1308 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1309 expected = 152;
1310 ok(stubMsg.BufferLength == expected || stubMsg.BufferLength == expected + 16, /* win64 */
1311 "size %u instead of %u\n", stubMsg.BufferLength, expected);
1312 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1313 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1314 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1315 ok(next == buffer + expected, "got %p expect %p\n", next, buffer + expected);
1316 wirev = (DWORD*)buffer;
1317
1318 wirev = check_variant_header(wirev, &v, expected);
1319 ok(*wirev == 4, "wv[5] %08x\n", *wirev);
1320 wirev++;
1321 ok(*wirev, "wv[6] %08x\n", *wirev); /* win2k: this is lpsa. winxp: this is (char*)lpsa + 1 */
1322 wirev++;
1323 check_safearray(wirev, lpsa);
1324 VariantInit(&v2);
1325 stubMsg.Buffer = buffer;
1326 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1327 ok(next == buffer + expected, "got %p expect %p\n", next, buffer + expected);
1328 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1329 ok(SafeArrayGetDim(*V_ARRAYREF(&v)) == SafeArrayGetDim(*V_ARRAYREF(&v2)), "array dims differ\n");
1330 SafeArrayGetLBound(*V_ARRAYREF(&v), 1, &bound);
1331 SafeArrayGetLBound(*V_ARRAYREF(&v2), 1, &bound2);
1332 ok(bound == bound2, "array lbounds differ\n");
1333 SafeArrayGetUBound(*V_ARRAYREF(&v), 1, &bound);
1334 SafeArrayGetUBound(*V_ARRAYREF(&v2), 1, &bound2);
1335 ok(bound == bound2, "array ubounds differ\n");
1336 if (pSafeArrayGetVartype)
1337 {
1338 pSafeArrayGetVartype(*V_ARRAYREF(&v), &vt);
1339 pSafeArrayGetVartype(*V_ARRAYREF(&v2), &vt2);
1340 ok(vt == vt2, "array vts differ %x %x\n", vt, vt2);
1341 }
1342 VARIANT_UserFree(&umcb.Flags, &v2);
1343 HeapFree(GetProcessHeap(), 0, oldbuffer);
1344 hr = SafeArrayDestroy(lpsa);
1345 ok(hr == S_OK, "got 0x%08x\n", hr);
1346
1347 /*** VARIANT BYREF ***/
1348 VariantInit(&v);
1349 VariantInit(&v2);
1350 V_VT(&v2) = VT_R8;
1351 V_R8(&v2) = 3.1415;
1352 V_VT(&v) = VT_VARIANT | VT_BYREF;
1353 V_VARIANTREF(&v) = &v2;
1354
1355 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1356 ok(stubMsg.BufferLength == 64, "size %d\n", stubMsg.BufferLength);
1357 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1358 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1359 memset(buffer, 0xcc, stubMsg.BufferLength);
1360 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1361 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1362 wirev = (DWORD*)buffer;
1363 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength);
1364
1365 ok(*wirev == sizeof(VARIANT), "wv[5] %08x\n", *wirev);
1366 wirev++;
1367 ok(*wirev == ('U' | 's' << 8 | 'e' << 16 | 'r' << 24), "wv[6] %08x\n", *wirev); /* 'User' */
1368 wirev++;
1369 ok(*wirev == 0xcccccccc, "wv[7] %08x\n", *wirev); /* pad */
1370 wirev++;
1371 wirev = check_variant_header(wirev, &v2, stubMsg.BufferLength - 32);
1372 ok(*wirev == 0xcccccccc, "wv[13] %08x\n", *wirev); /* pad for VT_R8 */
1373 wirev++;
1374 ok(*(double*)wirev == V_R8(&v2), "wv[6] %08x wv[7] %08x\n", *wirev, *(wirev+1));
1375 VariantInit(&v3);
1376 stubMsg.Buffer = buffer;
1377 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v3);
1378 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1379 ok(V_VT(&v) == V_VT(&v3), "got vt %d expect %d\n", V_VT(&v), V_VT(&v3));
1380 ok(V_VT(V_VARIANTREF(&v)) == V_VT(V_VARIANTREF(&v3)), "vts differ %x %x\n",
1381 V_VT(V_VARIANTREF(&v)), V_VT(V_VARIANTREF(&v3)));
1382 ok(V_R8(V_VARIANTREF(&v)) == V_R8(V_VARIANTREF(&v3)), "r8s differ\n");
1383 VARIANT_UserFree(&umcb.Flags, &v3);
1384 HeapFree(GetProcessHeap(), 0, oldbuffer);
1385
1386 /*** UNKNOWN ***/
1387 heap_unknown = HeapAlloc(GetProcessHeap(), 0, sizeof(*heap_unknown));
1388 heap_unknown->IUnknown_iface.lpVtbl = &HeapUnknown_Vtbl;
1389 heap_unknown->refs = 1;
1390 VariantInit(&v);
1391 VariantInit(&v2);
1392 V_VT(&v) = VT_UNKNOWN;
1393 V_UNKNOWN(&v) = &heap_unknown->IUnknown_iface;
1394
1395 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1396 ok(stubMsg.BufferLength > 40, "size %d\n", stubMsg.BufferLength);
1397 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1398 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1399 memset(buffer, 0xcc, stubMsg.BufferLength);
1400 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1401 todo_wine
1402 ok(heap_unknown->refs == 2, "got refcount %d\n", heap_unknown->refs);
1403 wirev = (DWORD*)buffer;
1404 wirev = check_variant_header(wirev, &v, next - buffer);
1405
1406 ok(*wirev == (DWORD_PTR)V_UNKNOWN(&v) /* Win9x */ ||
1407 *wirev == (DWORD_PTR)V_UNKNOWN(&v) + 1 /* NT */, "wv[5] %08x\n", *wirev);
1408 wirev++;
1409 ok(*wirev == next - buffer - 0x20, "wv[6] %08x\n", *wirev);
1410 wirev++;
1411 ok(*wirev == next - buffer - 0x20, "wv[7] %08x\n", *wirev);
1412 wirev++;
1413 ok(*wirev == 0x574f454d, "wv[8] %08x\n", *wirev);
1414 VariantInit(&v3);
1415 V_VT(&v3) = VT_UNKNOWN;
1416 V_UNKNOWN(&v3) = &heap_unknown->IUnknown_iface;
1417 IUnknown_AddRef(V_UNKNOWN(&v3));
1418 stubMsg.Buffer = buffer;
1419 todo_wine
1420 ok(heap_unknown->refs == 3, "got refcount %d\n", heap_unknown->refs);
1421 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v3);
1422 ok(V_VT(&v) == V_VT(&v3), "got vt %d expect %d\n", V_VT(&v), V_VT(&v3));
1423 ok(V_UNKNOWN(&v) == V_UNKNOWN(&v3), "got %p expect %p\n", V_UNKNOWN(&v), V_UNKNOWN(&v3));
1424 VARIANT_UserFree(&umcb.Flags, &v3);
1425 ok(heap_unknown->refs == 1, "%d refcounts of IUnknown leaked\n", heap_unknown->refs - 1);
1426 IUnknown_Release(&heap_unknown->IUnknown_iface);
1427 HeapFree(GetProcessHeap(), 0, oldbuffer);
1428
1429 /*** NULL UNKNOWN ***/
1430 VariantInit(&v);
1431 V_VT(&v) = VT_UNKNOWN;
1432 V_UNKNOWN(&v) = NULL;
1433
1434 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1435 ok(stubMsg.BufferLength >= 24, "size %d\n", stubMsg.BufferLength);
1436 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1437 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1438 memset(buffer, 0xcc, stubMsg.BufferLength);
1439 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1440 wirev = (DWORD*)buffer;
1441 wirev = check_variant_header(wirev, &v, next - buffer);
1442 ok(*wirev == 0, "wv[5] %08x\n", *wirev);
1443
1444 VariantInit(&v2);
1445 stubMsg.Buffer = buffer;
1446 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1447 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1448 ok(V_UNKNOWN(&v2) == NULL, "got %p expect NULL\n", V_UNKNOWN(&v2));
1449 VARIANT_UserFree(&umcb.Flags, &v2);
1450 HeapFree(GetProcessHeap(), 0, oldbuffer);
1451
1452 /*** UNKNOWN BYREF ***/
1453 heap_unknown = HeapAlloc(GetProcessHeap(), 0, sizeof(*heap_unknown));
1454 heap_unknown->IUnknown_iface.lpVtbl = &HeapUnknown_Vtbl;
1455 heap_unknown->refs = 1;
1456 VariantInit(&v);
1457 VariantInit(&v2);
1458 V_VT(&v) = VT_UNKNOWN | VT_BYREF;
1459 V_UNKNOWNREF(&v) = (IUnknown **)&heap_unknown;
1460
1461 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1462 ok(stubMsg.BufferLength >= 44, "size %d\n", stubMsg.BufferLength);
1463 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1464 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1465 memset(buffer, 0xcc, stubMsg.BufferLength);
1466 ok(heap_unknown->refs == 1, "got refcount %d\n", heap_unknown->refs);
1467 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1468 todo_wine
1469 ok(heap_unknown->refs == 2, "got refcount %d\n", heap_unknown->refs);
1470 wirev = (DWORD*)buffer;
1471 wirev = check_variant_header(wirev, &v, next - buffer);
1472
1473 ok(*wirev == 4, "wv[5] %08x\n", *wirev);
1474 wirev++;
1475 ok(*wirev == (DWORD_PTR)heap_unknown /* Win9x, Win2000 */ ||
1476 *wirev == (DWORD_PTR)heap_unknown + 1 /* XP */, "wv[6] %08x\n", *wirev);
1477 wirev++;
1478 ok(*wirev == next - buffer - 0x24, "wv[7] %08x\n", *wirev);
1479 wirev++;
1480 ok(*wirev == next - buffer - 0x24, "wv[8] %08x\n", *wirev);
1481 wirev++;
1482 ok(*wirev == 0x574f454d, "wv[9] %08x\n", *wirev);
1483
1484 VariantInit(&v3);
1485 V_VT(&v3) = VT_UNKNOWN;
1486 V_UNKNOWN(&v3) = &heap_unknown->IUnknown_iface;
1487 IUnknown_AddRef(V_UNKNOWN(&v3));
1488 stubMsg.Buffer = buffer;
1489 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v3);
1490 ok(heap_unknown->refs == 2, "got refcount %d\n", heap_unknown->refs);
1491 ok(V_VT(&v) == V_VT(&v3), "got vt %d expect %d\n", V_VT(&v), V_VT(&v3));
1492 ok(*V_UNKNOWNREF(&v) == *V_UNKNOWNREF(&v3), "got %p expect %p\n", *V_UNKNOWNREF(&v), *V_UNKNOWNREF(&v3));
1493 VARIANT_UserFree(&umcb.Flags, &v3);
1494 ok(heap_unknown->refs == 1, "%d refcounts of IUnknown leaked\n", heap_unknown->refs - 1);
1495 IUnknown_Release(&heap_unknown->IUnknown_iface);
1496 HeapFree(GetProcessHeap(), 0, oldbuffer);
1497 }
1498
1499
1500 START_TEST(usrmarshal)
1501 {
1502 HANDLE hOleaut32 = GetModuleHandleA("oleaut32.dll");
1503 #define GETPTR(func) p##func = (void*)GetProcAddress(hOleaut32, #func)
1504 GETPTR(SafeArrayGetIID);
1505 GETPTR(SafeArrayGetVartype);
1506 GETPTR(VarBstrCmp);
1507 #undef GETPTR
1508
1509 if (!pSafeArrayGetIID || !pSafeArrayGetVartype)
1510 win_skip("SafeArrayGetIID and/or SafeArrayGetVartype is not available, some tests will be skipped\n");
1511
1512 CoInitialize(NULL);
1513
1514 test_marshal_LPSAFEARRAY();
1515 test_marshal_BSTR();
1516 test_marshal_VARIANT();
1517
1518 CoUninitialize();
1519 }