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