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