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