kernel32: GlobalMemoryStatusEx: return the size of physical memory + swapsize in...
[wine] / dlls / oleaut32 / tests / usrmarshal.c
1 /*
2  * Marshaling Tests
3  *
4  * Copyright 2004 Robert Shearman
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #include <stdarg.h>
22
23 #include "windef.h"
24 #include "winbase.h"
25 #include "objbase.h"
26 #include "propidl.h" /* for LPSAFEARRAY_User* routines */
27
28 #include "wine/test.h"
29
30 #if (__STDC__ && !defined(_FORCENAMELESSUNION)) || defined(NONAMELESSUNION)
31 # define V_U2(A)  ((A)->n1.n2)
32 #else
33 # define V_U2(A)  (*(A))
34 #endif
35
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
41
42 static inline SF_TYPE get_union_type(SAFEARRAY *psa)
43 {
44     VARTYPE vt;
45     HRESULT hr;
46
47     hr = SafeArrayGetVartype(psa, &vt);
48     if (FAILED(hr))
49     {
50         switch(psa->cbElements)
51         {
52         case 1: vt = VT_I1; break;
53         case 2: vt = VT_I2; break;
54         case 4: vt = VT_I4; break;
55         case 8: vt = VT_I8; break;
56         default: return 0;
57         }
58     }
59
60     if (psa->fFeatures & FADF_HAVEIID)
61         return SF_HAVEIID;
62
63     switch (vt)
64     {
65     case VT_I1:
66     case VT_UI1:      return SF_I1;
67     case VT_BOOL:
68     case VT_I2:
69     case VT_UI2:      return SF_I2;
70     case VT_INT:
71     case VT_UINT:
72     case VT_I4:
73     case VT_UI4:
74     case VT_R4:       return SF_I4;
75     case VT_DATE:
76     case VT_CY:
77     case VT_R8:
78     case VT_I8:
79     case VT_UI8:      return SF_I8;
80     case VT_INT_PTR:
81     case VT_UINT_PTR: return (sizeof(UINT_PTR) == 4 ? SF_I4 : SF_I8);
82     case VT_BSTR:     return SF_BSTR;
83     case VT_DISPATCH: return SF_DISPATCH;
84     case VT_VARIANT:  return SF_VARIANT;
85     case VT_UNKNOWN:  return SF_UNKNOWN;
86     /* Note: Return a non-zero size to indicate vt is valid. The actual size
87      * of a UDT is taken from the result of IRecordInfo_GetSize().
88      */
89     case VT_RECORD:   return SF_RECORD;
90     default:          return SF_ERROR;
91     }
92 }
93
94 static ULONG get_cell_count(const SAFEARRAY *psa)
95 {
96     const SAFEARRAYBOUND* psab = psa->rgsabound;
97     USHORT cCount = psa->cDims;
98     ULONG ulNumCells = 1;
99
100     while (cCount--)
101     {
102          if (!psab->cElements)
103             return 0;
104         ulNumCells *= psab->cElements;
105         psab++;
106     }
107     return ulNumCells;
108 }
109
110 static void check_safearray(void *buffer, LPSAFEARRAY lpsa)
111 {
112     unsigned char *wiresa = buffer;
113     VARTYPE vt;
114     SF_TYPE sftype;
115     ULONG cell_count;
116
117     if(!lpsa)
118     {
119         ok(*(void **)wiresa == NULL, "wiresa + 0x0 should be NULL instead of 0x%08x\n", *(DWORD *)wiresa);
120         return;
121     }
122
123     if(FAILED(SafeArrayGetVartype(lpsa, &vt)))
124         vt = 0;
125
126     sftype = get_union_type(lpsa);
127     cell_count = get_cell_count(lpsa);
128
129     ok(*(DWORD *)wiresa, "wiresa + 0x0 should be non-NULL instead of 0x%08x\n", *(DWORD *)wiresa); /* win2k: this is lpsa. winxp: this is 0x00000001 */
130     wiresa += sizeof(DWORD);
131     ok(*(DWORD *)wiresa == lpsa->cDims, "wiresa + 0x4 should be lpsa->cDims instead of 0x%08x\n", *(DWORD *)wiresa);
132     wiresa += sizeof(DWORD);
133     ok(*(WORD *)wiresa == lpsa->cDims, "wiresa + 0x8 should be lpsa->cDims instead of 0x%04x\n", *(WORD *)wiresa);
134     wiresa += sizeof(WORD);
135     ok(*(WORD *)wiresa == lpsa->fFeatures, "wiresa + 0xc should be lpsa->fFeatures instead of 0x%08x\n", *(WORD *)wiresa);
136     wiresa += sizeof(WORD);
137     ok(*(DWORD *)wiresa == lpsa->cbElements, "wiresa + 0x10 should be lpsa->cbElements instead of 0x%08x\n", *(DWORD *)wiresa);
138     wiresa += sizeof(DWORD);
139     ok(*(WORD *)wiresa == lpsa->cLocks, "wiresa + 0x16 should be lpsa->cLocks instead of 0x%04x\n", *(WORD *)wiresa);
140     wiresa += sizeof(WORD);
141     ok(*(WORD *)wiresa == vt, "wiresa + 0x14 should be %04x instead of 0x%04x\n", vt, *(WORD *)wiresa);
142     wiresa += sizeof(WORD);
143     ok(*(DWORD *)wiresa == sftype, "wiresa + 0x18 should be %08x instead of 0x%08x\n", (DWORD)sftype, *(DWORD *)wiresa);
144     wiresa += sizeof(DWORD);
145     ok(*(DWORD *)wiresa == cell_count, "wiresa + 0x1c should be %u instead of %u\n", cell_count, *(DWORD *)wiresa);
146     wiresa += sizeof(DWORD);
147     ok(*(DWORD_PTR *)wiresa == (DWORD_PTR)lpsa->pvData, "wiresa + 0x20 should be lpsa->pvData instead of 0x%08lx\n", *(DWORD_PTR *)wiresa);
148     wiresa += sizeof(DWORD_PTR);
149     if(sftype == SF_HAVEIID)
150     {
151         GUID guid;
152         SafeArrayGetIID(lpsa, &guid);
153         ok(IsEqualGUID(&guid, (GUID*)wiresa), "guid mismatch\n");
154         wiresa += sizeof(GUID);
155     }
156     ok(!memcmp(wiresa, lpsa->rgsabound, sizeof(lpsa->rgsabound[0]) * lpsa->cDims), "bounds mismatch\n");
157     wiresa += sizeof(lpsa->rgsabound[0]) * lpsa->cDims;
158
159     ok(*(DWORD *)wiresa == cell_count, "wiresa + 0x2c should be %u instead of %u\n", cell_count, *(DWORD*)wiresa);
160     wiresa += sizeof(DWORD);
161     /* elements are now pointed to by wiresa */
162 }
163
164 static void test_marshal_LPSAFEARRAY(void)
165 {
166     unsigned char *buffer;
167     unsigned long size;
168     LPSAFEARRAY lpsa;
169     LPSAFEARRAY lpsa2 = NULL;
170     SAFEARRAYBOUND sab;
171     MIDL_STUB_MESSAGE stubMsg = { 0 };
172     USER_MARSHAL_CB umcb = { 0 };
173     HRESULT hr;
174     VARTYPE vt;
175
176     umcb.Flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
177     umcb.pReserve = NULL;
178     umcb.pStubMsg = &stubMsg;
179
180     sab.lLbound = 5;
181     sab.cElements = 10;
182
183     lpsa = SafeArrayCreate(VT_I2, 1, &sab);
184     *(DWORD *)lpsa->pvData = 0xcafebabe;
185
186     lpsa->cLocks = 7;
187     size = LPSAFEARRAY_UserSize(&umcb.Flags, 1, &lpsa);
188     ok(size == 68, "size should be 68 bytes, not %ld\n", size);
189     size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
190     ok(size == 64, "size should be 64 bytes, not %ld\n", size);
191     buffer = (unsigned char *)HeapAlloc(GetProcessHeap(), 0, size);
192     LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
193
194     check_safearray(buffer, lpsa);
195
196     if (LPSAFEARRAY_UNMARSHAL_WORKS)
197     {
198         VARTYPE vt, vt2;
199         LPSAFEARRAY_UserUnmarshal(&umcb.Flags, buffer, &lpsa2);
200         ok(lpsa2 != NULL, "LPSAFEARRAY didn't unmarshal\n");
201         SafeArrayGetVartype(lpsa, &vt);
202         SafeArrayGetVartype(lpsa2, &vt2);
203         ok(vt == vt2, "vts differ %x %x\n", vt, vt2);
204         LPSAFEARRAY_UserFree(&umcb.Flags, &lpsa2);
205     }
206     HeapFree(GetProcessHeap(), 0, buffer);
207     SafeArrayDestroy(lpsa);
208
209     /* test NULL safe array */
210     lpsa = NULL;
211
212     size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
213     ok(size == 4, "size should be 4 bytes, not %ld\n", size);
214     buffer = (unsigned char *)HeapAlloc(GetProcessHeap(), 0, size);
215     LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
216     check_safearray(buffer, lpsa);
217
218     if (LPSAFEARRAY_UNMARSHAL_WORKS)
219     {
220         LPSAFEARRAY_UserUnmarshal(&umcb.Flags, buffer, &lpsa2);
221         ok(lpsa2 == NULL, "NULL LPSAFEARRAY didn't unmarshal\n");
222         LPSAFEARRAY_UserFree(&umcb.Flags, &lpsa2);
223     }
224     HeapFree(GetProcessHeap(), 0, buffer);
225
226     sab.lLbound = 5;
227     sab.cElements = 10;
228
229     lpsa = SafeArrayCreate(VT_R8, 1, &sab);
230     *(double *)lpsa->pvData = 3.1415;
231
232     lpsa->cLocks = 7;
233     size = LPSAFEARRAY_UserSize(&umcb.Flags, 1, &lpsa);
234     ok(size == 128, "size should be 128 bytes, not %ld\n", size);
235     size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
236     ok(size == 128, "size should be 128 bytes, not %ld\n", size);
237     buffer = (unsigned char *)HeapAlloc(GetProcessHeap(), 0, size);
238     LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
239
240     check_safearray(buffer, lpsa);
241
242     HeapFree(GetProcessHeap(), 0, buffer);
243     SafeArrayDestroy(lpsa);
244
245     /* VARTYPE-less arrays can be marshaled if cbElements is 1,2,4 or 8 as type SF_In */
246     hr = SafeArrayAllocDescriptor(1, &lpsa);
247     ok(hr == S_OK, "saad failed %08x\n", hr);
248     lpsa->cbElements = 8;
249     lpsa->rgsabound[0].lLbound = 2;
250     lpsa->rgsabound[0].cElements = 48;
251     hr = SafeArrayAllocData(lpsa);
252     ok(hr == S_OK, "saad failed %08x\n", hr);
253
254     hr = SafeArrayGetVartype(lpsa, &vt);
255     ok(hr == E_INVALIDARG, "ret %08x\n", hr);
256
257     size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
258     ok(size == 432, "size %ld\n", size);
259     buffer = (unsigned char *)HeapAlloc(GetProcessHeap(), 0, size);
260     LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
261     check_safearray(buffer, lpsa);
262     HeapFree(GetProcessHeap(), 0, buffer);
263     SafeArrayDestroyData(lpsa);
264     SafeArrayDestroyDescriptor(lpsa);
265 }
266
267 static void check_bstr(void *buffer, BSTR b)
268 {
269     DWORD *wireb = buffer;
270     DWORD len = SysStringByteLen(b);
271
272     ok(*wireb == (len + 1) / 2, "wv[0] %08x\n", *wireb);
273     wireb++;
274     if(b)
275         ok(*wireb == len, "wv[1] %08x\n", *wireb);
276     else
277         ok(*wireb == 0xffffffff, "wv[1] %08x\n", *wireb);
278     wireb++;
279     ok(*wireb == (len + 1) / 2, "wv[2] %08x\n", *wireb);
280     if(len)
281     {
282         wireb++;
283         ok(!memcmp(wireb, b, (len + 1) & ~1), "strings differ\n");
284     }
285     return;
286 }
287
288 static void test_marshal_BSTR(void)
289 {
290     unsigned long size;
291     MIDL_STUB_MESSAGE stubMsg = { 0 };
292     USER_MARSHAL_CB umcb = { 0 };
293     unsigned char *buffer, *next;
294     BSTR b, b2;
295     WCHAR str[] = {'m','a','r','s','h','a','l',' ','t','e','s','t','1',0};
296     DWORD len;
297
298     umcb.Flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
299     umcb.pReserve = NULL;
300     umcb.pStubMsg = &stubMsg;
301
302     b = SysAllocString(str);
303     len = SysStringLen(b);
304     ok(len == 13, "get %d\n", len);
305
306     /* BSTRs are DWORD aligned */
307     size = BSTR_UserSize(&umcb.Flags, 1, &b);
308     ok(size == 42, "size %ld\n", size);
309
310     size = BSTR_UserSize(&umcb.Flags, 0, &b);
311     ok(size == 38, "size %ld\n", size);
312
313     buffer = HeapAlloc(GetProcessHeap(), 0, size);
314     next = BSTR_UserMarshal(&umcb.Flags, buffer, &b);
315     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
316     check_bstr(buffer, b);
317
318     if (BSTR_UNMARSHAL_WORKS)
319     {
320         b2 = NULL;
321         next = BSTR_UserUnmarshal(&umcb.Flags, buffer, &b2);
322         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
323         ok(b2 != NULL, "BSTR didn't unmarshal\n");
324         ok(!memcmp(b, b2, (len + 1) * 2), "strings differ\n");
325         BSTR_UserFree(&umcb.Flags, &b2);
326     }
327
328     HeapFree(GetProcessHeap(), 0, buffer);
329     SysFreeString(b);
330
331     b = NULL;
332     size = BSTR_UserSize(&umcb.Flags, 0, &b);
333     ok(size == 12, "size %ld\n", size);
334
335     buffer = HeapAlloc(GetProcessHeap(), 0, size);
336     next = BSTR_UserMarshal(&umcb.Flags, buffer, &b);
337     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
338
339     check_bstr(buffer, b);
340     if (BSTR_UNMARSHAL_WORKS)
341     {
342         b2 = NULL;
343         next = BSTR_UserUnmarshal(&umcb.Flags, buffer, &b2);
344         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
345         ok(b2 == NULL, "NULL BSTR didn't unmarshal\n");
346         BSTR_UserFree(&umcb.Flags, &b2);
347     }
348     HeapFree(GetProcessHeap(), 0, buffer);
349
350     b = SysAllocStringByteLen("abc", 3);
351     *(((char*)b) + 3) = 'd';
352     len = SysStringLen(b);
353     ok(len == 1, "get %d\n", len);
354     len = SysStringByteLen(b);
355     ok(len == 3, "get %d\n", len);
356
357     size = BSTR_UserSize(&umcb.Flags, 0, &b);
358     ok(size == 16, "size %ld\n", size);
359
360     buffer = HeapAlloc(GetProcessHeap(), 0, size);
361     memset(buffer, 0xcc, size);
362     next = BSTR_UserMarshal(&umcb.Flags, buffer, &b);
363     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
364     check_bstr(buffer, b);
365     ok(buffer[15] == 'd', "buffer[15] %02x\n", buffer[15]);
366
367     if (BSTR_UNMARSHAL_WORKS)
368     {
369         b2 = NULL;
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, "BSTR didn't unmarshal\n");
373         ok(!memcmp(b, b2, len), "strings differ\n");
374         BSTR_UserFree(&umcb.Flags, &b2);
375     }
376     HeapFree(GetProcessHeap(), 0, buffer);
377     SysFreeString(b);
378
379     b = SysAllocStringByteLen("", 0);
380     len = SysStringLen(b);
381     ok(len == 0, "get %d\n", len);
382     len = SysStringByteLen(b);
383     ok(len == 0, "get %d\n", len);
384
385     size = BSTR_UserSize(&umcb.Flags, 0, &b);
386     ok(size == 12, "size %ld\n", size);
387
388     buffer = HeapAlloc(GetProcessHeap(), 0, 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
393     if (BSTR_UNMARSHAL_WORKS)
394     {
395         b2 = NULL;
396         next = BSTR_UserUnmarshal(&umcb.Flags, buffer, &b2);
397         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
398         ok(b2 != NULL, "NULL LPSAFEARRAY didn't unmarshal\n");
399         len = SysStringByteLen(b2);
400         ok(len == 0, "byte len %d\n", len);
401         BSTR_UserFree(&umcb.Flags, &b2);
402     }
403     HeapFree(GetProcessHeap(), 0, buffer);
404     SysFreeString(b);
405 }
406
407 static void check_variant_header(DWORD *wirev, VARIANT *v, unsigned long size)
408 {
409     WORD *wp;
410     DWORD switch_is;
411
412     ok(*wirev == (size + 7) >> 3, "wv[0] %08x, expected %08lx\n", *wirev, (size + 7) >> 3);
413     wirev++;
414     ok(*wirev == 0, "wv[1] %08x\n", *wirev);
415     wirev++;
416     wp = (WORD*)wirev;
417     ok(*wp == V_VT(v), "vt %04x expected %04x\n", *wp, V_VT(v));
418     wp++;
419     ok(*wp == V_U2(v).wReserved1, "res1 %04x expected %04x\n", *wp, V_U2(v).wReserved1);
420     wp++;
421     ok(*wp == V_U2(v).wReserved2, "res2 %04x expected %04x\n", *wp, V_U2(v).wReserved2);
422     wp++;
423     ok(*wp == V_U2(v).wReserved3, "res3 %04x expected %04x\n", *wp, V_U2(v).wReserved3);
424     wp++;
425     wirev = (DWORD*)wp;
426     switch_is = V_VT(v);
427     if(switch_is & VT_ARRAY)
428         switch_is &= ~VT_TYPEMASK;
429     ok(*wirev == switch_is, "switch_is %08x expected %08x\n", *wirev, switch_is);
430 }
431
432 static void test_marshal_VARIANT(void)
433 {
434     unsigned long size;
435     VARIANT v, v2;
436     MIDL_STUB_MESSAGE stubMsg = { 0 };
437     USER_MARSHAL_CB umcb = { 0 };
438     unsigned char *buffer, *next;
439     ULONG ul;
440     short s;
441     double d;
442     DWORD *wirev;
443     BSTR b;
444     WCHAR str[] = {'m','a','r','s','h','a','l',' ','t','e','s','t',0};
445     SAFEARRAYBOUND sab;
446     LPSAFEARRAY lpsa;
447     DECIMAL dec, dec2;
448
449     umcb.Flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
450     umcb.pReserve = NULL;
451     umcb.pStubMsg = &stubMsg;
452
453     /*** I1 ***/
454     VariantInit(&v);
455     V_VT(&v) = VT_I1;
456     V_I1(&v) = 0x12;
457
458     /* Variants have an alignment of 8 */
459     size = VARIANT_UserSize(&umcb.Flags, 1, &v);
460     ok(size == 29, "size %ld\n", size);
461
462     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
463     ok(size == 21, "size %ld\n", size);
464
465     buffer = HeapAlloc(GetProcessHeap(), 0, size);
466     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
467     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
468     wirev = (DWORD*)buffer;
469     
470     check_variant_header(wirev, &v, size);
471     wirev += 5;
472     ok(*(char*)wirev == V_I1(&v), "wv[5] %08x\n", *wirev);
473     if (VARIANT_UNMARSHAL_WORKS)
474     {
475         VariantInit(&v2);
476         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
477         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
478         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
479         ok(V_I1(&v) == V_I1(&v2), "got i1 %x expect %x\n", V_I1(&v), V_I1(&v2));
480
481         VARIANT_UserFree(&umcb.Flags, &v2);
482     }
483     HeapFree(GetProcessHeap(), 0, buffer);
484
485     /*** I2 ***/
486     VariantInit(&v);
487     V_VT(&v) = VT_I2;
488     V_I2(&v) = 0x1234;
489
490     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
491     ok(size == 22, "size %ld\n", size);
492
493     buffer = HeapAlloc(GetProcessHeap(), 0, size);
494     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
495     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
496     wirev = (DWORD*)buffer;
497
498     check_variant_header(wirev, &v, size);
499     wirev += 5;
500     ok(*(short*)wirev == V_I2(&v), "wv[5] %08x\n", *wirev);
501     if (VARIANT_UNMARSHAL_WORKS)
502     {
503         VariantInit(&v2);
504         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
505         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
506         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
507         ok(V_I2(&v) == V_I2(&v2), "got i2 %x expect %x\n", V_I2(&v), V_I2(&v2));
508
509         VARIANT_UserFree(&umcb.Flags, &v2);
510     }
511     HeapFree(GetProcessHeap(), 0, buffer);
512
513     /*** I2 BYREF ***/
514     VariantInit(&v);
515     V_VT(&v) = VT_I2 | VT_BYREF;
516     s = 0x1234;
517     V_I2REF(&v) = &s;
518
519     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
520     ok(size == 26, "size %ld\n", size);
521
522     buffer = HeapAlloc(GetProcessHeap(), 0, size);
523     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
524     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
525     wirev = (DWORD*)buffer;
526
527     check_variant_header(wirev, &v, size);
528     wirev += 5;
529     ok(*wirev == 0x4, "wv[5] %08x\n", *wirev);
530     wirev++;
531     ok(*(short*)wirev == s, "wv[6] %08x\n", *wirev);
532     if (VARIANT_UNMARSHAL_WORKS)
533     {
534         VariantInit(&v2);
535         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
536         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
537         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
538         ok(*V_I2REF(&v) == *V_I2REF(&v2), "got i2 ref %x expect ui4 ref %x\n", *V_I2REF(&v), *V_I2REF(&v2));
539
540         VARIANT_UserFree(&umcb.Flags, &v2);
541     }
542     HeapFree(GetProcessHeap(), 0, buffer);
543
544     /*** I4 ***/
545     VariantInit(&v);
546     V_VT(&v) = VT_I4;
547     V_I4(&v) = 0x1234;
548
549     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
550     ok(size == 24, "size %ld\n", size);
551
552     buffer = HeapAlloc(GetProcessHeap(), 0, size);
553     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
554     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
555     wirev = (DWORD*)buffer;
556     
557     check_variant_header(wirev, &v, size);
558     wirev += 5;
559     ok(*wirev == V_I4(&v), "wv[5] %08x\n", *wirev);
560
561     if (VARIANT_UNMARSHAL_WORKS)
562     {
563         VariantInit(&v2);
564         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
565         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
566         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
567         ok(V_I4(&v) == V_I4(&v2), "got i4 %x expect %x\n", V_I4(&v), V_I4(&v2));
568
569         VARIANT_UserFree(&umcb.Flags, &v2);
570     }
571
572     HeapFree(GetProcessHeap(), 0, buffer);
573
574     /*** UI4 ***/
575     VariantInit(&v);
576     V_VT(&v) = VT_UI4;
577     V_UI4(&v) = 0x1234;
578
579     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
580     ok(size == 24, "size %ld\n", size);
581
582     buffer = HeapAlloc(GetProcessHeap(), 0, size);
583     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
584     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
585     wirev = (DWORD*)buffer;
586     
587     check_variant_header(wirev, &v, size);
588     wirev += 5;
589     ok(*wirev == 0x1234, "wv[5] %08x\n", *wirev);
590     if (VARIANT_UNMARSHAL_WORKS)
591     {
592         VariantInit(&v2);
593         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
594         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
595         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
596         ok(V_UI4(&v) == V_UI4(&v2), "got ui4 %x expect %x\n", V_UI4(&v), V_UI4(&v2));
597
598         VARIANT_UserFree(&umcb.Flags, &v2);
599     }
600
601     HeapFree(GetProcessHeap(), 0, buffer);
602
603     /*** UI4 BYREF ***/
604     VariantInit(&v);
605     V_VT(&v) = VT_UI4 | VT_BYREF;
606     ul = 0x1234;
607     V_UI4REF(&v) = &ul;
608
609     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
610     ok(size == 28, "size %ld\n", size);
611
612     buffer = HeapAlloc(GetProcessHeap(), 0, size);
613     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
614     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
615     wirev = (DWORD*)buffer;
616     
617     check_variant_header(wirev, &v, size);
618     wirev += 5;
619     ok(*wirev == 0x4, "wv[5] %08x\n", *wirev);
620     wirev++;
621     ok(*wirev == ul, "wv[6] %08x\n", *wirev);
622
623     if (VARIANT_UNMARSHAL_WORKS)
624     {
625         VariantInit(&v2);
626         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
627         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
628         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
629         ok(*V_UI4REF(&v) == *V_UI4REF(&v2), "got ui4 ref %x expect ui4 ref %x\n", *V_UI4REF(&v), *V_UI4REF(&v2));
630
631         VARIANT_UserFree(&umcb.Flags, &v2);
632     }
633     HeapFree(GetProcessHeap(), 0, buffer);
634
635     /*** R4 ***/
636     VariantInit(&v);
637     V_VT(&v) = VT_R4;
638     V_R8(&v) = 3.1415;
639
640     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
641     ok(size == 24, "size %ld\n", size);
642
643     buffer = HeapAlloc(GetProcessHeap(), 0, size);
644     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
645     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
646     wirev = (DWORD*)buffer;
647      
648     check_variant_header(wirev, &v, size);
649     wirev += 5;
650     ok(*(float*)wirev == V_R4(&v), "wv[5] %08x\n", *wirev);
651     if (VARIANT_UNMARSHAL_WORKS)
652     {
653         VariantInit(&v2);
654         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
655         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
656         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
657         ok(V_R4(&v) == V_R4(&v2), "got r4 %f expect %f\n", V_R4(&v), V_R4(&v2));
658
659         VARIANT_UserFree(&umcb.Flags, &v2);
660     }
661     HeapFree(GetProcessHeap(), 0, buffer);
662
663     /*** R8 ***/
664     VariantInit(&v);
665     V_VT(&v) = VT_R8;
666     V_R8(&v) = 3.1415;
667
668     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
669     ok(size == 32, "size %ld\n", size);
670
671     buffer = HeapAlloc(GetProcessHeap(), 0, size);
672     memset(buffer, 0xcc, size);
673     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
674     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
675     wirev = (DWORD*)buffer;
676     
677     check_variant_header(wirev, &v, size);
678     wirev += 5;
679     ok(*wirev == 0xcccccccc, "wv[5] %08x\n", *wirev); /* pad */
680     wirev++;
681     ok(*(double*)wirev == V_R8(&v), "wv[6] %08x, wv[7] %08x\n", *wirev, *(wirev+1));
682     if (VARIANT_UNMARSHAL_WORKS)
683     {
684         VariantInit(&v2);
685         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
686         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
687         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
688         ok(V_R8(&v) == V_R8(&v2), "got r8 %f expect %f\n", V_R8(&v), V_R8(&v2));
689
690         VARIANT_UserFree(&umcb.Flags, &v2);
691     }
692     HeapFree(GetProcessHeap(), 0, buffer);
693
694     /*** R8 BYREF ***/
695     VariantInit(&v);
696     V_VT(&v) = VT_R8 | VT_BYREF;
697     d = 3.1415;
698     V_R8REF(&v) = &d;
699
700     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
701     ok(size == 32, "size %ld\n", size);
702
703     buffer = HeapAlloc(GetProcessHeap(), 0, size);
704     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
705     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
706     wirev = (DWORD*)buffer;
707     
708     check_variant_header(wirev, &v, size);
709     wirev += 5;
710     ok(*wirev == 8, "wv[5] %08x\n", *wirev);
711     wirev++;
712     ok(*(double*)wirev == d, "wv[6] %08x wv[7] %08x\n", *wirev, *(wirev+1));
713     if (VARIANT_UNMARSHAL_WORKS)
714     {
715         VariantInit(&v2);
716         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
717         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
718         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
719         ok(*V_R8REF(&v) == *V_R8REF(&v2), "got r8 ref %f expect %f\n", *V_R8REF(&v), *V_R8REF(&v2));
720
721         VARIANT_UserFree(&umcb.Flags, &v2);
722     }
723     HeapFree(GetProcessHeap(), 0, buffer);
724
725     /*** VARIANT_BOOL ***/
726     VariantInit(&v);
727     V_VT(&v) = VT_BOOL;
728     V_BOOL(&v) = 0x1234;
729
730     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
731     ok(size == 22, "size %ld\n", size);
732
733     buffer = HeapAlloc(GetProcessHeap(), 0, size);
734     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
735     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
736     wirev = (DWORD*)buffer;
737     
738     check_variant_header(wirev, &v, size);
739     wirev += 5;
740     ok(*(short*)wirev == V_BOOL(&v), "wv[5] %04x\n", *(WORD*)wirev);
741     if (VARIANT_UNMARSHAL_WORKS)
742     {
743         VariantInit(&v2);
744         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
745         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
746         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
747         ok(V_BOOL(&v) == V_BOOL(&v2), "got bool %x expect %x\n", V_BOOL(&v), V_BOOL(&v2));
748
749         VARIANT_UserFree(&umcb.Flags, &v2);
750     }
751     HeapFree(GetProcessHeap(), 0, buffer);
752
753     /*** DECIMAL ***/
754     VarDecFromI4(0x12345678, &dec);
755     VariantInit(&v);
756     V_DECIMAL(&v) = dec;
757     V_VT(&v) = VT_DECIMAL;
758
759     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
760     ok(size == 40, "size %ld\n", size);
761
762     buffer = HeapAlloc(GetProcessHeap(), 0, size);
763     memset(buffer, 0xcc, size);
764     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
765     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
766     wirev = (DWORD*)buffer;
767
768     check_variant_header(wirev, &v, size);
769     wirev += 5;
770     ok(*wirev == 0xcccccccc, "wirev[5] %08x\n", *wirev); /* pad */
771     wirev++;
772     dec2 = dec;
773     dec2.wReserved = VT_DECIMAL;
774     ok(!memcmp(wirev, &dec2, sizeof(dec2)), "wirev[6] %08x wirev[7] %08x wirev[8] %08x wirev[9] %08x\n",
775        *wirev, *(wirev + 1), *(wirev + 2), *(wirev + 3));
776     if (VARIANT_UNMARSHAL_WORKS)
777     {
778         VariantInit(&v2);
779         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
780         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
781         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
782         ok(!memcmp(&V_DECIMAL(&v), & V_DECIMAL(&v2), sizeof(DECIMAL)), "decimals differ\n");
783
784         VARIANT_UserFree(&umcb.Flags, &v2);
785     }
786     HeapFree(GetProcessHeap(), 0, buffer);
787
788     /*** DECIMAL BYREF ***/
789     VariantInit(&v);
790     V_VT(&v) = VT_DECIMAL | VT_BYREF;
791     V_DECIMALREF(&v) = &dec;
792
793     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
794     ok(size == 40, "size %ld\n", size);
795
796     buffer = HeapAlloc(GetProcessHeap(), 0, size);
797     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
798     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
799     wirev = (DWORD*)buffer;
800     
801     check_variant_header(wirev, &v, size);
802     wirev += 5;
803     ok(*wirev == 16, "wv[5] %08x\n", *wirev);
804     wirev++;
805     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));
806     if (VARIANT_UNMARSHAL_WORKS)
807     {
808         VariantInit(&v2);
809         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
810         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
811         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
812         ok(!memcmp(V_DECIMALREF(&v), V_DECIMALREF(&v2), sizeof(DECIMAL)), "decimals differ\n");
813
814         VARIANT_UserFree(&umcb.Flags, &v2);
815     }
816     HeapFree(GetProcessHeap(), 0, buffer);
817
818     /*** EMPTY ***/
819     VariantInit(&v);
820     V_VT(&v) = VT_EMPTY;
821
822     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
823     ok(size == 20, "size %ld\n", size);
824
825     buffer = HeapAlloc(GetProcessHeap(), 0, size);
826     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
827     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
828     wirev = (DWORD*)buffer;
829
830     check_variant_header(wirev, &v, size);
831     if (VARIANT_UNMARSHAL_WORKS)
832     {
833         VariantInit(&v2);
834         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
835         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
836         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
837
838         VARIANT_UserFree(&umcb.Flags, &v2);
839     }
840     HeapFree(GetProcessHeap(), 0, buffer);
841
842     /*** NULL ***/
843     VariantInit(&v);
844     V_VT(&v) = VT_NULL;
845
846     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
847     ok(size == 20, "size %ld\n", size);
848
849     buffer = HeapAlloc(GetProcessHeap(), 0, size);
850     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
851     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
852     wirev = (DWORD*)buffer;
853
854     check_variant_header(wirev, &v, size);
855     if (VARIANT_UNMARSHAL_WORKS)
856     {
857         VariantInit(&v2);
858         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
859         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
860         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
861
862         VARIANT_UserFree(&umcb.Flags, &v2);
863     }
864     HeapFree(GetProcessHeap(), 0, buffer);
865
866     /*** BSTR ***/
867     b = SysAllocString(str);
868     VariantInit(&v);
869     V_VT(&v) = VT_BSTR;
870     V_BSTR(&v) = b;
871
872     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
873     ok(size == 60, "size %ld\n", size);
874     buffer = HeapAlloc(GetProcessHeap(), 0, size);
875     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
876     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
877     wirev = (DWORD*)buffer;
878     
879     check_variant_header(wirev, &v, size);
880     wirev += 5;
881     ok(*wirev, "wv[5] %08x\n", *wirev); /* win2k: this is b. winxp: this is (char*)b + 1 */
882     wirev++;
883     check_bstr(wirev, V_BSTR(&v));
884     if (VARIANT_UNMARSHAL_WORKS)
885     {
886         VariantInit(&v2);
887         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
888         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
889         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
890         ok(SysStringByteLen(V_BSTR(&v)) == SysStringByteLen(V_BSTR(&v2)), "bstr string lens differ\n");
891         ok(!memcmp(V_BSTR(&v), V_BSTR(&v2), SysStringByteLen(V_BSTR(&v))), "bstrs differ\n");
892
893         VARIANT_UserFree(&umcb.Flags, &v2);
894     }
895     HeapFree(GetProcessHeap(), 0, buffer);
896
897     /*** BSTR BYREF ***/
898     VariantInit(&v);
899     V_VT(&v) = VT_BSTR | VT_BYREF;
900     V_BSTRREF(&v) = &b;
901
902     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
903     ok(size == 64, "size %ld\n", size);
904     buffer = HeapAlloc(GetProcessHeap(), 0, size);
905     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
906     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
907     wirev = (DWORD*)buffer;
908     
909     check_variant_header(wirev, &v, size);
910     wirev += 5;
911     ok(*wirev == 0x4, "wv[5] %08x\n", *wirev);
912     wirev++;
913     ok(*wirev, "wv[6] %08x\n", *wirev); /* win2k: this is b. winxp: this is (char*)b + 1 */
914     wirev++;
915     check_bstr(wirev, b);
916     if (VARIANT_UNMARSHAL_WORKS)
917     {
918         VariantInit(&v2);
919         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
920         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
921         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
922         ok(SysStringByteLen(*V_BSTRREF(&v)) == SysStringByteLen(*V_BSTRREF(&v2)), "bstr string lens differ\n");
923         ok(!memcmp(*V_BSTRREF(&v), *V_BSTRREF(&v2), SysStringByteLen(*V_BSTRREF(&v))), "bstrs differ\n");
924
925         VARIANT_UserFree(&umcb.Flags, &v2);
926     }
927     HeapFree(GetProcessHeap(), 0, buffer);
928     SysFreeString(b);
929
930     /*** ARRAY ***/
931     sab.lLbound = 5;
932     sab.cElements = 10;
933
934     lpsa = SafeArrayCreate(VT_R8, 1, &sab);
935     *(DWORD *)lpsa->pvData = 0xcafebabe;
936     *((DWORD *)lpsa->pvData + 1) = 0xdeadbeef;
937     lpsa->cLocks = 7;
938
939     VariantInit(&v);
940     V_VT(&v) = VT_UI4 | VT_ARRAY;
941     V_ARRAY(&v) = lpsa;
942
943     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
944     ok(size == 152, "size %ld\n", size);
945     buffer = HeapAlloc(GetProcessHeap(), 0, size);
946     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
947     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
948     wirev = (DWORD*)buffer;
949     
950     check_variant_header(wirev, &v, size);
951     wirev += 5;
952     ok(*wirev, "wv[5] %08x\n", *wirev); /* win2k: this is lpsa. winxp: this is (char*)lpsa + 1 */
953     wirev++;
954     check_safearray(wirev, lpsa);
955     if (VARIANT_UNMARSHAL_WORKS)
956     {
957         LONG bound, bound2;
958         VARTYPE vt, vt2;
959         VariantInit(&v2);
960         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
961         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
962         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
963         ok(SafeArrayGetDim(V_ARRAY(&v)) == SafeArrayGetDim(V_ARRAY(&v)), "array dims differ\n");  
964         SafeArrayGetLBound(V_ARRAY(&v), 1, &bound);
965         SafeArrayGetLBound(V_ARRAY(&v2), 1, &bound2);
966         ok(bound == bound2, "array lbounds differ\n");
967         SafeArrayGetUBound(V_ARRAY(&v), 1, &bound);
968         SafeArrayGetUBound(V_ARRAY(&v2), 1, &bound2);
969         ok(bound == bound2, "array ubounds differ\n");
970         SafeArrayGetVartype(V_ARRAY(&v), &vt);
971         SafeArrayGetVartype(V_ARRAY(&v2), &vt2);
972         ok(vt == vt2, "array vts differ %x %x\n", vt, vt2);
973         VARIANT_UserFree(&umcb.Flags, &v2);
974     }
975     HeapFree(GetProcessHeap(), 0, buffer);
976
977     /*** ARRAY BYREF ***/
978     VariantInit(&v);
979     V_VT(&v) = VT_UI4 | VT_ARRAY | VT_BYREF;
980     V_ARRAYREF(&v) = &lpsa;
981
982     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
983     ok(size == 152, "size %ld\n", size);
984     buffer = HeapAlloc(GetProcessHeap(), 0, size);
985     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
986     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
987     wirev = (DWORD*)buffer;
988     
989     check_variant_header(wirev, &v, size);
990     wirev += 5;
991     ok(*wirev == 4, "wv[5] %08x\n", *wirev);
992     wirev++;
993     ok(*wirev, "wv[6] %08x\n", *wirev); /* win2k: this is lpsa. winxp: this is (char*)lpsa + 1 */
994     wirev++;
995     check_safearray(wirev, lpsa);
996     if (VARIANT_UNMARSHAL_WORKS)
997     {
998         LONG bound, bound2;
999         VARTYPE vt, vt2;
1000         VariantInit(&v2);
1001         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1002         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
1003         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1004         ok(SafeArrayGetDim(*V_ARRAYREF(&v)) == SafeArrayGetDim(*V_ARRAYREF(&v)), "array dims differ\n");  
1005         SafeArrayGetLBound(*V_ARRAYREF(&v), 1, &bound);
1006         SafeArrayGetLBound(*V_ARRAYREF(&v2), 1, &bound2);
1007         ok(bound == bound2, "array lbounds differ\n");
1008         SafeArrayGetUBound(*V_ARRAYREF(&v), 1, &bound);
1009         SafeArrayGetUBound(*V_ARRAYREF(&v2), 1, &bound2);
1010         ok(bound == bound2, "array ubounds differ\n");
1011         SafeArrayGetVartype(*V_ARRAYREF(&v), &vt);
1012         SafeArrayGetVartype(*V_ARRAYREF(&v2), &vt2);
1013         ok(vt == vt2, "array vts differ %x %x\n", vt, vt2);
1014         VARIANT_UserFree(&umcb.Flags, &v2);
1015     }
1016     HeapFree(GetProcessHeap(), 0, buffer);
1017     SafeArrayDestroy(lpsa);
1018
1019     /*** VARIANT BYREF ***/
1020     VariantInit(&v);
1021     VariantInit(&v2);
1022     V_VT(&v2) = VT_R8;
1023     V_R8(&v2) = 3.1415;
1024     V_VT(&v) = VT_VARIANT | VT_BYREF;
1025     V_VARIANTREF(&v) = &v2;
1026
1027     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
1028     ok(size == 64, "size %ld\n", size);
1029     buffer = HeapAlloc(GetProcessHeap(), 0, size);
1030     memset(buffer, 0xcc, size);
1031     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1032     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
1033     wirev = (DWORD*)buffer;
1034     check_variant_header(wirev, &v, size);
1035     wirev += 5;
1036
1037     ok(*wirev == 16, "wv[5] %08x\n", *wirev);
1038     wirev++;
1039     ok(*wirev == ('U' | 's' << 8 | 'e' << 16 | 'r' << 24), "wv[6] %08x\n", *wirev); /* 'User' */
1040     wirev++;
1041     ok(*wirev == 0xcccccccc, "wv[7] %08x\n", *wirev); /* pad */
1042     wirev++;
1043     check_variant_header(wirev, &v2, size - 32);
1044     wirev += 5;
1045     ok(*wirev == 0xcccccccc, "wv[13] %08x\n", *wirev); /* pad for VT_R8 */
1046     wirev++;
1047     ok(*(double*)wirev == V_R8(&v2), "wv[6] %08x wv[7] %08x\n", *wirev, *(wirev+1));
1048     if (VARIANT_UNMARSHAL_WORKS)
1049     {
1050         VARIANT v3;
1051         VariantInit(&v3);
1052         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v3);
1053         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
1054         ok(V_VT(&v) == V_VT(&v3), "got vt %d expect %d\n", V_VT(&v), V_VT(&v3));
1055         ok(V_VT(V_VARIANTREF(&v)) == V_VT(V_VARIANTREF(&v3)), "vts differ %x %x\n",
1056            V_VT(V_VARIANTREF(&v)), V_VT(V_VARIANTREF(&v3))); 
1057         ok(V_R8(V_VARIANTREF(&v)) == V_R8(V_VARIANTREF(&v3)), "r8s differ\n"); 
1058         VARIANT_UserFree(&umcb.Flags, &v3);
1059     }
1060     HeapFree(GetProcessHeap(), 0, buffer);
1061 }
1062
1063
1064 START_TEST(usrmarshal)
1065 {
1066     CoInitialize(NULL);
1067
1068     test_marshal_LPSAFEARRAY();
1069     test_marshal_BSTR();
1070     test_marshal_VARIANT();
1071
1072     CoUninitialize();
1073 }