push 5b1efc32b5a8acb1d5b5e60584746392dd0c436e
[wine/hacks.git] / dlls / oleaut32 / tests / usrmarshal.c
blobe9c53e9133103bc198700d852f719b1a938aebfe
1 /*
2 * Marshaling Tests
4 * Copyright 2004 Robert Shearman
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.
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.
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
21 #define COBJMACROS
23 #include <stdarg.h>
25 #include "windef.h"
26 #include "winbase.h"
27 #include "objbase.h"
28 #include "propidl.h" /* for LPSAFEARRAY_User* routines */
30 #include "wine/test.h"
32 #if (__STDC__ && !defined(_FORCENAMELESSUNION)) || defined(NONAMELESSUNION)
33 # define V_U2(A) ((A)->n1.n2)
34 #else
35 # define V_U2(A) (*(A))
36 #endif
38 #define LPSAFEARRAY_UNMARSHAL_WORKS 1
39 #define BSTR_UNMARSHAL_WORKS 1
40 #define VARIANT_UNMARSHAL_WORKS 1
42 static inline SF_TYPE get_union_type(SAFEARRAY *psa)
44 VARTYPE vt;
45 HRESULT hr;
47 hr = SafeArrayGetVartype(psa, &vt);
48 if (FAILED(hr))
50 if(psa->fFeatures & FADF_VARIANT) return SF_VARIANT;
52 switch(psa->cbElements)
54 case 1: vt = VT_I1; break;
55 case 2: vt = VT_I2; break;
56 case 4: vt = VT_I4; break;
57 case 8: vt = VT_I8; break;
58 default: return 0;
62 if (psa->fFeatures & FADF_HAVEIID)
63 return SF_HAVEIID;
65 switch (vt)
67 case VT_I1:
68 case VT_UI1: return SF_I1;
69 case VT_BOOL:
70 case VT_I2:
71 case VT_UI2: return SF_I2;
72 case VT_INT:
73 case VT_UINT:
74 case VT_I4:
75 case VT_UI4:
76 case VT_R4: return SF_I4;
77 case VT_DATE:
78 case VT_CY:
79 case VT_R8:
80 case VT_I8:
81 case VT_UI8: return SF_I8;
82 case VT_INT_PTR:
83 case VT_UINT_PTR: return (sizeof(UINT_PTR) == 4 ? SF_I4 : SF_I8);
84 case VT_BSTR: return SF_BSTR;
85 case VT_DISPATCH: return SF_DISPATCH;
86 case VT_VARIANT: return SF_VARIANT;
87 case VT_UNKNOWN: return SF_UNKNOWN;
88 /* Note: Return a non-zero size to indicate vt is valid. The actual size
89 * of a UDT is taken from the result of IRecordInfo_GetSize().
91 case VT_RECORD: return SF_RECORD;
92 default: return SF_ERROR;
96 static ULONG get_cell_count(const SAFEARRAY *psa)
98 const SAFEARRAYBOUND* psab = psa->rgsabound;
99 USHORT cCount = psa->cDims;
100 ULONG ulNumCells = 1;
102 while (cCount--)
104 if (!psab->cElements)
105 return 0;
106 ulNumCells *= psab->cElements;
107 psab++;
109 return ulNumCells;
112 static DWORD elem_wire_size(LPSAFEARRAY lpsa, SF_TYPE sftype)
114 if (sftype == SF_BSTR)
115 return sizeof(DWORD);
116 else
117 return lpsa->cbElements;
120 static void check_safearray(void *buffer, LPSAFEARRAY lpsa)
122 unsigned char *wiresa = buffer;
123 VARTYPE vt;
124 SF_TYPE sftype;
125 ULONG cell_count;
127 if(!lpsa)
129 ok(*(DWORD *)wiresa == 0, "wiresa + 0x0 should be NULL instead of 0x%08x\n", *(DWORD *)wiresa);
130 return;
133 if(FAILED(SafeArrayGetVartype(lpsa, &vt)))
134 vt = 0;
136 sftype = get_union_type(lpsa);
137 cell_count = get_cell_count(lpsa);
139 ok(*(DWORD *)wiresa, "wiresa + 0x0 should be non-NULL instead of 0x%08x\n", *(DWORD *)wiresa); /* win2k: this is lpsa. winxp: this is 0x00000001 */
140 wiresa += sizeof(DWORD);
141 ok(*(DWORD *)wiresa == lpsa->cDims, "wiresa + 0x4 should be lpsa->cDims instead of 0x%08x\n", *(DWORD *)wiresa);
142 wiresa += sizeof(DWORD);
143 ok(*(WORD *)wiresa == lpsa->cDims, "wiresa + 0x8 should be lpsa->cDims instead of 0x%04x\n", *(WORD *)wiresa);
144 wiresa += sizeof(WORD);
145 ok(*(WORD *)wiresa == lpsa->fFeatures, "wiresa + 0xa should be lpsa->fFeatures instead of 0x%08x\n", *(WORD *)wiresa);
146 wiresa += sizeof(WORD);
147 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);
148 wiresa += sizeof(DWORD);
149 ok(*(WORD *)wiresa == lpsa->cLocks, "wiresa + 0x10 should be lpsa->cLocks instead of 0x%04x\n", *(WORD *)wiresa);
150 wiresa += sizeof(WORD);
151 ok(*(WORD *)wiresa == vt, "wiresa + 0x12 should be %04x instead of 0x%04x\n", vt, *(WORD *)wiresa);
152 wiresa += sizeof(WORD);
153 ok(*(DWORD *)wiresa == sftype, "wiresa + 0x14 should be %08x instead of 0x%08x\n", (DWORD)sftype, *(DWORD *)wiresa);
154 wiresa += sizeof(DWORD);
155 ok(*(DWORD *)wiresa == cell_count, "wiresa + 0x18 should be %u instead of %u\n", cell_count, *(DWORD *)wiresa);
156 wiresa += sizeof(DWORD);
157 ok(*(DWORD *)wiresa, "wiresa + 0x1c should be non-zero instead of 0x%08x\n", *(DWORD *)wiresa);
158 wiresa += sizeof(DWORD);
159 if(sftype == SF_HAVEIID)
161 GUID guid;
162 SafeArrayGetIID(lpsa, &guid);
163 ok(IsEqualGUID(&guid, wiresa), "guid mismatch\n");
164 wiresa += sizeof(GUID);
166 ok(!memcmp(wiresa, lpsa->rgsabound, sizeof(lpsa->rgsabound[0]) * lpsa->cDims), "bounds mismatch\n");
167 wiresa += sizeof(lpsa->rgsabound[0]) * lpsa->cDims;
169 ok(*(DWORD *)wiresa == cell_count, "wiresa + 0x28 should be %u instead of %u\n", cell_count, *(DWORD*)wiresa);
170 wiresa += sizeof(DWORD);
171 /* elements are now pointed to by wiresa */
174 static void * WINAPI user_allocate(SIZE_T size)
176 return CoTaskMemAlloc(size);
179 static void WINAPI user_free(void *p)
181 CoTaskMemFree(p);
184 static void init_user_marshal_cb(USER_MARSHAL_CB *umcb,
185 PMIDL_STUB_MESSAGE stub_msg,
186 PRPC_MESSAGE rpc_msg, unsigned char *buffer,
187 unsigned int size, MSHCTX context)
189 memset(rpc_msg, 0, sizeof(*rpc_msg));
190 rpc_msg->Buffer = buffer;
191 rpc_msg->BufferLength = size;
193 memset(stub_msg, 0, sizeof(*stub_msg));
194 stub_msg->RpcMsg = rpc_msg;
195 stub_msg->Buffer = buffer;
196 stub_msg->pfnAllocate = user_allocate;
197 stub_msg->pfnFree = user_free;
199 memset(umcb, 0, sizeof(*umcb));
200 umcb->Flags = MAKELONG(context, NDR_LOCAL_DATA_REPRESENTATION);
201 umcb->pStubMsg = stub_msg;
202 umcb->Signature = USER_MARSHAL_CB_SIGNATURE;
203 umcb->CBType = buffer ? USER_MARSHAL_CB_UNMARSHALL : USER_MARSHAL_CB_BUFFER_SIZE;
206 static void test_marshal_LPSAFEARRAY(void)
208 unsigned char *buffer, *next;
209 ULONG size, expected;
210 LPSAFEARRAY lpsa;
211 LPSAFEARRAY lpsa2 = NULL;
212 SAFEARRAYBOUND sab;
213 RPC_MESSAGE rpc_msg;
214 MIDL_STUB_MESSAGE stub_msg;
215 USER_MARSHAL_CB umcb;
216 HRESULT hr;
217 VARTYPE vt;
218 OLECHAR *values[10];
219 int expected_bstr_size;
220 int i;
221 LONG indices[1];
223 sab.lLbound = 5;
224 sab.cElements = 10;
226 lpsa = SafeArrayCreate(VT_I2, 1, &sab);
227 *(DWORD *)lpsa->pvData = 0xcafebabe;
229 lpsa->cLocks = 7;
230 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
231 size = LPSAFEARRAY_UserSize(&umcb.Flags, 1, &lpsa);
232 expected = (44 + 1 + sizeof(ULONG) - 1) & ~(sizeof(ULONG) - 1);
233 expected += sab.cElements * sizeof(USHORT);
234 ok(size == expected || size == expected + 12, /* win64 */
235 "size should be %u bytes, not %u\n", expected, size);
236 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
237 size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
238 expected = 44 + sab.cElements * sizeof(USHORT);
239 ok(size == expected || size == expected + 12, /* win64 */
240 "size should be %u bytes, not %u\n", expected, size);
241 buffer = HeapAlloc(GetProcessHeap(), 0, size);
242 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
243 next = LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
244 ok(next - buffer == expected, "Marshaled %u bytes, expected %u\n", (ULONG) (next - buffer), expected);
246 check_safearray(buffer, lpsa);
248 if (LPSAFEARRAY_UNMARSHAL_WORKS)
250 VARTYPE vt, vt2;
251 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
252 LPSAFEARRAY_UserUnmarshal(&umcb.Flags, buffer, &lpsa2);
253 ok(lpsa2 != NULL, "LPSAFEARRAY didn't unmarshal\n");
254 SafeArrayGetVartype(lpsa, &vt);
255 SafeArrayGetVartype(lpsa2, &vt2);
256 ok(vt == vt2, "vts differ %x %x\n", vt, vt2);
257 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
258 LPSAFEARRAY_UserFree(&umcb.Flags, &lpsa2);
260 HeapFree(GetProcessHeap(), 0, buffer);
261 lpsa->cLocks = 0;
262 SafeArrayDestroy(lpsa);
264 /* test NULL safe array */
265 lpsa = NULL;
267 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
268 size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
269 expected = 4;
270 ok(size == expected, "size should be 4 bytes, not %d\n", size);
271 buffer = HeapAlloc(GetProcessHeap(), 0, size);
272 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
273 next = LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
274 ok(next - buffer == expected, "Marshaled %u bytes, expected %u\n", (ULONG) (next - buffer), expected);
275 check_safearray(buffer, lpsa);
277 if (LPSAFEARRAY_UNMARSHAL_WORKS)
279 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
280 LPSAFEARRAY_UserUnmarshal(&umcb.Flags, buffer, &lpsa2);
281 ok(lpsa2 == NULL, "NULL LPSAFEARRAY didn't unmarshal\n");
282 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
283 LPSAFEARRAY_UserFree(&umcb.Flags, &lpsa2);
285 HeapFree(GetProcessHeap(), 0, buffer);
287 sab.lLbound = 5;
288 sab.cElements = 10;
290 lpsa = SafeArrayCreate(VT_R8, 1, &sab);
291 *(double *)lpsa->pvData = 3.1415;
293 lpsa->cLocks = 7;
294 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
295 size = LPSAFEARRAY_UserSize(&umcb.Flags, 1, &lpsa);
296 expected = (44 + 1 + (sizeof(double) - 1)) & ~(sizeof(double) - 1);
297 expected += sab.cElements * sizeof(double);
298 ok(size == expected || size == expected + 16, /* win64 */
299 "size should be %u bytes, not %u\n", expected, size);
300 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
301 expected = (44 + (sizeof(double) - 1)) & ~(sizeof(double) - 1);
302 expected += sab.cElements * sizeof(double);
303 size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
304 ok(size == expected || size == expected + 8, /* win64 */
305 "size should be %u bytes, not %u\n", expected, size);
306 buffer = HeapAlloc(GetProcessHeap(), 0, size);
307 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
308 next = LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
309 ok(next - buffer == expected, "Marshaled %u bytes, expected %u\n", (ULONG) (next - buffer), expected);
311 check_safearray(buffer, lpsa);
313 HeapFree(GetProcessHeap(), 0, buffer);
314 lpsa->cLocks = 0;
315 SafeArrayDestroy(lpsa);
317 /* VARTYPE-less arrays can be marshaled if cbElements is 1,2,4 or 8 as type SF_In */
318 hr = SafeArrayAllocDescriptor(1, &lpsa);
319 ok(hr == S_OK, "saad failed %08x\n", hr);
320 lpsa->cbElements = 8;
321 lpsa->rgsabound[0].lLbound = 2;
322 lpsa->rgsabound[0].cElements = 48;
323 hr = SafeArrayAllocData(lpsa);
324 ok(hr == S_OK, "saad failed %08x\n", hr);
326 hr = SafeArrayGetVartype(lpsa, &vt);
327 ok(hr == E_INVALIDARG, "ret %08x\n", hr);
329 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
330 size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
331 expected = (44 + lpsa->cbElements - 1) & ~(lpsa->cbElements - 1);
332 expected += lpsa->cbElements * lpsa->rgsabound[0].cElements;
333 ok(size == expected || size == expected + 8, /* win64 */
334 "size should be %u bytes, not %u\n", expected, size);
335 buffer = HeapAlloc(GetProcessHeap(), 0, size);
336 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
337 next = LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
338 ok(next - buffer == expected, "Marshaled %u bytes, expected %u\n", (ULONG) (next - buffer), expected);
339 check_safearray(buffer, lpsa);
340 HeapFree(GetProcessHeap(), 0, buffer);
341 SafeArrayDestroyData(lpsa);
342 SafeArrayDestroyDescriptor(lpsa);
344 /* Test an array of VT_BSTR */
345 sab.lLbound = 3;
346 sab.cElements = sizeof(values) / sizeof(values[0]);
348 lpsa = SafeArrayCreate(VT_BSTR, 1, &sab);
349 expected_bstr_size = 0;
350 for (i = 0; i < sab.cElements; i++)
352 int j;
353 WCHAR buf[128];
354 for (j = 0; j <= i; j++)
355 buf[j] = 'a' + j;
356 buf[j] = 0;
357 indices[0] = i + sab.lLbound;
358 values[i] = SysAllocString(buf);
359 hr = SafeArrayPutElement(lpsa, indices, values[i]);
360 ok(hr == S_OK, "Failed to put bstr element hr 0x%x\n", hr);
361 expected_bstr_size += (j * sizeof(WCHAR)) + (3 * sizeof(DWORD));
362 if (i % 2 == 0) /* Account for DWORD padding. Works so long as cElements is even */
363 expected_bstr_size += sizeof(WCHAR);
366 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
367 size = LPSAFEARRAY_UserSize(&umcb.Flags, 1, &lpsa);
368 expected = 44 + (sab.cElements * sizeof(DWORD)) + expected_bstr_size;
369 todo_wine
370 ok(size == expected + sizeof(DWORD) || size == (expected + sizeof(DWORD) + 12 /* win64 */),
371 "size should be %u bytes, not %u\n", expected + (ULONG) sizeof(DWORD), size);
372 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
373 size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
374 todo_wine
375 ok(size == expected || size == (expected + 12 /* win64 */),
376 "size should be %u bytes, not %u\n", expected, size);
377 buffer = HeapAlloc(GetProcessHeap(), 0, size);
378 memset(buffer, 0xcc, size);
379 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
380 next = LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
381 todo_wine
382 ok(next - buffer == expected, "Marshaled %u bytes, expected %u\n", (ULONG) (next - buffer), expected);
384 check_safearray(buffer, lpsa);
386 lpsa2 = NULL;
387 if (LPSAFEARRAY_UNMARSHAL_WORKS)
389 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
390 next = LPSAFEARRAY_UserUnmarshal(&umcb.Flags, buffer, &lpsa2);
391 todo_wine
392 ok(next - buffer == expected, "Marshaled %u bytes, expected %u\n", (ULONG) (next - buffer), expected);
393 ok(lpsa2 != NULL, "LPSAFEARRAY didn't unmarshal, result %p\n", next);
396 for (i = 0; i < sizeof(values) / sizeof(values[0]); i++)
398 BSTR gotvalue = NULL;
400 if (lpsa2)
402 indices[0] = i + sab.lLbound;
403 hr = SafeArrayGetElement(lpsa2, indices, &gotvalue);
404 ok(hr == S_OK, "Failed to get bstr element at hres 0x%x\n", hr);
405 if (hr == S_OK)
407 ok(VarBstrCmp(values[i], gotvalue, 0, 0) == VARCMP_EQ, "String %d does not match\n", i);
408 SysFreeString(gotvalue);
412 SysFreeString(values[i]);
415 if (LPSAFEARRAY_UNMARSHAL_WORKS)
417 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
418 LPSAFEARRAY_UserFree(&umcb.Flags, &lpsa2);
421 HeapFree(GetProcessHeap(), 0, buffer);
422 SafeArrayDestroy(lpsa);
425 /* VARTYPE-less arrays with FADF_VARIANT */
426 hr = SafeArrayAllocDescriptor(1, &lpsa);
427 ok(hr == S_OK, "saad failed %08x\n", hr);
428 lpsa->cbElements = sizeof(VARIANT);
429 lpsa->fFeatures = FADF_VARIANT;
430 lpsa->rgsabound[0].lLbound = 2;
431 lpsa->rgsabound[0].cElements = 48;
432 hr = SafeArrayAllocData(lpsa);
433 ok(hr == S_OK, "saad failed %08x\n", hr);
435 hr = SafeArrayGetVartype(lpsa, &vt);
436 ok(hr == E_INVALIDARG, "ret %08x\n", hr);
438 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
439 size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
440 expected = 44 + 28 * lpsa->rgsabound[0].cElements;
441 todo_wine
442 ok(size == expected || size == expected + 8, /* win64 */
443 "size should be %u bytes, not %u\n", expected, size);
444 buffer = HeapAlloc(GetProcessHeap(), 0, size);
445 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
446 next = LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
447 todo_wine
448 ok(next - buffer == expected, "Marshaled %u bytes, expected %u\n", (ULONG) (next - buffer), expected);
449 lpsa->cbElements = 16; /* VARIANT wire size */
450 check_safearray(buffer, lpsa);
451 HeapFree(GetProcessHeap(), 0, buffer);
452 SafeArrayDestroyData(lpsa);
453 SafeArrayDestroyDescriptor(lpsa);
456 static void check_bstr(void *buffer, BSTR b)
458 DWORD *wireb = buffer;
459 DWORD len = SysStringByteLen(b);
461 ok(*wireb == (len + 1) / 2, "wv[0] %08x\n", *wireb);
462 wireb++;
463 if(b)
464 ok(*wireb == len, "wv[1] %08x\n", *wireb);
465 else
466 ok(*wireb == 0xffffffff, "wv[1] %08x\n", *wireb);
467 wireb++;
468 ok(*wireb == (len + 1) / 2, "wv[2] %08x\n", *wireb);
469 if(len)
471 wireb++;
472 ok(!memcmp(wireb, b, (len + 1) & ~1), "strings differ\n");
474 return;
477 static void test_marshal_BSTR(void)
479 ULONG size;
480 RPC_MESSAGE rpc_msg;
481 MIDL_STUB_MESSAGE stub_msg;
482 USER_MARSHAL_CB umcb;
483 unsigned char *buffer, *next;
484 BSTR b, b2;
485 WCHAR str[] = {'m','a','r','s','h','a','l',' ','t','e','s','t','1',0};
486 DWORD len;
488 b = SysAllocString(str);
489 len = SysStringLen(b);
490 ok(len == 13, "get %d\n", len);
492 /* BSTRs are DWORD aligned */
494 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
495 size = BSTR_UserSize(&umcb.Flags, 1, &b);
496 ok(size == 42, "size %d\n", size);
498 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
499 size = BSTR_UserSize(&umcb.Flags, 0, &b);
500 ok(size == 38, "size %d\n", size);
502 buffer = HeapAlloc(GetProcessHeap(), 0, size);
503 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
504 next = BSTR_UserMarshal(&umcb.Flags, buffer, &b);
505 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
506 check_bstr(buffer, b);
508 if (BSTR_UNMARSHAL_WORKS)
510 b2 = NULL;
511 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
512 next = BSTR_UserUnmarshal(&umcb.Flags, buffer, &b2);
513 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
514 ok(b2 != NULL, "BSTR didn't unmarshal\n");
515 ok(!memcmp(b, b2, (len + 1) * 2), "strings differ\n");
516 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
517 BSTR_UserFree(&umcb.Flags, &b2);
520 HeapFree(GetProcessHeap(), 0, buffer);
521 SysFreeString(b);
523 b = NULL;
524 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
525 size = BSTR_UserSize(&umcb.Flags, 0, &b);
526 ok(size == 12, "size %d\n", size);
528 buffer = HeapAlloc(GetProcessHeap(), 0, size);
529 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
530 next = BSTR_UserMarshal(&umcb.Flags, buffer, &b);
531 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
533 check_bstr(buffer, b);
534 if (BSTR_UNMARSHAL_WORKS)
536 b2 = NULL;
537 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
538 next = BSTR_UserUnmarshal(&umcb.Flags, buffer, &b2);
539 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
540 ok(b2 == NULL, "NULL BSTR didn't unmarshal\n");
541 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
542 BSTR_UserFree(&umcb.Flags, &b2);
544 HeapFree(GetProcessHeap(), 0, buffer);
546 b = SysAllocStringByteLen("abc", 3);
547 *(((char*)b) + 3) = 'd';
548 len = SysStringLen(b);
549 ok(len == 1, "get %d\n", len);
550 len = SysStringByteLen(b);
551 ok(len == 3, "get %d\n", len);
553 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
554 size = BSTR_UserSize(&umcb.Flags, 0, &b);
555 ok(size == 16, "size %d\n", size);
557 buffer = HeapAlloc(GetProcessHeap(), 0, size);
558 memset(buffer, 0xcc, size);
559 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
560 next = BSTR_UserMarshal(&umcb.Flags, buffer, &b);
561 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
562 check_bstr(buffer, b);
563 ok(buffer[15] == 'd', "buffer[15] %02x\n", buffer[15]);
565 if (BSTR_UNMARSHAL_WORKS)
567 b2 = NULL;
568 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
569 next = BSTR_UserUnmarshal(&umcb.Flags, buffer, &b2);
570 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
571 ok(b2 != NULL, "BSTR didn't unmarshal\n");
572 ok(!memcmp(b, b2, len), "strings differ\n");
573 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
574 BSTR_UserFree(&umcb.Flags, &b2);
576 HeapFree(GetProcessHeap(), 0, buffer);
577 SysFreeString(b);
579 b = SysAllocStringByteLen("", 0);
580 len = SysStringLen(b);
581 ok(len == 0, "get %d\n", len);
582 len = SysStringByteLen(b);
583 ok(len == 0, "get %d\n", len);
585 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
586 size = BSTR_UserSize(&umcb.Flags, 0, &b);
587 ok(size == 12, "size %d\n", size);
589 buffer = HeapAlloc(GetProcessHeap(), 0, size);
590 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
591 next = BSTR_UserMarshal(&umcb.Flags, buffer, &b);
592 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
593 check_bstr(buffer, b);
595 if (BSTR_UNMARSHAL_WORKS)
597 b2 = NULL;
598 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
599 next = BSTR_UserUnmarshal(&umcb.Flags, buffer, &b2);
600 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
601 ok(b2 != NULL, "NULL LPSAFEARRAY didn't unmarshal\n");
602 len = SysStringByteLen(b2);
603 ok(len == 0, "byte len %d\n", len);
604 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
605 BSTR_UserFree(&umcb.Flags, &b2);
607 HeapFree(GetProcessHeap(), 0, buffer);
608 SysFreeString(b);
611 typedef struct
613 const IUnknownVtbl *lpVtbl;
614 ULONG refs;
615 } HeapUnknown;
617 static HRESULT WINAPI HeapUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
619 if (IsEqualIID(riid, &IID_IUnknown))
621 IUnknown_AddRef(iface);
622 *ppv = iface;
623 return S_OK;
625 *ppv = NULL;
626 return E_NOINTERFACE;
629 static ULONG WINAPI HeapUnknown_AddRef(IUnknown *iface)
631 HeapUnknown *This = (HeapUnknown *)iface;
632 return InterlockedIncrement((LONG*)&This->refs);
635 static ULONG WINAPI HeapUnknown_Release(IUnknown *iface)
637 HeapUnknown *This = (HeapUnknown *)iface;
638 ULONG refs = InterlockedDecrement((LONG*)&This->refs);
639 if (!refs) HeapFree(GetProcessHeap(), 0, This);
640 return refs;
643 static const IUnknownVtbl HeapUnknown_Vtbl =
645 HeapUnknown_QueryInterface,
646 HeapUnknown_AddRef,
647 HeapUnknown_Release
650 static void check_variant_header(DWORD *wirev, VARIANT *v, ULONG size)
652 WORD *wp;
653 DWORD switch_is;
655 ok(*wirev == (size + 7) >> 3, "wv[0] %08x, expected %08x\n", *wirev, (size + 7) >> 3);
656 wirev++;
657 ok(*wirev == 0, "wv[1] %08x\n", *wirev);
658 wirev++;
659 wp = (WORD*)wirev;
660 ok(*wp == V_VT(v), "vt %04x expected %04x\n", *wp, V_VT(v));
661 wp++;
662 ok(*wp == V_U2(v).wReserved1, "res1 %04x expected %04x\n", *wp, V_U2(v).wReserved1);
663 wp++;
664 ok(*wp == V_U2(v).wReserved2, "res2 %04x expected %04x\n", *wp, V_U2(v).wReserved2);
665 wp++;
666 ok(*wp == V_U2(v).wReserved3, "res3 %04x expected %04x\n", *wp, V_U2(v).wReserved3);
667 wp++;
668 wirev = (DWORD*)wp;
669 switch_is = V_VT(v);
670 if(switch_is & VT_ARRAY)
671 switch_is &= ~VT_TYPEMASK;
672 ok(*wirev == switch_is, "switch_is %08x expected %08x\n", *wirev, switch_is);
675 /* Win9x and WinME don't always align as needed. Variants have
676 * an alignment of 8.
678 static void *alloc_aligned(SIZE_T size, void **buf)
680 *buf = HeapAlloc(GetProcessHeap(), 0, size + 7);
681 return (void *)(((UINT_PTR)*buf + 7) & ~7);
684 static void test_marshal_VARIANT(void)
686 VARIANT v, v2;
687 MIDL_STUB_MESSAGE stubMsg = { 0 };
688 RPC_MESSAGE rpcMsg = { 0 };
689 USER_MARSHAL_CB umcb = { 0 };
690 unsigned char *buffer, *next;
691 void *oldbuffer;
692 ULONG ul;
693 short s;
694 double d;
695 DWORD *wirev;
696 BSTR b;
697 WCHAR str[] = {'m','a','r','s','h','a','l',' ','t','e','s','t',0};
698 SAFEARRAYBOUND sab;
699 LPSAFEARRAY lpsa;
700 DECIMAL dec, dec2;
701 HeapUnknown *heap_unknown;
702 DWORD expected;
704 stubMsg.RpcMsg = &rpcMsg;
706 umcb.Flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
707 umcb.pStubMsg = &stubMsg;
708 umcb.pReserve = NULL;
709 umcb.Signature = USER_MARSHAL_CB_SIGNATURE;
710 umcb.CBType = USER_MARSHAL_CB_UNMARSHALL;
712 /*** I1 ***/
713 VariantInit(&v);
714 V_VT(&v) = VT_I1;
715 V_I1(&v) = 0x12;
717 /* check_variant_header tests wReserved[123], so initialize to unique values.
718 * (Could probably also do this by setting the variant to a known DECIMAL.)
720 V_U2(&v).wReserved1 = 0x1234;
721 V_U2(&v).wReserved2 = 0x5678;
722 V_U2(&v).wReserved3 = 0x9abc;
724 /* Variants have an alignment of 8 */
725 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 1, &v);
726 ok(stubMsg.BufferLength == 29, "size %d\n", stubMsg.BufferLength);
728 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
729 ok(stubMsg.BufferLength == 21, "size %d\n", stubMsg.BufferLength);
731 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
732 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
733 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
734 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
735 wirev = (DWORD*)buffer;
737 check_variant_header(wirev, &v, stubMsg.BufferLength);
738 wirev += 5;
739 ok(*(char*)wirev == V_I1(&v), "wv[5] %08x\n", *wirev);
740 if (VARIANT_UNMARSHAL_WORKS)
742 VariantInit(&v2);
743 stubMsg.Buffer = buffer;
744 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
745 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
746 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
747 ok(V_I1(&v) == V_I1(&v2), "got i1 %x expect %x\n", V_I1(&v), V_I1(&v2));
749 VARIANT_UserFree(&umcb.Flags, &v2);
751 HeapFree(GetProcessHeap(), 0, oldbuffer);
753 /*** I2 ***/
754 VariantInit(&v);
755 V_VT(&v) = VT_I2;
756 V_I2(&v) = 0x1234;
758 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
759 ok(stubMsg.BufferLength == 22, "size %d\n", stubMsg.BufferLength);
761 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
762 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
763 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
764 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
765 wirev = (DWORD*)buffer;
767 check_variant_header(wirev, &v, stubMsg.BufferLength);
768 wirev += 5;
769 ok(*(short*)wirev == V_I2(&v), "wv[5] %08x\n", *wirev);
770 if (VARIANT_UNMARSHAL_WORKS)
772 VariantInit(&v2);
773 stubMsg.Buffer = buffer;
774 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
775 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
776 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
777 ok(V_I2(&v) == V_I2(&v2), "got i2 %x expect %x\n", V_I2(&v), V_I2(&v2));
779 VARIANT_UserFree(&umcb.Flags, &v2);
781 HeapFree(GetProcessHeap(), 0, oldbuffer);
783 /*** I2 BYREF ***/
784 VariantInit(&v);
785 V_VT(&v) = VT_I2 | VT_BYREF;
786 s = 0x1234;
787 V_I2REF(&v) = &s;
789 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
790 ok(stubMsg.BufferLength == 26, "size %d\n", stubMsg.BufferLength);
792 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
793 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
794 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
795 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
796 wirev = (DWORD*)buffer;
798 check_variant_header(wirev, &v, stubMsg.BufferLength);
799 wirev += 5;
800 ok(*wirev == 0x4, "wv[5] %08x\n", *wirev);
801 wirev++;
802 ok(*(short*)wirev == s, "wv[6] %08x\n", *wirev);
803 if (VARIANT_UNMARSHAL_WORKS)
805 void *mem;
806 VariantInit(&v2);
807 V_VT(&v2) = VT_I2 | VT_BYREF;
808 V_BYREF(&v2) = mem = CoTaskMemAlloc(sizeof(V_I2(&v2)));
809 stubMsg.Buffer = buffer;
810 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
811 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
812 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
813 ok(V_BYREF(&v2) == mem, "didn't reuse existing memory\n");
814 ok(*V_I2REF(&v) == *V_I2REF(&v2), "got i2 ref %x expect ui4 ref %x\n", *V_I2REF(&v), *V_I2REF(&v2));
816 VARIANT_UserFree(&umcb.Flags, &v2);
818 HeapFree(GetProcessHeap(), 0, oldbuffer);
820 /*** I4 ***/
821 VariantInit(&v);
822 V_VT(&v) = VT_I4;
823 V_I4(&v) = 0x1234;
825 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
826 ok(stubMsg.BufferLength == 24, "size %d\n", stubMsg.BufferLength);
828 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
829 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
830 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
831 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
832 wirev = (DWORD*)buffer;
834 check_variant_header(wirev, &v, stubMsg.BufferLength);
835 wirev += 5;
836 ok(*wirev == V_I4(&v), "wv[5] %08x\n", *wirev);
838 if (VARIANT_UNMARSHAL_WORKS)
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_I4(&v) == V_I4(&v2), "got i4 %x expect %x\n", V_I4(&v), V_I4(&v2));
847 VARIANT_UserFree(&umcb.Flags, &v2);
849 HeapFree(GetProcessHeap(), 0, oldbuffer);
851 /*** UI4 ***/
852 VariantInit(&v);
853 V_VT(&v) = VT_UI4;
854 V_UI4(&v) = 0x1234;
856 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
857 ok(stubMsg.BufferLength == 24, "size %d\n", stubMsg.BufferLength);
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;
865 check_variant_header(wirev, &v, stubMsg.BufferLength);
866 wirev += 5;
867 ok(*wirev == 0x1234, "wv[5] %08x\n", *wirev);
868 if (VARIANT_UNMARSHAL_WORKS)
870 VariantInit(&v2);
871 stubMsg.Buffer = buffer;
872 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
873 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
874 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
875 ok(V_UI4(&v) == V_UI4(&v2), "got ui4 %x expect %x\n", V_UI4(&v), V_UI4(&v2));
877 VARIANT_UserFree(&umcb.Flags, &v2);
879 HeapFree(GetProcessHeap(), 0, oldbuffer);
881 /*** UI4 BYREF ***/
882 VariantInit(&v);
883 V_VT(&v) = VT_UI4 | VT_BYREF;
884 ul = 0x1234;
885 V_UI4REF(&v) = &ul;
887 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
888 ok(stubMsg.BufferLength == 28, "size %d\n", stubMsg.BufferLength);
890 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
891 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
892 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
893 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
894 wirev = (DWORD*)buffer;
896 check_variant_header(wirev, &v, stubMsg.BufferLength);
897 wirev += 5;
898 ok(*wirev == 0x4, "wv[5] %08x\n", *wirev);
899 wirev++;
900 ok(*wirev == ul, "wv[6] %08x\n", *wirev);
902 if (VARIANT_UNMARSHAL_WORKS)
904 VariantInit(&v2);
905 stubMsg.Buffer = buffer;
906 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
907 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
908 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
909 ok(*V_UI4REF(&v) == *V_UI4REF(&v2), "got ui4 ref %x expect ui4 ref %x\n", *V_UI4REF(&v), *V_UI4REF(&v2));
911 VARIANT_UserFree(&umcb.Flags, &v2);
913 HeapFree(GetProcessHeap(), 0, oldbuffer);
915 /*** R4 ***/
916 VariantInit(&v);
917 V_VT(&v) = VT_R4;
918 V_R8(&v) = 3.1415;
920 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
921 ok(stubMsg.BufferLength == 24, "size %d\n", stubMsg.BufferLength);
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;
929 check_variant_header(wirev, &v, stubMsg.BufferLength);
930 wirev += 5;
931 ok(*(float*)wirev == V_R4(&v), "wv[5] %08x\n", *wirev);
932 if (VARIANT_UNMARSHAL_WORKS)
934 VariantInit(&v2);
935 stubMsg.Buffer = buffer;
936 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
937 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
938 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
939 ok(V_R4(&v) == V_R4(&v2), "got r4 %f expect %f\n", V_R4(&v), V_R4(&v2));
941 VARIANT_UserFree(&umcb.Flags, &v2);
943 HeapFree(GetProcessHeap(), 0, oldbuffer);
945 /*** R8 ***/
946 VariantInit(&v);
947 V_VT(&v) = VT_R8;
948 V_R8(&v) = 3.1415;
950 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
951 ok(stubMsg.BufferLength == 32, "size %d\n", stubMsg.BufferLength);
953 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
954 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
955 memset(buffer, 0xcc, stubMsg.BufferLength);
956 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
957 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
958 wirev = (DWORD*)buffer;
960 check_variant_header(wirev, &v, stubMsg.BufferLength);
961 wirev += 5;
962 ok(*wirev == 0xcccccccc, "wv[5] %08x\n", *wirev); /* pad */
963 wirev++;
964 ok(*(double*)wirev == V_R8(&v), "wv[6] %08x, wv[7] %08x\n", *wirev, *(wirev+1));
965 if (VARIANT_UNMARSHAL_WORKS)
967 VariantInit(&v2);
968 stubMsg.Buffer = buffer;
969 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
970 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
971 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
972 ok(V_R8(&v) == V_R8(&v2), "got r8 %f expect %f\n", V_R8(&v), V_R8(&v2));
974 VARIANT_UserFree(&umcb.Flags, &v2);
976 HeapFree(GetProcessHeap(), 0, oldbuffer);
978 /*** R8 BYREF ***/
979 VariantInit(&v);
980 V_VT(&v) = VT_R8 | VT_BYREF;
981 d = 3.1415;
982 V_R8REF(&v) = &d;
984 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
985 ok(stubMsg.BufferLength == 32, "size %d\n", stubMsg.BufferLength);
987 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
988 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
989 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
990 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
991 wirev = (DWORD*)buffer;
993 check_variant_header(wirev, &v, stubMsg.BufferLength);
994 wirev += 5;
995 ok(*wirev == 8, "wv[5] %08x\n", *wirev);
996 wirev++;
997 ok(*(double*)wirev == d, "wv[6] %08x wv[7] %08x\n", *wirev, *(wirev+1));
998 if (VARIANT_UNMARSHAL_WORKS)
1000 VariantInit(&v2);
1001 stubMsg.Buffer = buffer;
1002 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1003 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1004 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1005 ok(*V_R8REF(&v) == *V_R8REF(&v2), "got r8 ref %f expect %f\n", *V_R8REF(&v), *V_R8REF(&v2));
1007 VARIANT_UserFree(&umcb.Flags, &v2);
1009 HeapFree(GetProcessHeap(), 0, oldbuffer);
1011 /*** VARIANT_BOOL ***/
1012 VariantInit(&v);
1013 V_VT(&v) = VT_BOOL;
1014 V_BOOL(&v) = 0x1234;
1016 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1017 ok(stubMsg.BufferLength == 22, "size %d\n", stubMsg.BufferLength);
1019 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1020 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1021 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1022 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1023 wirev = (DWORD*)buffer;
1025 check_variant_header(wirev, &v, stubMsg.BufferLength);
1026 wirev += 5;
1027 ok(*(short*)wirev == V_BOOL(&v), "wv[5] %04x\n", *(WORD*)wirev);
1028 if (VARIANT_UNMARSHAL_WORKS)
1030 VariantInit(&v2);
1031 stubMsg.Buffer = buffer;
1032 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1033 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1034 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1035 ok(V_BOOL(&v) == V_BOOL(&v2), "got bool %x expect %x\n", V_BOOL(&v), V_BOOL(&v2));
1037 VARIANT_UserFree(&umcb.Flags, &v2);
1039 HeapFree(GetProcessHeap(), 0, oldbuffer);
1041 /*** DECIMAL ***/
1042 VarDecFromI4(0x12345678, &dec);
1043 dec.wReserved = 0xfedc; /* Also initialize reserved field, as we check it later */
1044 VariantInit(&v);
1045 V_DECIMAL(&v) = dec;
1046 V_VT(&v) = VT_DECIMAL;
1048 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1049 ok(stubMsg.BufferLength == 40, "size %d\n", stubMsg.BufferLength);
1051 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1052 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1053 memset(buffer, 0xcc, stubMsg.BufferLength);
1054 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1055 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1056 wirev = (DWORD*)buffer;
1058 check_variant_header(wirev, &v, stubMsg.BufferLength);
1059 wirev += 5;
1060 ok(*wirev == 0xcccccccc, "wirev[5] %08x\n", *wirev); /* pad */
1061 wirev++;
1062 dec2 = dec;
1063 dec2.wReserved = VT_DECIMAL;
1064 ok(!memcmp(wirev, &dec2, sizeof(dec2)), "wirev[6] %08x wirev[7] %08x wirev[8] %08x wirev[9] %08x\n",
1065 *wirev, *(wirev + 1), *(wirev + 2), *(wirev + 3));
1066 if (VARIANT_UNMARSHAL_WORKS)
1068 VariantInit(&v2);
1069 stubMsg.Buffer = buffer;
1070 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1071 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1072 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1073 ok(!memcmp(&V_DECIMAL(&v), & V_DECIMAL(&v2), sizeof(DECIMAL)), "decimals differ\n");
1075 VARIANT_UserFree(&umcb.Flags, &v2);
1077 HeapFree(GetProcessHeap(), 0, oldbuffer);
1079 /*** DECIMAL BYREF ***/
1080 VariantInit(&v);
1081 V_VT(&v) = VT_DECIMAL | VT_BYREF;
1082 V_DECIMALREF(&v) = &dec;
1084 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1085 ok(stubMsg.BufferLength == 40, "size %d\n", stubMsg.BufferLength);
1087 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1088 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1089 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1090 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1091 wirev = (DWORD*)buffer;
1093 check_variant_header(wirev, &v, stubMsg.BufferLength);
1094 wirev += 5;
1095 ok(*wirev == 16, "wv[5] %08x\n", *wirev);
1096 wirev++;
1097 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));
1098 if (VARIANT_UNMARSHAL_WORKS)
1100 VariantInit(&v2);
1101 /* check_variant_header tests wReserved[123], so initialize to unique values.
1102 * (Could probably also do this by setting the variant to a known DECIMAL.)
1104 V_U2(&v2).wReserved1 = 0x0123;
1105 V_U2(&v2).wReserved2 = 0x4567;
1106 V_U2(&v2).wReserved3 = 0x89ab;
1108 stubMsg.Buffer = buffer;
1109 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1110 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1111 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1112 ok(!memcmp(V_DECIMALREF(&v), V_DECIMALREF(&v2), sizeof(DECIMAL)), "decimals differ\n");
1114 VARIANT_UserFree(&umcb.Flags, &v2);
1116 HeapFree(GetProcessHeap(), 0, oldbuffer);
1118 /*** EMPTY ***/
1119 VariantInit(&v);
1120 V_VT(&v) = VT_EMPTY;
1122 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1123 ok(stubMsg.BufferLength == 20, "size %d\n", stubMsg.BufferLength);
1125 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1126 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1127 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1128 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1129 wirev = (DWORD*)buffer;
1131 check_variant_header(wirev, &v, stubMsg.BufferLength);
1132 if (VARIANT_UNMARSHAL_WORKS)
1134 VariantInit(&v2);
1135 stubMsg.Buffer = buffer;
1136 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1137 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1138 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1140 VARIANT_UserFree(&umcb.Flags, &v2);
1142 HeapFree(GetProcessHeap(), 0, oldbuffer);
1144 /*** NULL ***/
1145 VariantInit(&v);
1146 V_VT(&v) = VT_NULL;
1148 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1149 ok(stubMsg.BufferLength == 20, "size %d\n", stubMsg.BufferLength);
1151 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1152 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1153 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1154 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1155 wirev = (DWORD*)buffer;
1157 check_variant_header(wirev, &v, stubMsg.BufferLength);
1158 if (VARIANT_UNMARSHAL_WORKS)
1160 VariantInit(&v2);
1161 stubMsg.Buffer = buffer;
1162 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1163 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1164 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1166 VARIANT_UserFree(&umcb.Flags, &v2);
1168 HeapFree(GetProcessHeap(), 0, oldbuffer);
1170 /*** BSTR ***/
1171 b = SysAllocString(str);
1172 VariantInit(&v);
1173 V_VT(&v) = VT_BSTR;
1174 V_BSTR(&v) = b;
1176 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1177 ok(stubMsg.BufferLength == 60, "size %d\n", stubMsg.BufferLength);
1178 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1179 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1180 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1181 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1182 wirev = (DWORD*)buffer;
1184 check_variant_header(wirev, &v, stubMsg.BufferLength);
1185 wirev += 5;
1186 ok(*wirev, "wv[5] %08x\n", *wirev); /* win2k: this is b. winxp: this is (char*)b + 1 */
1187 wirev++;
1188 check_bstr(wirev, V_BSTR(&v));
1189 if (VARIANT_UNMARSHAL_WORKS)
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 ok(SysStringByteLen(V_BSTR(&v)) == SysStringByteLen(V_BSTR(&v2)), "bstr string lens differ\n");
1197 ok(!memcmp(V_BSTR(&v), V_BSTR(&v2), SysStringByteLen(V_BSTR(&v))), "bstrs differ\n");
1199 VARIANT_UserFree(&umcb.Flags, &v2);
1201 HeapFree(GetProcessHeap(), 0, oldbuffer);
1203 /*** BSTR BYREF ***/
1204 VariantInit(&v);
1205 V_VT(&v) = VT_BSTR | VT_BYREF;
1206 V_BSTRREF(&v) = &b;
1208 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1209 ok(stubMsg.BufferLength == 64, "size %d\n", stubMsg.BufferLength);
1210 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1211 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1212 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1213 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1214 wirev = (DWORD*)buffer;
1216 check_variant_header(wirev, &v, stubMsg.BufferLength);
1217 wirev += 5;
1218 ok(*wirev == 0x4, "wv[5] %08x\n", *wirev);
1219 wirev++;
1220 ok(*wirev, "wv[6] %08x\n", *wirev); /* win2k: this is b. winxp: this is (char*)b + 1 */
1221 wirev++;
1222 check_bstr(wirev, b);
1223 if (VARIANT_UNMARSHAL_WORKS)
1225 VariantInit(&v2);
1226 stubMsg.Buffer = buffer;
1227 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1228 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1229 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1230 ok(SysStringByteLen(*V_BSTRREF(&v)) == SysStringByteLen(*V_BSTRREF(&v2)), "bstr string lens differ\n");
1231 ok(!memcmp(*V_BSTRREF(&v), *V_BSTRREF(&v2), SysStringByteLen(*V_BSTRREF(&v))), "bstrs differ\n");
1233 VARIANT_UserFree(&umcb.Flags, &v2);
1235 HeapFree(GetProcessHeap(), 0, oldbuffer);
1236 SysFreeString(b);
1238 /*** ARRAY ***/
1239 sab.lLbound = 5;
1240 sab.cElements = 10;
1242 lpsa = SafeArrayCreate(VT_R8, 1, &sab);
1243 *(DWORD *)lpsa->pvData = 0xcafebabe;
1244 *((DWORD *)lpsa->pvData + 1) = 0xdeadbeef;
1246 VariantInit(&v);
1247 V_VT(&v) = VT_UI4 | VT_ARRAY;
1248 V_ARRAY(&v) = lpsa;
1250 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1251 expected = 152;
1252 ok(stubMsg.BufferLength == expected || stubMsg.BufferLength == expected + 8, /* win64 */
1253 "size %u instead of %u\n", stubMsg.BufferLength, expected);
1254 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1255 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1256 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1257 ok(next == buffer + expected, "got %p expect %p\n", next, buffer + expected);
1258 wirev = (DWORD*)buffer;
1260 check_variant_header(wirev, &v, expected);
1261 wirev += 5;
1262 ok(*wirev, "wv[5] %08x\n", *wirev); /* win2k: this is lpsa. winxp: this is (char*)lpsa + 1 */
1263 wirev++;
1264 check_safearray(wirev, lpsa);
1265 if (VARIANT_UNMARSHAL_WORKS)
1267 LONG bound, bound2;
1268 VARTYPE vt, vt2;
1269 VariantInit(&v2);
1270 stubMsg.Buffer = buffer;
1271 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1272 ok(next == buffer + expected, "got %p expect %p\n", next, buffer + expected);
1273 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1274 ok(SafeArrayGetDim(V_ARRAY(&v)) == SafeArrayGetDim(V_ARRAY(&v)), "array dims differ\n");
1275 SafeArrayGetLBound(V_ARRAY(&v), 1, &bound);
1276 SafeArrayGetLBound(V_ARRAY(&v2), 1, &bound2);
1277 ok(bound == bound2, "array lbounds differ\n");
1278 SafeArrayGetUBound(V_ARRAY(&v), 1, &bound);
1279 SafeArrayGetUBound(V_ARRAY(&v2), 1, &bound2);
1280 ok(bound == bound2, "array ubounds differ\n");
1281 SafeArrayGetVartype(V_ARRAY(&v), &vt);
1282 SafeArrayGetVartype(V_ARRAY(&v2), &vt2);
1283 ok(vt == vt2, "array vts differ %x %x\n", vt, vt2);
1284 VARIANT_UserFree(&umcb.Flags, &v2);
1286 HeapFree(GetProcessHeap(), 0, oldbuffer);
1288 /*** ARRAY BYREF ***/
1289 VariantInit(&v);
1290 V_VT(&v) = VT_UI4 | VT_ARRAY | VT_BYREF;
1291 V_ARRAYREF(&v) = &lpsa;
1293 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1294 expected = 152;
1295 ok(stubMsg.BufferLength == expected || stubMsg.BufferLength == expected + 16, /* win64 */
1296 "size %u instead of %u\n", stubMsg.BufferLength, expected);
1297 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1298 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1299 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1300 ok(next == buffer + expected, "got %p expect %p\n", next, buffer + expected);
1301 wirev = (DWORD*)buffer;
1303 check_variant_header(wirev, &v, expected);
1304 wirev += 5;
1305 ok(*wirev == 4, "wv[5] %08x\n", *wirev);
1306 wirev++;
1307 ok(*wirev, "wv[6] %08x\n", *wirev); /* win2k: this is lpsa. winxp: this is (char*)lpsa + 1 */
1308 wirev++;
1309 check_safearray(wirev, lpsa);
1310 if (VARIANT_UNMARSHAL_WORKS)
1312 LONG bound, bound2;
1313 VARTYPE vt, vt2;
1314 VariantInit(&v2);
1315 stubMsg.Buffer = buffer;
1316 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1317 ok(next == buffer + expected, "got %p expect %p\n", next, buffer + expected);
1318 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1319 ok(SafeArrayGetDim(*V_ARRAYREF(&v)) == SafeArrayGetDim(*V_ARRAYREF(&v)), "array dims differ\n");
1320 SafeArrayGetLBound(*V_ARRAYREF(&v), 1, &bound);
1321 SafeArrayGetLBound(*V_ARRAYREF(&v2), 1, &bound2);
1322 ok(bound == bound2, "array lbounds differ\n");
1323 SafeArrayGetUBound(*V_ARRAYREF(&v), 1, &bound);
1324 SafeArrayGetUBound(*V_ARRAYREF(&v2), 1, &bound2);
1325 ok(bound == bound2, "array ubounds differ\n");
1326 SafeArrayGetVartype(*V_ARRAYREF(&v), &vt);
1327 SafeArrayGetVartype(*V_ARRAYREF(&v2), &vt2);
1328 ok(vt == vt2, "array vts differ %x %x\n", vt, vt2);
1329 VARIANT_UserFree(&umcb.Flags, &v2);
1331 HeapFree(GetProcessHeap(), 0, oldbuffer);
1332 SafeArrayDestroy(lpsa);
1334 /*** VARIANT BYREF ***/
1335 VariantInit(&v);
1336 VariantInit(&v2);
1337 V_VT(&v2) = VT_R8;
1338 V_R8(&v2) = 3.1415;
1339 V_VT(&v) = VT_VARIANT | VT_BYREF;
1340 V_VARIANTREF(&v) = &v2;
1342 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1343 ok(stubMsg.BufferLength == 64, "size %d\n", stubMsg.BufferLength);
1344 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1345 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1346 memset(buffer, 0xcc, stubMsg.BufferLength);
1347 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1348 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1349 wirev = (DWORD*)buffer;
1350 check_variant_header(wirev, &v, stubMsg.BufferLength);
1351 wirev += 5;
1353 ok(*wirev == sizeof(VARIANT), "wv[5] %08x\n", *wirev);
1354 wirev++;
1355 ok(*wirev == ('U' | 's' << 8 | 'e' << 16 | 'r' << 24), "wv[6] %08x\n", *wirev); /* 'User' */
1356 wirev++;
1357 ok(*wirev == 0xcccccccc, "wv[7] %08x\n", *wirev); /* pad */
1358 wirev++;
1359 check_variant_header(wirev, &v2, stubMsg.BufferLength - 32);
1360 wirev += 5;
1361 ok(*wirev == 0xcccccccc, "wv[13] %08x\n", *wirev); /* pad for VT_R8 */
1362 wirev++;
1363 ok(*(double*)wirev == V_R8(&v2), "wv[6] %08x wv[7] %08x\n", *wirev, *(wirev+1));
1364 if (VARIANT_UNMARSHAL_WORKS)
1366 VARIANT v3;
1367 VariantInit(&v3);
1368 stubMsg.Buffer = buffer;
1369 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v3);
1370 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1371 ok(V_VT(&v) == V_VT(&v3), "got vt %d expect %d\n", V_VT(&v), V_VT(&v3));
1372 ok(V_VT(V_VARIANTREF(&v)) == V_VT(V_VARIANTREF(&v3)), "vts differ %x %x\n",
1373 V_VT(V_VARIANTREF(&v)), V_VT(V_VARIANTREF(&v3)));
1374 ok(V_R8(V_VARIANTREF(&v)) == V_R8(V_VARIANTREF(&v3)), "r8s differ\n");
1375 VARIANT_UserFree(&umcb.Flags, &v3);
1377 HeapFree(GetProcessHeap(), 0, oldbuffer);
1379 /*** UNKNOWN ***/
1380 heap_unknown = HeapAlloc(GetProcessHeap(), 0, sizeof(*heap_unknown));
1381 heap_unknown->lpVtbl = &HeapUnknown_Vtbl;
1382 heap_unknown->refs = 1;
1383 VariantInit(&v);
1384 VariantInit(&v2);
1385 V_VT(&v) = VT_UNKNOWN;
1386 V_UNKNOWN(&v) = (IUnknown *)heap_unknown;
1388 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1389 ok(stubMsg.BufferLength > 32, "size %d\n", stubMsg.BufferLength);
1390 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1391 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1392 memset(buffer, 0xcc, stubMsg.BufferLength);
1393 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1394 wirev = (DWORD*)buffer;
1395 check_variant_header(wirev, &v, next - buffer);
1396 wirev += 5;
1398 todo_wine
1399 ok(*wirev == (DWORD_PTR)V_UNKNOWN(&v) /* Win9x */ ||
1400 *wirev == (DWORD_PTR)V_UNKNOWN(&v) + 1 /* NT */, "wv[5] %08x\n", *wirev);
1401 wirev++;
1402 todo_wine
1403 ok(*wirev == next - buffer - 0x20, "wv[6] %08x\n", *wirev);
1404 wirev++;
1405 todo_wine
1406 ok(*wirev == next - buffer - 0x20, "wv[7] %08x\n", *wirev);
1407 wirev++;
1408 todo_wine
1409 ok(*wirev == 0x574f454d, "wv[8] %08x\n", *wirev);
1410 if (VARIANT_UNMARSHAL_WORKS)
1412 VARIANT v3;
1413 VariantInit(&v3);
1414 V_VT(&v3) = VT_UNKNOWN;
1415 V_UNKNOWN(&v3) = (IUnknown *)heap_unknown;
1416 IUnknown_AddRef(V_UNKNOWN(&v3));
1417 stubMsg.Buffer = buffer;
1418 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v3);
1419 ok(V_VT(&v) == V_VT(&v3), "got vt %d expect %d\n", V_VT(&v), V_VT(&v3));
1420 ok(V_UNKNOWN(&v) == V_UNKNOWN(&v3), "got %p expect %p\n", V_UNKNOWN(&v), V_UNKNOWN(&v3));
1421 VARIANT_UserFree(&umcb.Flags, &v3);
1422 ok(heap_unknown->refs == 1, "%d refcounts of IUnknown leaked\n", heap_unknown->refs - 1);
1423 IUnknown_Release((IUnknown *)heap_unknown);
1425 HeapFree(GetProcessHeap(), 0, oldbuffer);
1427 /*** UNKNOWN BYREF ***/
1428 heap_unknown = HeapAlloc(GetProcessHeap(), 0, sizeof(*heap_unknown));
1429 heap_unknown->lpVtbl = &HeapUnknown_Vtbl;
1430 heap_unknown->refs = 1;
1431 VariantInit(&v);
1432 VariantInit(&v2);
1433 V_VT(&v) = VT_UNKNOWN | VT_BYREF;
1434 V_UNKNOWNREF(&v) = (IUnknown **)&heap_unknown;
1436 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1437 ok(stubMsg.BufferLength > 36, "size %d\n", stubMsg.BufferLength);
1438 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1439 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1440 memset(buffer, 0xcc, stubMsg.BufferLength);
1441 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1442 wirev = (DWORD*)buffer;
1443 check_variant_header(wirev, &v, next - buffer);
1444 wirev += 5;
1446 ok(*wirev == 4, "wv[5] %08x\n", *wirev);
1447 wirev++;
1448 todo_wine
1449 ok(*wirev == (DWORD_PTR)heap_unknown /* Win9x, Win2000 */ ||
1450 *wirev == (DWORD_PTR)heap_unknown + 1 /* XP */, "wv[6] %08x\n", *wirev);
1451 wirev++;
1452 todo_wine
1453 ok(*wirev == next - buffer - 0x24, "wv[7] %08x\n", *wirev);
1454 wirev++;
1455 todo_wine
1456 ok(*wirev == next - buffer - 0x24, "wv[8] %08x\n", *wirev);
1457 wirev++;
1458 todo_wine
1459 ok(*wirev == 0x574f454d, "wv[9] %08x\n", *wirev);
1460 if (VARIANT_UNMARSHAL_WORKS)
1462 VARIANT v3;
1463 VariantInit(&v3);
1464 V_VT(&v3) = VT_UNKNOWN;
1465 V_UNKNOWN(&v3) = (IUnknown *)heap_unknown;
1466 IUnknown_AddRef(V_UNKNOWN(&v3));
1467 stubMsg.Buffer = buffer;
1468 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v3);
1469 ok(V_VT(&v) == V_VT(&v3), "got vt %d expect %d\n", V_VT(&v), V_VT(&v3));
1470 ok(*V_UNKNOWNREF(&v) == *V_UNKNOWNREF(&v3), "got %p expect %p\n", *V_UNKNOWNREF(&v), *V_UNKNOWNREF(&v3));
1471 VARIANT_UserFree(&umcb.Flags, &v3);
1472 ok(heap_unknown->refs == 1, "%d refcounts of IUnknown leaked\n", heap_unknown->refs - 1);
1473 IUnknown_Release((IUnknown *)heap_unknown);
1475 HeapFree(GetProcessHeap(), 0, oldbuffer);
1479 START_TEST(usrmarshal)
1481 CoInitialize(NULL);
1483 test_marshal_LPSAFEARRAY();
1484 test_marshal_BSTR();
1485 test_marshal_VARIANT();
1487 CoUninitialize();