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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 = SysStringLen(b);
232 ok(*wireb == len, "wv[0] %08lx\n", *wireb);
235 ok(*wireb == len * 2, "wv[1] %08lx\n", *wireb);
237 ok(*wireb == 0xffffffff, "wv[1] %08lx\n", *wireb);
239 ok(*wireb == len, "wv[2] %08lx\n", *wireb);
243 ok(!memcmp(wireb, b, len * 2), "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;
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 BSTR_UserMarshal(&umcb.Flags, buffer, &b);
275 check_bstr(buffer, b);
277 if (BSTR_UNMARSHAL_WORKS)
280 BSTR_UserUnmarshal(&umcb.Flags, buffer, &b2);
281 ok(b2 != NULL, "NULL LPSAFEARRAY didn't unmarshal\n");
282 ok(!memcmp(b, b2, (len + 1) * 2), "strings differ\n");
283 BSTR_UserFree(&umcb.Flags, &b2);
286 HeapFree(GetProcessHeap(), 0, buffer);
290 size = BSTR_UserSize(&umcb.Flags, 0, &b);
291 ok(size == 12, "size %ld\n", size);
293 buffer = HeapAlloc(GetProcessHeap(), 0, size);
294 BSTR_UserMarshal(&umcb.Flags, buffer, &b);
296 check_bstr(buffer, b);
297 HeapFree(GetProcessHeap(), 0, buffer);
301 static void check_variant_header(DWORD *wirev, VARIANT *v, unsigned long size)
306 ok(*wirev == (size + 7) >> 3, "wv[0] %08lx, expected %08lx\n", *wirev, (size + 7) >> 3);
308 ok(*wirev == 0, "wv[1] %08lx\n", *wirev);
311 ok(*wp == V_VT(v), "vt %04x expected %04x\n", *wp, V_VT(v));
313 ok(*wp == v->n1.n2.wReserved1, "res1 %04x expected %04x\n", *wp, v->n1.n2.wReserved1);
315 ok(*wp == v->n1.n2.wReserved2, "res2 %04x expected %04x\n", *wp, v->n1.n2.wReserved2);
317 ok(*wp == v->n1.n2.wReserved3, "res3 %04x expected %04x\n", *wp, v->n1.n2.wReserved3);
321 if(switch_is & VT_ARRAY)
322 switch_is &= ~VT_TYPEMASK;
323 ok(*wirev == switch_is, "switch_is %08lx expected %08lx\n", *wirev, switch_is);
326 static void test_marshal_VARIANT(void)
330 MIDL_STUB_MESSAGE stubMsg = { 0 };
331 USER_MARSHAL_CB umcb = { 0 };
332 unsigned char *buffer, *next;
338 WCHAR str[] = {'m','a','r','s','h','a','l',' ','t','e','s','t',0};
343 umcb.Flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
344 umcb.pReserve = NULL;
345 umcb.pStubMsg = &stubMsg;
352 /* Variants have an alignment of 8 */
353 size = VARIANT_UserSize(&umcb.Flags, 1, &v);
354 ok(size == 29, "size %ld\n", size);
356 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
357 ok(size == 21, "size %ld\n", size);
359 buffer = HeapAlloc(GetProcessHeap(), 0, size);
360 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
361 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
362 wirev = (DWORD*)buffer;
364 check_variant_header(wirev, &v, size);
366 ok(*(char*)wirev == V_I1(&v), "wv[5] %08lx\n", *wirev);
367 if (VARIANT_UNMARSHAL_WORKS)
370 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
371 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
372 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
373 ok(V_I1(&v) == V_I1(&v2), "got i1 %x expect %x\n", V_I1(&v), V_I1(&v2));
375 VARIANT_UserFree(&umcb.Flags, &v2);
377 HeapFree(GetProcessHeap(), 0, buffer);
384 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
385 ok(size == 22, "size %ld\n", size);
387 buffer = HeapAlloc(GetProcessHeap(), 0, size);
388 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
389 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
390 wirev = (DWORD*)buffer;
392 check_variant_header(wirev, &v, size);
394 ok(*(short*)wirev == V_I2(&v), "wv[5] %08lx\n", *wirev);
395 if (VARIANT_UNMARSHAL_WORKS)
398 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
399 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
400 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
401 ok(V_I2(&v) == V_I2(&v2), "got i2 %x expect %x\n", V_I2(&v), V_I2(&v2));
403 VARIANT_UserFree(&umcb.Flags, &v2);
405 HeapFree(GetProcessHeap(), 0, buffer);
409 V_VT(&v) = VT_I2 | VT_BYREF;
413 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
414 ok(size == 26, "size %ld\n", size);
416 buffer = HeapAlloc(GetProcessHeap(), 0, size);
417 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
418 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
419 wirev = (DWORD*)buffer;
421 check_variant_header(wirev, &v, size);
423 ok(*wirev == 0x4, "wv[5] %08lx\n", *wirev);
425 ok(*(short*)wirev == s, "wv[6] %08lx\n", *wirev);
426 if (VARIANT_UNMARSHAL_WORKS)
429 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
430 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
431 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
432 ok(*V_I2REF(&v) == *V_I2REF(&v2), "got i2 ref %x expect ui4 ref %x\n", *V_I2REF(&v), *V_I2REF(&v2));
434 VARIANT_UserFree(&umcb.Flags, &v2);
436 HeapFree(GetProcessHeap(), 0, buffer);
443 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
444 ok(size == 24, "size %ld\n", size);
446 buffer = HeapAlloc(GetProcessHeap(), 0, size);
447 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
448 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
449 wirev = (DWORD*)buffer;
451 check_variant_header(wirev, &v, size);
453 ok(*wirev == V_I4(&v), "wv[5] %08lx\n", *wirev);
455 if (VARIANT_UNMARSHAL_WORKS)
458 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
459 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
460 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
461 ok(V_I4(&v) == V_I4(&v2), "got i4 %lx expect %lx\n", V_I4(&v), V_I4(&v2));
463 VARIANT_UserFree(&umcb.Flags, &v2);
466 HeapFree(GetProcessHeap(), 0, buffer);
473 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
474 ok(size == 24, "size %ld\n", size);
476 buffer = HeapAlloc(GetProcessHeap(), 0, size);
477 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
478 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
479 wirev = (DWORD*)buffer;
481 check_variant_header(wirev, &v, size);
483 ok(*wirev == 0x1234, "wv[5] %08lx\n", *wirev);
484 if (VARIANT_UNMARSHAL_WORKS)
487 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
488 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
489 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
490 ok(V_UI4(&v) == V_UI4(&v2), "got ui4 %lx expect %lx\n", V_UI4(&v), V_UI4(&v2));
492 VARIANT_UserFree(&umcb.Flags, &v2);
495 HeapFree(GetProcessHeap(), 0, buffer);
499 V_VT(&v) = VT_UI4 | VT_BYREF;
503 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
504 ok(size == 28, "size %ld\n", size);
506 buffer = HeapAlloc(GetProcessHeap(), 0, size);
507 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
508 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
509 wirev = (DWORD*)buffer;
511 check_variant_header(wirev, &v, size);
513 ok(*wirev == 0x4, "wv[5] %08lx\n", *wirev);
515 ok(*wirev == ul, "wv[6] %08lx\n", *wirev);
517 if (VARIANT_UNMARSHAL_WORKS)
520 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
521 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
522 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
523 ok(*V_UI4REF(&v) == *V_UI4REF(&v2), "got ui4 ref %lx expect ui4 ref %lx\n", *V_UI4REF(&v), *V_UI4REF(&v2));
525 VARIANT_UserFree(&umcb.Flags, &v2);
527 HeapFree(GetProcessHeap(), 0, buffer);
534 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
535 ok(size == 24, "size %ld\n", size);
537 buffer = HeapAlloc(GetProcessHeap(), 0, size);
538 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
539 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
540 wirev = (DWORD*)buffer;
542 check_variant_header(wirev, &v, size);
544 ok(*(float*)wirev == V_R4(&v), "wv[5] %08lx\n", *wirev);
545 if (VARIANT_UNMARSHAL_WORKS)
548 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
549 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
550 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
551 ok(V_R4(&v) == V_R4(&v2), "got r4 %f expect %f\n", V_R4(&v), V_R4(&v2));
553 VARIANT_UserFree(&umcb.Flags, &v2);
555 HeapFree(GetProcessHeap(), 0, buffer);
562 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
563 ok(size == 32, "size %ld\n", size);
565 buffer = HeapAlloc(GetProcessHeap(), 0, size);
566 memset(buffer, 0xcc, size);
567 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
568 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
569 wirev = (DWORD*)buffer;
571 check_variant_header(wirev, &v, size);
573 ok(*wirev == 0xcccccccc, "wv[5] %08lx\n", *wirev); /* pad */
575 ok(*(double*)wirev == V_R8(&v), "wv[6] %08lx, wv[7] %08lx\n", *wirev, *(wirev+1));
576 if (VARIANT_UNMARSHAL_WORKS)
579 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
580 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
581 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
582 ok(V_R8(&v) == V_R8(&v2), "got r8 %f expect %f\n", V_R8(&v), V_R8(&v2));
584 VARIANT_UserFree(&umcb.Flags, &v2);
586 HeapFree(GetProcessHeap(), 0, buffer);
590 V_VT(&v) = VT_R8 | VT_BYREF;
594 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
595 ok(size == 32, "size %ld\n", size);
597 buffer = HeapAlloc(GetProcessHeap(), 0, size);
598 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
599 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
600 wirev = (DWORD*)buffer;
602 check_variant_header(wirev, &v, size);
604 ok(*wirev == 8, "wv[5] %08lx\n", *wirev);
606 ok(*(double*)wirev == d, "wv[6] %08lx wv[7] %08lx\n", *wirev, *(wirev+1));
607 if (VARIANT_UNMARSHAL_WORKS)
610 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
611 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
612 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
613 ok(*V_R8REF(&v) == *V_R8REF(&v2), "got r8 ref %f expect %f\n", *V_R8REF(&v), *V_R8REF(&v2));
615 VARIANT_UserFree(&umcb.Flags, &v2);
617 HeapFree(GetProcessHeap(), 0, buffer);
619 /*** VARIANT_BOOL ***/
624 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
625 ok(size == 22, "size %ld\n", size);
627 buffer = HeapAlloc(GetProcessHeap(), 0, size);
628 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
629 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
630 wirev = (DWORD*)buffer;
632 check_variant_header(wirev, &v, size);
634 ok(*(short*)wirev == V_BOOL(&v), "wv[5] %04x\n", *(WORD*)wirev);
635 if (VARIANT_UNMARSHAL_WORKS)
638 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
639 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
640 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
641 ok(V_BOOL(&v) == V_BOOL(&v2), "got bool %x expect %x\n", V_BOOL(&v), V_BOOL(&v2));
643 VARIANT_UserFree(&umcb.Flags, &v2);
645 HeapFree(GetProcessHeap(), 0, buffer);
648 VarDecFromI4(0x12345678, &dec);
651 V_VT(&v) = VT_DECIMAL;
653 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
654 ok(size == 40, "size %ld\n", size);
656 buffer = HeapAlloc(GetProcessHeap(), 0, size);
657 memset(buffer, 0xcc, size);
658 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
659 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
660 wirev = (DWORD*)buffer;
662 check_variant_header(wirev, &v, size);
664 ok(*wirev == 0xcccccccc, "wirev[5] %08lx\n", *wirev); /* pad */
667 dec2.wReserved = VT_DECIMAL;
668 ok(!memcmp(wirev, &dec2, sizeof(dec2)), "wirev[6] %08lx wirev[7] %08lx wirev[8] %08lx wirev[9] %08lx\n",
669 *wirev, *(wirev + 1), *(wirev + 2), *(wirev + 3));
670 if (VARIANT_UNMARSHAL_WORKS)
673 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
674 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
675 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
676 ok(!memcmp(&V_DECIMAL(&v), & V_DECIMAL(&v2), sizeof(DECIMAL)), "decimals differ\n");
678 VARIANT_UserFree(&umcb.Flags, &v2);
680 HeapFree(GetProcessHeap(), 0, buffer);
682 /*** DECIMAL BYREF ***/
684 V_VT(&v) = VT_DECIMAL | VT_BYREF;
685 V_DECIMALREF(&v) = &dec;
687 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
688 ok(size == 40, "size %ld\n", size);
690 buffer = HeapAlloc(GetProcessHeap(), 0, size);
691 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
692 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
693 wirev = (DWORD*)buffer;
695 check_variant_header(wirev, &v, size);
697 ok(*wirev == 16, "wv[5] %08lx\n", *wirev);
699 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));
700 if (VARIANT_UNMARSHAL_WORKS)
703 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
704 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
705 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
706 ok(!memcmp(V_DECIMALREF(&v), V_DECIMALREF(&v2), sizeof(DECIMAL)), "decimals differ\n");
708 VARIANT_UserFree(&umcb.Flags, &v2);
710 HeapFree(GetProcessHeap(), 0, buffer);
716 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
717 ok(size == 20, "size %ld\n", size);
719 buffer = HeapAlloc(GetProcessHeap(), 0, size);
720 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
721 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
722 wirev = (DWORD*)buffer;
724 check_variant_header(wirev, &v, size);
725 if (VARIANT_UNMARSHAL_WORKS)
728 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
729 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
730 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
732 VARIANT_UserFree(&umcb.Flags, &v2);
734 HeapFree(GetProcessHeap(), 0, buffer);
740 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
741 ok(size == 20, "size %ld\n", size);
743 buffer = HeapAlloc(GetProcessHeap(), 0, size);
744 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
745 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
746 wirev = (DWORD*)buffer;
748 check_variant_header(wirev, &v, size);
749 if (VARIANT_UNMARSHAL_WORKS)
752 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
753 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
754 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
756 VARIANT_UserFree(&umcb.Flags, &v2);
758 HeapFree(GetProcessHeap(), 0, buffer);
761 b = SysAllocString(str);
766 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
767 ok(size == 60, "size %ld\n", size);
768 buffer = HeapAlloc(GetProcessHeap(), 0, size);
769 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
770 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
771 wirev = (DWORD*)buffer;
773 check_variant_header(wirev, &v, size);
775 ok(*wirev, "wv[5] %08lx\n", *wirev); /* win2k: this is b. winxp: this is (char*)b + 1 */
777 check_bstr(wirev, V_BSTR(&v));
778 if (VARIANT_UNMARSHAL_WORKS)
781 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
782 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
783 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
784 ok(SysStringByteLen(V_BSTR(&v)) == SysStringByteLen(V_BSTR(&v2)), "bstr string lens differ\n");
785 ok(!memcmp(V_BSTR(&v), V_BSTR(&v2), SysStringByteLen(V_BSTR(&v))), "bstrs differ\n");
787 VARIANT_UserFree(&umcb.Flags, &v2);
789 HeapFree(GetProcessHeap(), 0, buffer);
793 V_VT(&v) = VT_BSTR | VT_BYREF;
796 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
797 ok(size == 64, "size %ld\n", size);
798 buffer = HeapAlloc(GetProcessHeap(), 0, size);
799 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
800 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
801 wirev = (DWORD*)buffer;
803 check_variant_header(wirev, &v, size);
805 ok(*wirev == 0x4, "wv[5] %08lx\n", *wirev);
807 ok(*wirev, "wv[6] %08lx\n", *wirev); /* win2k: this is b. winxp: this is (char*)b + 1 */
809 check_bstr(wirev, b);
810 if (VARIANT_UNMARSHAL_WORKS)
813 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
814 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
815 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
816 ok(SysStringByteLen(*V_BSTRREF(&v)) == SysStringByteLen(*V_BSTRREF(&v2)), "bstr string lens differ\n");
817 ok(!memcmp(*V_BSTRREF(&v), *V_BSTRREF(&v2), SysStringByteLen(*V_BSTRREF(&v))), "bstrs differ\n");
819 VARIANT_UserFree(&umcb.Flags, &v2);
821 HeapFree(GetProcessHeap(), 0, buffer);
828 lpsa = SafeArrayCreate(VT_R8, 1, &sab);
829 *(DWORD *)lpsa->pvData = 0xcafebabe;
830 *((DWORD *)lpsa->pvData + 1) = 0xdeadbeef;
834 V_VT(&v) = VT_UI4 | VT_ARRAY;
837 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
838 ok(size == 152, "size %ld\n", size);
839 buffer = HeapAlloc(GetProcessHeap(), 0, size);
840 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
841 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
842 wirev = (DWORD*)buffer;
844 check_variant_header(wirev, &v, size);
846 ok(*wirev, "wv[5] %08lx\n", *wirev); /* win2k: this is lpsa. winxp: this is (char*)lpsa + 1 */
848 check_safearray(wirev, lpsa);
849 if (VARIANT_UNMARSHAL_WORKS)
854 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
855 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
856 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
857 ok(SafeArrayGetDim(V_ARRAY(&v)) == SafeArrayGetDim(V_ARRAY(&v)), "array dims differ\n");
858 SafeArrayGetLBound(V_ARRAY(&v), 1, &bound);
859 SafeArrayGetLBound(V_ARRAY(&v2), 1, &bound2);
860 ok(bound == bound2, "array lbounds differ\n");
861 SafeArrayGetUBound(V_ARRAY(&v), 1, &bound);
862 SafeArrayGetUBound(V_ARRAY(&v2), 1, &bound2);
863 ok(bound == bound2, "array ubounds differ\n");
864 SafeArrayGetVartype(V_ARRAY(&v), &vt);
865 SafeArrayGetVartype(V_ARRAY(&v2), &vt2);
866 ok(vt == vt2, "array vts differ %x %x\n", vt, vt2);
867 VARIANT_UserFree(&umcb.Flags, &v2);
869 HeapFree(GetProcessHeap(), 0, buffer);
871 /*** ARRAY BYREF ***/
873 V_VT(&v) = VT_UI4 | VT_ARRAY | VT_BYREF;
874 V_ARRAYREF(&v) = &lpsa;
876 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
877 ok(size == 152, "size %ld\n", size);
878 buffer = HeapAlloc(GetProcessHeap(), 0, size);
879 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
880 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
881 wirev = (DWORD*)buffer;
883 check_variant_header(wirev, &v, size);
885 ok(*wirev == 4, "wv[5] %08lx\n", *wirev);
887 ok(*wirev, "wv[6] %08lx\n", *wirev); /* win2k: this is lpsa. winxp: this is (char*)lpsa + 1 */
889 check_safearray(wirev, lpsa);
890 if (VARIANT_UNMARSHAL_WORKS)
895 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
896 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
897 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
898 ok(SafeArrayGetDim(*V_ARRAYREF(&v)) == SafeArrayGetDim(*V_ARRAYREF(&v)), "array dims differ\n");
899 SafeArrayGetLBound(*V_ARRAYREF(&v), 1, &bound);
900 SafeArrayGetLBound(*V_ARRAYREF(&v2), 1, &bound2);
901 ok(bound == bound2, "array lbounds differ\n");
902 SafeArrayGetUBound(*V_ARRAYREF(&v), 1, &bound);
903 SafeArrayGetUBound(*V_ARRAYREF(&v2), 1, &bound2);
904 ok(bound == bound2, "array ubounds differ\n");
905 SafeArrayGetVartype(*V_ARRAYREF(&v), &vt);
906 SafeArrayGetVartype(*V_ARRAYREF(&v2), &vt2);
907 ok(vt == vt2, "array vts differ %x %x\n", vt, vt2);
908 VARIANT_UserFree(&umcb.Flags, &v2);
910 HeapFree(GetProcessHeap(), 0, buffer);
911 SafeArrayDestroy(lpsa);
913 /*** VARIANT BYREF ***/
918 V_VT(&v) = VT_VARIANT | VT_BYREF;
919 V_VARIANTREF(&v) = &v2;
921 size = VARIANT_UserSize(&umcb.Flags, 0, &v);
922 ok(size == 64, "size %ld\n", size);
923 buffer = HeapAlloc(GetProcessHeap(), 0, size);
924 memset(buffer, 0xcc, size);
925 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
926 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
927 wirev = (DWORD*)buffer;
928 check_variant_header(wirev, &v, size);
931 ok(*wirev == 16, "wv[5] %08lx\n", *wirev);
933 ok(*wirev == ('U' | 's' << 8 | 'e' << 16 | 'r' << 24), "wv[6] %08lx\n", *wirev); /* 'User' */
935 ok(*wirev == 0xcccccccc, "wv[7] %08lx\n", *wirev); /* pad */
937 check_variant_header(wirev, &v2, size - 32);
939 ok(*wirev == 0xcccccccc, "wv[13] %08lx\n", *wirev); /* pad for VT_R8 */
941 ok(*(double*)wirev == V_R8(&v2), "wv[6] %08lx wv[7] %08lx\n", *wirev, *(wirev+1));
942 if (VARIANT_UNMARSHAL_WORKS)
946 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v3);
947 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
948 ok(V_VT(&v) == V_VT(&v3), "got vt %d expect %d\n", V_VT(&v), V_VT(&v3));
949 ok(V_VT(V_VARIANTREF(&v)) == V_VT(V_VARIANTREF(&v3)), "vts differ %x %x\n",
950 V_VT(V_VARIANTREF(&v)), V_VT(V_VARIANTREF(&v3)));
951 ok(V_R8(V_VARIANTREF(&v)) == V_R8(V_VARIANTREF(&v3)), "r8s differ\n");
952 VARIANT_UserFree(&umcb.Flags, &v3);
954 HeapFree(GetProcessHeap(), 0, buffer);
958 START_TEST(usrmarshal)
962 test_marshal_LPSAFEARRAY();
964 test_marshal_VARIANT();