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
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)
35 # define V_U2(A) (*(A))
38 /* doesn't work on Windows due to needing more of the
39 * MIDL_STUB_MESSAGE structure to be filled out */
40 #define LPSAFEARRAY_UNMARSHAL_WORKS 0
41 #define BSTR_UNMARSHAL_WORKS 0
42 #define VARIANT_UNMARSHAL_WORKS 1
44 static inline SF_TYPE get_union_type(SAFEARRAY *psa)
49 hr = SafeArrayGetVartype(psa, &vt);
52 if(psa->fFeatures & FADF_VARIANT) return SF_VARIANT;
54 switch(psa->cbElements)
56 case 1: vt = VT_I1; break;
57 case 2: vt = VT_I2; break;
58 case 4: vt = VT_I4; break;
59 case 8: vt = VT_I8; break;
64 if (psa->fFeatures & FADF_HAVEIID)
70 case VT_UI1: return SF_I1;
73 case VT_UI2: return SF_I2;
78 case VT_R4: return SF_I4;
83 case VT_UI8: return SF_I8;
85 case VT_UINT_PTR: return (sizeof(UINT_PTR) == 4 ? SF_I4 : SF_I8);
86 case VT_BSTR: return SF_BSTR;
87 case VT_DISPATCH: return SF_DISPATCH;
88 case VT_VARIANT: return SF_VARIANT;
89 case VT_UNKNOWN: return SF_UNKNOWN;
90 /* Note: Return a non-zero size to indicate vt is valid. The actual size
91 * of a UDT is taken from the result of IRecordInfo_GetSize().
93 case VT_RECORD: return SF_RECORD;
94 default: return SF_ERROR;
98 static ULONG get_cell_count(const SAFEARRAY *psa)
100 const SAFEARRAYBOUND* psab = psa->rgsabound;
101 USHORT cCount = psa->cDims;
102 ULONG ulNumCells = 1;
106 if (!psab->cElements)
108 ulNumCells *= psab->cElements;
114 static void check_safearray(void *buffer, LPSAFEARRAY lpsa)
116 unsigned char *wiresa = buffer;
123 ok(*(void **)wiresa == NULL, "wiresa + 0x0 should be NULL instead of 0x%08x\n", *(DWORD *)wiresa);
127 if(FAILED(SafeArrayGetVartype(lpsa, &vt)))
130 sftype = get_union_type(lpsa);
131 cell_count = get_cell_count(lpsa);
133 ok(*(DWORD *)wiresa, "wiresa + 0x0 should be non-NULL instead of 0x%08x\n", *(DWORD *)wiresa); /* win2k: this is lpsa. winxp: this is 0x00000001 */
134 wiresa += sizeof(DWORD);
135 ok(*(DWORD *)wiresa == lpsa->cDims, "wiresa + 0x4 should be lpsa->cDims instead of 0x%08x\n", *(DWORD *)wiresa);
136 wiresa += sizeof(DWORD);
137 ok(*(WORD *)wiresa == lpsa->cDims, "wiresa + 0x8 should be lpsa->cDims instead of 0x%04x\n", *(WORD *)wiresa);
138 wiresa += sizeof(WORD);
139 ok(*(WORD *)wiresa == lpsa->fFeatures, "wiresa + 0xc should be lpsa->fFeatures instead of 0x%08x\n", *(WORD *)wiresa);
140 wiresa += sizeof(WORD);
141 ok(*(DWORD *)wiresa == lpsa->cbElements, "wiresa + 0x10 should be lpsa->cbElements instead of 0x%08x\n", *(DWORD *)wiresa);
142 wiresa += sizeof(DWORD);
143 ok(*(WORD *)wiresa == lpsa->cLocks, "wiresa + 0x16 should be lpsa->cLocks instead of 0x%04x\n", *(WORD *)wiresa);
144 wiresa += sizeof(WORD);
145 ok(*(WORD *)wiresa == vt, "wiresa + 0x14 should be %04x instead of 0x%04x\n", vt, *(WORD *)wiresa);
146 wiresa += sizeof(WORD);
147 ok(*(DWORD *)wiresa == sftype, "wiresa + 0x18 should be %08x instead of 0x%08x\n", (DWORD)sftype, *(DWORD *)wiresa);
148 wiresa += sizeof(DWORD);
149 ok(*(DWORD *)wiresa == cell_count, "wiresa + 0x1c should be %u instead of %u\n", cell_count, *(DWORD *)wiresa);
150 wiresa += sizeof(DWORD);
151 ok(*(DWORD_PTR *)wiresa == (DWORD_PTR)lpsa->pvData, "wiresa + 0x20 should be lpsa->pvData instead of 0x%08lx\n", *(DWORD_PTR *)wiresa);
152 wiresa += sizeof(DWORD_PTR);
153 if(sftype == SF_HAVEIID)
156 SafeArrayGetIID(lpsa, &guid);
157 ok(IsEqualGUID(&guid, (GUID*)wiresa), "guid mismatch\n");
158 wiresa += sizeof(GUID);
160 ok(!memcmp(wiresa, lpsa->rgsabound, sizeof(lpsa->rgsabound[0]) * lpsa->cDims), "bounds mismatch\n");
161 wiresa += sizeof(lpsa->rgsabound[0]) * lpsa->cDims;
163 ok(*(DWORD *)wiresa == cell_count, "wiresa + 0x2c should be %u instead of %u\n", cell_count, *(DWORD*)wiresa);
164 wiresa += sizeof(DWORD);
165 /* elements are now pointed to by wiresa */
168 static void test_marshal_LPSAFEARRAY(void)
170 unsigned char *buffer;
173 LPSAFEARRAY lpsa2 = NULL;
175 MIDL_STUB_MESSAGE stubMsg = { 0 };
176 USER_MARSHAL_CB umcb = { 0 };
180 umcb.Flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
181 umcb.pReserve = NULL;
182 umcb.pStubMsg = &stubMsg;
187 lpsa = SafeArrayCreate(VT_I2, 1, &sab);
188 *(DWORD *)lpsa->pvData = 0xcafebabe;
191 size = LPSAFEARRAY_UserSize(&umcb.Flags, 1, &lpsa);
192 ok(size == 68, "size should be 68 bytes, not %ld\n", size);
193 size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
194 ok(size == 64, "size should be 64 bytes, not %ld\n", size);
195 buffer = HeapAlloc(GetProcessHeap(), 0, size);
196 LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
198 check_safearray(buffer, lpsa);
200 if (LPSAFEARRAY_UNMARSHAL_WORKS)
203 LPSAFEARRAY_UserUnmarshal(&umcb.Flags, buffer, &lpsa2);
204 ok(lpsa2 != NULL, "LPSAFEARRAY didn't unmarshal\n");
205 SafeArrayGetVartype(lpsa, &vt);
206 SafeArrayGetVartype(lpsa2, &vt2);
207 ok(vt == vt2, "vts differ %x %x\n", vt, vt2);
208 LPSAFEARRAY_UserFree(&umcb.Flags, &lpsa2);
210 HeapFree(GetProcessHeap(), 0, buffer);
211 SafeArrayDestroy(lpsa);
213 /* test NULL safe array */
216 size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
217 ok(size == 4, "size should be 4 bytes, not %ld\n", size);
218 buffer = HeapAlloc(GetProcessHeap(), 0, size);
219 LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
220 check_safearray(buffer, lpsa);
222 if (LPSAFEARRAY_UNMARSHAL_WORKS)
224 LPSAFEARRAY_UserUnmarshal(&umcb.Flags, buffer, &lpsa2);
225 ok(lpsa2 == NULL, "NULL LPSAFEARRAY didn't unmarshal\n");
226 LPSAFEARRAY_UserFree(&umcb.Flags, &lpsa2);
228 HeapFree(GetProcessHeap(), 0, buffer);
233 lpsa = SafeArrayCreate(VT_R8, 1, &sab);
234 *(double *)lpsa->pvData = 3.1415;
237 size = LPSAFEARRAY_UserSize(&umcb.Flags, 1, &lpsa);
238 ok(size == 128, "size should be 128 bytes, not %ld\n", size);
239 size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
240 ok(size == 128, "size should be 128 bytes, not %ld\n", size);
241 buffer = HeapAlloc(GetProcessHeap(), 0, size);
242 LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
244 check_safearray(buffer, lpsa);
246 HeapFree(GetProcessHeap(), 0, buffer);
247 SafeArrayDestroy(lpsa);
249 /* VARTYPE-less arrays can be marshaled if cbElements is 1,2,4 or 8 as type SF_In */
250 hr = SafeArrayAllocDescriptor(1, &lpsa);
251 ok(hr == S_OK, "saad failed %08x\n", hr);
252 lpsa->cbElements = 8;
253 lpsa->rgsabound[0].lLbound = 2;
254 lpsa->rgsabound[0].cElements = 48;
255 hr = SafeArrayAllocData(lpsa);
256 ok(hr == S_OK, "saad failed %08x\n", hr);
258 hr = SafeArrayGetVartype(lpsa, &vt);
259 ok(hr == E_INVALIDARG, "ret %08x\n", hr);
261 size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
262 ok(size == 432, "size %ld\n", size);
263 buffer = HeapAlloc(GetProcessHeap(), 0, size);
264 LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
265 check_safearray(buffer, lpsa);
266 HeapFree(GetProcessHeap(), 0, buffer);
267 SafeArrayDestroyData(lpsa);
268 SafeArrayDestroyDescriptor(lpsa);
270 /* VARTYPE-less arrays with FADF_VARIANT */
271 hr = SafeArrayAllocDescriptor(1, &lpsa);
272 ok(hr == S_OK, "saad failed %08x\n", hr);
273 lpsa->cbElements = 16;
274 lpsa->fFeatures = FADF_VARIANT;
275 lpsa->rgsabound[0].lLbound = 2;
276 lpsa->rgsabound[0].cElements = 48;
277 hr = SafeArrayAllocData(lpsa);
278 ok(hr == S_OK, "saad failed %08x\n", hr);
280 hr = SafeArrayGetVartype(lpsa, &vt);
281 ok(hr == E_INVALIDARG, "ret %08x\n", hr);
283 size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
285 ok(size == 1388, "size %ld\n", size);
286 buffer = HeapAlloc(GetProcessHeap(), 0, size);
287 LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
288 check_safearray(buffer, lpsa);
289 HeapFree(GetProcessHeap(), 0, buffer);
290 SafeArrayDestroyData(lpsa);
291 SafeArrayDestroyDescriptor(lpsa);
294 static void check_bstr(void *buffer, BSTR b)
296 DWORD *wireb = buffer;
297 DWORD len = SysStringByteLen(b);
299 ok(*wireb == (len + 1) / 2, "wv[0] %08x\n", *wireb);
302 ok(*wireb == len, "wv[1] %08x\n", *wireb);
304 ok(*wireb == 0xffffffff, "wv[1] %08x\n", *wireb);
306 ok(*wireb == (len + 1) / 2, "wv[2] %08x\n", *wireb);
310 ok(!memcmp(wireb, b, (len + 1) & ~1), "strings differ\n");
315 static void test_marshal_BSTR(void)
318 MIDL_STUB_MESSAGE stubMsg = { 0 };
319 USER_MARSHAL_CB umcb = { 0 };
320 unsigned char *buffer, *next;
322 WCHAR str[] = {'m','a','r','s','h','a','l',' ','t','e','s','t','1',0};
325 umcb.Flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
326 umcb.pReserve = NULL;
327 umcb.pStubMsg = &stubMsg;
329 b = SysAllocString(str);
330 len = SysStringLen(b);
331 ok(len == 13, "get %d\n", len);
333 /* BSTRs are DWORD aligned */
334 size = BSTR_UserSize(&umcb.Flags, 1, &b);
335 ok(size == 42, "size %ld\n", size);
337 size = BSTR_UserSize(&umcb.Flags, 0, &b);
338 ok(size == 38, "size %ld\n", size);
340 buffer = HeapAlloc(GetProcessHeap(), 0, size);
341 next = BSTR_UserMarshal(&umcb.Flags, buffer, &b);
342 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
343 check_bstr(buffer, b);
345 if (BSTR_UNMARSHAL_WORKS)
348 next = BSTR_UserUnmarshal(&umcb.Flags, buffer, &b2);
349 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
350 ok(b2 != NULL, "BSTR didn't unmarshal\n");
351 ok(!memcmp(b, b2, (len + 1) * 2), "strings differ\n");
352 BSTR_UserFree(&umcb.Flags, &b2);
355 HeapFree(GetProcessHeap(), 0, buffer);
359 size = BSTR_UserSize(&umcb.Flags, 0, &b);
360 ok(size == 12, "size %ld\n", size);
362 buffer = HeapAlloc(GetProcessHeap(), 0, size);
363 next = BSTR_UserMarshal(&umcb.Flags, buffer, &b);
364 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
366 check_bstr(buffer, b);
367 if (BSTR_UNMARSHAL_WORKS)
370 next = BSTR_UserUnmarshal(&umcb.Flags, buffer, &b2);
371 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
372 ok(b2 == NULL, "NULL BSTR didn't unmarshal\n");
373 BSTR_UserFree(&umcb.Flags, &b2);
375 HeapFree(GetProcessHeap(), 0, buffer);
377 b = SysAllocStringByteLen("abc", 3);
378 *(((char*)b) + 3) = 'd';
379 len = SysStringLen(b);
380 ok(len == 1, "get %d\n", len);
381 len = SysStringByteLen(b);
382 ok(len == 3, "get %d\n", len);
384 size = BSTR_UserSize(&umcb.Flags, 0, &b);
385 ok(size == 16, "size %ld\n", size);
387 buffer = HeapAlloc(GetProcessHeap(), 0, size);
388 memset(buffer, 0xcc, size);
389 next = BSTR_UserMarshal(&umcb.Flags, buffer, &b);
390 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
391 check_bstr(buffer, b);
392 ok(buffer[15] == 'd', "buffer[15] %02x\n", buffer[15]);
394 if (BSTR_UNMARSHAL_WORKS)
397 next = BSTR_UserUnmarshal(&umcb.Flags, buffer, &b2);
398 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
399 ok(b2 != NULL, "BSTR didn't unmarshal\n");
400 ok(!memcmp(b, b2, len), "strings differ\n");
401 BSTR_UserFree(&umcb.Flags, &b2);
403 HeapFree(GetProcessHeap(), 0, buffer);
406 b = SysAllocStringByteLen("", 0);
407 len = SysStringLen(b);
408 ok(len == 0, "get %d\n", len);
409 len = SysStringByteLen(b);
410 ok(len == 0, "get %d\n", len);
412 size = BSTR_UserSize(&umcb.Flags, 0, &b);
413 ok(size == 12, "size %ld\n", size);
415 buffer = HeapAlloc(GetProcessHeap(), 0, size);
416 next = BSTR_UserMarshal(&umcb.Flags, buffer, &b);
417 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
418 check_bstr(buffer, b);
420 if (BSTR_UNMARSHAL_WORKS)
423 next = BSTR_UserUnmarshal(&umcb.Flags, buffer, &b2);
424 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
425 ok(b2 != NULL, "NULL LPSAFEARRAY didn't unmarshal\n");
426 len = SysStringByteLen(b2);
427 ok(len == 0, "byte len %d\n", len);
428 BSTR_UserFree(&umcb.Flags, &b2);
430 HeapFree(GetProcessHeap(), 0, buffer);
436 const IUnknownVtbl *lpVtbl;
440 static HRESULT WINAPI HeapUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
442 if (IsEqualIID(riid, &IID_IUnknown))
444 IUnknown_AddRef(iface);
445 *ppv = (LPVOID)iface;
449 return E_NOINTERFACE;
452 static ULONG WINAPI HeapUnknown_AddRef(IUnknown *iface)
454 HeapUnknown *This = (HeapUnknown *)iface;
455 return InterlockedIncrement((LONG*)&This->refs);
458 static ULONG WINAPI HeapUnknown_Release(IUnknown *iface)
460 HeapUnknown *This = (HeapUnknown *)iface;
461 ULONG refs = InterlockedDecrement((LONG*)&This->refs);
462 if (!refs) HeapFree(GetProcessHeap(), 0, This);
466 static const IUnknownVtbl HeapUnknown_Vtbl =
468 HeapUnknown_QueryInterface,
473 static void check_variant_header(DWORD *wirev, VARIANT *v, unsigned long size)
478 ok(*wirev == (size + 7) >> 3, "wv[0] %08x, expected %08lx\n", *wirev, (size + 7) >> 3);
480 ok(*wirev == 0, "wv[1] %08x\n", *wirev);
483 ok(*wp == V_VT(v), "vt %04x expected %04x\n", *wp, V_VT(v));
485 ok(*wp == V_U2(v).wReserved1, "res1 %04x expected %04x\n", *wp, V_U2(v).wReserved1);
487 ok(*wp == V_U2(v).wReserved2, "res2 %04x expected %04x\n", *wp, V_U2(v).wReserved2);
489 ok(*wp == V_U2(v).wReserved3, "res3 %04x expected %04x\n", *wp, V_U2(v).wReserved3);
493 if(switch_is & VT_ARRAY)
494 switch_is &= ~VT_TYPEMASK;
495 ok(*wirev == switch_is, "switch_is %08x expected %08x\n", *wirev, switch_is);
498 static void test_marshal_VARIANT(void)
501 MIDL_STUB_MESSAGE stubMsg = { 0 };
502 RPC_MESSAGE rpcMsg = { 0 };
503 USER_MARSHAL_CB umcb = { 0 };
504 unsigned char *buffer, *next;
510 WCHAR str[] = {'m','a','r','s','h','a','l',' ','t','e','s','t',0};
514 HeapUnknown *heap_unknown;
516 stubMsg.RpcMsg = &rpcMsg;
518 umcb.Flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
519 umcb.pStubMsg = &stubMsg;
520 umcb.pReserve = NULL;
521 umcb.Signature = USER_MARSHAL_CB_SIGNATURE;
522 umcb.CBType = USER_MARSHAL_CB_UNMARSHALL;
529 /* Variants have an alignment of 8 */
530 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 1, &v);
531 ok(stubMsg.BufferLength == 29, "size %d\n", stubMsg.BufferLength);
533 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
534 ok(stubMsg.BufferLength == 21, "size %d\n", stubMsg.BufferLength);
536 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = HeapAlloc(GetProcessHeap(), 0, stubMsg.BufferLength);
537 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
538 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
539 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
540 wirev = (DWORD*)buffer;
542 check_variant_header(wirev, &v, stubMsg.BufferLength);
544 ok(*(char*)wirev == V_I1(&v), "wv[5] %08x\n", *wirev);
545 if (VARIANT_UNMARSHAL_WORKS)
548 stubMsg.Buffer = buffer;
549 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
550 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
551 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
552 ok(V_I1(&v) == V_I1(&v2), "got i1 %x expect %x\n", V_I1(&v), V_I1(&v2));
554 VARIANT_UserFree(&umcb.Flags, &v2);
556 HeapFree(GetProcessHeap(), 0, buffer);
563 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
564 ok(stubMsg.BufferLength == 22, "size %d\n", stubMsg.BufferLength);
566 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = HeapAlloc(GetProcessHeap(), 0, stubMsg.BufferLength);
567 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
568 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
569 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
570 wirev = (DWORD*)buffer;
572 check_variant_header(wirev, &v, stubMsg.BufferLength);
574 ok(*(short*)wirev == V_I2(&v), "wv[5] %08x\n", *wirev);
575 if (VARIANT_UNMARSHAL_WORKS)
578 stubMsg.Buffer = buffer;
579 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
580 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
581 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
582 ok(V_I2(&v) == V_I2(&v2), "got i2 %x expect %x\n", V_I2(&v), V_I2(&v2));
584 VARIANT_UserFree(&umcb.Flags, &v2);
586 HeapFree(GetProcessHeap(), 0, buffer);
590 V_VT(&v) = VT_I2 | VT_BYREF;
594 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
595 ok(stubMsg.BufferLength == 26, "size %d\n", stubMsg.BufferLength);
597 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = HeapAlloc(GetProcessHeap(), 0, stubMsg.BufferLength);
598 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
599 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
600 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
601 wirev = (DWORD*)buffer;
603 check_variant_header(wirev, &v, stubMsg.BufferLength);
605 ok(*wirev == 0x4, "wv[5] %08x\n", *wirev);
607 ok(*(short*)wirev == s, "wv[6] %08x\n", *wirev);
608 if (VARIANT_UNMARSHAL_WORKS)
611 stubMsg.Buffer = buffer;
612 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
613 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
614 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
615 ok(*V_I2REF(&v) == *V_I2REF(&v2), "got i2 ref %x expect ui4 ref %x\n", *V_I2REF(&v), *V_I2REF(&v2));
617 VARIANT_UserFree(&umcb.Flags, &v2);
619 HeapFree(GetProcessHeap(), 0, buffer);
626 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
627 ok(stubMsg.BufferLength == 24, "size %d\n", stubMsg.BufferLength);
629 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = HeapAlloc(GetProcessHeap(), 0, stubMsg.BufferLength);
630 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
631 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
632 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
633 wirev = (DWORD*)buffer;
635 check_variant_header(wirev, &v, stubMsg.BufferLength);
637 ok(*wirev == V_I4(&v), "wv[5] %08x\n", *wirev);
639 if (VARIANT_UNMARSHAL_WORKS)
642 stubMsg.Buffer = buffer;
643 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
644 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
645 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
646 ok(V_I4(&v) == V_I4(&v2), "got i4 %x expect %x\n", V_I4(&v), V_I4(&v2));
648 VARIANT_UserFree(&umcb.Flags, &v2);
651 HeapFree(GetProcessHeap(), 0, buffer);
658 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
659 ok(stubMsg.BufferLength == 24, "size %d\n", stubMsg.BufferLength);
661 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = HeapAlloc(GetProcessHeap(), 0, stubMsg.BufferLength);
662 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
663 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
664 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
665 wirev = (DWORD*)buffer;
667 check_variant_header(wirev, &v, stubMsg.BufferLength);
669 ok(*wirev == 0x1234, "wv[5] %08x\n", *wirev);
670 if (VARIANT_UNMARSHAL_WORKS)
673 stubMsg.Buffer = buffer;
674 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
675 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
676 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
677 ok(V_UI4(&v) == V_UI4(&v2), "got ui4 %x expect %x\n", V_UI4(&v), V_UI4(&v2));
679 VARIANT_UserFree(&umcb.Flags, &v2);
682 HeapFree(GetProcessHeap(), 0, buffer);
686 V_VT(&v) = VT_UI4 | VT_BYREF;
690 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
691 ok(stubMsg.BufferLength == 28, "size %d\n", stubMsg.BufferLength);
693 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = HeapAlloc(GetProcessHeap(), 0, stubMsg.BufferLength);
694 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
695 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
696 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
697 wirev = (DWORD*)buffer;
699 check_variant_header(wirev, &v, stubMsg.BufferLength);
701 ok(*wirev == 0x4, "wv[5] %08x\n", *wirev);
703 ok(*wirev == ul, "wv[6] %08x\n", *wirev);
705 if (VARIANT_UNMARSHAL_WORKS)
708 stubMsg.Buffer = buffer;
709 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
710 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
711 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
712 ok(*V_UI4REF(&v) == *V_UI4REF(&v2), "got ui4 ref %x expect ui4 ref %x\n", *V_UI4REF(&v), *V_UI4REF(&v2));
714 VARIANT_UserFree(&umcb.Flags, &v2);
716 HeapFree(GetProcessHeap(), 0, buffer);
723 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
724 ok(stubMsg.BufferLength == 24, "size %d\n", stubMsg.BufferLength);
726 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = HeapAlloc(GetProcessHeap(), 0, stubMsg.BufferLength);
727 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
728 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
729 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
730 wirev = (DWORD*)buffer;
732 check_variant_header(wirev, &v, stubMsg.BufferLength);
734 ok(*(float*)wirev == V_R4(&v), "wv[5] %08x\n", *wirev);
735 if (VARIANT_UNMARSHAL_WORKS)
738 stubMsg.Buffer = buffer;
739 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
740 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
741 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
742 ok(V_R4(&v) == V_R4(&v2), "got r4 %f expect %f\n", V_R4(&v), V_R4(&v2));
744 VARIANT_UserFree(&umcb.Flags, &v2);
746 HeapFree(GetProcessHeap(), 0, buffer);
753 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
754 ok(stubMsg.BufferLength == 32, "size %d\n", stubMsg.BufferLength);
756 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = HeapAlloc(GetProcessHeap(), 0, stubMsg.BufferLength);
757 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
758 memset(buffer, 0xcc, stubMsg.BufferLength);
759 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
760 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
761 wirev = (DWORD*)buffer;
763 check_variant_header(wirev, &v, stubMsg.BufferLength);
765 ok(*wirev == 0xcccccccc, "wv[5] %08x\n", *wirev); /* pad */
767 ok(*(double*)wirev == V_R8(&v), "wv[6] %08x, wv[7] %08x\n", *wirev, *(wirev+1));
768 if (VARIANT_UNMARSHAL_WORKS)
771 stubMsg.Buffer = buffer;
772 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
773 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
774 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
775 ok(V_R8(&v) == V_R8(&v2), "got r8 %f expect %f\n", V_R8(&v), V_R8(&v2));
777 VARIANT_UserFree(&umcb.Flags, &v2);
779 HeapFree(GetProcessHeap(), 0, buffer);
783 V_VT(&v) = VT_R8 | VT_BYREF;
787 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
788 ok(stubMsg.BufferLength == 32, "size %d\n", stubMsg.BufferLength);
790 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = HeapAlloc(GetProcessHeap(), 0, stubMsg.BufferLength);
791 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
792 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
793 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
794 wirev = (DWORD*)buffer;
796 check_variant_header(wirev, &v, stubMsg.BufferLength);
798 ok(*wirev == 8, "wv[5] %08x\n", *wirev);
800 ok(*(double*)wirev == d, "wv[6] %08x wv[7] %08x\n", *wirev, *(wirev+1));
801 if (VARIANT_UNMARSHAL_WORKS)
804 stubMsg.Buffer = buffer;
805 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
806 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
807 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
808 ok(*V_R8REF(&v) == *V_R8REF(&v2), "got r8 ref %f expect %f\n", *V_R8REF(&v), *V_R8REF(&v2));
810 VARIANT_UserFree(&umcb.Flags, &v2);
812 HeapFree(GetProcessHeap(), 0, buffer);
814 /*** VARIANT_BOOL ***/
819 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
820 ok(stubMsg.BufferLength == 22, "size %d\n", stubMsg.BufferLength);
822 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = HeapAlloc(GetProcessHeap(), 0, stubMsg.BufferLength);
823 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
824 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
825 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
826 wirev = (DWORD*)buffer;
828 check_variant_header(wirev, &v, stubMsg.BufferLength);
830 ok(*(short*)wirev == V_BOOL(&v), "wv[5] %04x\n", *(WORD*)wirev);
831 if (VARIANT_UNMARSHAL_WORKS)
834 stubMsg.Buffer = buffer;
835 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
836 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
837 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
838 ok(V_BOOL(&v) == V_BOOL(&v2), "got bool %x expect %x\n", V_BOOL(&v), V_BOOL(&v2));
840 VARIANT_UserFree(&umcb.Flags, &v2);
842 HeapFree(GetProcessHeap(), 0, buffer);
845 VarDecFromI4(0x12345678, &dec);
848 V_VT(&v) = VT_DECIMAL;
850 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
851 ok(stubMsg.BufferLength == 40, "size %d\n", stubMsg.BufferLength);
853 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = HeapAlloc(GetProcessHeap(), 0, stubMsg.BufferLength);
854 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
855 memset(buffer, 0xcc, stubMsg.BufferLength);
856 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
857 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
858 wirev = (DWORD*)buffer;
860 check_variant_header(wirev, &v, stubMsg.BufferLength);
862 ok(*wirev == 0xcccccccc, "wirev[5] %08x\n", *wirev); /* pad */
865 dec2.wReserved = VT_DECIMAL;
866 ok(!memcmp(wirev, &dec2, sizeof(dec2)), "wirev[6] %08x wirev[7] %08x wirev[8] %08x wirev[9] %08x\n",
867 *wirev, *(wirev + 1), *(wirev + 2), *(wirev + 3));
868 if (VARIANT_UNMARSHAL_WORKS)
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(!memcmp(&V_DECIMAL(&v), & V_DECIMAL(&v2), sizeof(DECIMAL)), "decimals differ\n");
877 VARIANT_UserFree(&umcb.Flags, &v2);
879 HeapFree(GetProcessHeap(), 0, buffer);
881 /*** DECIMAL BYREF ***/
883 V_VT(&v) = VT_DECIMAL | VT_BYREF;
884 V_DECIMALREF(&v) = &dec;
886 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
887 ok(stubMsg.BufferLength == 40, "size %d\n", stubMsg.BufferLength);
889 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = HeapAlloc(GetProcessHeap(), 0, stubMsg.BufferLength);
890 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
891 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
892 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
893 wirev = (DWORD*)buffer;
895 check_variant_header(wirev, &v, stubMsg.BufferLength);
897 ok(*wirev == 16, "wv[5] %08x\n", *wirev);
899 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));
900 if (VARIANT_UNMARSHAL_WORKS)
903 stubMsg.Buffer = buffer;
904 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
905 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
906 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
907 ok(!memcmp(V_DECIMALREF(&v), V_DECIMALREF(&v2), sizeof(DECIMAL)), "decimals differ\n");
909 VARIANT_UserFree(&umcb.Flags, &v2);
911 HeapFree(GetProcessHeap(), 0, buffer);
917 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
918 ok(stubMsg.BufferLength == 20, "size %d\n", stubMsg.BufferLength);
920 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = HeapAlloc(GetProcessHeap(), 0, stubMsg.BufferLength);
921 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
922 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
923 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
924 wirev = (DWORD*)buffer;
926 check_variant_header(wirev, &v, stubMsg.BufferLength);
927 if (VARIANT_UNMARSHAL_WORKS)
930 stubMsg.Buffer = buffer;
931 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
932 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
933 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
935 VARIANT_UserFree(&umcb.Flags, &v2);
937 HeapFree(GetProcessHeap(), 0, buffer);
943 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
944 ok(stubMsg.BufferLength == 20, "size %d\n", stubMsg.BufferLength);
946 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = HeapAlloc(GetProcessHeap(), 0, stubMsg.BufferLength);
947 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
948 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
949 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
950 wirev = (DWORD*)buffer;
952 check_variant_header(wirev, &v, stubMsg.BufferLength);
953 if (VARIANT_UNMARSHAL_WORKS)
956 stubMsg.Buffer = buffer;
957 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
958 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
959 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
961 VARIANT_UserFree(&umcb.Flags, &v2);
963 HeapFree(GetProcessHeap(), 0, buffer);
966 b = SysAllocString(str);
971 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
972 ok(stubMsg.BufferLength == 60, "size %d\n", stubMsg.BufferLength);
973 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = HeapAlloc(GetProcessHeap(), 0, stubMsg.BufferLength);
974 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
975 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
976 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
977 wirev = (DWORD*)buffer;
979 check_variant_header(wirev, &v, stubMsg.BufferLength);
981 ok(*wirev, "wv[5] %08x\n", *wirev); /* win2k: this is b. winxp: this is (char*)b + 1 */
983 check_bstr(wirev, V_BSTR(&v));
984 if (VARIANT_UNMARSHAL_WORKS)
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(SysStringByteLen(V_BSTR(&v)) == SysStringByteLen(V_BSTR(&v2)), "bstr string lens differ\n");
992 ok(!memcmp(V_BSTR(&v), V_BSTR(&v2), SysStringByteLen(V_BSTR(&v))), "bstrs differ\n");
994 VARIANT_UserFree(&umcb.Flags, &v2);
996 HeapFree(GetProcessHeap(), 0, buffer);
1000 V_VT(&v) = VT_BSTR | VT_BYREF;
1003 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1004 ok(stubMsg.BufferLength == 64, "size %d\n", stubMsg.BufferLength);
1005 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = HeapAlloc(GetProcessHeap(), 0, stubMsg.BufferLength);
1006 stubMsg.BufferEnd = stubMsg.Buffer + 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;
1011 check_variant_header(wirev, &v, stubMsg.BufferLength);
1013 ok(*wirev == 0x4, "wv[5] %08x\n", *wirev);
1015 ok(*wirev, "wv[6] %08x\n", *wirev); /* win2k: this is b. winxp: this is (char*)b + 1 */
1017 check_bstr(wirev, b);
1018 if (VARIANT_UNMARSHAL_WORKS)
1021 stubMsg.Buffer = buffer;
1022 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1023 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1024 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1025 ok(SysStringByteLen(*V_BSTRREF(&v)) == SysStringByteLen(*V_BSTRREF(&v2)), "bstr string lens differ\n");
1026 ok(!memcmp(*V_BSTRREF(&v), *V_BSTRREF(&v2), SysStringByteLen(*V_BSTRREF(&v))), "bstrs differ\n");
1028 VARIANT_UserFree(&umcb.Flags, &v2);
1030 HeapFree(GetProcessHeap(), 0, buffer);
1037 lpsa = SafeArrayCreate(VT_R8, 1, &sab);
1038 *(DWORD *)lpsa->pvData = 0xcafebabe;
1039 *((DWORD *)lpsa->pvData + 1) = 0xdeadbeef;
1043 V_VT(&v) = VT_UI4 | VT_ARRAY;
1046 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1047 ok(stubMsg.BufferLength == 152, "size %d\n", stubMsg.BufferLength);
1048 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = HeapAlloc(GetProcessHeap(), 0, stubMsg.BufferLength);
1049 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1050 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1051 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1052 wirev = (DWORD*)buffer;
1054 check_variant_header(wirev, &v, stubMsg.BufferLength);
1056 ok(*wirev, "wv[5] %08x\n", *wirev); /* win2k: this is lpsa. winxp: this is (char*)lpsa + 1 */
1058 check_safearray(wirev, lpsa);
1059 if (VARIANT_UNMARSHAL_WORKS)
1064 stubMsg.Buffer = buffer;
1065 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1066 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1067 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1068 ok(SafeArrayGetDim(V_ARRAY(&v)) == SafeArrayGetDim(V_ARRAY(&v)), "array dims differ\n");
1069 SafeArrayGetLBound(V_ARRAY(&v), 1, &bound);
1070 SafeArrayGetLBound(V_ARRAY(&v2), 1, &bound2);
1071 ok(bound == bound2, "array lbounds differ\n");
1072 SafeArrayGetUBound(V_ARRAY(&v), 1, &bound);
1073 SafeArrayGetUBound(V_ARRAY(&v2), 1, &bound2);
1074 ok(bound == bound2, "array ubounds differ\n");
1075 SafeArrayGetVartype(V_ARRAY(&v), &vt);
1076 SafeArrayGetVartype(V_ARRAY(&v2), &vt2);
1077 ok(vt == vt2, "array vts differ %x %x\n", vt, vt2);
1078 VARIANT_UserFree(&umcb.Flags, &v2);
1080 HeapFree(GetProcessHeap(), 0, buffer);
1082 /*** ARRAY BYREF ***/
1084 V_VT(&v) = VT_UI4 | VT_ARRAY | VT_BYREF;
1085 V_ARRAYREF(&v) = &lpsa;
1087 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1088 ok(stubMsg.BufferLength == 152, "size %d\n", stubMsg.BufferLength);
1089 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = HeapAlloc(GetProcessHeap(), 0, stubMsg.BufferLength);
1090 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1091 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1092 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1093 wirev = (DWORD*)buffer;
1095 check_variant_header(wirev, &v, stubMsg.BufferLength);
1097 ok(*wirev == 4, "wv[5] %08x\n", *wirev);
1099 ok(*wirev, "wv[6] %08x\n", *wirev); /* win2k: this is lpsa. winxp: this is (char*)lpsa + 1 */
1101 check_safearray(wirev, lpsa);
1102 if (VARIANT_UNMARSHAL_WORKS)
1107 stubMsg.Buffer = buffer;
1108 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1109 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1110 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1111 ok(SafeArrayGetDim(*V_ARRAYREF(&v)) == SafeArrayGetDim(*V_ARRAYREF(&v)), "array dims differ\n");
1112 SafeArrayGetLBound(*V_ARRAYREF(&v), 1, &bound);
1113 SafeArrayGetLBound(*V_ARRAYREF(&v2), 1, &bound2);
1114 ok(bound == bound2, "array lbounds differ\n");
1115 SafeArrayGetUBound(*V_ARRAYREF(&v), 1, &bound);
1116 SafeArrayGetUBound(*V_ARRAYREF(&v2), 1, &bound2);
1117 ok(bound == bound2, "array ubounds differ\n");
1118 SafeArrayGetVartype(*V_ARRAYREF(&v), &vt);
1119 SafeArrayGetVartype(*V_ARRAYREF(&v2), &vt2);
1120 ok(vt == vt2, "array vts differ %x %x\n", vt, vt2);
1121 VARIANT_UserFree(&umcb.Flags, &v2);
1123 HeapFree(GetProcessHeap(), 0, buffer);
1124 SafeArrayDestroy(lpsa);
1126 /*** VARIANT BYREF ***/
1131 V_VT(&v) = VT_VARIANT | VT_BYREF;
1132 V_VARIANTREF(&v) = &v2;
1134 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1135 ok(stubMsg.BufferLength == 64, "size %d\n", stubMsg.BufferLength);
1136 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = HeapAlloc(GetProcessHeap(), 0, stubMsg.BufferLength);
1137 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1138 memset(buffer, 0xcc, stubMsg.BufferLength);
1139 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1140 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1141 wirev = (DWORD*)buffer;
1142 check_variant_header(wirev, &v, stubMsg.BufferLength);
1145 ok(*wirev == 16, "wv[5] %08x\n", *wirev);
1147 ok(*wirev == ('U' | 's' << 8 | 'e' << 16 | 'r' << 24), "wv[6] %08x\n", *wirev); /* 'User' */
1149 ok(*wirev == 0xcccccccc, "wv[7] %08x\n", *wirev); /* pad */
1151 check_variant_header(wirev, &v2, stubMsg.BufferLength - 32);
1153 ok(*wirev == 0xcccccccc, "wv[13] %08x\n", *wirev); /* pad for VT_R8 */
1155 ok(*(double*)wirev == V_R8(&v2), "wv[6] %08x wv[7] %08x\n", *wirev, *(wirev+1));
1156 if (VARIANT_UNMARSHAL_WORKS)
1160 stubMsg.Buffer = buffer;
1161 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v3);
1162 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1163 ok(V_VT(&v) == V_VT(&v3), "got vt %d expect %d\n", V_VT(&v), V_VT(&v3));
1164 ok(V_VT(V_VARIANTREF(&v)) == V_VT(V_VARIANTREF(&v3)), "vts differ %x %x\n",
1165 V_VT(V_VARIANTREF(&v)), V_VT(V_VARIANTREF(&v3)));
1166 ok(V_R8(V_VARIANTREF(&v)) == V_R8(V_VARIANTREF(&v3)), "r8s differ\n");
1167 VARIANT_UserFree(&umcb.Flags, &v3);
1169 HeapFree(GetProcessHeap(), 0, buffer);
1172 heap_unknown = HeapAlloc(GetProcessHeap(), 0, sizeof(*heap_unknown));
1173 heap_unknown->lpVtbl = &HeapUnknown_Vtbl;
1174 heap_unknown->refs = 1;
1177 V_VT(&v) = VT_UNKNOWN;
1178 V_UNKNOWN(&v) = (IUnknown *)heap_unknown;
1180 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1181 ok(stubMsg.BufferLength > 32, "size %d\n", stubMsg.BufferLength);
1182 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = HeapAlloc(GetProcessHeap(), 0, stubMsg.BufferLength);
1183 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1184 memset(buffer, 0xcc, stubMsg.BufferLength);
1185 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1186 wirev = (DWORD*)buffer;
1187 check_variant_header(wirev, &v, next - buffer);
1191 ok(*wirev == (DWORD_PTR)V_UNKNOWN(&v) /* Win9x */ ||
1192 *wirev == (DWORD_PTR)V_UNKNOWN(&v) + 1 /* NT */, "wv[5] %08x\n", *wirev);
1195 ok(*wirev == next - buffer - 0x20, "wv[6] %08x\n", *wirev);
1198 ok(*wirev == next - buffer - 0x20, "wv[7] %08x\n", *wirev);
1201 ok(*wirev == 0x574f454d, "wv[8] %08x\n", *wirev);
1202 if (VARIANT_UNMARSHAL_WORKS)
1206 V_VT(&v3) = VT_UNKNOWN;
1207 V_UNKNOWN(&v3) = (IUnknown *)heap_unknown;
1208 IUnknown_AddRef(V_UNKNOWN(&v3));
1209 stubMsg.Buffer = buffer;
1210 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v3);
1211 ok(V_VT(&v) == V_VT(&v3), "got vt %d expect %d\n", V_VT(&v), V_VT(&v3));
1212 ok(V_VT(V_VARIANTREF(&v)) == V_VT(V_VARIANTREF(&v3)), "vts differ %x %x\n",
1213 V_VT(V_VARIANTREF(&v)), V_VT(V_VARIANTREF(&v3)));
1214 ok(V_R8(V_VARIANTREF(&v)) == V_R8(V_VARIANTREF(&v3)), "r8s differ\n");
1215 VARIANT_UserFree(&umcb.Flags, &v3);
1216 ok(heap_unknown->refs == 1, "%d refcounts of IUnknown leaked\n", heap_unknown->refs - 1);
1217 IUnknown_Release((IUnknown *)heap_unknown);
1219 HeapFree(GetProcessHeap(), 0, buffer);
1221 /*** UNKNOWN BYREF ***/
1222 heap_unknown = HeapAlloc(GetProcessHeap(), 0, sizeof(*heap_unknown));
1223 heap_unknown->lpVtbl = &HeapUnknown_Vtbl;
1224 heap_unknown->refs = 1;
1227 V_VT(&v) = VT_UNKNOWN | VT_BYREF;
1228 V_UNKNOWNREF(&v) = (IUnknown **)&heap_unknown;
1230 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1231 ok(stubMsg.BufferLength > 36, "size %d\n", stubMsg.BufferLength);
1232 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = HeapAlloc(GetProcessHeap(), 0, stubMsg.BufferLength);
1233 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1234 memset(buffer, 0xcc, stubMsg.BufferLength);
1235 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1236 wirev = (DWORD*)buffer;
1237 check_variant_header(wirev, &v, next - buffer);
1240 ok(*wirev == 4, "wv[5] %08x\n", *wirev);
1243 ok(*wirev == (DWORD_PTR)heap_unknown /* Win9x, Win2000 */ ||
1244 *wirev == (DWORD_PTR)heap_unknown + 1 /* XP */, "wv[6] %08x\n", *wirev);
1247 ok(*wirev == next - buffer - 0x24, "wv[7] %08x\n", *wirev);
1250 ok(*wirev == next - buffer - 0x24, "wv[8] %08x\n", *wirev);
1253 ok(*wirev == 0x574f454d, "wv[9] %08x\n", *wirev);
1254 if (VARIANT_UNMARSHAL_WORKS)
1258 V_VT(&v3) = VT_UNKNOWN;
1259 V_UNKNOWN(&v3) = (IUnknown *)heap_unknown;
1260 IUnknown_AddRef(V_UNKNOWN(&v3));
1261 stubMsg.Buffer = buffer;
1262 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v3);
1263 ok(V_VT(&v) == V_VT(&v3), "got vt %d expect %d\n", V_VT(&v), V_VT(&v3));
1264 ok(*V_UNKNOWNREF(&v) == *V_UNKNOWNREF(&v3), "got %p expect %p\n", *V_UNKNOWNREF(&v), *V_UNKNOWNREF(&v3));
1265 VARIANT_UserFree(&umcb.Flags, &v3);
1266 ok(heap_unknown->refs == 1, "%d refcounts of IUnknown leaked\n", heap_unknown->refs - 1);
1267 IUnknown_Release((IUnknown *)heap_unknown);
1269 HeapFree(GetProcessHeap(), 0, buffer);
1273 START_TEST(usrmarshal)
1277 test_marshal_LPSAFEARRAY();
1278 test_marshal_BSTR();
1279 test_marshal_VARIANT();