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