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 97 static ULONG get_cell_count(const SAFEARRAY *psa) 98 { 99 const SAFEARRAYBOUND* psab = psa->rgsabound; 100 USHORT cCount = psa->cDims; 101 ULONG ulNumCells = 1; 102 103 while (cCount--) 104 { 105 if (!psab->cElements) 106 return 0; 107 ulNumCells *= psab->cElements; 108 psab++; 109 } 110 return ulNumCells; 111 } 112 113 static DWORD elem_wire_size(LPSAFEARRAY lpsa, SF_TYPE sftype) 114 { 115 if (sftype == SF_BSTR) 116 return sizeof(DWORD); 117 else 118 return lpsa->cbElements; 119 } 120 121 static void check_safearray(void *buffer, LPSAFEARRAY lpsa) 122 { 123 unsigned char *wiresa = buffer; 124 const SAFEARRAYBOUND *bounds; 125 VARTYPE vt; 126 SF_TYPE sftype; 127 ULONG cell_count; 128 int i; 129 130 if(!lpsa) 131 { 132 ok(*(DWORD *)wiresa == 0, "wiresa + 0x0 should be NULL instead of 0x%08x\n", *(DWORD *)wiresa); 133 return; 134 } 135 136 if (!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 191 static void * WINAPI user_allocate(SIZE_T size) 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 203 static void init_user_marshal_cb(USER_MARSHAL_CB *umcb, 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)); 219 umcb->Flags = MAKELONG(context, NDR_LOCAL_DATA_REPRESENTATION); 220 umcb->pStubMsg = stub_msg; 221 umcb->Signature = USER_MARSHAL_CB_SIGNATURE; 222 umcb->CBType = buffer ? USER_MARSHAL_CB_UNMARSHALL : USER_MARSHAL_CB_BUFFER_SIZE; 223 } 224 225 static void test_marshal_LPSAFEARRAY(void) 226 { 227 unsigned char *buffer, *next; 228 ULONG size, expected; 229 LPSAFEARRAY lpsa; 230 LPSAFEARRAY lpsa2 = NULL; 231 SAFEARRAYBOUND sab[2]; 232 RPC_MESSAGE rpc_msg; 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); 260 buffer = HeapAlloc(GetProcessHeap(), 0, 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"); 281 HeapFree(GetProcessHeap(), 0, buffer); 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); 307 buffer = HeapAlloc(GetProcessHeap(), 0, 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); 327 HeapFree(GetProcessHeap(), 0, buffer); 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); 339 buffer = HeapAlloc(GetProcessHeap(), 0, 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); 350 HeapFree(GetProcessHeap(), 0, buffer); 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); 371 buffer = HeapAlloc(GetProcessHeap(), 0, 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 379 HeapFree(GetProcessHeap(), 0, buffer); 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); 405 buffer = HeapAlloc(GetProcessHeap(), 0, 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); 411 HeapFree(GetProcessHeap(), 0, buffer); 412 hr = SafeArrayDestroyData(lpsa); 413 ok(hr == S_OK, "got 0x%08x\n", hr); 414 hr = SafeArrayDestroyDescriptor(lpsa); 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 = sizeof(values) / sizeof(values[0]); 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; 431 values[i] = SysAllocString(buf); 432 hr = SafeArrayPutElement(lpsa, indices, values[i]); 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); 450 buffer = HeapAlloc(GetProcessHeap(), 0, 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 < sizeof(values) / sizeof(values[0]); 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 483 SysFreeString(values[i]); 484 } 485 486 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE); 487 LPSAFEARRAY_UserFree(&umcb.Flags, &lpsa2); 488 489 HeapFree(GetProcessHeap(), 0, buffer); 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); 515 buffer = HeapAlloc(GetProcessHeap(), 0, 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); 523 HeapFree(GetProcessHeap(), 0, buffer); 524 hr = SafeArrayDestroyData(lpsa); 525 ok(hr == S_OK, "got 0x%08x\n", hr); 526 hr = SafeArrayDestroyDescriptor(lpsa); 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; 533 DWORD len = SysStringByteLen(b); 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; 554 RPC_MESSAGE rpc_msg; 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 576 buffer = HeapAlloc(GetProcessHeap(), 0, size); 577 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE); 578 next = BSTR_UserMarshal(&umcb.Flags, buffer, &b); 579 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size); 580 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 591 HeapFree(GetProcessHeap(), 0, buffer); 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 599 buffer = HeapAlloc(GetProcessHeap(), 0, size); 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); 612 HeapFree(GetProcessHeap(), 0, buffer); 613 614 b = SysAllocStringByteLen("abc", 3); 615 *(((char*)b) + 3) = 'd'; 616 len = SysStringLen(b); 617 ok(len == 1, "get %d\n", len); 618 len = SysStringByteLen(b); 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 625 buffer = HeapAlloc(GetProcessHeap(), 0, size); 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); 641 HeapFree(GetProcessHeap(), 0, buffer); 642 SysFreeString(b); 643 644 b = SysAllocStringByteLen("", 0); 645 len = SysStringLen(b); 646 ok(len == 0, "get %d\n", len); 647 len = SysStringByteLen(b); 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 654 buffer = HeapAlloc(GetProcessHeap(), 0, size); 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"); 665 len = SysStringByteLen(b2); 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); 669 HeapFree(GetProcessHeap(), 0, buffer); 670 SysFreeString(b); 671 } 672 673 typedef struct 674 { 675 IUnknown IUnknown_iface; 676 ULONG refs; 677 } HeapUnknown; 678 679 static inline HeapUnknown *impl_from_IUnknown(IUnknown *iface) 680 { 681 return CONTAINING_RECORD(iface, HeapUnknown, IUnknown_iface); 682 } 683 684 static HRESULT WINAPI HeapUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv) 685 { 686 if (IsEqualIID(riid, &IID_IUnknown)) 687 { 688 IUnknown_AddRef(iface); 689 *ppv = iface; 690 return S_OK; 691 } 692 *ppv = NULL; 693 return E_NOINTERFACE; 694 } 695 696 static ULONG WINAPI HeapUnknown_AddRef(IUnknown *iface) 697 { 698 HeapUnknown *This = impl_from_IUnknown(iface); 699 return InterlockedIncrement((LONG*)&This->refs); 700 } 701 702 static ULONG WINAPI HeapUnknown_Release(IUnknown *iface) 703 { 704 HeapUnknown *This = impl_from_IUnknown(iface); 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 { 712 HeapUnknown_QueryInterface, 713 HeapUnknown_AddRef, 714 HeapUnknown_Release 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; 726 } variant_wire_t; 727 728 static DWORD *check_variant_header(DWORD *wirev, VARIANT *v, ULONG size) 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 781 stubMsg.RpcMsg = &rpcMsg; 782 783 umcb.Flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION); 784 umcb.pStubMsg = &stubMsg; 785 umcb.pReserve = NULL; 786 umcb.Signature = USER_MARSHAL_CB_SIGNATURE; 787 umcb.CBType = USER_MARSHAL_CB_UNMARSHALL; 788 789 /*** I1 ***/ 790 VariantInit(&v); 791 V_VT(&v) = VT_I1; 792 V_I1(&v) = 0x12; 793 794 /* check_variant_header tests wReserved[123], so initialize to unique values. 795 * (Could probably also do this by setting the variant to a known DECIMAL.) 796 */ 797 V_U2(&v).wReserved1 = 0x1234; 798 V_U2(&v).wReserved2 = 0x5678; 799 V_U2(&v).wReserved3 = 0x9abc; 800 801 /* Variants have an alignment of 8 */ 802 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 1, &v); 803 ok(stubMsg.BufferLength == 29, "size %d\n", stubMsg.BufferLength); 804 805 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v); 806 ok(stubMsg.BufferLength == 21, "size %d\n", stubMsg.BufferLength); 807 808 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer); 809 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength; 810 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v); 811 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength); 812 wirev = (DWORD*)buffer; 813 814 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength); 815 ok(*(char*)wirev == V_I1(&v), "wv[5] %08x\n", *wirev); 816 VariantInit(&v2); 817 stubMsg.Buffer = buffer; 818 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2); 819 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength); 820 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2)); 821 ok(V_I1(&v) == V_I1(&v2), "got i1 %x expect %x\n", V_I1(&v), V_I1(&v2)); 822 823 VARIANT_UserFree(&umcb.Flags, &v2); 824 HeapFree(GetProcessHeap(), 0, oldbuffer); 825 826 /*** I2 ***/ 827 VariantInit(&v); 828 V_VT(&v) = VT_I2; 829 V_I2(&v) = 0x1234; 830 831 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v); 832 ok(stubMsg.BufferLength == 22, "size %d\n", stubMsg.BufferLength); 833 834 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer); 835 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength; 836 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v); 837 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength); 838 wirev = (DWORD*)buffer; 839 840 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength); 841 ok(*(short*)wirev == V_I2(&v), "wv[5] %08x\n", *wirev); 842 VariantInit(&v2); 843 stubMsg.Buffer = buffer; 844 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2); 845 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength); 846 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2)); 847 ok(V_I2(&v) == V_I2(&v2), "got i2 %x expect %x\n", V_I2(&v), V_I2(&v2)); 848 849 VARIANT_UserFree(&umcb.Flags, &v2); 850 HeapFree(GetProcessHeap(), 0, oldbuffer); 851 852 /*** I2 BYREF ***/ 853 VariantInit(&v); 854 V_VT(&v) = VT_I2 | VT_BYREF; 855 s = 0x1234; 856 V_I2REF(&v) = &s; 857 858 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v); 859 ok(stubMsg.BufferLength == 26, "size %d\n", stubMsg.BufferLength); 860 861 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer); 862 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength; 863 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v); 864 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength); 865 wirev = (DWORD*)buffer; 866 867 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength); 868 ok(*wirev == 0x4, "wv[5] %08x\n", *wirev); 869 wirev++; 870 ok(*(short*)wirev == s, "wv[6] %08x\n", *wirev); 871 VariantInit(&v2); 872 V_VT(&v2) = VT_I2 | VT_BYREF; 873 V_BYREF(&v2) = mem = CoTaskMemAlloc(sizeof(V_I2(&v2))); 874 stubMsg.Buffer = buffer; 875 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2); 876 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength); 877 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2)); 878 ok(V_BYREF(&v2) == mem, "didn't reuse existing memory\n"); 879 ok(*V_I2REF(&v) == *V_I2REF(&v2), "got i2 ref %x expect ui4 ref %x\n", *V_I2REF(&v), *V_I2REF(&v2)); 880 881 VARIANT_UserFree(&umcb.Flags, &v2); 882 HeapFree(GetProcessHeap(), 0, oldbuffer); 883 884 /*** I4 ***/ 885 VariantInit(&v); 886 V_VT(&v) = VT_I4; 887 V_I4(&v) = 0x1234; 888 889 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v); 890 ok(stubMsg.BufferLength == 24, "size %d\n", stubMsg.BufferLength); 891 892 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer); 893 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength; 894 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v); 895 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength); 896 wirev = (DWORD*)buffer; 897 898 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength); 899 ok(*wirev == V_I4(&v), "wv[5] %08x\n", *wirev); 900 901 VariantInit(&v2); 902 stubMsg.Buffer = buffer; 903 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2); 904 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength); 905 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2)); 906 ok(V_I4(&v) == V_I4(&v2), "got i4 %x expect %x\n", V_I4(&v), V_I4(&v2)); 907 908 VARIANT_UserFree(&umcb.Flags, &v2); 909 HeapFree(GetProcessHeap(), 0, oldbuffer); 910 911 /*** UI4 ***/ 912 VariantInit(&v); 913 V_VT(&v) = VT_UI4; 914 V_UI4(&v) = 0x1234; 915 916 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v); 917 ok(stubMsg.BufferLength == 24, "size %d\n", stubMsg.BufferLength); 918 919 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer); 920 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength; 921 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v); 922 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength); 923 wirev = (DWORD*)buffer; 924 925 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength); 926 ok(*wirev == 0x1234, "wv[5] %08x\n", *wirev); 927 VariantInit(&v2); 928 stubMsg.Buffer = buffer; 929 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2); 930 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength); 931 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2)); 932 ok(V_UI4(&v) == V_UI4(&v2), "got ui4 %x expect %x\n", V_UI4(&v), V_UI4(&v2)); 933 934 VARIANT_UserFree(&umcb.Flags, &v2); 935 HeapFree(GetProcessHeap(), 0, oldbuffer); 936 937 /*** UI4 BYREF ***/ 938 VariantInit(&v); 939 V_VT(&v) = VT_UI4 | VT_BYREF; 940 ul = 0x1234; 941 V_UI4REF(&v) = &ul; 942 943 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v); 944 ok(stubMsg.BufferLength == 28, "size %d\n", stubMsg.BufferLength); 945 946 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer); 947 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength; 948 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v); 949 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength); 950 wirev = (DWORD*)buffer; 951 952 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength); 953 ok(*wirev == 0x4, "wv[5] %08x\n", *wirev); 954 wirev++; 955 ok(*wirev == ul, "wv[6] %08x\n", *wirev); 956 957 VariantInit(&v2); 958 stubMsg.Buffer = buffer; 959 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2); 960 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength); 961 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2)); 962 ok(*V_UI4REF(&v) == *V_UI4REF(&v2), "got ui4 ref %x expect ui4 ref %x\n", *V_UI4REF(&v), *V_UI4REF(&v2)); 963 964 VARIANT_UserFree(&umcb.Flags, &v2); 965 HeapFree(GetProcessHeap(), 0, oldbuffer); 966 967 /*** R4 ***/ 968 VariantInit(&v); 969 V_VT(&v) = VT_R4; 970 V_R8(&v) = 3.1415; 971 972 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v); 973 ok(stubMsg.BufferLength == 24, "size %d\n", stubMsg.BufferLength); 974 975 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer); 976 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength; 977 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v); 978 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength); 979 wirev = (DWORD*)buffer; 980 981 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength); 982 ok(*(float*)wirev == V_R4(&v), "wv[5] %08x\n", *wirev); 983 VariantInit(&v2); 984 stubMsg.Buffer = buffer; 985 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2); 986 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength); 987 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2)); 988 ok(V_R4(&v) == V_R4(&v2), "got r4 %f expect %f\n", V_R4(&v), V_R4(&v2)); 989 990 VARIANT_UserFree(&umcb.Flags, &v2); 991 HeapFree(GetProcessHeap(), 0, oldbuffer); 992 993 /*** R8 ***/ 994 VariantInit(&v); 995 V_VT(&v) = VT_R8; 996 V_R8(&v) = 3.1415; 997 998 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v); 999 ok(stubMsg.BufferLength == 32, "size %d\n", stubMsg.BufferLength); 1000 1001 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer); 1002 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength; 1003 memset(buffer, 0xcc, stubMsg.BufferLength); 1004 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v); 1005 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength); 1006 wirev = (DWORD*)buffer; 1007 1008 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength); 1009 ok(*wirev == 0xcccccccc, "wv[5] %08x\n", *wirev); /* pad */ 1010 wirev++; 1011 ok(*(double*)wirev == V_R8(&v), "wv[6] %08x, wv[7] %08x\n", *wirev, *(wirev+1)); 1012 VariantInit(&v2); 1013 stubMsg.Buffer = buffer; 1014 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2); 1015 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength); 1016 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2)); 1017 ok(V_R8(&v) == V_R8(&v2), "got r8 %f expect %f\n", V_R8(&v), V_R8(&v2)); 1018 1019 VARIANT_UserFree(&umcb.Flags, &v2); 1020 HeapFree(GetProcessHeap(), 0, oldbuffer); 1021 1022 /*** R8 BYREF ***/ 1023 VariantInit(&v); 1024 V_VT(&v) = VT_R8 | VT_BYREF; 1025 d = 3.1415; 1026 V_R8REF(&v) = &d; 1027 1028 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v); 1029 ok(stubMsg.BufferLength == 32, "size %d\n", stubMsg.BufferLength); 1030 1031 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer); 1032 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength; 1033 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v); 1034 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength); 1035 wirev = (DWORD*)buffer; 1036 1037 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength); 1038 ok(*wirev == 8, "wv[5] %08x\n", *wirev); 1039 wirev++; 1040 ok(*(double*)wirev == d, "wv[6] %08x wv[7] %08x\n", *wirev, *(wirev+1)); 1041 VariantInit(&v2); 1042 stubMsg.Buffer = buffer; 1043 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2); 1044 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength); 1045 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2)); 1046 ok(*V_R8REF(&v) == *V_R8REF(&v2), "got r8 ref %f expect %f\n", *V_R8REF(&v), *V_R8REF(&v2)); 1047 1048 VARIANT_UserFree(&umcb.Flags, &v2); 1049 HeapFree(GetProcessHeap(), 0, oldbuffer); 1050 1051 /*** VARIANT_BOOL ***/ 1052 VariantInit(&v); 1053 V_VT(&v) = VT_BOOL; 1054 V_BOOL(&v) = 0x1234; 1055 1056 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v); 1057 ok(stubMsg.BufferLength == 22, "size %d\n", stubMsg.BufferLength); 1058 1059 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer); 1060 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength; 1061 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v); 1062 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength); 1063 wirev = (DWORD*)buffer; 1064 1065 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength); 1066 ok(*(short*)wirev == V_BOOL(&v), "wv[5] %04x\n", *(WORD*)wirev); 1067 VariantInit(&v2); 1068 stubMsg.Buffer = buffer; 1069 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2); 1070 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength); 1071 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2)); 1072 ok(V_BOOL(&v) == V_BOOL(&v2), "got bool %x expect %x\n", V_BOOL(&v), V_BOOL(&v2)); 1073 1074 VARIANT_UserFree(&umcb.Flags, &v2); 1075 HeapFree(GetProcessHeap(), 0, oldbuffer); 1076 1077 /*** DECIMAL ***/ 1078 VarDecFromI4(0x12345678, &dec); 1079 dec.wReserved = 0xfedc; /* Also initialize reserved field, as we check it later */ 1080 VariantInit(&v); 1081 V_DECIMAL(&v) = dec; 1082 V_VT(&v) = VT_DECIMAL; 1083 1084 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v); 1085 ok(stubMsg.BufferLength == 40, "size %d\n", stubMsg.BufferLength); 1086 1087 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer); 1088 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength; 1089 memset(buffer, 0xcc, stubMsg.BufferLength); 1090 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v); 1091 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength); 1092 wirev = (DWORD*)buffer; 1093 1094 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength); 1095 ok(*wirev == 0xcccccccc, "wirev[5] %08x\n", *wirev); /* pad */ 1096 wirev++; 1097 dec2 = dec; 1098 dec2.wReserved = VT_DECIMAL; 1099 ok(!memcmp(wirev, &dec2, sizeof(dec2)), "wirev[6] %08x wirev[7] %08x wirev[8] %08x wirev[9] %08x\n", 1100 *wirev, *(wirev + 1), *(wirev + 2), *(wirev + 3)); 1101 VariantInit(&v2); 1102 stubMsg.Buffer = buffer; 1103 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2); 1104 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength); 1105 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2)); 1106 ok(!memcmp(&V_DECIMAL(&v), & V_DECIMAL(&v2), sizeof(DECIMAL)), "decimals differ\n"); 1107 1108 VARIANT_UserFree(&umcb.Flags, &v2); 1109 HeapFree(GetProcessHeap(), 0, oldbuffer); 1110 1111 /*** DECIMAL BYREF ***/ 1112 VariantInit(&v); 1113 V_VT(&v) = VT_DECIMAL | VT_BYREF; 1114 V_DECIMALREF(&v) = &dec; 1115 1116 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v); 1117 ok(stubMsg.BufferLength == 40, "size %d\n", stubMsg.BufferLength); 1118 1119 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer); 1120 stubMsg.BufferEnd = stubMsg.Buffer + 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 == 16, "wv[5] %08x\n", *wirev); 1127 wirev++; 1128 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)); 1129 VariantInit(&v2); 1130 /* check_variant_header tests wReserved[123], so initialize to unique values. 1131 * (Could probably also do this by setting the variant to a known DECIMAL.) 1132 */ 1133 V_U2(&v2).wReserved1 = 0x0123; 1134 V_U2(&v2).wReserved2 = 0x4567; 1135 V_U2(&v2).wReserved3 = 0x89ab; 1136 1137 stubMsg.Buffer = buffer; 1138 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2); 1139 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength); 1140 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2)); 1141 ok(!memcmp(V_DECIMALREF(&v), V_DECIMALREF(&v2), sizeof(DECIMAL)), "decimals differ\n"); 1142 1143 VARIANT_UserFree(&umcb.Flags, &v2); 1144 HeapFree(GetProcessHeap(), 0, oldbuffer); 1145 1146 /*** EMPTY ***/ 1147 VariantInit(&v); 1148 V_VT(&v) = VT_EMPTY; 1149 1150 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v); 1151 ok(stubMsg.BufferLength == 20, "size %d\n", stubMsg.BufferLength); 1152 1153 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer); 1154 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength; 1155 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v); 1156 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength); 1157 wirev = (DWORD*)buffer; 1158 1159 check_variant_header(wirev, &v, stubMsg.BufferLength); 1160 VariantInit(&v2); 1161 stubMsg.Buffer = buffer; 1162 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2); 1163 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength); 1164 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2)); 1165 1166 VARIANT_UserFree(&umcb.Flags, &v2); 1167 HeapFree(GetProcessHeap(), 0, oldbuffer); 1168 1169 /*** NULL ***/ 1170 VariantInit(&v); 1171 V_VT(&v) = VT_NULL; 1172 1173 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v); 1174 ok(stubMsg.BufferLength == 20, "size %d\n", stubMsg.BufferLength); 1175 1176 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer); 1177 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength; 1178 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v); 1179 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength); 1180 wirev = (DWORD*)buffer; 1181 1182 check_variant_header(wirev, &v, stubMsg.BufferLength); 1183 VariantInit(&v2); 1184 stubMsg.Buffer = buffer; 1185 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2); 1186 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength); 1187 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2)); 1188 1189 VARIANT_UserFree(&umcb.Flags, &v2); 1190 HeapFree(GetProcessHeap(), 0, oldbuffer); 1191 1192 /*** BSTR ***/ 1193 b = SysAllocString(str); 1194 VariantInit(&v); 1195 V_VT(&v) = VT_BSTR; 1196 V_BSTR(&v) = b; 1197 1198 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v); 1199 ok(stubMsg.BufferLength == 60, "size %d\n", stubMsg.BufferLength); 1200 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer); 1201 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength; 1202 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v); 1203 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength); 1204 wirev = (DWORD*)buffer; 1205 1206 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength); 1207 ok(*wirev, "wv[5] %08x\n", *wirev); /* win2k: this is b. winxp: this is (char*)b + 1 */ 1208 wirev++; 1209 check_bstr(wirev, V_BSTR(&v)); 1210 VariantInit(&v2); 1211 stubMsg.Buffer = buffer; 1212 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2); 1213 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength); 1214 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2)); 1215 ok(SysStringByteLen(V_BSTR(&v)) == SysStringByteLen(V_BSTR(&v2)), "bstr string lens differ\n"); 1216 ok(!memcmp(V_BSTR(&v), V_BSTR(&v2), SysStringByteLen(V_BSTR(&v))), "bstrs differ\n"); 1217 1218 VARIANT_UserFree(&umcb.Flags, &v2); 1219 HeapFree(GetProcessHeap(), 0, oldbuffer); 1220 1221 /*** BSTR BYREF ***/ 1222 VariantInit(&v); 1223 V_VT(&v) = VT_BSTR | VT_BYREF; 1224 V_BSTRREF(&v) = &b; 1225 1226 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v); 1227 ok(stubMsg.BufferLength == 64, "size %d\n", stubMsg.BufferLength); 1228 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer); 1229 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength; 1230 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v); 1231 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength); 1232 wirev = (DWORD*)buffer; 1233 1234 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength); 1235 ok(*wirev == 0x4, "wv[5] %08x\n", *wirev); 1236 wirev++; 1237 ok(*wirev, "wv[6] %08x\n", *wirev); /* win2k: this is b. winxp: this is (char*)b + 1 */ 1238 wirev++; 1239 check_bstr(wirev, b); 1240 b2 = SysAllocString(str); 1241 b2[0] = 0; 1242 V_VT(&v2) = VT_BSTR | VT_BYREF; 1243 V_BSTRREF(&v2) = &b2; 1244 mem = b2; 1245 VariantInit(&v2); 1246 stubMsg.Buffer = buffer; 1247 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2); 1248 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength); 1249 ok(mem == b2, "BSTR should be reused\n"); 1250 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2)); 1251 ok(SysStringByteLen(*V_BSTRREF(&v)) == SysStringByteLen(*V_BSTRREF(&v2)), "bstr string lens differ\n"); 1252 ok(!memcmp(*V_BSTRREF(&v), *V_BSTRREF(&v2), SysStringByteLen(*V_BSTRREF(&v))), "bstrs differ\n"); 1253 1254 SysFreeString(b2); 1255 HeapFree(GetProcessHeap(), 0, oldbuffer); 1256 SysFreeString(b); 1257 1258 /*** ARRAY ***/ 1259 sab.lLbound = 5; 1260 sab.cElements = 10; 1261 1262 lpsa = SafeArrayCreate(VT_R8, 1, &sab); 1263 *(DWORD *)lpsa->pvData = 0xcafebabe; 1264 *((DWORD *)lpsa->pvData + 1) = 0xdeadbeef; 1265 1266 VariantInit(&v); 1267 V_VT(&v) = VT_UI4 | VT_ARRAY; 1268 V_ARRAY(&v) = lpsa; 1269 1270 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v); 1271 expected = 152; 1272 ok(stubMsg.BufferLength == expected || stubMsg.BufferLength == expected + 8, /* win64 */ 1273 "size %u instead of %u\n", stubMsg.BufferLength, expected); 1274 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer); 1275 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength; 1276 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v); 1277 ok(next == buffer + expected, "got %p expect %p\n", next, buffer + expected); 1278 wirev = (DWORD*)buffer; 1279 1280 wirev = check_variant_header(wirev, &v, expected); 1281 ok(*wirev, "wv[5] %08x\n", *wirev); /* win2k: this is lpsa. winxp: this is (char*)lpsa + 1 */ 1282 wirev++; 1283 check_safearray(wirev, lpsa); 1284 VariantInit(&v2); 1285 stubMsg.Buffer = buffer; 1286 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2); 1287 ok(next == buffer + expected, "got %p expect %p\n", next, buffer + expected); 1288 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2)); 1289 ok(SafeArrayGetDim(V_ARRAY(&v)) == SafeArrayGetDim(V_ARRAY(&v2)), "array dims differ\n"); 1290 SafeArrayGetLBound(V_ARRAY(&v), 1, &bound); 1291 SafeArrayGetLBound(V_ARRAY(&v2), 1, &bound2); 1292 ok(bound == bound2, "array lbounds differ\n"); 1293 SafeArrayGetUBound(V_ARRAY(&v), 1, &bound); 1294 SafeArrayGetUBound(V_ARRAY(&v2), 1, &bound2); 1295 ok(bound == bound2, "array ubounds differ\n"); 1296 if (pSafeArrayGetVartype) 1297 { 1298 pSafeArrayGetVartype(V_ARRAY(&v), &vt); 1299 pSafeArrayGetVartype(V_ARRAY(&v2), &vt2); 1300 ok(vt == vt2, "array vts differ %x %x\n", vt, vt2); 1301 } 1302 VARIANT_UserFree(&umcb.Flags, &v2); 1303 HeapFree(GetProcessHeap(), 0, oldbuffer); 1304 1305 /*** ARRAY BYREF ***/ 1306 VariantInit(&v); 1307 V_VT(&v) = VT_UI4 | VT_ARRAY | VT_BYREF; 1308 V_ARRAYREF(&v) = &lpsa; 1309 1310 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v); 1311 expected = 152; 1312 ok(stubMsg.BufferLength == expected || stubMsg.BufferLength == expected + 16, /* win64 */ 1313 "size %u instead of %u\n", stubMsg.BufferLength, expected); 1314 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer); 1315 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength; 1316 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v); 1317 ok(next == buffer + expected, "got %p expect %p\n", next, buffer + expected); 1318 wirev = (DWORD*)buffer; 1319 1320 wirev = check_variant_header(wirev, &v, expected); 1321 ok(*wirev == 4, "wv[5] %08x\n", *wirev); 1322 wirev++; 1323 ok(*wirev, "wv[6] %08x\n", *wirev); /* win2k: this is lpsa. winxp: this is (char*)lpsa + 1 */ 1324 wirev++; 1325 check_safearray(wirev, lpsa); 1326 VariantInit(&v2); 1327 stubMsg.Buffer = buffer; 1328 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2); 1329 ok(next == buffer + expected, "got %p expect %p\n", next, buffer + expected); 1330 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2)); 1331 ok(SafeArrayGetDim(*V_ARRAYREF(&v)) == SafeArrayGetDim(*V_ARRAYREF(&v2)), "array dims differ\n"); 1332 SafeArrayGetLBound(*V_ARRAYREF(&v), 1, &bound); 1333 SafeArrayGetLBound(*V_ARRAYREF(&v2), 1, &bound2); 1334 ok(bound == bound2, "array lbounds differ\n"); 1335 SafeArrayGetUBound(*V_ARRAYREF(&v), 1, &bound); 1336 SafeArrayGetUBound(*V_ARRAYREF(&v2), 1, &bound2); 1337 ok(bound == bound2, "array ubounds differ\n"); 1338 if (pSafeArrayGetVartype) 1339 { 1340 pSafeArrayGetVartype(*V_ARRAYREF(&v), &vt); 1341 pSafeArrayGetVartype(*V_ARRAYREF(&v2), &vt2); 1342 ok(vt == vt2, "array vts differ %x %x\n", vt, vt2); 1343 } 1344 VARIANT_UserFree(&umcb.Flags, &v2); 1345 HeapFree(GetProcessHeap(), 0, oldbuffer); 1346 1347 /*** ARRAY BYREF ***/ 1348 VariantInit(&v); 1349 V_VT(&v) = VT_UI4 | VT_ARRAY | VT_BYREF; 1350 V_ARRAYREF(&v) = &lpsa; 1351 lpsa->fFeatures |= FADF_STATIC; 1352 1353 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v); 1354 expected = 152; 1355 ok(stubMsg.BufferLength == expected || stubMsg.BufferLength == expected + 16, /* win64 */ 1356 "size %u instead of %u\n", stubMsg.BufferLength, expected); 1357 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer); 1358 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength; 1359 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v); 1360 ok(next == buffer + expected, "got %p expect %p\n", next, buffer + expected); 1361 wirev = (DWORD*)buffer; 1362 1363 wirev = check_variant_header(wirev, &v, expected); 1364 ok(*wirev == 4, "wv[5] %08x\n", *wirev); 1365 wirev++; 1366 ok(*wirev, "wv[6] %08x\n", *wirev); /* win2k: this is lpsa. winxp: this is (char*)lpsa + 1 */ 1367 wirev++; 1368 check_safearray(wirev, lpsa); 1369 lpsa_copy = lpsa2 = SafeArrayCreate(VT_I8, 1, &sab); 1370 /* set FADF_STATIC feature to make sure lpsa2->pvData pointer changes if new data buffer is allocated */ 1371 lpsa2->fFeatures |= FADF_STATIC; 1372 mem = lpsa2->pvData; 1373 V_VT(&v2) = VT_UI4 | VT_ARRAY | VT_BYREF; 1374 V_ARRAYREF(&v2) = &lpsa2; 1375 stubMsg.Buffer = buffer; 1376 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2); 1377 ok(next == buffer + expected, "got %p expect %p\n", next, buffer + expected); 1378 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2)); 1379 ok(lpsa2 == lpsa_copy, "safearray should be reused\n"); 1380 ok(mem == lpsa2->pvData, "safearray data should be reused\n"); 1381 ok(SafeArrayGetDim(*V_ARRAYREF(&v)) == SafeArrayGetDim(*V_ARRAYREF(&v2)), "array dims differ\n"); 1382 SafeArrayGetLBound(*V_ARRAYREF(&v), 1, &bound); 1383 SafeArrayGetLBound(*V_ARRAYREF(&v2), 1, &bound2); 1384 ok(bound == bound2, "array lbounds differ\n"); 1385 SafeArrayGetUBound(*V_ARRAYREF(&v), 1, &bound); 1386 SafeArrayGetUBound(*V_ARRAYREF(&v2), 1, &bound2); 1387 ok(bound == bound2, "array ubounds differ\n"); 1388 if (pSafeArrayGetVartype) 1389 { 1390 pSafeArrayGetVartype(*V_ARRAYREF(&v), &vt); 1391 pSafeArrayGetVartype(*V_ARRAYREF(&v2), &vt2); 1392 ok(vt == vt2, "array vts differ %x %x\n", vt, vt2); 1393 } 1394 lpsa2->fFeatures &= ~FADF_STATIC; 1395 hr = SafeArrayDestroy(*V_ARRAYREF(&v2)); 1396 ok(hr == S_OK, "got 0x%08x\n", hr); 1397 HeapFree(GetProcessHeap(), 0, oldbuffer); 1398 lpsa->fFeatures &= ~FADF_STATIC; 1399 hr = SafeArrayDestroy(lpsa); 1400 ok(hr == S_OK, "got 0x%08x\n", hr); 1401 1402 /*** VARIANT BYREF ***/ 1403 VariantInit(&v); 1404 VariantInit(&v2); 1405 V_VT(&v2) = VT_R8; 1406 V_R8(&v2) = 3.1415; 1407 V_VT(&v) = VT_VARIANT | VT_BYREF; 1408 V_VARIANTREF(&v) = &v2; 1409 1410 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v); 1411 ok(stubMsg.BufferLength == 64, "size %d\n", stubMsg.BufferLength); 1412 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer); 1413 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength; 1414 memset(buffer, 0xcc, stubMsg.BufferLength); 1415 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v); 1416 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength); 1417 wirev = (DWORD*)buffer; 1418 wirev = check_variant_header(wirev, &v, stubMsg.BufferLength); 1419 1420 ok(*wirev == sizeof(VARIANT), "wv[5] %08x\n", *wirev); 1421 wirev++; 1422 ok(*wirev == ('U' | 's' << 8 | 'e' << 16 | 'r' << 24), "wv[6] %08x\n", *wirev); /* 'User' */ 1423 wirev++; 1424 ok(*wirev == 0xcccccccc, "wv[7] %08x\n", *wirev); /* pad */ 1425 wirev++; 1426 wirev = check_variant_header(wirev, &v2, stubMsg.BufferLength - 32); 1427 ok(*wirev == 0xcccccccc, "wv[13] %08x\n", *wirev); /* pad for VT_R8 */ 1428 wirev++; 1429 ok(*(double*)wirev == V_R8(&v2), "wv[6] %08x wv[7] %08x\n", *wirev, *(wirev+1)); 1430 VariantInit(&v3); 1431 stubMsg.Buffer = buffer; 1432 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v3); 1433 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength); 1434 ok(V_VT(&v) == V_VT(&v3), "got vt %d expect %d\n", V_VT(&v), V_VT(&v3)); 1435 ok(V_VT(V_VARIANTREF(&v)) == V_VT(V_VARIANTREF(&v3)), "vts differ %x %x\n", 1436 V_VT(V_VARIANTREF(&v)), V_VT(V_VARIANTREF(&v3))); 1437 ok(V_R8(V_VARIANTREF(&v)) == V_R8(V_VARIANTREF(&v3)), "r8s differ\n"); 1438 VARIANT_UserFree(&umcb.Flags, &v3); 1439 HeapFree(GetProcessHeap(), 0, oldbuffer); 1440 1441 /*** UNKNOWN ***/ 1442 heap_unknown = HeapAlloc(GetProcessHeap(), 0, sizeof(*heap_unknown)); 1443 heap_unknown->IUnknown_iface.lpVtbl = &HeapUnknown_Vtbl; 1444 heap_unknown->refs = 1; 1445 VariantInit(&v); 1446 VariantInit(&v2); 1447 V_VT(&v) = VT_UNKNOWN; 1448 V_UNKNOWN(&v) = &heap_unknown->IUnknown_iface; 1449 1450 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v); 1451 ok(stubMsg.BufferLength > 40, "size %d\n", stubMsg.BufferLength); 1452 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer); 1453 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength; 1454 memset(buffer, 0xcc, stubMsg.BufferLength); 1455 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v); 1456 todo_wine 1457 ok(heap_unknown->refs == 2, "got refcount %d\n", heap_unknown->refs); 1458 wirev = (DWORD*)buffer; 1459 wirev = check_variant_header(wirev, &v, next - buffer); 1460 1461 ok(*wirev == (DWORD_PTR)V_UNKNOWN(&v) /* Win9x */ || 1462 *wirev == (DWORD_PTR)V_UNKNOWN(&v) + 1 /* NT */, "wv[5] %08x\n", *wirev); 1463 wirev++; 1464 ok(*wirev == next - buffer - 0x20, "wv[6] %08x\n", *wirev); 1465 wirev++; 1466 ok(*wirev == next - buffer - 0x20, "wv[7] %08x\n", *wirev); 1467 wirev++; 1468 ok(*wirev == 0x574f454d, "wv[8] %08x\n", *wirev); 1469 VariantInit(&v3); 1470 V_VT(&v3) = VT_UNKNOWN; 1471 V_UNKNOWN(&v3) = &heap_unknown->IUnknown_iface; 1472 IUnknown_AddRef(V_UNKNOWN(&v3)); 1473 stubMsg.Buffer = buffer; 1474 todo_wine 1475 ok(heap_unknown->refs == 3, "got refcount %d\n", heap_unknown->refs); 1476 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v3); 1477 ok(V_VT(&v) == V_VT(&v3), "got vt %d expect %d\n", V_VT(&v), V_VT(&v3)); 1478 ok(V_UNKNOWN(&v) == V_UNKNOWN(&v3), "got %p expect %p\n", V_UNKNOWN(&v), V_UNKNOWN(&v3)); 1479 VARIANT_UserFree(&umcb.Flags, &v3); 1480 ok(heap_unknown->refs == 1, "%d refcounts of IUnknown leaked\n", heap_unknown->refs - 1); 1481 IUnknown_Release(&heap_unknown->IUnknown_iface); 1482 HeapFree(GetProcessHeap(), 0, oldbuffer); 1483 1484 /*** NULL UNKNOWN ***/ 1485 VariantInit(&v); 1486 V_VT(&v) = VT_UNKNOWN; 1487 V_UNKNOWN(&v) = NULL; 1488 1489 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v); 1490 ok(stubMsg.BufferLength >= 24, "size %d\n", stubMsg.BufferLength); 1491 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer); 1492 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength; 1493 memset(buffer, 0xcc, stubMsg.BufferLength); 1494 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v); 1495 wirev = (DWORD*)buffer; 1496 wirev = check_variant_header(wirev, &v, next - buffer); 1497 ok(*wirev == 0, "wv[5] %08x\n", *wirev); 1498 1499 VariantInit(&v2); 1500 stubMsg.Buffer = buffer; 1501 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2); 1502 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2)); 1503 ok(V_UNKNOWN(&v2) == NULL, "got %p expect NULL\n", V_UNKNOWN(&v2)); 1504 VARIANT_UserFree(&umcb.Flags, &v2); 1505 HeapFree(GetProcessHeap(), 0, oldbuffer); 1506 1507 /*** UNKNOWN BYREF ***/ 1508 heap_unknown = HeapAlloc(GetProcessHeap(), 0, sizeof(*heap_unknown)); 1509 heap_unknown->IUnknown_iface.lpVtbl = &HeapUnknown_Vtbl; 1510 heap_unknown->refs = 1; 1511 VariantInit(&v); 1512 VariantInit(&v2); 1513 V_VT(&v) = VT_UNKNOWN | VT_BYREF; 1514 V_UNKNOWNREF(&v) = (IUnknown **)&heap_unknown; 1515 1516 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v); 1517 ok(stubMsg.BufferLength >= 44, "size %d\n", stubMsg.BufferLength); 1518 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer); 1519 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength; 1520 memset(buffer, 0xcc, stubMsg.BufferLength); 1521 ok(heap_unknown->refs == 1, "got refcount %d\n", heap_unknown->refs); 1522 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v); 1523 todo_wine 1524 ok(heap_unknown->refs == 2, "got refcount %d\n", heap_unknown->refs); 1525 wirev = (DWORD*)buffer; 1526 wirev = check_variant_header(wirev, &v, next - buffer); 1527 1528 ok(*wirev == 4, "wv[5] %08x\n", *wirev); 1529 wirev++; 1530 ok(*wirev == (DWORD_PTR)heap_unknown /* Win9x, Win2000 */ || 1531 *wirev == (DWORD_PTR)heap_unknown + 1 /* XP */, "wv[6] %08x\n", *wirev); 1532 wirev++; 1533 ok(*wirev == next - buffer - 0x24, "wv[7] %08x\n", *wirev); 1534 wirev++; 1535 ok(*wirev == next - buffer - 0x24, "wv[8] %08x\n", *wirev); 1536 wirev++; 1537 ok(*wirev == 0x574f454d, "wv[9] %08x\n", *wirev); 1538 1539 VariantInit(&v3); 1540 V_VT(&v3) = VT_UNKNOWN; 1541 V_UNKNOWN(&v3) = &heap_unknown->IUnknown_iface; 1542 IUnknown_AddRef(V_UNKNOWN(&v3)); 1543 stubMsg.Buffer = buffer; 1544 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v3); 1545 ok(heap_unknown->refs == 2, "got refcount %d\n", heap_unknown->refs); 1546 ok(V_VT(&v) == V_VT(&v3), "got vt %d expect %d\n", V_VT(&v), V_VT(&v3)); 1547 ok(*V_UNKNOWNREF(&v) == *V_UNKNOWNREF(&v3), "got %p expect %p\n", *V_UNKNOWNREF(&v), *V_UNKNOWNREF(&v3)); 1548 VARIANT_UserFree(&umcb.Flags, &v3); 1549 ok(heap_unknown->refs == 1, "%d refcounts of IUnknown leaked\n", heap_unknown->refs - 1); 1550 IUnknown_Release(&heap_unknown->IUnknown_iface); 1551 HeapFree(GetProcessHeap(), 0, oldbuffer); 1552 } 1553 1554 1555 START_TEST(usrmarshal) 1556 { 1557 HANDLE hOleaut32 = GetModuleHandleA("oleaut32.dll"); 1558 #define GETPTR(func) p##func = (void*)GetProcAddress(hOleaut32, #func) 1559 GETPTR(SafeArrayGetIID); 1560 GETPTR(SafeArrayGetVartype); 1561 GETPTR(VarBstrCmp); 1562 #undef GETPTR 1563 1564 if (!pSafeArrayGetIID || !pSafeArrayGetVartype) 1565 win_skip("SafeArrayGetIID and/or SafeArrayGetVartype is not available, some tests will be skipped\n"); 1566 1567 CoInitialize(NULL); 1568 1569 test_marshal_LPSAFEARRAY(); 1570 test_marshal_BSTR(); 1571 test_marshal_VARIANT(); 1572 1573 CoUninitialize(); 1574 } 1575