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
26 #include "propidl.h" /* for LPSAFEARRAY_User* routines */
28 #include "wine/test.h"
30 #if (__STDC__ && !defined(_FORCENAMELESSUNION)) || defined(NONAMELESSUNION)
31 # define V_U2(A) ((A)->n1.n2)
33 # define V_U2(A) (*(A))
36 /* doesn't work on Windows due to needing more of the
37 * MIDL_STUB_MESSAGE structure to be filled out */
38 #define LPSAFEARRAY_UNMARSHAL_WORKS 0
39 #define BSTR_UNMARSHAL_WORKS 0
40 #define VARIANT_UNMARSHAL_WORKS 0
42 static inline SF_TYPE get_union_type(SAFEARRAY *psa)
47 hr = SafeArrayGetVartype(psa, &vt);
51 if (psa->fFeatures & FADF_HAVEIID)
57 case VT_UI1: return SF_I1;
60 case VT_UI2: return SF_I2;
65 case VT_R4: return SF_I4;
70 case VT_UI8: return SF_I8;
72 case VT_UINT_PTR: return (sizeof(UINT_PTR) == 4 ? SF_I4 : SF_I8);
73 case VT_BSTR: return SF_BSTR;
74 case VT_DISPATCH: return SF_DISPATCH;
75 case VT_VARIANT: return SF_VARIANT;
76 case VT_UNKNOWN: return SF_UNKNOWN;
77 /* Note: Return a non-zero size to indicate vt is valid. The actual size
78 * of a UDT is taken from the result of IRecordInfo_GetSize().
80 case VT_RECORD: return SF_RECORD;
81 default: return SF_ERROR;
85 static ULONG get_cell_count(const SAFEARRAY *psa)
87 const SAFEARRAYBOUND* psab = psa->rgsabound;
88 USHORT cCount = psa->cDims;
95 ulNumCells *= psab->cElements;
101 static void check_safearray(void *buffer, LPSAFEARRAY lpsa)
103 unsigned char *wiresa = buffer;
110 ok(*(void **)wiresa == NULL, "wiresa + 0x0 should be NULL instead of 0x%08lx\n", *(DWORD *)wiresa);
114 SafeArrayGetVartype(lpsa, &vt);
115 sftype = get_union_type(lpsa);
116 cell_count = get_cell_count(lpsa);
118 ok(*(DWORD *)wiresa, "wiresa + 0x0 should be non-NULL instead of 0x%08lx\n", *(DWORD *)wiresa); /* win2k: this is lpsa. winxp: this is 0x00000001 */
119 wiresa += sizeof(DWORD);
120 ok(*(DWORD *)wiresa == lpsa->cDims, "wiresa + 0x4 should be lpsa->cDims instead of 0x%08lx\n", *(DWORD *)wiresa);
121 wiresa += sizeof(DWORD);
122 ok(*(WORD *)wiresa == lpsa->cDims, "wiresa + 0x8 should be lpsa->cDims instead of 0x%04x\n", *(WORD *)wiresa);
123 wiresa += sizeof(WORD);
124 ok(*(WORD *)wiresa == lpsa->fFeatures, "wiresa + 0xc should be lpsa->fFeatures instead of 0x%08x\n", *(WORD *)wiresa);
125 wiresa += sizeof(WORD);
126 ok(*(DWORD *)wiresa == lpsa->cbElements, "wiresa + 0x10 should be lpsa->cbElements instead of 0x%08lx\n", *(DWORD *)wiresa);
127 wiresa += sizeof(DWORD);
128 ok(*(WORD *)wiresa == lpsa->cLocks, "wiresa + 0x16 should be lpsa->cLocks instead of 0x%04x\n", *(WORD *)wiresa);
129 wiresa += sizeof(WORD);
130 ok(*(WORD *)wiresa == vt, "wiresa + 0x14 should be %04x instead of 0x%04x\n", vt, *(WORD *)wiresa);
131 wiresa += sizeof(WORD);
132 ok(*(DWORD *)wiresa == sftype, "wiresa + 0x18 should be %08lx instead of 0x%08lx\n", (DWORD)sftype, *(DWORD *)wiresa);
133 wiresa += sizeof(DWORD);
134 ok(*(DWORD *)wiresa == cell_count, "wiresa + 0x1c should be %lu instead of %lu\n", cell_count, *(DWORD *)wiresa);
135 wiresa += sizeof(DWORD);
136 ok(*(DWORD_PTR *)wiresa == (DWORD_PTR)lpsa->pvData, "wiresa + 0x20 should be lpsa->pvData instead of 0x%08lx\n", *(DWORD_PTR *)wiresa);
137 wiresa += sizeof(DWORD_PTR);
138 if(sftype == SF_HAVEIID)
141 SafeArrayGetIID(lpsa, &guid);
142 ok(IsEqualGUID(&guid, (GUID*)wiresa), "guid mismatch\n");
143 wiresa += sizeof(GUID);
145 ok(!memcmp(wiresa, lpsa->rgsabound, sizeof(lpsa->rgsabound[0]) * lpsa->cDims), "bounds mismatch\n");
146 wiresa += sizeof(lpsa->rgsabound[0]) * lpsa->cDims;
148 ok(*(DWORD *)wiresa == cell_count, "wiresa + 0x2c should be %lu instead of %lu\n", cell_count, *(DWORD*)wiresa);
149 wiresa += sizeof(DWORD);
150 /* elements are now pointed to by wiresa */
153 static void test_marshal_LPSAFEARRAY(void)
155 unsigned char *buffer;
158 LPSAFEARRAY lpsa2 = NULL;
160 MIDL_STUB_MESSAGE stubMsg = { 0 };
161 USER_MARSHAL_CB umcb = { 0 };
163 umcb.Flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
164 umcb.pReserve = NULL;
165 umcb.pStubMsg = &stubMsg;
170 lpsa = SafeArrayCreate(VT_I2, 1, &sab);
171 *(DWORD *)lpsa->pvData = 0xcafebabe;
174 size = LPSAFEARRAY_UserSize(&umcb.Flags, 1, &lpsa);
175 ok(size == 68, "size should be 68 bytes, not %ld\n", size);
176 size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
177 ok(size == 64, "size should be 64 bytes, not %ld\n", size);
178 buffer = (unsigned char *)HeapAlloc(GetProcessHeap(), 0, size);
179 LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
181 check_safearray(buffer, lpsa);
183 if (LPSAFEARRAY_UNMARSHAL_WORKS)
186 LPSAFEARRAY_UserUnmarshal(&umcb.Flags, buffer, &lpsa2);
187 ok(lpsa2 != NULL, "LPSAFEARRAY didn't unmarshal\n");
188 SafeArrayGetVartype(lpsa, &vt);
189 SafeArrayGetVartype(lpsa2, &vt2);
190 ok(vt == vt2, "vts differ %x %x\n", vt, vt2);
191 LPSAFEARRAY_UserFree(&umcb.Flags, &lpsa2);
193 HeapFree(GetProcessHeap(), 0, buffer);
194 SafeArrayDestroy(lpsa);
196 /* test NULL safe array */
199 size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
200 ok(size == 4, "size should be 4 bytes, not %ld\n", size);
201 buffer = (unsigned char *)HeapAlloc(GetProcessHeap(), 0, size);
202 LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
203 check_safearray(buffer, lpsa);
205 if (LPSAFEARRAY_UNMARSHAL_WORKS)
207 LPSAFEARRAY_UserUnmarshal(&umcb.Flags, buffer, &lpsa2);
208 ok(lpsa2 == NULL, "NULL LPSAFEARRAY didn't unmarshal\n");
209 LPSAFEARRAY_UserFree(&umcb.Flags, &lpsa2);
211 HeapFree(GetProcessHeap(), 0, buffer);
216 lpsa = SafeArrayCreate(VT_R8, 1, &sab);
217 *(double *)lpsa->pvData = 3.1415;
220 size = LPSAFEARRAY_UserSize(&umcb.Flags, 1, &lpsa);
221 ok(size == 128, "size should be 128 bytes, not %ld\n", size);
222 size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
223 ok(size == 128, "size should be 128 bytes, not %ld\n", size);
224 buffer = (unsigned char *)HeapAlloc(GetProcessHeap(), 0, size);
225 LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
227 check_safearray(buffer, lpsa);
229 HeapFree(GetProcessHeap(), 0, buffer);
230 SafeArrayDestroy(lpsa);
233 static void check_bstr(void *buffer, BSTR b)
235 DWORD *wireb = buffer;
236 DWORD len = SysStringByteLen(b);
238 ok(*wireb == (len + 1) / 2, "wv[0] %08lx\n", *wireb);
241 ok(*wireb == len, "wv[1] %08lx\n", *wireb);
243 ok(*wireb == 0xffffffff, "wv[1] %08lx\n", *wireb);
245 ok(*wireb == (len + 1) / 2, "wv[2] %08lx\n", *wireb);
249 ok(!memcmp(wireb, b, (len + 1) & ~1), "strings differ\n");
254 static void test_marshal_BSTR(void)
257 MIDL_STUB_MESSAGE stubMsg = { 0 };
258 USER_MARSHAL_CB umcb = { 0 };
259 unsigned char *buffer, *next;
261 WCHAR str[] = {'m','a','r','s','h','a','l',' ','t','e','s','t','1',0};
264 umcb.Flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
265 umcb.pReserve = NULL;
266 umcb.pStubMsg = &stubMsg;
268 b = SysAllocString(str);
269 len = SysStringLen(b);
270 ok(len == 13, "get %ld\n", len);
272 /* BSTRs are DWORD aligned */
273 size = BSTR_UserSize(&umcb.Flags, 1, &b);
274 ok(size == 42, "size %ld\n", size);
276 size = BSTR_UserSize(&umcb.Flags, 0, &b);
277 ok(size == 38, "size %ld\n", size);
279 buffer = HeapAlloc(GetProcessHeap(), 0, size);
280 next = BSTR_UserMarshal(&umcb.Flags, buffer, &b);
281 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
282 check_bstr(buffer, b);
284 if (BSTR_UNMARSHAL_WORKS)
287 next = BSTR_UserUnmarshal(&umcb.Flags, buffer, &b2);
288 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
289 ok(b2 != NULL, "BSTR didn't unmarshal\n");
290 ok(!memcmp(b, b2, (len + 1) * 2), "strings differ\n");
291 BSTR_UserFree(&umcb.Flags, &b2);
294 HeapFree(GetProcessHeap(), 0, buffer);
298 size = BSTR_UserSize(&umcb.Flags, 0, &b);
299 ok(size == 12, "size %ld\n", size);
301 buffer = HeapAlloc(GetProcessHeap(), 0, size);
302 next = BSTR_UserMarshal(&umcb.Flags, buffer, &b);
303 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
305 check_bstr(buffer, b);
306 if (BSTR_UNMARSHAL_WORKS)
309 next = BSTR_UserUnmarshal(&umcb.Flags, buffer, &b2);
310 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
311 ok(b2 == NULL, "NULL BSTR didn't unmarshal\n");
312 BSTR_UserFree(&umcb.Flags, &b2);
314 HeapFree(GetProcessHeap(), 0, buffer);
316 b = SysAllocStringByteLen("abc", 3);
317 *(((char*)b) + 3) = 'd';
318 len = SysStringLen(b);
319 ok(len == 1, "get %ld\n", len);
320 len = SysStringByteLen(b);
321 ok(len == 3, "get %ld\n", len);
323 size = BSTR_UserSize(&umcb.Flags, 0, &b);
324 ok(size == 16, "size %ld\n", size);
326 buffer = HeapAlloc(GetProcessHeap(), 0, size);
327 memset(buffer, 0xcc, size);
328 next = BSTR_UserMarshal(&umcb.Flags, buffer, &b);
329 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
330 check_bstr(buffer, b);
331 ok(buffer[15] == 'd', "buffer[15] %02x\n", buffer[15]);
333 if (BSTR_UNMARSHAL_WORKS)
336 next = BSTR_UserUnmarshal(&umcb.Flags, buffer, &b2);
337 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
338 ok(b2 != NULL, "BSTR didn't unmarshal\n");
339 ok(!memcmp(b, b2, len), "strings differ\n");
340 BSTR_UserFree(&umcb.Flags, &b2);
342 HeapFree(GetProcessHeap(), 0, buffer);
345 b = SysAllocStringByteLen("", 0);
346 len = SysStringLen(b);
347 ok(len == 0, "get %ld\n", len);
348 len = SysStringByteLen(b);
349 ok(len == 0, "get %ld\n", len);
351 size = BSTR_UserSize(&umcb.Flags, 0, &b);
352 ok(size == 12, "size %ld\n", size);
354 buffer = HeapAlloc(GetProcessHeap(), 0, size);
355 next = BSTR_UserMarshal(&umcb.Flags, buffer, &b);
356 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
357 check_bstr(buffer, b);
359 if (BSTR_UNMARSHAL_WORKS)
362 next = BSTR_UserUnmarshal(&umcb.Flags, buffer, &b2);
363 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
364 ok(b2 != NULL, "NULL LPSAFEARRAY didn't unmarshal\n");
365 len = SysStringByteLen(b2);
366 ok(len == 0, "byte len %ld\n", len);
367 BSTR_UserFree(&umcb.Flags, &b2);
369 HeapFree(GetProcessHeap(), 0, buffer);
373 static void check_variant_header(DWORD *wirev, VARIANT *v, unsigned long size)
378 ok(*wirev == (size + 7) >> 3, "wv[0] %08lx, expected %08lx\n", *wirev, (size + 7) >> 3);
380 ok(*wirev == 0, "wv[1] %08lx\n", *wirev);
383 ok(*wp == V_VT(v), "vt %04x expected %04x\n", *wp, V_VT(v));
385 ok(*wp == V_U2(v).wReserved1, "res1 %04x expected %04x\n", *wp, V_U2(v).wReserved1);
387 ok(*wp == V_U2(v).wReserved2, "res2 %04x expected %04x\n", *wp, V_U2(v).wReserved2);
389 ok(*wp == V_U2(v).wReserved3, "res3 %04x expected %04x\n", *wp, V_U2(v).wReserved3);
393 if(switch_is & VT_ARRAY)
394 switch_is &= ~VT_TYPEMASK;
395 ok(*wirev == switch_is, "switch_is %08lx expected %08lx\n", *wirev, switch_is);
398 static void test_marshal_VARIANT(void)
402 MIDL_STUB_MESSAGE stubMsg = { 0 };
403 USER_MARSHAL_CB umcb = { 0 };
404 unsigned char *buffer, *next;
410 WCHAR str[] = {'m','a','r','s','h','a','l',' ','t','e','s','t',0};
415 umcb.Flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
416 umcb.pReserve = NULL;
417 umcb.pStubMsg = &stubMsg;
424 /* Variants have an alignment of 8 */
425 size = VARIANT_UserSize(&umcb.Flags, 1, &v);
426 ok(size == 29, "size %ld\n", size);
428 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
429 ok(size == 21, "size %ld\n", size);
431 buffer = HeapAlloc(GetProcessHeap(), 0, size);
432 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
433 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
434 wirev = (DWORD*)buffer;
436 check_variant_header(wirev, &v, size);
438 ok(*(char*)wirev == V_I1(&v), "wv[5] %08lx\n", *wirev);
439 if (VARIANT_UNMARSHAL_WORKS)
442 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
443 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
444 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
445 ok(V_I1(&v) == V_I1(&v2), "got i1 %x expect %x\n", V_I1(&v), V_I1(&v2));
447 VARIANT_UserFree(&umcb.Flags, &v2);
449 HeapFree(GetProcessHeap(), 0, buffer);
456 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
457 ok(size == 22, "size %ld\n", size);
459 buffer = HeapAlloc(GetProcessHeap(), 0, size);
460 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
461 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
462 wirev = (DWORD*)buffer;
464 check_variant_header(wirev, &v, size);
466 ok(*(short*)wirev == V_I2(&v), "wv[5] %08lx\n", *wirev);
467 if (VARIANT_UNMARSHAL_WORKS)
470 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
471 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
472 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
473 ok(V_I2(&v) == V_I2(&v2), "got i2 %x expect %x\n", V_I2(&v), V_I2(&v2));
475 VARIANT_UserFree(&umcb.Flags, &v2);
477 HeapFree(GetProcessHeap(), 0, buffer);
481 V_VT(&v) = VT_I2 | VT_BYREF;
485 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
486 ok(size == 26, "size %ld\n", size);
488 buffer = HeapAlloc(GetProcessHeap(), 0, size);
489 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
490 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
491 wirev = (DWORD*)buffer;
493 check_variant_header(wirev, &v, size);
495 ok(*wirev == 0x4, "wv[5] %08lx\n", *wirev);
497 ok(*(short*)wirev == s, "wv[6] %08lx\n", *wirev);
498 if (VARIANT_UNMARSHAL_WORKS)
501 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
502 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
503 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
504 ok(*V_I2REF(&v) == *V_I2REF(&v2), "got i2 ref %x expect ui4 ref %x\n", *V_I2REF(&v), *V_I2REF(&v2));
506 VARIANT_UserFree(&umcb.Flags, &v2);
508 HeapFree(GetProcessHeap(), 0, buffer);
515 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
516 ok(size == 24, "size %ld\n", size);
518 buffer = HeapAlloc(GetProcessHeap(), 0, size);
519 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
520 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
521 wirev = (DWORD*)buffer;
523 check_variant_header(wirev, &v, size);
525 ok(*wirev == V_I4(&v), "wv[5] %08lx\n", *wirev);
527 if (VARIANT_UNMARSHAL_WORKS)
530 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
531 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
532 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
533 ok(V_I4(&v) == V_I4(&v2), "got i4 %lx expect %lx\n", V_I4(&v), V_I4(&v2));
535 VARIANT_UserFree(&umcb.Flags, &v2);
538 HeapFree(GetProcessHeap(), 0, buffer);
545 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
546 ok(size == 24, "size %ld\n", size);
548 buffer = HeapAlloc(GetProcessHeap(), 0, size);
549 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
550 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
551 wirev = (DWORD*)buffer;
553 check_variant_header(wirev, &v, size);
555 ok(*wirev == 0x1234, "wv[5] %08lx\n", *wirev);
556 if (VARIANT_UNMARSHAL_WORKS)
559 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
560 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
561 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
562 ok(V_UI4(&v) == V_UI4(&v2), "got ui4 %lx expect %lx\n", V_UI4(&v), V_UI4(&v2));
564 VARIANT_UserFree(&umcb.Flags, &v2);
567 HeapFree(GetProcessHeap(), 0, buffer);
571 V_VT(&v) = VT_UI4 | VT_BYREF;
575 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
576 ok(size == 28, "size %ld\n", size);
578 buffer = HeapAlloc(GetProcessHeap(), 0, size);
579 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
580 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
581 wirev = (DWORD*)buffer;
583 check_variant_header(wirev, &v, size);
585 ok(*wirev == 0x4, "wv[5] %08lx\n", *wirev);
587 ok(*wirev == ul, "wv[6] %08lx\n", *wirev);
589 if (VARIANT_UNMARSHAL_WORKS)
592 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
593 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
594 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
595 ok(*V_UI4REF(&v) == *V_UI4REF(&v2), "got ui4 ref %lx expect ui4 ref %lx\n", *V_UI4REF(&v), *V_UI4REF(&v2));
597 VARIANT_UserFree(&umcb.Flags, &v2);
599 HeapFree(GetProcessHeap(), 0, buffer);
606 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
607 ok(size == 24, "size %ld\n", size);
609 buffer = HeapAlloc(GetProcessHeap(), 0, size);
610 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
611 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
612 wirev = (DWORD*)buffer;
614 check_variant_header(wirev, &v, size);
616 ok(*(float*)wirev == V_R4(&v), "wv[5] %08lx\n", *wirev);
617 if (VARIANT_UNMARSHAL_WORKS)
620 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
621 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
622 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
623 ok(V_R4(&v) == V_R4(&v2), "got r4 %f expect %f\n", V_R4(&v), V_R4(&v2));
625 VARIANT_UserFree(&umcb.Flags, &v2);
627 HeapFree(GetProcessHeap(), 0, buffer);
634 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
635 ok(size == 32, "size %ld\n", size);
637 buffer = HeapAlloc(GetProcessHeap(), 0, size);
638 memset(buffer, 0xcc, size);
639 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
640 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
641 wirev = (DWORD*)buffer;
643 check_variant_header(wirev, &v, size);
645 ok(*wirev == 0xcccccccc, "wv[5] %08lx\n", *wirev); /* pad */
647 ok(*(double*)wirev == V_R8(&v), "wv[6] %08lx, wv[7] %08lx\n", *wirev, *(wirev+1));
648 if (VARIANT_UNMARSHAL_WORKS)
651 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
652 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
653 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
654 ok(V_R8(&v) == V_R8(&v2), "got r8 %f expect %f\n", V_R8(&v), V_R8(&v2));
656 VARIANT_UserFree(&umcb.Flags, &v2);
658 HeapFree(GetProcessHeap(), 0, buffer);
662 V_VT(&v) = VT_R8 | VT_BYREF;
666 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
667 ok(size == 32, "size %ld\n", size);
669 buffer = HeapAlloc(GetProcessHeap(), 0, size);
670 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
671 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
672 wirev = (DWORD*)buffer;
674 check_variant_header(wirev, &v, size);
676 ok(*wirev == 8, "wv[5] %08lx\n", *wirev);
678 ok(*(double*)wirev == d, "wv[6] %08lx wv[7] %08lx\n", *wirev, *(wirev+1));
679 if (VARIANT_UNMARSHAL_WORKS)
682 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
683 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
684 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
685 ok(*V_R8REF(&v) == *V_R8REF(&v2), "got r8 ref %f expect %f\n", *V_R8REF(&v), *V_R8REF(&v2));
687 VARIANT_UserFree(&umcb.Flags, &v2);
689 HeapFree(GetProcessHeap(), 0, buffer);
691 /*** VARIANT_BOOL ***/
696 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
697 ok(size == 22, "size %ld\n", size);
699 buffer = HeapAlloc(GetProcessHeap(), 0, size);
700 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
701 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
702 wirev = (DWORD*)buffer;
704 check_variant_header(wirev, &v, size);
706 ok(*(short*)wirev == V_BOOL(&v), "wv[5] %04x\n", *(WORD*)wirev);
707 if (VARIANT_UNMARSHAL_WORKS)
710 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
711 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
712 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
713 ok(V_BOOL(&v) == V_BOOL(&v2), "got bool %x expect %x\n", V_BOOL(&v), V_BOOL(&v2));
715 VARIANT_UserFree(&umcb.Flags, &v2);
717 HeapFree(GetProcessHeap(), 0, buffer);
720 VarDecFromI4(0x12345678, &dec);
723 V_VT(&v) = VT_DECIMAL;
725 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
726 ok(size == 40, "size %ld\n", size);
728 buffer = HeapAlloc(GetProcessHeap(), 0, size);
729 memset(buffer, 0xcc, size);
730 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
731 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
732 wirev = (DWORD*)buffer;
734 check_variant_header(wirev, &v, size);
736 ok(*wirev == 0xcccccccc, "wirev[5] %08lx\n", *wirev); /* pad */
739 dec2.wReserved = VT_DECIMAL;
740 ok(!memcmp(wirev, &dec2, sizeof(dec2)), "wirev[6] %08lx wirev[7] %08lx wirev[8] %08lx wirev[9] %08lx\n",
741 *wirev, *(wirev + 1), *(wirev + 2), *(wirev + 3));
742 if (VARIANT_UNMARSHAL_WORKS)
745 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
746 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
747 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
748 ok(!memcmp(&V_DECIMAL(&v), & V_DECIMAL(&v2), sizeof(DECIMAL)), "decimals differ\n");
750 VARIANT_UserFree(&umcb.Flags, &v2);
752 HeapFree(GetProcessHeap(), 0, buffer);
754 /*** DECIMAL BYREF ***/
756 V_VT(&v) = VT_DECIMAL | VT_BYREF;
757 V_DECIMALREF(&v) = &dec;
759 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
760 ok(size == 40, "size %ld\n", size);
762 buffer = HeapAlloc(GetProcessHeap(), 0, size);
763 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
764 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
765 wirev = (DWORD*)buffer;
767 check_variant_header(wirev, &v, size);
769 ok(*wirev == 16, "wv[5] %08lx\n", *wirev);
771 ok(!memcmp(wirev, &dec, sizeof(dec)), "wirev[6] %08lx wirev[7] %08lx wirev[8] %08lx wirev[9] %08lx\n", *wirev, *(wirev + 1), *(wirev + 2), *(wirev + 3));
772 if (VARIANT_UNMARSHAL_WORKS)
775 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
776 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
777 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
778 ok(!memcmp(V_DECIMALREF(&v), V_DECIMALREF(&v2), sizeof(DECIMAL)), "decimals differ\n");
780 VARIANT_UserFree(&umcb.Flags, &v2);
782 HeapFree(GetProcessHeap(), 0, buffer);
788 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
789 ok(size == 20, "size %ld\n", size);
791 buffer = HeapAlloc(GetProcessHeap(), 0, size);
792 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
793 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
794 wirev = (DWORD*)buffer;
796 check_variant_header(wirev, &v, size);
797 if (VARIANT_UNMARSHAL_WORKS)
800 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
801 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
802 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
804 VARIANT_UserFree(&umcb.Flags, &v2);
806 HeapFree(GetProcessHeap(), 0, buffer);
812 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
813 ok(size == 20, "size %ld\n", size);
815 buffer = HeapAlloc(GetProcessHeap(), 0, size);
816 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
817 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
818 wirev = (DWORD*)buffer;
820 check_variant_header(wirev, &v, size);
821 if (VARIANT_UNMARSHAL_WORKS)
824 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
825 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
826 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
828 VARIANT_UserFree(&umcb.Flags, &v2);
830 HeapFree(GetProcessHeap(), 0, buffer);
833 b = SysAllocString(str);
838 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
839 ok(size == 60, "size %ld\n", size);
840 buffer = HeapAlloc(GetProcessHeap(), 0, size);
841 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
842 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
843 wirev = (DWORD*)buffer;
845 check_variant_header(wirev, &v, size);
847 ok(*wirev, "wv[5] %08lx\n", *wirev); /* win2k: this is b. winxp: this is (char*)b + 1 */
849 check_bstr(wirev, V_BSTR(&v));
850 if (VARIANT_UNMARSHAL_WORKS)
853 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
854 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
855 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
856 ok(SysStringByteLen(V_BSTR(&v)) == SysStringByteLen(V_BSTR(&v2)), "bstr string lens differ\n");
857 ok(!memcmp(V_BSTR(&v), V_BSTR(&v2), SysStringByteLen(V_BSTR(&v))), "bstrs differ\n");
859 VARIANT_UserFree(&umcb.Flags, &v2);
861 HeapFree(GetProcessHeap(), 0, buffer);
865 V_VT(&v) = VT_BSTR | VT_BYREF;
868 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
869 ok(size == 64, "size %ld\n", size);
870 buffer = HeapAlloc(GetProcessHeap(), 0, size);
871 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
872 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
873 wirev = (DWORD*)buffer;
875 check_variant_header(wirev, &v, size);
877 ok(*wirev == 0x4, "wv[5] %08lx\n", *wirev);
879 ok(*wirev, "wv[6] %08lx\n", *wirev); /* win2k: this is b. winxp: this is (char*)b + 1 */
881 check_bstr(wirev, b);
882 if (VARIANT_UNMARSHAL_WORKS)
885 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
886 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
887 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
888 ok(SysStringByteLen(*V_BSTRREF(&v)) == SysStringByteLen(*V_BSTRREF(&v2)), "bstr string lens differ\n");
889 ok(!memcmp(*V_BSTRREF(&v), *V_BSTRREF(&v2), SysStringByteLen(*V_BSTRREF(&v))), "bstrs differ\n");
891 VARIANT_UserFree(&umcb.Flags, &v2);
893 HeapFree(GetProcessHeap(), 0, buffer);
900 lpsa = SafeArrayCreate(VT_R8, 1, &sab);
901 *(DWORD *)lpsa->pvData = 0xcafebabe;
902 *((DWORD *)lpsa->pvData + 1) = 0xdeadbeef;
906 V_VT(&v) = VT_UI4 | VT_ARRAY;
909 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
910 ok(size == 152, "size %ld\n", size);
911 buffer = HeapAlloc(GetProcessHeap(), 0, size);
912 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
913 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
914 wirev = (DWORD*)buffer;
916 check_variant_header(wirev, &v, size);
918 ok(*wirev, "wv[5] %08lx\n", *wirev); /* win2k: this is lpsa. winxp: this is (char*)lpsa + 1 */
920 check_safearray(wirev, lpsa);
921 if (VARIANT_UNMARSHAL_WORKS)
926 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
927 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
928 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
929 ok(SafeArrayGetDim(V_ARRAY(&v)) == SafeArrayGetDim(V_ARRAY(&v)), "array dims differ\n");
930 SafeArrayGetLBound(V_ARRAY(&v), 1, &bound);
931 SafeArrayGetLBound(V_ARRAY(&v2), 1, &bound2);
932 ok(bound == bound2, "array lbounds differ\n");
933 SafeArrayGetUBound(V_ARRAY(&v), 1, &bound);
934 SafeArrayGetUBound(V_ARRAY(&v2), 1, &bound2);
935 ok(bound == bound2, "array ubounds differ\n");
936 SafeArrayGetVartype(V_ARRAY(&v), &vt);
937 SafeArrayGetVartype(V_ARRAY(&v2), &vt2);
938 ok(vt == vt2, "array vts differ %x %x\n", vt, vt2);
939 VARIANT_UserFree(&umcb.Flags, &v2);
941 HeapFree(GetProcessHeap(), 0, buffer);
943 /*** ARRAY BYREF ***/
945 V_VT(&v) = VT_UI4 | VT_ARRAY | VT_BYREF;
946 V_ARRAYREF(&v) = &lpsa;
948 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
949 ok(size == 152, "size %ld\n", size);
950 buffer = HeapAlloc(GetProcessHeap(), 0, size);
951 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
952 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
953 wirev = (DWORD*)buffer;
955 check_variant_header(wirev, &v, size);
957 ok(*wirev == 4, "wv[5] %08lx\n", *wirev);
959 ok(*wirev, "wv[6] %08lx\n", *wirev); /* win2k: this is lpsa. winxp: this is (char*)lpsa + 1 */
961 check_safearray(wirev, lpsa);
962 if (VARIANT_UNMARSHAL_WORKS)
967 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
968 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
969 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
970 ok(SafeArrayGetDim(*V_ARRAYREF(&v)) == SafeArrayGetDim(*V_ARRAYREF(&v)), "array dims differ\n");
971 SafeArrayGetLBound(*V_ARRAYREF(&v), 1, &bound);
972 SafeArrayGetLBound(*V_ARRAYREF(&v2), 1, &bound2);
973 ok(bound == bound2, "array lbounds differ\n");
974 SafeArrayGetUBound(*V_ARRAYREF(&v), 1, &bound);
975 SafeArrayGetUBound(*V_ARRAYREF(&v2), 1, &bound2);
976 ok(bound == bound2, "array ubounds differ\n");
977 SafeArrayGetVartype(*V_ARRAYREF(&v), &vt);
978 SafeArrayGetVartype(*V_ARRAYREF(&v2), &vt2);
979 ok(vt == vt2, "array vts differ %x %x\n", vt, vt2);
980 VARIANT_UserFree(&umcb.Flags, &v2);
982 HeapFree(GetProcessHeap(), 0, buffer);
983 SafeArrayDestroy(lpsa);
985 /*** VARIANT BYREF ***/
990 V_VT(&v) = VT_VARIANT | VT_BYREF;
991 V_VARIANTREF(&v) = &v2;
993 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
994 ok(size == 64, "size %ld\n", size);
995 buffer = HeapAlloc(GetProcessHeap(), 0, size);
996 memset(buffer, 0xcc, size);
997 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
998 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
999 wirev = (DWORD*)buffer;
1000 check_variant_header(wirev, &v, size);
1003 ok(*wirev == 16, "wv[5] %08lx\n", *wirev);
1005 ok(*wirev == ('U' | 's' << 8 | 'e' << 16 | 'r' << 24), "wv[6] %08lx\n", *wirev); /* 'User' */
1007 ok(*wirev == 0xcccccccc, "wv[7] %08lx\n", *wirev); /* pad */
1009 check_variant_header(wirev, &v2, size - 32);
1011 ok(*wirev == 0xcccccccc, "wv[13] %08lx\n", *wirev); /* pad for VT_R8 */
1013 ok(*(double*)wirev == V_R8(&v2), "wv[6] %08lx wv[7] %08lx\n", *wirev, *(wirev+1));
1014 if (VARIANT_UNMARSHAL_WORKS)
1018 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v3);
1019 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
1020 ok(V_VT(&v) == V_VT(&v3), "got vt %d expect %d\n", V_VT(&v), V_VT(&v3));
1021 ok(V_VT(V_VARIANTREF(&v)) == V_VT(V_VARIANTREF(&v3)), "vts differ %x %x\n",
1022 V_VT(V_VARIANTREF(&v)), V_VT(V_VARIANTREF(&v3)));
1023 ok(V_R8(V_VARIANTREF(&v)) == V_R8(V_VARIANTREF(&v3)), "r8s differ\n");
1024 VARIANT_UserFree(&umcb.Flags, &v3);
1026 HeapFree(GetProcessHeap(), 0, buffer);
1030 START_TEST(usrmarshal)
1034 test_marshal_LPSAFEARRAY();
1035 test_marshal_BSTR();
1036 test_marshal_VARIANT();