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 /* doesn't work on Windows due to needing more of the
31 * MIDL_STUB_MESSAGE structure to be filled out */
32 #define LPSAFEARRAY_UNMARSHAL_WORKS 0
33 #define BSTR_UNMARSHAL_WORKS 0
34 #define VARIANT_UNMARSHAL_WORKS 0
36 static inline SF_TYPE get_union_type(SAFEARRAY *psa)
41 hr = SafeArrayGetVartype(psa, &vt);
45 if (psa->fFeatures & FADF_HAVEIID)
51 case VT_UI1: return SF_I1;
54 case VT_UI2: return SF_I2;
59 case VT_R4: return SF_I4;
64 case VT_UI8: return SF_I8;
66 case VT_UINT_PTR: return (sizeof(UINT_PTR) == 4 ? SF_I4 : SF_I8);
67 case VT_BSTR: return SF_BSTR;
68 case VT_DISPATCH: return SF_DISPATCH;
69 case VT_VARIANT: return SF_VARIANT;
70 case VT_UNKNOWN: return SF_UNKNOWN;
71 /* Note: Return a non-zero size to indicate vt is valid. The actual size
72 * of a UDT is taken from the result of IRecordInfo_GetSize().
74 case VT_RECORD: return SF_RECORD;
75 default: return SF_ERROR;
79 static ULONG get_cell_count(const SAFEARRAY *psa)
81 const SAFEARRAYBOUND* psab = psa->rgsabound;
82 USHORT cCount = psa->cDims;
89 ulNumCells *= psab->cElements;
95 static void check_safearray(void *buffer, LPSAFEARRAY lpsa)
97 unsigned char *wiresa = buffer;
104 ok(*(void **)wiresa == NULL, "wiresa + 0x0 should be NULL instead of 0x%08lx\n", *(DWORD *)wiresa);
108 SafeArrayGetVartype(lpsa, &vt);
109 sftype = get_union_type(lpsa);
110 cell_count = get_cell_count(lpsa);
112 ok(*(DWORD *)wiresa, "wiresa + 0x0 should be non-NULL instead of 0x%08lx\n", *(DWORD *)wiresa); /* win2k: this is lpsa. winxp: this is 0x00000001 */
113 wiresa += sizeof(DWORD);
114 ok(*(DWORD *)wiresa == lpsa->cDims, "wiresa + 0x4 should be lpsa->cDims instead of 0x%08lx\n", *(DWORD *)wiresa);
115 wiresa += sizeof(DWORD);
116 ok(*(WORD *)wiresa == lpsa->cDims, "wiresa + 0x8 should be lpsa->cDims instead of 0x%04x\n", *(WORD *)wiresa);
117 wiresa += sizeof(WORD);
118 ok(*(WORD *)wiresa == lpsa->fFeatures, "wiresa + 0xc should be lpsa->fFeatures instead of 0x%08x\n", *(WORD *)wiresa);
119 wiresa += sizeof(WORD);
120 ok(*(DWORD *)wiresa == lpsa->cbElements, "wiresa + 0x10 should be lpsa->cbElements instead of 0x%08lx\n", *(DWORD *)wiresa);
121 wiresa += sizeof(DWORD);
122 ok(*(WORD *)wiresa == lpsa->cLocks, "wiresa + 0x16 should be lpsa->cLocks instead of 0x%04x\n", *(WORD *)wiresa);
123 wiresa += sizeof(WORD);
124 ok(*(WORD *)wiresa == vt, "wiresa + 0x14 should be %04x instead of 0x%04x\n", vt, *(WORD *)wiresa);
125 wiresa += sizeof(WORD);
126 ok(*(DWORD *)wiresa == sftype, "wiresa + 0x18 should be %08lx instead of 0x%08lx\n", (DWORD)sftype, *(DWORD *)wiresa);
127 wiresa += sizeof(DWORD);
128 ok(*(DWORD *)wiresa == cell_count, "wiresa + 0x1c should be %lu instead of %lu\n", cell_count, *(DWORD *)wiresa);
129 wiresa += sizeof(DWORD);
130 ok(*(DWORD_PTR *)wiresa == (DWORD_PTR)lpsa->pvData, "wiresa + 0x20 should be lpsa->pvData instead of 0x%08lx\n", *(DWORD_PTR *)wiresa);
131 wiresa += sizeof(DWORD_PTR);
132 if(sftype == SF_HAVEIID)
135 SafeArrayGetIID(lpsa, &guid);
136 ok(IsEqualGUID(&guid, (GUID*)wiresa), "guid mismatch\n");
137 wiresa += sizeof(GUID);
139 ok(!memcmp(wiresa, lpsa->rgsabound, sizeof(lpsa->rgsabound[0]) * lpsa->cDims), "bounds mismatch\n");
140 wiresa += sizeof(lpsa->rgsabound[0]) * lpsa->cDims;
142 ok(*(DWORD *)wiresa == cell_count, "wiresa + 0x2c should be %lu instead of %lu\n", cell_count, *(DWORD*)wiresa);
143 wiresa += sizeof(DWORD);
144 /* elements are now pointed to by wiresa */
147 static void test_marshal_LPSAFEARRAY(void)
149 unsigned char *buffer;
152 LPSAFEARRAY lpsa2 = NULL;
154 MIDL_STUB_MESSAGE stubMsg = { 0 };
155 USER_MARSHAL_CB umcb = { 0 };
157 umcb.Flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
158 umcb.pReserve = NULL;
159 umcb.pStubMsg = &stubMsg;
164 lpsa = SafeArrayCreate(VT_I2, 1, &sab);
165 *(DWORD *)lpsa->pvData = 0xcafebabe;
168 size = LPSAFEARRAY_UserSize(&umcb.Flags, 1, &lpsa);
169 ok(size == 68, "size should be 68 bytes, not %ld\n", size);
170 size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
171 ok(size == 64, "size should be 64 bytes, not %ld\n", size);
172 buffer = (unsigned char *)HeapAlloc(GetProcessHeap(), 0, size);
173 LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
175 check_safearray(buffer, lpsa);
177 if (LPSAFEARRAY_UNMARSHAL_WORKS)
180 LPSAFEARRAY_UserUnmarshal(&umcb.Flags, buffer, &lpsa2);
181 ok(lpsa2 != NULL, "LPSAFEARRAY didn't unmarshal\n");
182 SafeArrayGetVartype(lpsa, &vt);
183 SafeArrayGetVartype(lpsa2, &vt2);
184 ok(vt == vt2, "vts differ %x %x\n", vt, vt2);
185 LPSAFEARRAY_UserFree(&umcb.Flags, &lpsa2);
187 HeapFree(GetProcessHeap(), 0, buffer);
188 SafeArrayDestroy(lpsa);
190 /* test NULL safe array */
193 size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
194 ok(size == 4, "size should be 4 bytes, not %ld\n", size);
195 buffer = (unsigned char *)HeapAlloc(GetProcessHeap(), 0, size);
196 LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
197 check_safearray(buffer, lpsa);
199 if (LPSAFEARRAY_UNMARSHAL_WORKS)
201 LPSAFEARRAY_UserUnmarshal(&umcb.Flags, buffer, &lpsa2);
202 ok(lpsa2 == NULL, "NULL LPSAFEARRAY didn't unmarshal\n");
203 LPSAFEARRAY_UserFree(&umcb.Flags, &lpsa2);
205 HeapFree(GetProcessHeap(), 0, buffer);
210 lpsa = SafeArrayCreate(VT_R8, 1, &sab);
211 *(double *)lpsa->pvData = 3.1415;
214 size = LPSAFEARRAY_UserSize(&umcb.Flags, 1, &lpsa);
215 ok(size == 128, "size should be 128 bytes, not %ld\n", size);
216 size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
217 ok(size == 128, "size should be 128 bytes, not %ld\n", size);
218 buffer = (unsigned char *)HeapAlloc(GetProcessHeap(), 0, size);
219 LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
221 check_safearray(buffer, lpsa);
223 HeapFree(GetProcessHeap(), 0, buffer);
224 SafeArrayDestroy(lpsa);
227 static void check_bstr(void *buffer, BSTR b)
229 DWORD *wireb = buffer;
230 DWORD len = SysStringByteLen(b);
232 ok(*wireb == (len + 1) / 2, "wv[0] %08lx\n", *wireb);
235 ok(*wireb == len, "wv[1] %08lx\n", *wireb);
237 ok(*wireb == 0xffffffff, "wv[1] %08lx\n", *wireb);
239 ok(*wireb == (len + 1) / 2, "wv[2] %08lx\n", *wireb);
243 ok(!memcmp(wireb, b, (len + 1) & ~1), "strings differ\n");
248 static void test_marshal_BSTR(void)
251 MIDL_STUB_MESSAGE stubMsg = { 0 };
252 USER_MARSHAL_CB umcb = { 0 };
253 unsigned char *buffer, *next;
255 WCHAR str[] = {'m','a','r','s','h','a','l',' ','t','e','s','t','1',0};
258 umcb.Flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
259 umcb.pReserve = NULL;
260 umcb.pStubMsg = &stubMsg;
262 b = SysAllocString(str);
263 len = SysStringLen(b);
264 ok(len == 13, "get %ld\n", len);
266 /* BSTRs are DWORD aligned */
267 size = BSTR_UserSize(&umcb.Flags, 1, &b);
268 ok(size == 42, "size %ld\n", size);
270 size = BSTR_UserSize(&umcb.Flags, 0, &b);
271 ok(size == 38, "size %ld\n", size);
273 buffer = HeapAlloc(GetProcessHeap(), 0, size);
274 next = BSTR_UserMarshal(&umcb.Flags, buffer, &b);
275 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
276 check_bstr(buffer, b);
278 if (BSTR_UNMARSHAL_WORKS)
281 next = BSTR_UserUnmarshal(&umcb.Flags, buffer, &b2);
282 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
283 ok(b2 != NULL, "BSTR didn't unmarshal\n");
284 ok(!memcmp(b, b2, (len + 1) * 2), "strings differ\n");
285 BSTR_UserFree(&umcb.Flags, &b2);
288 HeapFree(GetProcessHeap(), 0, buffer);
292 size = BSTR_UserSize(&umcb.Flags, 0, &b);
293 ok(size == 12, "size %ld\n", size);
295 buffer = HeapAlloc(GetProcessHeap(), 0, size);
296 next = BSTR_UserMarshal(&umcb.Flags, buffer, &b);
297 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
299 check_bstr(buffer, b);
300 if (BSTR_UNMARSHAL_WORKS)
303 next = BSTR_UserUnmarshal(&umcb.Flags, buffer, &b2);
304 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
305 ok(b2 == NULL, "NULL BSTR didn't unmarshal\n");
306 BSTR_UserFree(&umcb.Flags, &b2);
308 HeapFree(GetProcessHeap(), 0, buffer);
310 b = SysAllocStringByteLen("abc", 3);
311 *(((char*)b) + 3) = 'd';
312 len = SysStringLen(b);
313 ok(len == 1, "get %ld\n", len);
314 len = SysStringByteLen(b);
315 ok(len == 3, "get %ld\n", len);
317 size = BSTR_UserSize(&umcb.Flags, 0, &b);
318 ok(size == 16, "size %ld\n", size);
320 buffer = HeapAlloc(GetProcessHeap(), 0, size);
321 memset(buffer, 0xcc, size);
322 next = BSTR_UserMarshal(&umcb.Flags, buffer, &b);
323 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
324 check_bstr(buffer, b);
325 ok(buffer[15] == 'd', "buffer[15] %02x\n", buffer[15]);
327 if (BSTR_UNMARSHAL_WORKS)
330 next = BSTR_UserUnmarshal(&umcb.Flags, buffer, &b2);
331 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
332 ok(b2 != NULL, "BSTR didn't unmarshal\n");
333 ok(!memcmp(b, b2, len), "strings differ\n");
334 BSTR_UserFree(&umcb.Flags, &b2);
336 HeapFree(GetProcessHeap(), 0, buffer);
339 b = SysAllocStringByteLen("", 0);
340 len = SysStringLen(b);
341 ok(len == 0, "get %ld\n", len);
342 len = SysStringByteLen(b);
343 ok(len == 0, "get %ld\n", len);
345 size = BSTR_UserSize(&umcb.Flags, 0, &b);
346 ok(size == 12, "size %ld\n", size);
348 buffer = HeapAlloc(GetProcessHeap(), 0, size);
349 next = BSTR_UserMarshal(&umcb.Flags, buffer, &b);
350 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
351 check_bstr(buffer, b);
353 if (BSTR_UNMARSHAL_WORKS)
356 next = BSTR_UserUnmarshal(&umcb.Flags, buffer, &b2);
357 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
358 ok(b2 != NULL, "NULL LPSAFEARRAY didn't unmarshal\n");
359 len = SysStringByteLen(b2);
360 ok(len == 0, "byte len %ld\n", len);
361 BSTR_UserFree(&umcb.Flags, &b2);
363 HeapFree(GetProcessHeap(), 0, buffer);
367 static void check_variant_header(DWORD *wirev, VARIANT *v, unsigned long size)
372 ok(*wirev == (size + 7) >> 3, "wv[0] %08lx, expected %08lx\n", *wirev, (size + 7) >> 3);
374 ok(*wirev == 0, "wv[1] %08lx\n", *wirev);
377 ok(*wp == V_VT(v), "vt %04x expected %04x\n", *wp, V_VT(v));
379 ok(*wp == v->n1.n2.wReserved1, "res1 %04x expected %04x\n", *wp, v->n1.n2.wReserved1);
381 ok(*wp == v->n1.n2.wReserved2, "res2 %04x expected %04x\n", *wp, v->n1.n2.wReserved2);
383 ok(*wp == v->n1.n2.wReserved3, "res3 %04x expected %04x\n", *wp, v->n1.n2.wReserved3);
387 if(switch_is & VT_ARRAY)
388 switch_is &= ~VT_TYPEMASK;
389 ok(*wirev == switch_is, "switch_is %08lx expected %08lx\n", *wirev, switch_is);
392 static void test_marshal_VARIANT(void)
396 MIDL_STUB_MESSAGE stubMsg = { 0 };
397 USER_MARSHAL_CB umcb = { 0 };
398 unsigned char *buffer, *next;
404 WCHAR str[] = {'m','a','r','s','h','a','l',' ','t','e','s','t',0};
409 umcb.Flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
410 umcb.pReserve = NULL;
411 umcb.pStubMsg = &stubMsg;
418 /* Variants have an alignment of 8 */
419 size = VARIANT_UserSize(&umcb.Flags, 1, &v);
420 ok(size == 29, "size %ld\n", size);
422 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
423 ok(size == 21, "size %ld\n", size);
425 buffer = HeapAlloc(GetProcessHeap(), 0, size);
426 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
427 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
428 wirev = (DWORD*)buffer;
430 check_variant_header(wirev, &v, size);
432 ok(*(char*)wirev == V_I1(&v), "wv[5] %08lx\n", *wirev);
433 if (VARIANT_UNMARSHAL_WORKS)
436 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
437 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
438 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
439 ok(V_I1(&v) == V_I1(&v2), "got i1 %x expect %x\n", V_I1(&v), V_I1(&v2));
441 VARIANT_UserFree(&umcb.Flags, &v2);
443 HeapFree(GetProcessHeap(), 0, buffer);
450 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
451 ok(size == 22, "size %ld\n", size);
453 buffer = HeapAlloc(GetProcessHeap(), 0, size);
454 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
455 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
456 wirev = (DWORD*)buffer;
458 check_variant_header(wirev, &v, size);
460 ok(*(short*)wirev == V_I2(&v), "wv[5] %08lx\n", *wirev);
461 if (VARIANT_UNMARSHAL_WORKS)
464 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
465 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
466 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
467 ok(V_I2(&v) == V_I2(&v2), "got i2 %x expect %x\n", V_I2(&v), V_I2(&v2));
469 VARIANT_UserFree(&umcb.Flags, &v2);
471 HeapFree(GetProcessHeap(), 0, buffer);
475 V_VT(&v) = VT_I2 | VT_BYREF;
479 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
480 ok(size == 26, "size %ld\n", size);
482 buffer = HeapAlloc(GetProcessHeap(), 0, size);
483 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
484 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
485 wirev = (DWORD*)buffer;
487 check_variant_header(wirev, &v, size);
489 ok(*wirev == 0x4, "wv[5] %08lx\n", *wirev);
491 ok(*(short*)wirev == s, "wv[6] %08lx\n", *wirev);
492 if (VARIANT_UNMARSHAL_WORKS)
495 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
496 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
497 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
498 ok(*V_I2REF(&v) == *V_I2REF(&v2), "got i2 ref %x expect ui4 ref %x\n", *V_I2REF(&v), *V_I2REF(&v2));
500 VARIANT_UserFree(&umcb.Flags, &v2);
502 HeapFree(GetProcessHeap(), 0, buffer);
509 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
510 ok(size == 24, "size %ld\n", size);
512 buffer = HeapAlloc(GetProcessHeap(), 0, size);
513 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
514 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
515 wirev = (DWORD*)buffer;
517 check_variant_header(wirev, &v, size);
519 ok(*wirev == V_I4(&v), "wv[5] %08lx\n", *wirev);
521 if (VARIANT_UNMARSHAL_WORKS)
524 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
525 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
526 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
527 ok(V_I4(&v) == V_I4(&v2), "got i4 %lx expect %lx\n", V_I4(&v), V_I4(&v2));
529 VARIANT_UserFree(&umcb.Flags, &v2);
532 HeapFree(GetProcessHeap(), 0, buffer);
539 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
540 ok(size == 24, "size %ld\n", size);
542 buffer = HeapAlloc(GetProcessHeap(), 0, size);
543 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
544 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
545 wirev = (DWORD*)buffer;
547 check_variant_header(wirev, &v, size);
549 ok(*wirev == 0x1234, "wv[5] %08lx\n", *wirev);
550 if (VARIANT_UNMARSHAL_WORKS)
553 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
554 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
555 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
556 ok(V_UI4(&v) == V_UI4(&v2), "got ui4 %lx expect %lx\n", V_UI4(&v), V_UI4(&v2));
558 VARIANT_UserFree(&umcb.Flags, &v2);
561 HeapFree(GetProcessHeap(), 0, buffer);
565 V_VT(&v) = VT_UI4 | VT_BYREF;
569 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
570 ok(size == 28, "size %ld\n", size);
572 buffer = HeapAlloc(GetProcessHeap(), 0, size);
573 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
574 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
575 wirev = (DWORD*)buffer;
577 check_variant_header(wirev, &v, size);
579 ok(*wirev == 0x4, "wv[5] %08lx\n", *wirev);
581 ok(*wirev == ul, "wv[6] %08lx\n", *wirev);
583 if (VARIANT_UNMARSHAL_WORKS)
586 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
587 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
588 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
589 ok(*V_UI4REF(&v) == *V_UI4REF(&v2), "got ui4 ref %lx expect ui4 ref %lx\n", *V_UI4REF(&v), *V_UI4REF(&v2));
591 VARIANT_UserFree(&umcb.Flags, &v2);
593 HeapFree(GetProcessHeap(), 0, buffer);
600 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
601 ok(size == 24, "size %ld\n", size);
603 buffer = HeapAlloc(GetProcessHeap(), 0, size);
604 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
605 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
606 wirev = (DWORD*)buffer;
608 check_variant_header(wirev, &v, size);
610 ok(*(float*)wirev == V_R4(&v), "wv[5] %08lx\n", *wirev);
611 if (VARIANT_UNMARSHAL_WORKS)
614 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
615 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
616 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
617 ok(V_R4(&v) == V_R4(&v2), "got r4 %f expect %f\n", V_R4(&v), V_R4(&v2));
619 VARIANT_UserFree(&umcb.Flags, &v2);
621 HeapFree(GetProcessHeap(), 0, buffer);
628 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
629 ok(size == 32, "size %ld\n", size);
631 buffer = HeapAlloc(GetProcessHeap(), 0, size);
632 memset(buffer, 0xcc, size);
633 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
634 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
635 wirev = (DWORD*)buffer;
637 check_variant_header(wirev, &v, size);
639 ok(*wirev == 0xcccccccc, "wv[5] %08lx\n", *wirev); /* pad */
641 ok(*(double*)wirev == V_R8(&v), "wv[6] %08lx, wv[7] %08lx\n", *wirev, *(wirev+1));
642 if (VARIANT_UNMARSHAL_WORKS)
645 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
646 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
647 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
648 ok(V_R8(&v) == V_R8(&v2), "got r8 %f expect %f\n", V_R8(&v), V_R8(&v2));
650 VARIANT_UserFree(&umcb.Flags, &v2);
652 HeapFree(GetProcessHeap(), 0, buffer);
656 V_VT(&v) = VT_R8 | VT_BYREF;
660 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
661 ok(size == 32, "size %ld\n", size);
663 buffer = HeapAlloc(GetProcessHeap(), 0, size);
664 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
665 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
666 wirev = (DWORD*)buffer;
668 check_variant_header(wirev, &v, size);
670 ok(*wirev == 8, "wv[5] %08lx\n", *wirev);
672 ok(*(double*)wirev == d, "wv[6] %08lx wv[7] %08lx\n", *wirev, *(wirev+1));
673 if (VARIANT_UNMARSHAL_WORKS)
676 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
677 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
678 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
679 ok(*V_R8REF(&v) == *V_R8REF(&v2), "got r8 ref %f expect %f\n", *V_R8REF(&v), *V_R8REF(&v2));
681 VARIANT_UserFree(&umcb.Flags, &v2);
683 HeapFree(GetProcessHeap(), 0, buffer);
685 /*** VARIANT_BOOL ***/
690 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
691 ok(size == 22, "size %ld\n", size);
693 buffer = HeapAlloc(GetProcessHeap(), 0, size);
694 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
695 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
696 wirev = (DWORD*)buffer;
698 check_variant_header(wirev, &v, size);
700 ok(*(short*)wirev == V_BOOL(&v), "wv[5] %04x\n", *(WORD*)wirev);
701 if (VARIANT_UNMARSHAL_WORKS)
704 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
705 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
706 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
707 ok(V_BOOL(&v) == V_BOOL(&v2), "got bool %x expect %x\n", V_BOOL(&v), V_BOOL(&v2));
709 VARIANT_UserFree(&umcb.Flags, &v2);
711 HeapFree(GetProcessHeap(), 0, buffer);
714 VarDecFromI4(0x12345678, &dec);
717 V_VT(&v) = VT_DECIMAL;
719 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
720 ok(size == 40, "size %ld\n", size);
722 buffer = HeapAlloc(GetProcessHeap(), 0, size);
723 memset(buffer, 0xcc, size);
724 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
725 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
726 wirev = (DWORD*)buffer;
728 check_variant_header(wirev, &v, size);
730 ok(*wirev == 0xcccccccc, "wirev[5] %08lx\n", *wirev); /* pad */
733 dec2.wReserved = VT_DECIMAL;
734 ok(!memcmp(wirev, &dec2, sizeof(dec2)), "wirev[6] %08lx wirev[7] %08lx wirev[8] %08lx wirev[9] %08lx\n",
735 *wirev, *(wirev + 1), *(wirev + 2), *(wirev + 3));
736 if (VARIANT_UNMARSHAL_WORKS)
739 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
740 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
741 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
742 ok(!memcmp(&V_DECIMAL(&v), & V_DECIMAL(&v2), sizeof(DECIMAL)), "decimals differ\n");
744 VARIANT_UserFree(&umcb.Flags, &v2);
746 HeapFree(GetProcessHeap(), 0, buffer);
748 /*** DECIMAL BYREF ***/
750 V_VT(&v) = VT_DECIMAL | VT_BYREF;
751 V_DECIMALREF(&v) = &dec;
753 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
754 ok(size == 40, "size %ld\n", size);
756 buffer = HeapAlloc(GetProcessHeap(), 0, size);
757 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
758 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
759 wirev = (DWORD*)buffer;
761 check_variant_header(wirev, &v, size);
763 ok(*wirev == 16, "wv[5] %08lx\n", *wirev);
765 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));
766 if (VARIANT_UNMARSHAL_WORKS)
769 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
770 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
771 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
772 ok(!memcmp(V_DECIMALREF(&v), V_DECIMALREF(&v2), sizeof(DECIMAL)), "decimals differ\n");
774 VARIANT_UserFree(&umcb.Flags, &v2);
776 HeapFree(GetProcessHeap(), 0, buffer);
782 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
783 ok(size == 20, "size %ld\n", size);
785 buffer = HeapAlloc(GetProcessHeap(), 0, size);
786 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
787 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
788 wirev = (DWORD*)buffer;
790 check_variant_header(wirev, &v, size);
791 if (VARIANT_UNMARSHAL_WORKS)
794 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
795 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
796 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
798 VARIANT_UserFree(&umcb.Flags, &v2);
800 HeapFree(GetProcessHeap(), 0, buffer);
806 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
807 ok(size == 20, "size %ld\n", size);
809 buffer = HeapAlloc(GetProcessHeap(), 0, size);
810 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
811 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
812 wirev = (DWORD*)buffer;
814 check_variant_header(wirev, &v, size);
815 if (VARIANT_UNMARSHAL_WORKS)
818 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
819 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
820 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
822 VARIANT_UserFree(&umcb.Flags, &v2);
824 HeapFree(GetProcessHeap(), 0, buffer);
827 b = SysAllocString(str);
832 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
833 ok(size == 60, "size %ld\n", size);
834 buffer = HeapAlloc(GetProcessHeap(), 0, size);
835 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
836 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
837 wirev = (DWORD*)buffer;
839 check_variant_header(wirev, &v, size);
841 ok(*wirev, "wv[5] %08lx\n", *wirev); /* win2k: this is b. winxp: this is (char*)b + 1 */
843 check_bstr(wirev, V_BSTR(&v));
844 if (VARIANT_UNMARSHAL_WORKS)
847 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
848 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
849 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
850 ok(SysStringByteLen(V_BSTR(&v)) == SysStringByteLen(V_BSTR(&v2)), "bstr string lens differ\n");
851 ok(!memcmp(V_BSTR(&v), V_BSTR(&v2), SysStringByteLen(V_BSTR(&v))), "bstrs differ\n");
853 VARIANT_UserFree(&umcb.Flags, &v2);
855 HeapFree(GetProcessHeap(), 0, buffer);
859 V_VT(&v) = VT_BSTR | VT_BYREF;
862 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
863 ok(size == 64, "size %ld\n", size);
864 buffer = HeapAlloc(GetProcessHeap(), 0, size);
865 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
866 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
867 wirev = (DWORD*)buffer;
869 check_variant_header(wirev, &v, size);
871 ok(*wirev == 0x4, "wv[5] %08lx\n", *wirev);
873 ok(*wirev, "wv[6] %08lx\n", *wirev); /* win2k: this is b. winxp: this is (char*)b + 1 */
875 check_bstr(wirev, b);
876 if (VARIANT_UNMARSHAL_WORKS)
879 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
880 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
881 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
882 ok(SysStringByteLen(*V_BSTRREF(&v)) == SysStringByteLen(*V_BSTRREF(&v2)), "bstr string lens differ\n");
883 ok(!memcmp(*V_BSTRREF(&v), *V_BSTRREF(&v2), SysStringByteLen(*V_BSTRREF(&v))), "bstrs differ\n");
885 VARIANT_UserFree(&umcb.Flags, &v2);
887 HeapFree(GetProcessHeap(), 0, buffer);
894 lpsa = SafeArrayCreate(VT_R8, 1, &sab);
895 *(DWORD *)lpsa->pvData = 0xcafebabe;
896 *((DWORD *)lpsa->pvData + 1) = 0xdeadbeef;
900 V_VT(&v) = VT_UI4 | VT_ARRAY;
903 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
904 ok(size == 152, "size %ld\n", size);
905 buffer = HeapAlloc(GetProcessHeap(), 0, size);
906 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
907 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
908 wirev = (DWORD*)buffer;
910 check_variant_header(wirev, &v, size);
912 ok(*wirev, "wv[5] %08lx\n", *wirev); /* win2k: this is lpsa. winxp: this is (char*)lpsa + 1 */
914 check_safearray(wirev, lpsa);
915 if (VARIANT_UNMARSHAL_WORKS)
920 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
921 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
922 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
923 ok(SafeArrayGetDim(V_ARRAY(&v)) == SafeArrayGetDim(V_ARRAY(&v)), "array dims differ\n");
924 SafeArrayGetLBound(V_ARRAY(&v), 1, &bound);
925 SafeArrayGetLBound(V_ARRAY(&v2), 1, &bound2);
926 ok(bound == bound2, "array lbounds differ\n");
927 SafeArrayGetUBound(V_ARRAY(&v), 1, &bound);
928 SafeArrayGetUBound(V_ARRAY(&v2), 1, &bound2);
929 ok(bound == bound2, "array ubounds differ\n");
930 SafeArrayGetVartype(V_ARRAY(&v), &vt);
931 SafeArrayGetVartype(V_ARRAY(&v2), &vt2);
932 ok(vt == vt2, "array vts differ %x %x\n", vt, vt2);
933 VARIANT_UserFree(&umcb.Flags, &v2);
935 HeapFree(GetProcessHeap(), 0, buffer);
937 /*** ARRAY BYREF ***/
939 V_VT(&v) = VT_UI4 | VT_ARRAY | VT_BYREF;
940 V_ARRAYREF(&v) = &lpsa;
942 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
943 ok(size == 152, "size %ld\n", size);
944 buffer = HeapAlloc(GetProcessHeap(), 0, size);
945 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
946 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
947 wirev = (DWORD*)buffer;
949 check_variant_header(wirev, &v, size);
951 ok(*wirev == 4, "wv[5] %08lx\n", *wirev);
953 ok(*wirev, "wv[6] %08lx\n", *wirev); /* win2k: this is lpsa. winxp: this is (char*)lpsa + 1 */
955 check_safearray(wirev, lpsa);
956 if (VARIANT_UNMARSHAL_WORKS)
961 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
962 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
963 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
964 ok(SafeArrayGetDim(*V_ARRAYREF(&v)) == SafeArrayGetDim(*V_ARRAYREF(&v)), "array dims differ\n");
965 SafeArrayGetLBound(*V_ARRAYREF(&v), 1, &bound);
966 SafeArrayGetLBound(*V_ARRAYREF(&v2), 1, &bound2);
967 ok(bound == bound2, "array lbounds differ\n");
968 SafeArrayGetUBound(*V_ARRAYREF(&v), 1, &bound);
969 SafeArrayGetUBound(*V_ARRAYREF(&v2), 1, &bound2);
970 ok(bound == bound2, "array ubounds differ\n");
971 SafeArrayGetVartype(*V_ARRAYREF(&v), &vt);
972 SafeArrayGetVartype(*V_ARRAYREF(&v2), &vt2);
973 ok(vt == vt2, "array vts differ %x %x\n", vt, vt2);
974 VARIANT_UserFree(&umcb.Flags, &v2);
976 HeapFree(GetProcessHeap(), 0, buffer);
977 SafeArrayDestroy(lpsa);
979 /*** VARIANT BYREF ***/
984 V_VT(&v) = VT_VARIANT | VT_BYREF;
985 V_VARIANTREF(&v) = &v2;
987 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
988 ok(size == 64, "size %ld\n", size);
989 buffer = HeapAlloc(GetProcessHeap(), 0, size);
990 memset(buffer, 0xcc, size);
991 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
992 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
993 wirev = (DWORD*)buffer;
994 check_variant_header(wirev, &v, size);
997 ok(*wirev == 16, "wv[5] %08lx\n", *wirev);
999 ok(*wirev == ('U' | 's' << 8 | 'e' << 16 | 'r' << 24), "wv[6] %08lx\n", *wirev); /* 'User' */
1001 ok(*wirev == 0xcccccccc, "wv[7] %08lx\n", *wirev); /* pad */
1003 check_variant_header(wirev, &v2, size - 32);
1005 ok(*wirev == 0xcccccccc, "wv[13] %08lx\n", *wirev); /* pad for VT_R8 */
1007 ok(*(double*)wirev == V_R8(&v2), "wv[6] %08lx wv[7] %08lx\n", *wirev, *(wirev+1));
1008 if (VARIANT_UNMARSHAL_WORKS)
1012 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v3);
1013 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
1014 ok(V_VT(&v) == V_VT(&v3), "got vt %d expect %d\n", V_VT(&v), V_VT(&v3));
1015 ok(V_VT(V_VARIANTREF(&v)) == V_VT(V_VARIANTREF(&v3)), "vts differ %x %x\n",
1016 V_VT(V_VARIANTREF(&v)), V_VT(V_VARIANTREF(&v3)));
1017 ok(V_R8(V_VARIANTREF(&v)) == V_R8(V_VARIANTREF(&v3)), "r8s differ\n");
1018 VARIANT_UserFree(&umcb.Flags, &v3);
1020 HeapFree(GetProcessHeap(), 0, buffer);
1024 START_TEST(usrmarshal)
1028 test_marshal_LPSAFEARRAY();
1029 test_marshal_BSTR();
1030 test_marshal_VARIANT();