hlink: Site data should only be set if the hlink has an HlinkSite.
[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 #define COBJMACROS
22
23 #include <stdarg.h>
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "objbase.h"
28 #include "propidl.h" /* for LPSAFEARRAY_User* routines */
29
30 #include "wine/test.h"
31
32 #if (__STDC__ && !defined(_FORCENAMELESSUNION)) || defined(NONAMELESSUNION)
33 # define V_U2(A)  ((A)->n1.n2)
34 #else
35 # define V_U2(A)  (*(A))
36 #endif
37
38 #define LPSAFEARRAY_UNMARSHAL_WORKS 1
39 #define BSTR_UNMARSHAL_WORKS 1
40 #define VARIANT_UNMARSHAL_WORKS 1
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         if(psa->fFeatures & FADF_VARIANT) return SF_VARIANT;
51
52         switch(psa->cbElements)
53         {
54         case 1: vt = VT_I1; break;
55         case 2: vt = VT_I2; break;
56         case 4: vt = VT_I4; break;
57         case 8: vt = VT_I8; break;
58         default: return 0;
59         }
60     }
61
62     if (psa->fFeatures & FADF_HAVEIID)
63         return SF_HAVEIID;
64
65     switch (vt)
66     {
67     case VT_I1:
68     case VT_UI1:      return SF_I1;
69     case VT_BOOL:
70     case VT_I2:
71     case VT_UI2:      return SF_I2;
72     case VT_INT:
73     case VT_UINT:
74     case VT_I4:
75     case VT_UI4:
76     case VT_R4:       return SF_I4;
77     case VT_DATE:
78     case VT_CY:
79     case VT_R8:
80     case VT_I8:
81     case VT_UI8:      return SF_I8;
82     case VT_INT_PTR:
83     case VT_UINT_PTR: return (sizeof(UINT_PTR) == 4 ? SF_I4 : SF_I8);
84     case VT_BSTR:     return SF_BSTR;
85     case VT_DISPATCH: return SF_DISPATCH;
86     case VT_VARIANT:  return SF_VARIANT;
87     case VT_UNKNOWN:  return SF_UNKNOWN;
88     /* Note: Return a non-zero size to indicate vt is valid. The actual size
89      * of a UDT is taken from the result of IRecordInfo_GetSize().
90      */
91     case VT_RECORD:   return SF_RECORD;
92     default:          return SF_ERROR;
93     }
94 }
95
96 static ULONG get_cell_count(const SAFEARRAY *psa)
97 {
98     const SAFEARRAYBOUND* psab = psa->rgsabound;
99     USHORT cCount = psa->cDims;
100     ULONG ulNumCells = 1;
101
102     while (cCount--)
103     {
104          if (!psab->cElements)
105             return 0;
106         ulNumCells *= psab->cElements;
107         psab++;
108     }
109     return ulNumCells;
110 }
111
112 static DWORD elem_wire_size(LPSAFEARRAY lpsa, SF_TYPE sftype)
113 {
114     if (sftype == SF_BSTR)
115         return sizeof(DWORD);
116     else
117         return lpsa->cbElements;
118 }
119
120 static void check_safearray(void *buffer, LPSAFEARRAY lpsa)
121 {
122     unsigned char *wiresa = buffer;
123     const SAFEARRAYBOUND *bounds;
124     VARTYPE vt;
125     SF_TYPE sftype;
126     ULONG cell_count;
127     int i;
128
129     if(!lpsa)
130     {
131         ok(*(DWORD *)wiresa == 0, "wiresa + 0x0 should be NULL instead of 0x%08x\n", *(DWORD *)wiresa);
132         return;
133     }
134
135     if(FAILED(SafeArrayGetVartype(lpsa, &vt)))
136         vt = 0;
137
138     sftype = get_union_type(lpsa);
139     cell_count = get_cell_count(lpsa);
140
141     ok(*(DWORD *)wiresa, "wiresa + 0x0 should be non-NULL instead of 0x%08x\n", *(DWORD *)wiresa); /* win2k: this is lpsa. winxp: this is 0x00000001 */
142     wiresa += sizeof(DWORD);
143     ok(*(DWORD *)wiresa == lpsa->cDims, "wiresa + 0x4 should be lpsa->cDims instead of 0x%08x\n", *(DWORD *)wiresa);
144     wiresa += sizeof(DWORD);
145     ok(*(WORD *)wiresa == lpsa->cDims, "wiresa + 0x8 should be lpsa->cDims instead of 0x%04x\n", *(WORD *)wiresa);
146     wiresa += sizeof(WORD);
147     ok(*(WORD *)wiresa == lpsa->fFeatures, "wiresa + 0xa should be lpsa->fFeatures instead of 0x%08x\n", *(WORD *)wiresa);
148     wiresa += sizeof(WORD);
149     ok(*(DWORD *)wiresa == elem_wire_size(lpsa, sftype), "wiresa + 0xc should be 0x%08x instead of 0x%08x\n", elem_wire_size(lpsa, sftype), *(DWORD *)wiresa);
150     wiresa += sizeof(DWORD);
151     ok(*(WORD *)wiresa == lpsa->cLocks, "wiresa + 0x10 should be lpsa->cLocks instead of 0x%04x\n", *(WORD *)wiresa);
152     wiresa += sizeof(WORD);
153     ok(*(WORD *)wiresa == vt, "wiresa + 0x12 should be %04x instead of 0x%04x\n", vt, *(WORD *)wiresa);
154     wiresa += sizeof(WORD);
155     ok(*(DWORD *)wiresa == sftype, "wiresa + 0x14 should be %08x instead of 0x%08x\n", (DWORD)sftype, *(DWORD *)wiresa);
156     wiresa += sizeof(DWORD);
157     ok(*(DWORD *)wiresa == cell_count, "wiresa + 0x18 should be %u instead of %u\n", cell_count, *(DWORD *)wiresa);
158     wiresa += sizeof(DWORD);
159     ok(*(DWORD *)wiresa, "wiresa + 0x1c should be non-zero instead of 0x%08x\n", *(DWORD *)wiresa);
160     wiresa += sizeof(DWORD);
161     if(sftype == SF_HAVEIID)
162     {
163         GUID guid;
164         SafeArrayGetIID(lpsa, &guid);
165         ok(IsEqualGUID(&guid, wiresa), "guid mismatch\n");
166         wiresa += sizeof(GUID);
167     }
168
169     /* bounds are marshaled in natural dimensions order */
170     bounds = (SAFEARRAYBOUND*)wiresa;
171     for(i=0; i<lpsa->cDims; i++)
172     {
173         ok(memcmp(bounds, &lpsa->rgsabound[lpsa->cDims-i-1], sizeof(SAFEARRAYBOUND)) == 0,
174            "bounds mismatch for dimension %d, got (%d,%d), expected (%d,%d)\n", i,
175             bounds->lLbound, bounds->cElements, lpsa->rgsabound[lpsa->cDims-i-1].lLbound,
176             lpsa->rgsabound[lpsa->cDims-i-1].cElements);
177         bounds++;
178     }
179
180     wiresa += sizeof(lpsa->rgsabound[0]) * lpsa->cDims;
181
182     ok(*(DWORD *)wiresa == cell_count, "wiresa + 0x28 should be %u instead of %u\n", cell_count, *(DWORD*)wiresa);
183     wiresa += sizeof(DWORD);
184     /* elements are now pointed to by wiresa */
185 }
186
187 static void * WINAPI user_allocate(SIZE_T size)
188 {
189     return CoTaskMemAlloc(size);
190 }
191
192 static void WINAPI user_free(void *p)
193 {
194     CoTaskMemFree(p);
195 }
196
197 static void init_user_marshal_cb(USER_MARSHAL_CB *umcb,
198                                  PMIDL_STUB_MESSAGE stub_msg,
199                                  PRPC_MESSAGE rpc_msg, unsigned char *buffer,
200                                  unsigned int size, MSHCTX context)
201 {
202     memset(rpc_msg, 0, sizeof(*rpc_msg));
203     rpc_msg->Buffer = buffer;
204     rpc_msg->BufferLength = size;
205
206     memset(stub_msg, 0, sizeof(*stub_msg));
207     stub_msg->RpcMsg = rpc_msg;
208     stub_msg->Buffer = buffer;
209     stub_msg->pfnAllocate = user_allocate;
210     stub_msg->pfnFree = user_free;
211
212     memset(umcb, 0, sizeof(*umcb));
213     umcb->Flags = MAKELONG(context, NDR_LOCAL_DATA_REPRESENTATION);
214     umcb->pStubMsg = stub_msg;
215     umcb->Signature = USER_MARSHAL_CB_SIGNATURE;
216     umcb->CBType = buffer ? USER_MARSHAL_CB_UNMARSHALL : USER_MARSHAL_CB_BUFFER_SIZE;
217 }
218
219 static void test_marshal_LPSAFEARRAY(void)
220 {
221     unsigned char *buffer, *next;
222     ULONG size, expected;
223     LPSAFEARRAY lpsa;
224     LPSAFEARRAY lpsa2 = NULL;
225     SAFEARRAYBOUND sab[2];
226     RPC_MESSAGE rpc_msg;
227     MIDL_STUB_MESSAGE stub_msg;
228     USER_MARSHAL_CB umcb;
229     HRESULT hr;
230     VARTYPE vt;
231     OLECHAR *values[10];
232     int expected_bstr_size;
233     int i;
234     LONG indices[1];
235
236     sab[0].lLbound = 5;
237     sab[0].cElements = 10;
238
239     lpsa = SafeArrayCreate(VT_I2, 1, sab);
240     *(DWORD *)lpsa->pvData = 0xcafebabe;
241
242     lpsa->cLocks = 7;
243     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
244     size = LPSAFEARRAY_UserSize(&umcb.Flags, 1, &lpsa);
245     expected = (44 + 1 + sizeof(ULONG) - 1) & ~(sizeof(ULONG) - 1);
246     expected += sab[0].cElements * sizeof(USHORT);
247     ok(size == expected || size == expected + 12, /* win64 */
248        "size should be %u bytes, not %u\n", expected, size);
249     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
250     size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
251     expected = 44 + sab[0].cElements * sizeof(USHORT);
252     ok(size == expected || size == expected + 12, /* win64 */
253        "size should be %u bytes, not %u\n", expected, size);
254     buffer = HeapAlloc(GetProcessHeap(), 0, size);
255     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
256     next = LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
257     ok(next - buffer == expected, "Marshaled %u bytes, expected %u\n", (ULONG) (next - buffer), expected);
258
259     check_safearray(buffer, lpsa);
260
261     if (LPSAFEARRAY_UNMARSHAL_WORKS)
262     {
263         VARTYPE vt, vt2;
264         init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
265         LPSAFEARRAY_UserUnmarshal(&umcb.Flags, buffer, &lpsa2);
266         ok(lpsa2 != NULL, "LPSAFEARRAY didn't unmarshal\n");
267         SafeArrayGetVartype(lpsa, &vt);
268         SafeArrayGetVartype(lpsa2, &vt2);
269         ok(vt == vt2, "vts differ %x %x\n", vt, vt2);
270         init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
271         LPSAFEARRAY_UserFree(&umcb.Flags, &lpsa2);
272     }
273     HeapFree(GetProcessHeap(), 0, buffer);
274     lpsa->cLocks = 0;
275     SafeArrayDestroy(lpsa);
276
277     /* use two dimensions */
278     sab[0].lLbound = 5;
279     sab[0].cElements = 10;
280     sab[1].lLbound = 1;
281     sab[1].cElements = 2;
282
283     lpsa = SafeArrayCreate(VT_I2, 2, sab);
284     *(DWORD *)lpsa->pvData = 0xcafebabe;
285
286     lpsa->cLocks = 7;
287     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
288     size = LPSAFEARRAY_UserSize(&umcb.Flags, 1, &lpsa);
289     expected = (44 + 1 + +sizeof(SAFEARRAYBOUND) + sizeof(ULONG) - 1) & ~(sizeof(ULONG) - 1);
290     expected += max(sab[0].cElements, sab[1].cElements) * lpsa->cDims * sizeof(USHORT);
291     ok(size == expected || size == expected + 12, /* win64 */
292        "size should be %u bytes, not %u\n", expected, size);
293     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
294     size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
295     expected = 52 + max(sab[0].cElements, sab[1].cElements) * lpsa->cDims * sizeof(USHORT);
296     ok(size == expected || size == expected + 12, /* win64 */
297        "size should be %u bytes, not %u\n", expected, size);
298     buffer = HeapAlloc(GetProcessHeap(), 0, size);
299     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
300     next = LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
301     ok(next - buffer == expected, "Marshaled %u bytes, expected %u\n", (ULONG) (next - buffer), expected);
302
303     check_safearray(buffer, lpsa);
304
305     if (LPSAFEARRAY_UNMARSHAL_WORKS)
306     {
307         VARTYPE vt, vt2;
308         init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
309         LPSAFEARRAY_UserUnmarshal(&umcb.Flags, buffer, &lpsa2);
310         ok(lpsa2 != NULL, "LPSAFEARRAY didn't unmarshal\n");
311         SafeArrayGetVartype(lpsa, &vt);
312         SafeArrayGetVartype(lpsa2, &vt2);
313         ok(vt == vt2, "vts differ %x %x\n", vt, vt2);
314         init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
315         LPSAFEARRAY_UserFree(&umcb.Flags, &lpsa2);
316     }
317     HeapFree(GetProcessHeap(), 0, buffer);
318     lpsa->cLocks = 0;
319     SafeArrayDestroy(lpsa);
320
321     /* test NULL safe array */
322     lpsa = NULL;
323
324     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
325     size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
326     expected = 4;
327     ok(size == expected, "size should be 4 bytes, not %d\n", size);
328     buffer = HeapAlloc(GetProcessHeap(), 0, size);
329     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
330     next = LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
331     ok(next - buffer == expected, "Marshaled %u bytes, expected %u\n", (ULONG) (next - buffer), expected);
332     check_safearray(buffer, lpsa);
333
334     if (LPSAFEARRAY_UNMARSHAL_WORKS)
335     {
336         init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
337         LPSAFEARRAY_UserUnmarshal(&umcb.Flags, buffer, &lpsa2);
338         ok(lpsa2 == NULL, "NULL LPSAFEARRAY didn't unmarshal\n");
339         init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
340         LPSAFEARRAY_UserFree(&umcb.Flags, &lpsa2);
341     }
342     HeapFree(GetProcessHeap(), 0, buffer);
343
344     sab[0].lLbound = 5;
345     sab[0].cElements = 10;
346
347     lpsa = SafeArrayCreate(VT_R8, 1, sab);
348     *(double *)lpsa->pvData = 3.1415;
349
350     lpsa->cLocks = 7;
351     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
352     size = LPSAFEARRAY_UserSize(&umcb.Flags, 1, &lpsa);
353     expected = (44 + 1 + (sizeof(double) - 1)) & ~(sizeof(double) - 1);
354     expected += sab[0].cElements * sizeof(double);
355     ok(size == expected || size == expected + 16, /* win64 */
356        "size should be %u bytes, not %u\n", expected, size);
357     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
358     expected = (44 + (sizeof(double) - 1)) & ~(sizeof(double) - 1);
359     expected += sab[0].cElements * sizeof(double);
360     size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
361     ok(size == expected || size == expected + 8, /* win64 */
362        "size should be %u bytes, not %u\n", expected, size);
363     buffer = HeapAlloc(GetProcessHeap(), 0, size);
364     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
365     next = LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
366     ok(next - buffer == expected || broken(next - buffer + sizeof(DWORD) == expected),
367             "Marshaled %u bytes, expected %u\n", (ULONG) (next - buffer), expected);
368
369     check_safearray(buffer, lpsa);
370
371     HeapFree(GetProcessHeap(), 0, buffer);
372     lpsa->cLocks = 0;
373     SafeArrayDestroy(lpsa);
374
375     /* VARTYPE-less arrays can be marshaled if cbElements is 1,2,4 or 8 as type SF_In */
376     hr = SafeArrayAllocDescriptor(1, &lpsa);
377     ok(hr == S_OK, "saad failed %08x\n", hr);
378     lpsa->cbElements = 8;
379     lpsa->rgsabound[0].lLbound = 2;
380     lpsa->rgsabound[0].cElements = 48;
381     hr = SafeArrayAllocData(lpsa);
382     ok(hr == S_OK, "saad failed %08x\n", hr);
383
384     hr = SafeArrayGetVartype(lpsa, &vt);
385     ok(hr == E_INVALIDARG, "ret %08x\n", hr);
386
387     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
388     size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
389     expected = (44 + lpsa->cbElements - 1) & ~(lpsa->cbElements - 1);
390     expected += lpsa->cbElements * lpsa->rgsabound[0].cElements;
391     ok(size == expected || size == expected + 8,  /* win64 */
392        "size should be %u bytes, not %u\n", expected, size);
393     buffer = HeapAlloc(GetProcessHeap(), 0, size);
394     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
395     next = LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
396     ok(next - buffer == expected || broken(next - buffer + sizeof(DWORD) == expected),
397             "Marshaled %u bytes, expected %u\n", (ULONG) (next - buffer), expected);
398     check_safearray(buffer, lpsa);
399     HeapFree(GetProcessHeap(), 0, buffer);
400     SafeArrayDestroyData(lpsa);
401     SafeArrayDestroyDescriptor(lpsa);
402
403     /* Test an array of VT_BSTR */
404     sab[0].lLbound = 3;
405     sab[0].cElements = sizeof(values) / sizeof(values[0]);
406
407     lpsa = SafeArrayCreate(VT_BSTR, 1, sab);
408     expected_bstr_size = 0;
409     for (i = 0; i < sab[0].cElements; i++)
410     {
411         int j;
412         WCHAR buf[128];
413         for (j = 0; j <= i; j++)
414             buf[j] = 'a' + j;
415         buf[j] = 0;
416         indices[0] = i + sab[0].lLbound;
417         values[i] = SysAllocString(buf);
418         hr = SafeArrayPutElement(lpsa, indices, values[i]);
419         ok(hr == S_OK, "Failed to put bstr element hr 0x%x\n", hr);
420         expected_bstr_size += (j * sizeof(WCHAR)) + (3 * sizeof(DWORD));
421         if (i % 2 == 0) /* Account for DWORD padding.  Works so long as cElements is even */
422             expected_bstr_size += sizeof(WCHAR);
423     }
424
425     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
426     size = LPSAFEARRAY_UserSize(&umcb.Flags, 1, &lpsa);
427     expected = 44 + (sab[0].cElements * sizeof(DWORD)) + expected_bstr_size;
428     todo_wine
429     ok(size == expected + sizeof(DWORD) || size  == (expected + sizeof(DWORD) + 12 /* win64 */),
430             "size should be %u bytes, not %u\n", expected + (ULONG) sizeof(DWORD), size);
431     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
432     size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
433     todo_wine
434     ok(size == expected || size  == (expected + 12 /* win64 */),
435         "size should be %u bytes, not %u\n", expected, size);
436     buffer = HeapAlloc(GetProcessHeap(), 0, size);
437     memset(buffer, 0xcc, size);
438     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
439     next = LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
440     todo_wine
441     ok(next - buffer == expected, "Marshaled %u bytes, expected %u\n", (ULONG) (next - buffer), expected);
442
443     check_safearray(buffer, lpsa);
444
445     lpsa2 = NULL;
446     if (LPSAFEARRAY_UNMARSHAL_WORKS)
447     {
448         init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
449         next = LPSAFEARRAY_UserUnmarshal(&umcb.Flags, buffer, &lpsa2);
450         todo_wine
451         ok(next - buffer == expected, "Marshaled %u bytes, expected %u\n", (ULONG) (next - buffer), expected);
452         ok(lpsa2 != NULL, "LPSAFEARRAY didn't unmarshal, result %p\n", next);
453     }
454
455     for (i = 0; i < sizeof(values) / sizeof(values[0]); i++)
456     {
457         BSTR gotvalue = NULL;
458
459         if (lpsa2)
460         {
461             indices[0] = i + sab[0].lLbound;
462             hr = SafeArrayGetElement(lpsa2, indices, &gotvalue);
463             ok(hr == S_OK, "Failed to get bstr element at hres 0x%x\n", hr);
464             if (hr == S_OK)
465             {
466                 ok(VarBstrCmp(values[i], gotvalue, 0, 0) == VARCMP_EQ, "String %d does not match\n", i);
467                 SysFreeString(gotvalue);
468             }
469         }
470
471         SysFreeString(values[i]);
472     }
473
474     if (LPSAFEARRAY_UNMARSHAL_WORKS)
475     {
476         init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
477         LPSAFEARRAY_UserFree(&umcb.Flags, &lpsa2);
478     }
479
480     HeapFree(GetProcessHeap(), 0, buffer);
481     SafeArrayDestroy(lpsa);
482
483     /* VARTYPE-less arrays with FADF_VARIANT */
484     hr = SafeArrayAllocDescriptor(1, &lpsa);
485     ok(hr == S_OK, "saad failed %08x\n", hr);
486     lpsa->cbElements = sizeof(VARIANT);
487     lpsa->fFeatures = FADF_VARIANT;
488     lpsa->rgsabound[0].lLbound = 2;
489     lpsa->rgsabound[0].cElements = 48;
490     hr = SafeArrayAllocData(lpsa);
491     ok(hr == S_OK, "saad failed %08x\n", hr);
492
493     hr = SafeArrayGetVartype(lpsa, &vt);
494     ok(hr == E_INVALIDARG, "ret %08x\n", hr);
495
496     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
497     size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
498     expected = 44 + 28 * lpsa->rgsabound[0].cElements;
499     todo_wine
500     ok(size == expected || size == expected + 8,  /* win64 */
501        "size should be %u bytes, not %u\n", expected, size);
502     buffer = HeapAlloc(GetProcessHeap(), 0, size);
503     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
504     next = LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
505     todo_wine
506     ok(next - buffer == expected || broken(next - buffer + sizeof(DWORD) == expected),
507             "Marshaled %u bytes, expected %u\n", (ULONG) (next - buffer), expected);
508     lpsa->cbElements = 16;  /* VARIANT wire size */
509     check_safearray(buffer, lpsa);
510     HeapFree(GetProcessHeap(), 0, buffer);
511     SafeArrayDestroyData(lpsa);
512     SafeArrayDestroyDescriptor(lpsa);
513 }
514
515 static void check_bstr(void *buffer, BSTR b)
516 {
517     DWORD *wireb = buffer;
518     DWORD len = SysStringByteLen(b);
519
520     ok(*wireb == (len + 1) / 2, "wv[0] %08x\n", *wireb);
521     wireb++;
522     if(b)
523         ok(*wireb == len, "wv[1] %08x\n", *wireb);
524     else
525         ok(*wireb == 0xffffffff, "wv[1] %08x\n", *wireb);
526     wireb++;
527     ok(*wireb == (len + 1) / 2, "wv[2] %08x\n", *wireb);
528     if(len)
529     {
530         wireb++;
531         ok(!memcmp(wireb, b, (len + 1) & ~1), "strings differ\n");
532     }
533     return;
534 }
535
536 static void test_marshal_BSTR(void)
537 {
538     ULONG size;
539     RPC_MESSAGE rpc_msg;
540     MIDL_STUB_MESSAGE stub_msg;
541     USER_MARSHAL_CB umcb;
542     unsigned char *buffer, *next;
543     BSTR b, b2;
544     WCHAR str[] = {'m','a','r','s','h','a','l',' ','t','e','s','t','1',0};
545     DWORD len;
546
547     b = SysAllocString(str);
548     len = SysStringLen(b);
549     ok(len == 13, "get %d\n", len);
550
551     /* BSTRs are DWORD aligned */
552
553     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
554     size = BSTR_UserSize(&umcb.Flags, 1, &b);
555     ok(size == 42, "size %d\n", size);
556
557     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
558     size = BSTR_UserSize(&umcb.Flags, 0, &b);
559     ok(size == 38, "size %d\n", size);
560
561     buffer = HeapAlloc(GetProcessHeap(), 0, size);
562     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
563     next = BSTR_UserMarshal(&umcb.Flags, buffer, &b);
564     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
565     check_bstr(buffer, b);
566
567     if (BSTR_UNMARSHAL_WORKS)
568     {
569         b2 = NULL;
570         init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
571         next = BSTR_UserUnmarshal(&umcb.Flags, buffer, &b2);
572         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
573         ok(b2 != NULL, "BSTR didn't unmarshal\n");
574         ok(!memcmp(b, b2, (len + 1) * 2), "strings differ\n");
575         init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
576         BSTR_UserFree(&umcb.Flags, &b2);
577     }
578
579     HeapFree(GetProcessHeap(), 0, buffer);
580     SysFreeString(b);
581
582     b = NULL;
583     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
584     size = BSTR_UserSize(&umcb.Flags, 0, &b);
585     ok(size == 12, "size %d\n", size);
586
587     buffer = HeapAlloc(GetProcessHeap(), 0, size);
588     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
589     next = BSTR_UserMarshal(&umcb.Flags, buffer, &b);
590     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
591
592     check_bstr(buffer, b);
593     if (BSTR_UNMARSHAL_WORKS)
594     {
595         b2 = NULL;
596         init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
597         next = BSTR_UserUnmarshal(&umcb.Flags, buffer, &b2);
598         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
599         ok(b2 == NULL, "NULL BSTR didn't unmarshal\n");
600         init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
601         BSTR_UserFree(&umcb.Flags, &b2);
602     }
603     HeapFree(GetProcessHeap(), 0, buffer);
604
605     b = SysAllocStringByteLen("abc", 3);
606     *(((char*)b) + 3) = 'd';
607     len = SysStringLen(b);
608     ok(len == 1, "get %d\n", len);
609     len = SysStringByteLen(b);
610     ok(len == 3, "get %d\n", len);
611
612     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
613     size = BSTR_UserSize(&umcb.Flags, 0, &b);
614     ok(size == 16, "size %d\n", size);
615
616     buffer = HeapAlloc(GetProcessHeap(), 0, size);
617     memset(buffer, 0xcc, size);
618     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
619     next = BSTR_UserMarshal(&umcb.Flags, buffer, &b);
620     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
621     check_bstr(buffer, b);
622     ok(buffer[15] == 'd', "buffer[15] %02x\n", buffer[15]);
623
624     if (BSTR_UNMARSHAL_WORKS)
625     {
626         b2 = NULL;
627         init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
628         next = BSTR_UserUnmarshal(&umcb.Flags, buffer, &b2);
629         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
630         ok(b2 != NULL, "BSTR didn't unmarshal\n");
631         ok(!memcmp(b, b2, len), "strings differ\n");
632         init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
633         BSTR_UserFree(&umcb.Flags, &b2);
634     }
635     HeapFree(GetProcessHeap(), 0, buffer);
636     SysFreeString(b);
637
638     b = SysAllocStringByteLen("", 0);
639     len = SysStringLen(b);
640     ok(len == 0, "get %d\n", len);
641     len = SysStringByteLen(b);
642     ok(len == 0, "get %d\n", len);
643
644     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
645     size = BSTR_UserSize(&umcb.Flags, 0, &b);
646     ok(size == 12, "size %d\n", size);
647
648     buffer = HeapAlloc(GetProcessHeap(), 0, size);
649     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
650     next = BSTR_UserMarshal(&umcb.Flags, buffer, &b);
651     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
652     check_bstr(buffer, b);
653
654     if (BSTR_UNMARSHAL_WORKS)
655     {
656         b2 = NULL;
657         init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
658         next = BSTR_UserUnmarshal(&umcb.Flags, buffer, &b2);
659         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
660         ok(b2 != NULL, "NULL LPSAFEARRAY didn't unmarshal\n");
661         len = SysStringByteLen(b2);
662         ok(len == 0, "byte len %d\n", len);
663         init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
664         BSTR_UserFree(&umcb.Flags, &b2);
665     }
666     HeapFree(GetProcessHeap(), 0, buffer);
667     SysFreeString(b);
668 }
669
670 typedef struct
671 {
672     const IUnknownVtbl *lpVtbl;
673     ULONG refs;
674 } HeapUnknown;
675
676 static HRESULT WINAPI HeapUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
677 {
678     if (IsEqualIID(riid, &IID_IUnknown))
679     {
680         IUnknown_AddRef(iface);
681         *ppv = iface;
682         return S_OK;
683     }
684     *ppv = NULL;
685     return E_NOINTERFACE;
686 }
687
688 static ULONG WINAPI HeapUnknown_AddRef(IUnknown *iface)
689 {
690     HeapUnknown *This = (HeapUnknown *)iface;
691     return InterlockedIncrement((LONG*)&This->refs);
692 }
693
694 static ULONG WINAPI HeapUnknown_Release(IUnknown *iface)
695 {
696     HeapUnknown *This = (HeapUnknown *)iface;
697     ULONG refs = InterlockedDecrement((LONG*)&This->refs);
698     if (!refs) HeapFree(GetProcessHeap(), 0, This);
699     return refs;
700 }
701
702 static const IUnknownVtbl HeapUnknown_Vtbl =
703 {
704     HeapUnknown_QueryInterface,
705     HeapUnknown_AddRef,
706     HeapUnknown_Release
707 };
708
709 static void check_variant_header(DWORD *wirev, VARIANT *v, ULONG size)
710 {
711     WORD *wp;
712     DWORD switch_is;
713
714     ok(*wirev == (size + 7) >> 3, "wv[0] %08x, expected %08x\n", *wirev, (size + 7) >> 3);
715     wirev++;
716     ok(*wirev == 0, "wv[1] %08x\n", *wirev);
717     wirev++;
718     wp = (WORD*)wirev;
719     ok(*wp == V_VT(v), "vt %04x expected %04x\n", *wp, V_VT(v));
720     wp++;
721     ok(*wp == V_U2(v).wReserved1, "res1 %04x expected %04x\n", *wp, V_U2(v).wReserved1);
722     wp++;
723     ok(*wp == V_U2(v).wReserved2, "res2 %04x expected %04x\n", *wp, V_U2(v).wReserved2);
724     wp++;
725     ok(*wp == V_U2(v).wReserved3, "res3 %04x expected %04x\n", *wp, V_U2(v).wReserved3);
726     wp++;
727     wirev = (DWORD*)wp;
728     switch_is = V_VT(v);
729     if(switch_is & VT_ARRAY)
730         switch_is &= ~VT_TYPEMASK;
731     ok(*wirev == switch_is, "switch_is %08x expected %08x\n", *wirev, switch_is);
732 }
733
734 /* Win9x and WinME don't always align as needed. Variants have
735  * an alignment of 8.
736  */
737 static void *alloc_aligned(SIZE_T size, void **buf)
738 {
739     *buf = HeapAlloc(GetProcessHeap(), 0, size + 7);
740     return (void *)(((UINT_PTR)*buf + 7) & ~7);
741 }
742
743 static void test_marshal_VARIANT(void)
744 {
745     VARIANT v, v2;
746     MIDL_STUB_MESSAGE stubMsg = { 0 };
747     RPC_MESSAGE rpcMsg = { 0 };
748     USER_MARSHAL_CB umcb = { 0 };
749     unsigned char *buffer, *next;
750     void *oldbuffer;
751     ULONG ul;
752     short s;
753     double d;
754     DWORD *wirev;
755     BSTR b;
756     WCHAR str[] = {'m','a','r','s','h','a','l',' ','t','e','s','t',0};
757     SAFEARRAYBOUND sab;
758     LPSAFEARRAY lpsa;
759     DECIMAL dec, dec2;
760     HeapUnknown *heap_unknown;
761     DWORD expected;
762
763     stubMsg.RpcMsg = &rpcMsg;
764
765     umcb.Flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
766     umcb.pStubMsg = &stubMsg;
767     umcb.pReserve = NULL;
768     umcb.Signature = USER_MARSHAL_CB_SIGNATURE;
769     umcb.CBType = USER_MARSHAL_CB_UNMARSHALL;
770
771     /*** I1 ***/
772     VariantInit(&v);
773     V_VT(&v) = VT_I1;
774     V_I1(&v) = 0x12;
775
776     /* check_variant_header tests wReserved[123], so initialize to unique values.
777      * (Could probably also do this by setting the variant to a known DECIMAL.)
778      */
779     V_U2(&v).wReserved1 = 0x1234;
780     V_U2(&v).wReserved2 = 0x5678;
781     V_U2(&v).wReserved3 = 0x9abc;
782
783     /* Variants have an alignment of 8 */
784     rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 1, &v);
785     ok(stubMsg.BufferLength == 29, "size %d\n", stubMsg.BufferLength);
786
787     rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
788     ok(stubMsg.BufferLength == 21, "size %d\n", stubMsg.BufferLength);
789
790     buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
791     stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
792     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
793     ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
794     wirev = (DWORD*)buffer;
795     
796     check_variant_header(wirev, &v, stubMsg.BufferLength);
797     wirev += 5;
798     ok(*(char*)wirev == V_I1(&v), "wv[5] %08x\n", *wirev);
799     if (VARIANT_UNMARSHAL_WORKS)
800     {
801         VariantInit(&v2);
802         stubMsg.Buffer = buffer;
803         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
804         ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
805         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
806         ok(V_I1(&v) == V_I1(&v2), "got i1 %x expect %x\n", V_I1(&v), V_I1(&v2));
807
808         VARIANT_UserFree(&umcb.Flags, &v2);
809     }
810     HeapFree(GetProcessHeap(), 0, oldbuffer);
811
812     /*** I2 ***/
813     VariantInit(&v);
814     V_VT(&v) = VT_I2;
815     V_I2(&v) = 0x1234;
816
817     rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
818     ok(stubMsg.BufferLength == 22, "size %d\n", stubMsg.BufferLength);
819
820     buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
821     stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
822     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
823     ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
824     wirev = (DWORD*)buffer;
825
826     check_variant_header(wirev, &v, stubMsg.BufferLength);
827     wirev += 5;
828     ok(*(short*)wirev == V_I2(&v), "wv[5] %08x\n", *wirev);
829     if (VARIANT_UNMARSHAL_WORKS)
830     {
831         VariantInit(&v2);
832         stubMsg.Buffer = buffer;
833         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
834         ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
835         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
836         ok(V_I2(&v) == V_I2(&v2), "got i2 %x expect %x\n", V_I2(&v), V_I2(&v2));
837
838         VARIANT_UserFree(&umcb.Flags, &v2);
839     }
840     HeapFree(GetProcessHeap(), 0, oldbuffer);
841
842     /*** I2 BYREF ***/
843     VariantInit(&v);
844     V_VT(&v) = VT_I2 | VT_BYREF;
845     s = 0x1234;
846     V_I2REF(&v) = &s;
847
848     rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
849     ok(stubMsg.BufferLength == 26, "size %d\n", stubMsg.BufferLength);
850
851     buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
852     stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
853     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
854     ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
855     wirev = (DWORD*)buffer;
856
857     check_variant_header(wirev, &v, stubMsg.BufferLength);
858     wirev += 5;
859     ok(*wirev == 0x4, "wv[5] %08x\n", *wirev);
860     wirev++;
861     ok(*(short*)wirev == s, "wv[6] %08x\n", *wirev);
862     if (VARIANT_UNMARSHAL_WORKS)
863     {
864         void *mem;
865         VariantInit(&v2);
866         V_VT(&v2) = VT_I2 | VT_BYREF;
867         V_BYREF(&v2) = mem = CoTaskMemAlloc(sizeof(V_I2(&v2)));
868         stubMsg.Buffer = buffer;
869         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
870         ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
871         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
872         ok(V_BYREF(&v2) == mem, "didn't reuse existing memory\n");
873         ok(*V_I2REF(&v) == *V_I2REF(&v2), "got i2 ref %x expect ui4 ref %x\n", *V_I2REF(&v), *V_I2REF(&v2));
874
875         VARIANT_UserFree(&umcb.Flags, &v2);
876     }
877     HeapFree(GetProcessHeap(), 0, oldbuffer);
878
879     /*** I4 ***/
880     VariantInit(&v);
881     V_VT(&v) = VT_I4;
882     V_I4(&v) = 0x1234;
883
884     rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
885     ok(stubMsg.BufferLength == 24, "size %d\n", stubMsg.BufferLength);
886
887     buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
888     stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
889     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
890     ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
891     wirev = (DWORD*)buffer;
892     
893     check_variant_header(wirev, &v, stubMsg.BufferLength);
894     wirev += 5;
895     ok(*wirev == V_I4(&v), "wv[5] %08x\n", *wirev);
896
897     if (VARIANT_UNMARSHAL_WORKS)
898     {
899         VariantInit(&v2);
900         stubMsg.Buffer = buffer;
901         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
902         ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
903         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
904         ok(V_I4(&v) == V_I4(&v2), "got i4 %x expect %x\n", V_I4(&v), V_I4(&v2));
905
906         VARIANT_UserFree(&umcb.Flags, &v2);
907     }
908     HeapFree(GetProcessHeap(), 0, oldbuffer);
909
910     /*** UI4 ***/
911     VariantInit(&v);
912     V_VT(&v) = VT_UI4;
913     V_UI4(&v) = 0x1234;
914
915     rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
916     ok(stubMsg.BufferLength == 24, "size %d\n", stubMsg.BufferLength);
917
918     buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
919     stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
920     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
921     ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
922     wirev = (DWORD*)buffer;
923     
924     check_variant_header(wirev, &v, stubMsg.BufferLength);
925     wirev += 5;
926     ok(*wirev == 0x1234, "wv[5] %08x\n", *wirev);
927     if (VARIANT_UNMARSHAL_WORKS)
928     {
929         VariantInit(&v2);
930         stubMsg.Buffer = buffer;
931         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
932         ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
933         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
934         ok(V_UI4(&v) == V_UI4(&v2), "got ui4 %x expect %x\n", V_UI4(&v), V_UI4(&v2));
935
936         VARIANT_UserFree(&umcb.Flags, &v2);
937     }
938     HeapFree(GetProcessHeap(), 0, oldbuffer);
939
940     /*** UI4 BYREF ***/
941     VariantInit(&v);
942     V_VT(&v) = VT_UI4 | VT_BYREF;
943     ul = 0x1234;
944     V_UI4REF(&v) = &ul;
945
946     rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
947     ok(stubMsg.BufferLength == 28, "size %d\n", stubMsg.BufferLength);
948
949     buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
950     stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
951     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
952     ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
953     wirev = (DWORD*)buffer;
954     
955     check_variant_header(wirev, &v, stubMsg.BufferLength);
956     wirev += 5;
957     ok(*wirev == 0x4, "wv[5] %08x\n", *wirev);
958     wirev++;
959     ok(*wirev == ul, "wv[6] %08x\n", *wirev);
960
961     if (VARIANT_UNMARSHAL_WORKS)
962     {
963         VariantInit(&v2);
964         stubMsg.Buffer = buffer;
965         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
966         ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
967         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
968         ok(*V_UI4REF(&v) == *V_UI4REF(&v2), "got ui4 ref %x expect ui4 ref %x\n", *V_UI4REF(&v), *V_UI4REF(&v2));
969
970         VARIANT_UserFree(&umcb.Flags, &v2);
971     }
972     HeapFree(GetProcessHeap(), 0, oldbuffer);
973
974     /*** R4 ***/
975     VariantInit(&v);
976     V_VT(&v) = VT_R4;
977     V_R8(&v) = 3.1415;
978
979     rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
980     ok(stubMsg.BufferLength == 24, "size %d\n", stubMsg.BufferLength);
981
982     buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
983     stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
984     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
985     ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
986     wirev = (DWORD*)buffer;
987      
988     check_variant_header(wirev, &v, stubMsg.BufferLength);
989     wirev += 5;
990     ok(*(float*)wirev == V_R4(&v), "wv[5] %08x\n", *wirev);
991     if (VARIANT_UNMARSHAL_WORKS)
992     {
993         VariantInit(&v2);
994         stubMsg.Buffer = buffer;
995         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
996         ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
997         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
998         ok(V_R4(&v) == V_R4(&v2), "got r4 %f expect %f\n", V_R4(&v), V_R4(&v2));
999
1000         VARIANT_UserFree(&umcb.Flags, &v2);
1001     }
1002     HeapFree(GetProcessHeap(), 0, oldbuffer);
1003
1004     /*** R8 ***/
1005     VariantInit(&v);
1006     V_VT(&v) = VT_R8;
1007     V_R8(&v) = 3.1415;
1008
1009     rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1010     ok(stubMsg.BufferLength == 32, "size %d\n", stubMsg.BufferLength);
1011
1012     buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1013     stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1014     memset(buffer, 0xcc, stubMsg.BufferLength);
1015     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1016     ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1017     wirev = (DWORD*)buffer;
1018     
1019     check_variant_header(wirev, &v, stubMsg.BufferLength);
1020     wirev += 5;
1021     ok(*wirev == 0xcccccccc, "wv[5] %08x\n", *wirev); /* pad */
1022     wirev++;
1023     ok(*(double*)wirev == V_R8(&v), "wv[6] %08x, wv[7] %08x\n", *wirev, *(wirev+1));
1024     if (VARIANT_UNMARSHAL_WORKS)
1025     {
1026         VariantInit(&v2);
1027         stubMsg.Buffer = buffer;
1028         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1029         ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1030         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1031         ok(V_R8(&v) == V_R8(&v2), "got r8 %f expect %f\n", V_R8(&v), V_R8(&v2));
1032
1033         VARIANT_UserFree(&umcb.Flags, &v2);
1034     }
1035     HeapFree(GetProcessHeap(), 0, oldbuffer);
1036
1037     /*** R8 BYREF ***/
1038     VariantInit(&v);
1039     V_VT(&v) = VT_R8 | VT_BYREF;
1040     d = 3.1415;
1041     V_R8REF(&v) = &d;
1042
1043     rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1044     ok(stubMsg.BufferLength == 32, "size %d\n", stubMsg.BufferLength);
1045
1046     buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1047     stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1048     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1049     ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1050     wirev = (DWORD*)buffer;
1051     
1052     check_variant_header(wirev, &v, stubMsg.BufferLength);
1053     wirev += 5;
1054     ok(*wirev == 8, "wv[5] %08x\n", *wirev);
1055     wirev++;
1056     ok(*(double*)wirev == d, "wv[6] %08x wv[7] %08x\n", *wirev, *(wirev+1));
1057     if (VARIANT_UNMARSHAL_WORKS)
1058     {
1059         VariantInit(&v2);
1060         stubMsg.Buffer = buffer;
1061         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1062         ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1063         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1064         ok(*V_R8REF(&v) == *V_R8REF(&v2), "got r8 ref %f expect %f\n", *V_R8REF(&v), *V_R8REF(&v2));
1065
1066         VARIANT_UserFree(&umcb.Flags, &v2);
1067     }
1068     HeapFree(GetProcessHeap(), 0, oldbuffer);
1069
1070     /*** VARIANT_BOOL ***/
1071     VariantInit(&v);
1072     V_VT(&v) = VT_BOOL;
1073     V_BOOL(&v) = 0x1234;
1074
1075     rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1076     ok(stubMsg.BufferLength == 22, "size %d\n", stubMsg.BufferLength);
1077
1078     buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1079     stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1080     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1081     ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1082     wirev = (DWORD*)buffer;
1083     
1084     check_variant_header(wirev, &v, stubMsg.BufferLength);
1085     wirev += 5;
1086     ok(*(short*)wirev == V_BOOL(&v), "wv[5] %04x\n", *(WORD*)wirev);
1087     if (VARIANT_UNMARSHAL_WORKS)
1088     {
1089         VariantInit(&v2);
1090         stubMsg.Buffer = buffer;
1091         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1092         ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1093         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1094         ok(V_BOOL(&v) == V_BOOL(&v2), "got bool %x expect %x\n", V_BOOL(&v), V_BOOL(&v2));
1095
1096         VARIANT_UserFree(&umcb.Flags, &v2);
1097     }
1098     HeapFree(GetProcessHeap(), 0, oldbuffer);
1099
1100     /*** DECIMAL ***/
1101     VarDecFromI4(0x12345678, &dec);
1102     dec.wReserved = 0xfedc;          /* Also initialize reserved field, as we check it later */
1103     VariantInit(&v);
1104     V_DECIMAL(&v) = dec;
1105     V_VT(&v) = VT_DECIMAL;
1106
1107     rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1108     ok(stubMsg.BufferLength == 40, "size %d\n", stubMsg.BufferLength);
1109
1110     buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1111     stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1112     memset(buffer, 0xcc, stubMsg.BufferLength);
1113     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1114     ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1115     wirev = (DWORD*)buffer;
1116
1117     check_variant_header(wirev, &v, stubMsg.BufferLength);
1118     wirev += 5;
1119     ok(*wirev == 0xcccccccc, "wirev[5] %08x\n", *wirev); /* pad */
1120     wirev++;
1121     dec2 = dec;
1122     dec2.wReserved = VT_DECIMAL;
1123     ok(!memcmp(wirev, &dec2, sizeof(dec2)), "wirev[6] %08x wirev[7] %08x wirev[8] %08x wirev[9] %08x\n",
1124        *wirev, *(wirev + 1), *(wirev + 2), *(wirev + 3));
1125     if (VARIANT_UNMARSHAL_WORKS)
1126     {
1127         VariantInit(&v2);
1128         stubMsg.Buffer = buffer;
1129         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1130         ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1131         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1132         ok(!memcmp(&V_DECIMAL(&v), & V_DECIMAL(&v2), sizeof(DECIMAL)), "decimals differ\n");
1133
1134         VARIANT_UserFree(&umcb.Flags, &v2);
1135     }
1136     HeapFree(GetProcessHeap(), 0, oldbuffer);
1137
1138     /*** DECIMAL BYREF ***/
1139     VariantInit(&v);
1140     V_VT(&v) = VT_DECIMAL | VT_BYREF;
1141     V_DECIMALREF(&v) = &dec;
1142
1143     rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1144     ok(stubMsg.BufferLength == 40, "size %d\n", stubMsg.BufferLength);
1145
1146     buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1147     stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1148     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1149     ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1150     wirev = (DWORD*)buffer;
1151     
1152     check_variant_header(wirev, &v, stubMsg.BufferLength);
1153     wirev += 5;
1154     ok(*wirev == 16, "wv[5] %08x\n", *wirev);
1155     wirev++;
1156     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));
1157     if (VARIANT_UNMARSHAL_WORKS)
1158     {
1159         VariantInit(&v2);
1160         /* check_variant_header tests wReserved[123], so initialize to unique values.
1161          * (Could probably also do this by setting the variant to a known DECIMAL.)
1162          */
1163         V_U2(&v2).wReserved1 = 0x0123;
1164         V_U2(&v2).wReserved2 = 0x4567;
1165         V_U2(&v2).wReserved3 = 0x89ab;
1166
1167         stubMsg.Buffer = buffer;
1168         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1169         ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1170         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1171         ok(!memcmp(V_DECIMALREF(&v), V_DECIMALREF(&v2), sizeof(DECIMAL)), "decimals differ\n");
1172
1173         VARIANT_UserFree(&umcb.Flags, &v2);
1174     }
1175     HeapFree(GetProcessHeap(), 0, oldbuffer);
1176
1177     /*** EMPTY ***/
1178     VariantInit(&v);
1179     V_VT(&v) = VT_EMPTY;
1180
1181     rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1182     ok(stubMsg.BufferLength == 20, "size %d\n", stubMsg.BufferLength);
1183
1184     buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1185     stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1186     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1187     ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1188     wirev = (DWORD*)buffer;
1189
1190     check_variant_header(wirev, &v, stubMsg.BufferLength);
1191     if (VARIANT_UNMARSHAL_WORKS)
1192     {
1193         VariantInit(&v2);
1194         stubMsg.Buffer = buffer;
1195         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1196         ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1197         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1198
1199         VARIANT_UserFree(&umcb.Flags, &v2);
1200     }
1201     HeapFree(GetProcessHeap(), 0, oldbuffer);
1202
1203     /*** NULL ***/
1204     VariantInit(&v);
1205     V_VT(&v) = VT_NULL;
1206
1207     rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1208     ok(stubMsg.BufferLength == 20, "size %d\n", stubMsg.BufferLength);
1209
1210     buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1211     stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1212     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1213     ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1214     wirev = (DWORD*)buffer;
1215
1216     check_variant_header(wirev, &v, stubMsg.BufferLength);
1217     if (VARIANT_UNMARSHAL_WORKS)
1218     {
1219         VariantInit(&v2);
1220         stubMsg.Buffer = buffer;
1221         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1222         ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1223         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1224
1225         VARIANT_UserFree(&umcb.Flags, &v2);
1226     }
1227     HeapFree(GetProcessHeap(), 0, oldbuffer);
1228
1229     /*** BSTR ***/
1230     b = SysAllocString(str);
1231     VariantInit(&v);
1232     V_VT(&v) = VT_BSTR;
1233     V_BSTR(&v) = b;
1234
1235     rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1236     ok(stubMsg.BufferLength == 60, "size %d\n", stubMsg.BufferLength);
1237     buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1238     stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1239     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1240     ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1241     wirev = (DWORD*)buffer;
1242     
1243     check_variant_header(wirev, &v, stubMsg.BufferLength);
1244     wirev += 5;
1245     ok(*wirev, "wv[5] %08x\n", *wirev); /* win2k: this is b. winxp: this is (char*)b + 1 */
1246     wirev++;
1247     check_bstr(wirev, V_BSTR(&v));
1248     if (VARIANT_UNMARSHAL_WORKS)
1249     {
1250         VariantInit(&v2);
1251         stubMsg.Buffer = buffer;
1252         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1253         ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1254         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1255         ok(SysStringByteLen(V_BSTR(&v)) == SysStringByteLen(V_BSTR(&v2)), "bstr string lens differ\n");
1256         ok(!memcmp(V_BSTR(&v), V_BSTR(&v2), SysStringByteLen(V_BSTR(&v))), "bstrs differ\n");
1257
1258         VARIANT_UserFree(&umcb.Flags, &v2);
1259     }
1260     HeapFree(GetProcessHeap(), 0, oldbuffer);
1261
1262     /*** BSTR BYREF ***/
1263     VariantInit(&v);
1264     V_VT(&v) = VT_BSTR | VT_BYREF;
1265     V_BSTRREF(&v) = &b;
1266
1267     rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1268     ok(stubMsg.BufferLength == 64, "size %d\n", stubMsg.BufferLength);
1269     buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1270     stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1271     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1272     ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1273     wirev = (DWORD*)buffer;
1274     
1275     check_variant_header(wirev, &v, stubMsg.BufferLength);
1276     wirev += 5;
1277     ok(*wirev == 0x4, "wv[5] %08x\n", *wirev);
1278     wirev++;
1279     ok(*wirev, "wv[6] %08x\n", *wirev); /* win2k: this is b. winxp: this is (char*)b + 1 */
1280     wirev++;
1281     check_bstr(wirev, b);
1282     if (VARIANT_UNMARSHAL_WORKS)
1283     {
1284         VariantInit(&v2);
1285         stubMsg.Buffer = buffer;
1286         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1287         ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1288         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1289         ok(SysStringByteLen(*V_BSTRREF(&v)) == SysStringByteLen(*V_BSTRREF(&v2)), "bstr string lens differ\n");
1290         ok(!memcmp(*V_BSTRREF(&v), *V_BSTRREF(&v2), SysStringByteLen(*V_BSTRREF(&v))), "bstrs differ\n");
1291
1292         VARIANT_UserFree(&umcb.Flags, &v2);
1293     }
1294     HeapFree(GetProcessHeap(), 0, oldbuffer);
1295     SysFreeString(b);
1296
1297     /*** ARRAY ***/
1298     sab.lLbound = 5;
1299     sab.cElements = 10;
1300
1301     lpsa = SafeArrayCreate(VT_R8, 1, &sab);
1302     *(DWORD *)lpsa->pvData = 0xcafebabe;
1303     *((DWORD *)lpsa->pvData + 1) = 0xdeadbeef;
1304
1305     VariantInit(&v);
1306     V_VT(&v) = VT_UI4 | VT_ARRAY;
1307     V_ARRAY(&v) = lpsa;
1308
1309     rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1310     expected = 152;
1311     ok(stubMsg.BufferLength == expected || stubMsg.BufferLength == expected + 8, /* win64 */
1312        "size %u instead of %u\n", stubMsg.BufferLength, expected);
1313     buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1314     stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1315     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1316     ok(next == buffer + expected, "got %p expect %p\n", next, buffer + expected);
1317     wirev = (DWORD*)buffer;
1318     
1319     check_variant_header(wirev, &v, expected);
1320     wirev += 5;
1321     ok(*wirev, "wv[5] %08x\n", *wirev); /* win2k: this is lpsa. winxp: this is (char*)lpsa + 1 */
1322     wirev++;
1323     check_safearray(wirev, lpsa);
1324     if (VARIANT_UNMARSHAL_WORKS)
1325     {
1326         LONG bound, bound2;
1327         VARTYPE vt, vt2;
1328         VariantInit(&v2);
1329         stubMsg.Buffer = buffer;
1330         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1331         ok(next == buffer + expected, "got %p expect %p\n", next, buffer + expected);
1332         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1333         ok(SafeArrayGetDim(V_ARRAY(&v)) == SafeArrayGetDim(V_ARRAY(&v)), "array dims differ\n");  
1334         SafeArrayGetLBound(V_ARRAY(&v), 1, &bound);
1335         SafeArrayGetLBound(V_ARRAY(&v2), 1, &bound2);
1336         ok(bound == bound2, "array lbounds differ\n");
1337         SafeArrayGetUBound(V_ARRAY(&v), 1, &bound);
1338         SafeArrayGetUBound(V_ARRAY(&v2), 1, &bound2);
1339         ok(bound == bound2, "array ubounds differ\n");
1340         SafeArrayGetVartype(V_ARRAY(&v), &vt);
1341         SafeArrayGetVartype(V_ARRAY(&v2), &vt2);
1342         ok(vt == vt2, "array vts differ %x %x\n", vt, vt2);
1343         VARIANT_UserFree(&umcb.Flags, &v2);
1344     }
1345     HeapFree(GetProcessHeap(), 0, oldbuffer);
1346
1347     /*** ARRAY BYREF ***/
1348     VariantInit(&v);
1349     V_VT(&v) = VT_UI4 | VT_ARRAY | VT_BYREF;
1350     V_ARRAYREF(&v) = &lpsa;
1351
1352     rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1353     expected = 152;
1354     ok(stubMsg.BufferLength == expected || stubMsg.BufferLength == expected + 16, /* win64 */
1355        "size %u instead of %u\n", stubMsg.BufferLength, expected);
1356     buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1357     stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1358     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1359     ok(next == buffer + expected, "got %p expect %p\n", next, buffer + expected);
1360     wirev = (DWORD*)buffer;
1361
1362     check_variant_header(wirev, &v, expected);
1363     wirev += 5;
1364     ok(*wirev == 4, "wv[5] %08x\n", *wirev);
1365     wirev++;
1366     ok(*wirev, "wv[6] %08x\n", *wirev); /* win2k: this is lpsa. winxp: this is (char*)lpsa + 1 */
1367     wirev++;
1368     check_safearray(wirev, lpsa);
1369     if (VARIANT_UNMARSHAL_WORKS)
1370     {
1371         LONG bound, bound2;
1372         VARTYPE vt, vt2;
1373         VariantInit(&v2);
1374         stubMsg.Buffer = buffer;
1375         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1376         ok(next == buffer + expected, "got %p expect %p\n", next, buffer + expected);
1377         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1378         ok(SafeArrayGetDim(*V_ARRAYREF(&v)) == SafeArrayGetDim(*V_ARRAYREF(&v)), "array dims differ\n");  
1379         SafeArrayGetLBound(*V_ARRAYREF(&v), 1, &bound);
1380         SafeArrayGetLBound(*V_ARRAYREF(&v2), 1, &bound2);
1381         ok(bound == bound2, "array lbounds differ\n");
1382         SafeArrayGetUBound(*V_ARRAYREF(&v), 1, &bound);
1383         SafeArrayGetUBound(*V_ARRAYREF(&v2), 1, &bound2);
1384         ok(bound == bound2, "array ubounds differ\n");
1385         SafeArrayGetVartype(*V_ARRAYREF(&v), &vt);
1386         SafeArrayGetVartype(*V_ARRAYREF(&v2), &vt2);
1387         ok(vt == vt2, "array vts differ %x %x\n", vt, vt2);
1388         VARIANT_UserFree(&umcb.Flags, &v2);
1389     }
1390     HeapFree(GetProcessHeap(), 0, oldbuffer);
1391     SafeArrayDestroy(lpsa);
1392
1393     /*** VARIANT BYREF ***/
1394     VariantInit(&v);
1395     VariantInit(&v2);
1396     V_VT(&v2) = VT_R8;
1397     V_R8(&v2) = 3.1415;
1398     V_VT(&v) = VT_VARIANT | VT_BYREF;
1399     V_VARIANTREF(&v) = &v2;
1400
1401     rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1402     ok(stubMsg.BufferLength == 64, "size %d\n", stubMsg.BufferLength);
1403     buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1404     stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1405     memset(buffer, 0xcc, stubMsg.BufferLength);
1406     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1407     ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1408     wirev = (DWORD*)buffer;
1409     check_variant_header(wirev, &v, stubMsg.BufferLength);
1410     wirev += 5;
1411
1412     ok(*wirev == sizeof(VARIANT), "wv[5] %08x\n", *wirev);
1413     wirev++;
1414     ok(*wirev == ('U' | 's' << 8 | 'e' << 16 | 'r' << 24), "wv[6] %08x\n", *wirev); /* 'User' */
1415     wirev++;
1416     ok(*wirev == 0xcccccccc, "wv[7] %08x\n", *wirev); /* pad */
1417     wirev++;
1418     check_variant_header(wirev, &v2, stubMsg.BufferLength - 32);
1419     wirev += 5;
1420     ok(*wirev == 0xcccccccc, "wv[13] %08x\n", *wirev); /* pad for VT_R8 */
1421     wirev++;
1422     ok(*(double*)wirev == V_R8(&v2), "wv[6] %08x wv[7] %08x\n", *wirev, *(wirev+1));
1423     if (VARIANT_UNMARSHAL_WORKS)
1424     {
1425         VARIANT v3;
1426         VariantInit(&v3);
1427         stubMsg.Buffer = buffer;
1428         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v3);
1429         ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1430         ok(V_VT(&v) == V_VT(&v3), "got vt %d expect %d\n", V_VT(&v), V_VT(&v3));
1431         ok(V_VT(V_VARIANTREF(&v)) == V_VT(V_VARIANTREF(&v3)), "vts differ %x %x\n",
1432            V_VT(V_VARIANTREF(&v)), V_VT(V_VARIANTREF(&v3))); 
1433         ok(V_R8(V_VARIANTREF(&v)) == V_R8(V_VARIANTREF(&v3)), "r8s differ\n"); 
1434         VARIANT_UserFree(&umcb.Flags, &v3);
1435     }
1436     HeapFree(GetProcessHeap(), 0, oldbuffer);
1437
1438     /*** UNKNOWN ***/
1439     heap_unknown = HeapAlloc(GetProcessHeap(), 0, sizeof(*heap_unknown));
1440     heap_unknown->lpVtbl = &HeapUnknown_Vtbl;
1441     heap_unknown->refs = 1;
1442     VariantInit(&v);
1443     VariantInit(&v2);
1444     V_VT(&v) = VT_UNKNOWN;
1445     V_UNKNOWN(&v) = (IUnknown *)heap_unknown;
1446
1447     rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1448     ok(stubMsg.BufferLength > 32, "size %d\n", stubMsg.BufferLength);
1449     buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1450     stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1451     memset(buffer, 0xcc, stubMsg.BufferLength);
1452     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1453     wirev = (DWORD*)buffer;
1454     check_variant_header(wirev, &v, next - buffer);
1455     wirev += 5;
1456
1457     todo_wine
1458     ok(*wirev == (DWORD_PTR)V_UNKNOWN(&v) /* Win9x */ ||
1459        *wirev == (DWORD_PTR)V_UNKNOWN(&v) + 1 /* NT */, "wv[5] %08x\n", *wirev);
1460     wirev++;
1461     todo_wine
1462     ok(*wirev == next - buffer - 0x20, "wv[6] %08x\n", *wirev);
1463     wirev++;
1464     todo_wine
1465     ok(*wirev == next - buffer - 0x20, "wv[7] %08x\n", *wirev);
1466     wirev++;
1467     todo_wine
1468     ok(*wirev == 0x574f454d, "wv[8] %08x\n", *wirev);
1469     if (VARIANT_UNMARSHAL_WORKS)
1470     {
1471         VARIANT v3;
1472         VariantInit(&v3);
1473         V_VT(&v3) = VT_UNKNOWN;
1474         V_UNKNOWN(&v3) = (IUnknown *)heap_unknown;
1475         IUnknown_AddRef(V_UNKNOWN(&v3));
1476         stubMsg.Buffer = buffer;
1477         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v3);
1478         ok(V_VT(&v) == V_VT(&v3), "got vt %d expect %d\n", V_VT(&v), V_VT(&v3));
1479         ok(V_UNKNOWN(&v) == V_UNKNOWN(&v3), "got %p expect %p\n", V_UNKNOWN(&v), V_UNKNOWN(&v3));
1480         VARIANT_UserFree(&umcb.Flags, &v3);
1481         ok(heap_unknown->refs == 1, "%d refcounts of IUnknown leaked\n", heap_unknown->refs - 1);
1482         IUnknown_Release((IUnknown *)heap_unknown);
1483     }
1484     HeapFree(GetProcessHeap(), 0, oldbuffer);
1485
1486     /*** NULL UNKNOWN ***/
1487     VariantInit(&v);
1488     V_VT(&v) = VT_UNKNOWN;
1489     V_UNKNOWN(&v) = NULL;
1490
1491     rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1492     ok(stubMsg.BufferLength >= 24, "size %d\n", stubMsg.BufferLength);
1493     buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1494     stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1495     memset(buffer, 0xcc, stubMsg.BufferLength);
1496     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1497     wirev = (DWORD*)buffer;
1498     check_variant_header(wirev, &v, next - buffer);
1499     wirev += 5;
1500     ok(*wirev == 0, "wv[5] %08x\n", *wirev);
1501
1502     VariantInit(&v2);
1503     stubMsg.Buffer = buffer;
1504     next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1505     ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1506     ok(V_UNKNOWN(&v2) == NULL, "got %p expect NULL\n", V_UNKNOWN(&v2));
1507     VARIANT_UserFree(&umcb.Flags, &v2);
1508     HeapFree(GetProcessHeap(), 0, oldbuffer);
1509
1510     /*** UNKNOWN BYREF ***/
1511     heap_unknown = HeapAlloc(GetProcessHeap(), 0, sizeof(*heap_unknown));
1512     heap_unknown->lpVtbl = &HeapUnknown_Vtbl;
1513     heap_unknown->refs = 1;
1514     VariantInit(&v);
1515     VariantInit(&v2);
1516     V_VT(&v) = VT_UNKNOWN | VT_BYREF;
1517     V_UNKNOWNREF(&v) = (IUnknown **)&heap_unknown;
1518
1519     rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1520     ok(stubMsg.BufferLength > 36, "size %d\n", stubMsg.BufferLength);
1521     buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1522     stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1523     memset(buffer, 0xcc, stubMsg.BufferLength);
1524     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1525     wirev = (DWORD*)buffer;
1526     check_variant_header(wirev, &v, next - buffer);
1527     wirev += 5;
1528
1529     ok(*wirev == 4, "wv[5] %08x\n", *wirev);
1530     wirev++;
1531     todo_wine
1532     ok(*wirev == (DWORD_PTR)heap_unknown /* Win9x, Win2000 */ ||
1533        *wirev == (DWORD_PTR)heap_unknown + 1 /* XP */, "wv[6] %08x\n", *wirev);
1534     wirev++;
1535     todo_wine
1536     ok(*wirev == next - buffer - 0x24, "wv[7] %08x\n", *wirev);
1537     wirev++;
1538     todo_wine
1539     ok(*wirev == next - buffer - 0x24, "wv[8] %08x\n", *wirev);
1540     wirev++;
1541     todo_wine
1542     ok(*wirev == 0x574f454d, "wv[9] %08x\n", *wirev);
1543     if (VARIANT_UNMARSHAL_WORKS)
1544     {
1545         VARIANT v3;
1546         VariantInit(&v3);
1547         V_VT(&v3) = VT_UNKNOWN;
1548         V_UNKNOWN(&v3) = (IUnknown *)heap_unknown;
1549         IUnknown_AddRef(V_UNKNOWN(&v3));
1550         stubMsg.Buffer = buffer;
1551         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v3);
1552         ok(V_VT(&v) == V_VT(&v3), "got vt %d expect %d\n", V_VT(&v), V_VT(&v3));
1553         ok(*V_UNKNOWNREF(&v) == *V_UNKNOWNREF(&v3), "got %p expect %p\n", *V_UNKNOWNREF(&v), *V_UNKNOWNREF(&v3));
1554         VARIANT_UserFree(&umcb.Flags, &v3);
1555         ok(heap_unknown->refs == 1, "%d refcounts of IUnknown leaked\n", heap_unknown->refs - 1);
1556         IUnknown_Release((IUnknown *)heap_unknown);
1557     }
1558     HeapFree(GetProcessHeap(), 0, oldbuffer);
1559 }
1560
1561
1562 START_TEST(usrmarshal)
1563 {
1564     CoInitialize(NULL);
1565
1566     test_marshal_LPSAFEARRAY();
1567     test_marshal_BSTR();
1568     test_marshal_VARIANT();
1569
1570     CoUninitialize();
1571 }