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