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