1 /* 2 * User Marshaling Tests 3 * 4 * Copyright 2004-2006 Robert Shearman for CodeWeavers 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 ULONG __RPC_USER HMETAFILE_UserSize(ULONG *, ULONG, HMETAFILE *); 24 unsigned char * __RPC_USER HMETAFILE_UserMarshal(ULONG *, unsigned char *, HMETAFILE *); 25 unsigned char * __RPC_USER HMETAFILE_UserUnmarshal(ULONG *, unsigned char *, HMETAFILE *); 26 void __RPC_USER HMETAFILE_UserFree(ULONG *, HMETAFILE *); 27 28 ULONG __RPC_USER HENHMETAFILE_UserSize(ULONG *, ULONG, HENHMETAFILE *); 29 unsigned char * __RPC_USER HENHMETAFILE_UserMarshal (ULONG *, unsigned char *, HENHMETAFILE *); 30 unsigned char * __RPC_USER HENHMETAFILE_UserUnmarshal(ULONG *, unsigned char *, HENHMETAFILE *); 31 void __RPC_USER HENHMETAFILE_UserFree(ULONG *, HENHMETAFILE *); 32 33 ULONG __RPC_USER HMETAFILEPICT_UserSize(ULONG *, ULONG, HMETAFILEPICT *); 34 unsigned char * __RPC_USER HMETAFILEPICT_UserMarshal (ULONG *, unsigned char *, HMETAFILEPICT *); 35 unsigned char * __RPC_USER HMETAFILEPICT_UserUnmarshal(ULONG *, unsigned char *, HMETAFILEPICT *); 36 void __RPC_USER HMETAFILEPICT_UserFree(ULONG *, HMETAFILEPICT *); 37 38 ULONG __RPC_USER HBRUSH_UserSize(ULONG *, ULONG, HBRUSH *); 39 unsigned char * __RPC_USER HBRUSH_UserMarshal(ULONG *, unsigned char *, HBRUSH *); 40 unsigned char * __RPC_USER HBRUSH_UserUnmarshal(ULONG *, unsigned char *, HBRUSH *); 41 void __RPC_USER HBRUSH_UserFree(ULONG *, HBRUSH *); 42 43 static BOOL g_expect_user_alloc; 44 static void * WINAPI user_allocate(SIZE_T size) 45 { 46 ok(g_expect_user_alloc, "unexpected user_allocate call\n"); 47 return CoTaskMemAlloc(size); 48 } 49 50 static BOOL g_expect_user_free; 51 static void WINAPI user_free(void *p) 52 { 53 ok(g_expect_user_free, "unexpected user_free call\n"); 54 CoTaskMemFree(p); 55 } 56 57 static void init_user_marshal_cb(USER_MARSHAL_CB *umcb, 58 PMIDL_STUB_MESSAGE stub_msg, 59 PRPC_MESSAGE rpc_msg, unsigned char *buffer, 60 unsigned int size, MSHCTX context) 61 { 62 memset(rpc_msg, 0, sizeof(*rpc_msg)); 63 rpc_msg->Buffer = buffer; 64 rpc_msg->BufferLength = size; 65 66 memset(stub_msg, 0, sizeof(*stub_msg)); 67 stub_msg->RpcMsg = rpc_msg; 68 stub_msg->Buffer = buffer; 69 stub_msg->pfnAllocate = user_allocate; 70 stub_msg->pfnFree = user_free; 71 72 memset(umcb, 0, sizeof(*umcb)); 73 umcb->Flags = MAKELONG(context, NDR_LOCAL_DATA_REPRESENTATION); 74 umcb->pStubMsg = stub_msg; 75 umcb->Signature = USER_MARSHAL_CB_SIGNATURE; 76 umcb->CBType = buffer ? USER_MARSHAL_CB_UNMARSHALL : USER_MARSHAL_CB_BUFFER_SIZE; 77 } 78 79 #define RELEASEMARSHALDATA WM_USER 80 81 struct host_object_data 82 { 83 IStream *stream; 84 IID iid; 85 IUnknown *object; 86 MSHLFLAGS marshal_flags; 87 HANDLE marshal_event; 88 IMessageFilter *filter; 89 }; 90 91 static DWORD CALLBACK host_object_proc(LPVOID p) 92 { 93 struct host_object_data *data = p; 94 HRESULT hr; 95 MSG msg; 96 97 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 98 99 if (data->filter) 100 { 101 IMessageFilter * prev_filter = NULL; 102 hr = CoRegisterMessageFilter(data->filter, &prev_filter); 103 if (prev_filter) IMessageFilter_Release(prev_filter); 104 ok(hr == S_OK, "got %08x\n", hr); 105 } 106 107 hr = CoMarshalInterface(data->stream, &data->iid, data->object, MSHCTX_INPROC, NULL, data->marshal_flags); 108 ok(hr == S_OK, "got %08x\n", hr); 109 110 /* force the message queue to be created before signaling parent thread */ 111 PeekMessageA(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE); 112 113 SetEvent(data->marshal_event); 114 115 while (GetMessageA(&msg, NULL, 0, 0)) 116 { 117 if (msg.hwnd == NULL && msg.message == RELEASEMARSHALDATA) 118 { 119 CoReleaseMarshalData(data->stream); 120 SetEvent((HANDLE)msg.lParam); 121 } 122 else 123 DispatchMessageA(&msg); 124 } 125 126 HeapFree(GetProcessHeap(), 0, data); 127 128 CoUninitialize(); 129 130 return hr; 131 } 132 133 static DWORD start_host_object2(IStream *stream, REFIID riid, IUnknown *object, MSHLFLAGS marshal_flags, IMessageFilter *filter, HANDLE *thread) 134 { 135 DWORD tid = 0; 136 HANDLE marshal_event = CreateEventA(NULL, FALSE, FALSE, NULL); 137 struct host_object_data *data = HeapAlloc(GetProcessHeap(), 0, sizeof(*data)); 138 139 data->stream = stream; 140 data->iid = *riid; 141 data->object = object; 142 data->marshal_flags = marshal_flags; 143 data->marshal_event = marshal_event; 144 data->filter = filter; 145 146 *thread = CreateThread(NULL, 0, host_object_proc, data, 0, &tid); 147 148 /* wait for marshaling to complete before returning */ 149 ok( !WaitForSingleObject(marshal_event, 10000), "wait timed out\n" ); 150 CloseHandle(marshal_event); 151 152 return tid; 153 } 154 155 static void end_host_object(DWORD tid, HANDLE thread) 156 { 157 BOOL ret = PostThreadMessageA(tid, WM_QUIT, 0, 0); 158 ok(ret, "PostThreadMessage failed with error %d\n", GetLastError()); 159 /* be careful of races - don't return until hosting thread has terminated */ 160 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" ); 161 CloseHandle(thread); 162 } 163 164 static const char cf_marshaled[] = 165 { 166 0x9, 0x0, 0x0, 0x0, 167 0x0, 0x0, 0x0, 0x0, 168 0x9, 0x0, 0x0, 0x0, 169 'M', 0x0, 'y', 0x0, 170 'F', 0x0, 'o', 0x0, 171 'r', 0x0, 'm', 0x0, 172 'a', 0x0, 't', 0x0, 173 0x0, 0x0 174 }; 175 176 static void test_marshal_CLIPFORMAT(void) 177 { 178 USER_MARSHAL_CB umcb; 179 MIDL_STUB_MESSAGE stub_msg; 180 RPC_MESSAGE rpc_msg; 181 unsigned char *buffer; 182 ULONG i, size; 183 CLIPFORMAT cf = RegisterClipboardFormatA("MyFormat"); 184 CLIPFORMAT cf2; 185 186 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE); 187 size = CLIPFORMAT_UserSize(&umcb.Flags, 0, &cf); 188 ok(size == 8 + sizeof(cf_marshaled) || 189 broken(size == 12 + sizeof(cf_marshaled)) || /* win64 adds 4 extra (unused) bytes */ 190 broken(size == 8 + sizeof(cf_marshaled) - 2), /* win9x and winnt don't include the '\0' */ 191 "CLIPFORMAT: Wrong size %d\n", size); 192 193 buffer = HeapAlloc(GetProcessHeap(), 0, size); 194 memset( buffer, 0xcc, size ); 195 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE); 196 CLIPFORMAT_UserMarshal(&umcb.Flags, buffer, &cf); 197 ok(*(LONG *)(buffer + 0) == WDT_REMOTE_CALL, "CLIPFORMAT: Context should be WDT_REMOTE_CALL instead of 0x%08x\n", *(LONG *)(buffer + 0)); 198 ok(*(DWORD *)(buffer + 4) == cf, "CLIPFORMAT: Marshaled value should be 0x%04x instead of 0x%04x\n", cf, *(DWORD *)(buffer + 4)); 199 ok(!memcmp(buffer + 8, cf_marshaled, min( sizeof(cf_marshaled), size-8 )), "Marshaled data differs\n"); 200 if (size > sizeof(cf_marshaled) + 8) /* make sure the extra bytes are not used */ 201 for (i = sizeof(cf_marshaled) + 8; i < size; i++) 202 ok( buffer[i] == 0xcc, "buffer offset %u has been set to %x\n", i, buffer[i] ); 203 204 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE); 205 CLIPFORMAT_UserUnmarshal(&umcb.Flags, buffer, &cf2); 206 ok(cf == cf2, "CLIPFORMAT: Didn't unmarshal properly\n"); 207 HeapFree(GetProcessHeap(), 0, buffer); 208 209 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE); 210 CLIPFORMAT_UserFree(&umcb.Flags, &cf2); 211 } 212 213 static void test_marshal_HWND(void) 214 { 215 USER_MARSHAL_CB umcb; 216 MIDL_STUB_MESSAGE stub_msg; 217 RPC_MESSAGE rpc_msg; 218 unsigned char *buffer; 219 ULONG size; 220 HWND hwnd = GetDesktopWindow(); 221 HWND hwnd2; 222 wireHWND wirehwnd; 223 224 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL); 225 size = HWND_UserSize(&umcb.Flags, 0, &hwnd); 226 ok(size == sizeof(*wirehwnd), "Wrong size %d\n", size); 227 228 buffer = HeapAlloc(GetProcessHeap(), 0, size); 229 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL); 230 HWND_UserMarshal(&umcb.Flags, buffer, &hwnd); 231 wirehwnd = (wireHWND)buffer; 232 ok(wirehwnd->fContext == WDT_INPROC_CALL, "Context should be WDT_INPROC_CALL instead of 0x%08x\n", wirehwnd->fContext); 233 ok(wirehwnd->u.hInproc == (LONG_PTR)hwnd, "Marshaled value should be %p instead of %x\n", hwnd, wirehwnd->u.hRemote); 234 235 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL); 236 HWND_UserUnmarshal(&umcb.Flags, buffer, &hwnd2); 237 ok(hwnd == hwnd2, "Didn't unmarshal properly\n"); 238 HeapFree(GetProcessHeap(), 0, buffer); 239 240 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL); 241 HWND_UserFree(&umcb.Flags, &hwnd2); 242 } 243 244 static void test_marshal_HGLOBAL(void) 245 { 246 USER_MARSHAL_CB umcb; 247 MIDL_STUB_MESSAGE stub_msg; 248 RPC_MESSAGE rpc_msg; 249 unsigned char *buffer; 250 ULONG size, block_size; 251 HGLOBAL hglobal; 252 HGLOBAL hglobal2; 253 unsigned char *wirehglobal; 254 int i; 255 256 hglobal = NULL; 257 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL); 258 size = HGLOBAL_UserSize(&umcb.Flags, 0, &hglobal); 259 /* native is poorly programmed and allocates 4/8 bytes more than it needs to 260 * here - Wine doesn't have to emulate that */ 261 ok((size == 8) || broken(size == 12) || broken(size == 16), "Size should be 8, instead of %d\n", size); 262 buffer = HeapAlloc(GetProcessHeap(), 0, size); 263 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL); 264 HGLOBAL_UserMarshal(&umcb.Flags, buffer, &hglobal); 265 wirehglobal = buffer; 266 ok(*(ULONG *)wirehglobal == WDT_REMOTE_CALL, "Context should be WDT_REMOTE_CALL instead of 0x%08x\n", *(ULONG *)wirehglobal); 267 wirehglobal += sizeof(ULONG); 268 ok(*(ULONG *)wirehglobal == 0, "buffer+4 should be HGLOBAL\n"); 269 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL); 270 hglobal2 = NULL; 271 HGLOBAL_UserUnmarshal(&umcb.Flags, buffer, &hglobal2); 272 ok(hglobal2 == hglobal, "Didn't unmarshal properly\n"); 273 HeapFree(GetProcessHeap(), 0, buffer); 274 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL); 275 HGLOBAL_UserFree(&umcb.Flags, &hglobal2); 276 277 278 for(block_size = 0; block_size <= 17; block_size++) 279 { 280 ULONG actual_size, expected_size; 281 282 hglobal = GlobalAlloc(0, block_size); 283 buffer = GlobalLock(hglobal); 284 for (i = 0; i < block_size; i++) 285 buffer[i] = i; 286 GlobalUnlock(hglobal); 287 actual_size = GlobalSize(hglobal); 288 expected_size = actual_size + 5 * sizeof(DWORD); 289 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL); 290 size = HGLOBAL_UserSize(&umcb.Flags, 0, &hglobal); 291 /* native is poorly programmed and allocates 4/8 bytes more than it needs to 292 * here - Wine doesn't have to emulate that */ 293 ok(size == expected_size || 294 broken(size == expected_size + 4) || 295 broken(size == expected_size + 8), 296 "%d: got size %d\n", block_size, size); 297 buffer = HeapAlloc(GetProcessHeap(), 0, size); 298 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL); 299 HGLOBAL_UserMarshal(&umcb.Flags, buffer, &hglobal); 300 wirehglobal = buffer; 301 ok(*(ULONG *)wirehglobal == WDT_REMOTE_CALL, "Context should be WDT_REMOTE_CALL instead of 0x%08x\n", *(ULONG *)wirehglobal); 302 wirehglobal += sizeof(ULONG); 303 ok(*(ULONG *)wirehglobal == (ULONG)(ULONG_PTR)hglobal, "buffer+0x4 should be HGLOBAL\n"); 304 wirehglobal += sizeof(ULONG); 305 ok(*(ULONG *)wirehglobal == actual_size, "%d: buffer+0x8 %08x\n", block_size, *(ULONG *)wirehglobal); 306 wirehglobal += sizeof(ULONG); 307 ok(*(ULONG *)wirehglobal == (ULONG)(ULONG_PTR)hglobal, "buffer+0xc should be HGLOBAL\n"); 308 wirehglobal += sizeof(ULONG); 309 ok(*(ULONG *)wirehglobal == actual_size, "%d: buffer+0x10 %08x\n", block_size, *(ULONG *)wirehglobal); 310 wirehglobal += sizeof(ULONG); 311 for (i = 0; i < block_size; i++) 312 ok(wirehglobal[i] == i, "buffer+0x%x should be %d\n", 0x10 + i, i); 313 314 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL); 315 hglobal2 = NULL; 316 HGLOBAL_UserUnmarshal(&umcb.Flags, buffer, &hglobal2); 317 ok(hglobal2 != NULL, "Didn't unmarshal properly\n"); 318 HeapFree(GetProcessHeap(), 0, buffer); 319 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL); 320 HGLOBAL_UserFree(&umcb.Flags, &hglobal2); 321 GlobalFree(hglobal); 322 } 323 } 324 325 static HENHMETAFILE create_emf(void) 326 { 327 const RECT rect = {0, 0, 100, 100}; 328 HDC hdc = CreateEnhMetaFileA(NULL, NULL, &rect, "HENHMETAFILE Marshaling Test\0Test\0\0"); 329 ExtTextOutA(hdc, 0, 0, ETO_OPAQUE, &rect, "Test String", strlen("Test String"), NULL); 330 return CloseEnhMetaFile(hdc); 331 } 332 333 static void test_marshal_HENHMETAFILE(void) 334 { 335 USER_MARSHAL_CB umcb; 336 MIDL_STUB_MESSAGE stub_msg; 337 RPC_MESSAGE rpc_msg; 338 unsigned char *buffer; 339 ULONG size; 340 HENHMETAFILE hemf; 341 HENHMETAFILE hemf2 = NULL; 342 unsigned char *wirehemf; 343 344 hemf = create_emf(); 345 346 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE); 347 size = HENHMETAFILE_UserSize(&umcb.Flags, 0, &hemf); 348 ok(size > 20, "size should be at least 20 bytes, not %d\n", size); 349 buffer = HeapAlloc(GetProcessHeap(), 0, size); 350 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE); 351 HENHMETAFILE_UserMarshal(&umcb.Flags, buffer, &hemf); 352 wirehemf = buffer; 353 ok(*(DWORD *)wirehemf == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehemf); 354 wirehemf += sizeof(DWORD); 355 ok(*(DWORD *)wirehemf == (DWORD)(DWORD_PTR)hemf, "wirestgm + 0x4 should be hemf instead of 0x%08x\n", *(DWORD *)wirehemf); 356 wirehemf += sizeof(DWORD); 357 ok(*(DWORD *)wirehemf == (size - 0x10), "wirestgm + 0x8 should be size - 0x10 instead of 0x%08x\n", *(DWORD *)wirehemf); 358 wirehemf += sizeof(DWORD); 359 ok(*(DWORD *)wirehemf == (size - 0x10), "wirestgm + 0xc should be size - 0x10 instead of 0x%08x\n", *(DWORD *)wirehemf); 360 wirehemf += sizeof(DWORD); 361 ok(*(DWORD *)wirehemf == EMR_HEADER, "wirestgm + 0x10 should be EMR_HEADER instead of %d\n", *(DWORD *)wirehemf); 362 /* ... rest of data not tested - refer to tests for GetEnhMetaFileBits 363 * at this point */ 364 365 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE); 366 HENHMETAFILE_UserUnmarshal(&umcb.Flags, buffer, &hemf2); 367 ok(hemf2 != NULL, "HENHMETAFILE didn't unmarshal\n"); 368 HeapFree(GetProcessHeap(), 0, buffer); 369 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE); 370 HENHMETAFILE_UserFree(&umcb.Flags, &hemf2); 371 DeleteEnhMetaFile(hemf); 372 373 /* test NULL emf */ 374 hemf = NULL; 375 376 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE); 377 size = HENHMETAFILE_UserSize(&umcb.Flags, 0, &hemf); 378 ok(size == 8, "size should be 8 bytes, not %d\n", size); 379 buffer = HeapAlloc(GetProcessHeap(), 0, size); 380 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE); 381 HENHMETAFILE_UserMarshal(&umcb.Flags, buffer, &hemf); 382 wirehemf = buffer; 383 ok(*(DWORD *)wirehemf == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehemf); 384 wirehemf += sizeof(DWORD); 385 ok(*(DWORD *)wirehemf == (DWORD)(DWORD_PTR)hemf, "wirestgm + 0x4 should be hemf instead of 0x%08x\n", *(DWORD *)wirehemf); 386 387 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE); 388 HENHMETAFILE_UserUnmarshal(&umcb.Flags, buffer, &hemf2); 389 ok(hemf2 == NULL, "NULL HENHMETAFILE didn't unmarshal\n"); 390 HeapFree(GetProcessHeap(), 0, buffer); 391 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE); 392 HENHMETAFILE_UserFree(&umcb.Flags, &hemf2); 393 } 394 395 static HMETAFILE create_mf(void) 396 { 397 RECT rect = {0, 0, 100, 100}; 398 HDC hdc = CreateMetaFileA(NULL); 399 ExtTextOutA(hdc, 0, 0, ETO_OPAQUE, &rect, "Test String", strlen("Test String"), NULL); 400 return CloseMetaFile(hdc); 401 } 402 403 static void test_marshal_HMETAFILE(void) 404 { 405 USER_MARSHAL_CB umcb; 406 MIDL_STUB_MESSAGE stub_msg; 407 RPC_MESSAGE rpc_msg; 408 unsigned char *buffer; 409 ULONG size; 410 HMETAFILE hmf; 411 HMETAFILE hmf2 = NULL; 412 unsigned char *wirehmf; 413 414 hmf = create_mf(); 415 416 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE); 417 size = HMETAFILE_UserSize(&umcb.Flags, 0, &hmf); 418 ok(size > 20, "size should be at least 20 bytes, not %d\n", size); 419 buffer = HeapAlloc(GetProcessHeap(), 0, size); 420 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE); 421 HMETAFILE_UserMarshal(&umcb.Flags, buffer, &hmf); 422 wirehmf = buffer; 423 ok(*(DWORD *)wirehmf == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehmf); 424 wirehmf += sizeof(DWORD); 425 ok(*(DWORD *)wirehmf == (DWORD)(DWORD_PTR)hmf, "wirestgm + 0x4 should be hmf instead of 0x%08x\n", *(DWORD *)wirehmf); 426 wirehmf += sizeof(DWORD); 427 ok(*(DWORD *)wirehmf == (size - 0x10), "wirestgm + 0x8 should be size - 0x10 instead of 0x%08x\n", *(DWORD *)wirehmf); 428 wirehmf += sizeof(DWORD); 429 ok(*(DWORD *)wirehmf == (size - 0x10), "wirestgm + 0xc should be size - 0x10 instead of 0x%08x\n", *(DWORD *)wirehmf); 430 wirehmf += sizeof(DWORD); 431 ok(*(WORD *)wirehmf == 1, "wirestgm + 0x10 should be 1 instead of 0x%08x\n", *(DWORD *)wirehmf); 432 wirehmf += sizeof(DWORD); 433 /* ... rest of data not tested - refer to tests for GetMetaFileBits 434 * at this point */ 435 436 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE); 437 HMETAFILE_UserUnmarshal(&umcb.Flags, buffer, &hmf2); 438 ok(hmf2 != NULL, "HMETAFILE didn't unmarshal\n"); 439 HeapFree(GetProcessHeap(), 0, buffer); 440 HMETAFILE_UserFree(&umcb.Flags, &hmf2); 441 DeleteMetaFile(hmf); 442 443 /* test NULL emf */ 444 hmf = NULL; 445 446 size = HMETAFILE_UserSize(&umcb.Flags, 0, &hmf); 447 ok(size == 8, "size should be 8 bytes, not %d\n", size); 448 buffer = HeapAlloc(GetProcessHeap(), 0, size); 449 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE); 450 HMETAFILE_UserMarshal(&umcb.Flags, buffer, &hmf); 451 wirehmf = buffer; 452 ok(*(DWORD *)wirehmf == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehmf); 453 wirehmf += sizeof(DWORD); 454 ok(*(DWORD *)wirehmf == (DWORD)(DWORD_PTR)hmf, "wirestgm + 0x4 should be hmf instead of 0x%08x\n", *(DWORD *)wirehmf); 455 wirehmf += sizeof(DWORD); 456 457 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE); 458 HMETAFILE_UserUnmarshal(&umcb.Flags, buffer, &hmf2); 459 ok(hmf2 == NULL, "NULL HMETAFILE didn't unmarshal\n"); 460 HeapFree(GetProcessHeap(), 0, buffer); 461 HMETAFILE_UserFree(&umcb.Flags, &hmf2); 462 } 463 464 #define USER_MARSHAL_PTR_PREFIX \ 465 ( (DWORD)'U' | ( (DWORD)'s' << 8 ) | \ 466 ( (DWORD)'e' << 16 ) | ( (DWORD)'r' << 24 ) ) 467 468 static void test_marshal_HMETAFILEPICT(void) 469 { 470 USER_MARSHAL_CB umcb; 471 MIDL_STUB_MESSAGE stub_msg; 472 RPC_MESSAGE rpc_msg; 473 unsigned char *buffer, *buffer_end; 474 ULONG size; 475 HMETAFILEPICT hmfp; 476 HMETAFILEPICT hmfp2 = NULL; 477 METAFILEPICT *pmfp; 478 unsigned char *wirehmfp; 479 480 hmfp = GlobalAlloc(GMEM_MOVEABLE, sizeof(*pmfp)); 481 pmfp = GlobalLock(hmfp); 482 pmfp->mm = MM_ISOTROPIC; 483 pmfp->xExt = 1; 484 pmfp->yExt = 2; 485 pmfp->hMF = create_mf(); 486 GlobalUnlock(hmfp); 487 488 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE); 489 size = HMETAFILEPICT_UserSize(&umcb.Flags, 0, &hmfp); 490 ok(size > 20, "size should be at least 20 bytes, not %d\n", size); 491 buffer = HeapAlloc(GetProcessHeap(), 0, size); 492 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE); 493 buffer_end = HMETAFILEPICT_UserMarshal(&umcb.Flags, buffer, &hmfp); 494 wirehmfp = buffer; 495 ok(*(DWORD *)wirehmfp == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehmfp); 496 wirehmfp += sizeof(DWORD); 497 ok(*(DWORD *)wirehmfp == (DWORD)(DWORD_PTR)hmfp, "wirestgm + 0x4 should be hmf instead of 0x%08x\n", *(DWORD *)wirehmfp); 498 wirehmfp += sizeof(DWORD); 499 ok(*(DWORD *)wirehmfp == MM_ISOTROPIC, "wirestgm + 0x8 should be MM_ISOTROPIC instead of 0x%08x\n", *(DWORD *)wirehmfp); 500 wirehmfp += sizeof(DWORD); 501 ok(*(DWORD *)wirehmfp == 1, "wirestgm + 0xc should be 1 instead of 0x%08x\n", *(DWORD *)wirehmfp); 502 wirehmfp += sizeof(DWORD); 503 ok(*(DWORD *)wirehmfp == 2, "wirestgm + 0x10 should be 2 instead of 0x%08x\n", *(DWORD *)wirehmfp); 504 wirehmfp += sizeof(DWORD); 505 ok(*(DWORD *)wirehmfp == USER_MARSHAL_PTR_PREFIX, "wirestgm + 0x14 should be \"User\" instead of 0x%08x\n", *(DWORD *)wirehmfp); 506 wirehmfp += sizeof(DWORD); 507 ok(*(DWORD *)wirehmfp == WDT_REMOTE_CALL, "wirestgm + 0x18 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehmfp); 508 wirehmfp += sizeof(DWORD); 509 pmfp = GlobalLock(hmfp); 510 ok(*(DWORD *)wirehmfp == (DWORD)(DWORD_PTR)pmfp->hMF, "wirestgm + 0x1c should be pmfp->hMF instead of 0x%08x\n", *(DWORD *)wirehmfp); 511 GlobalUnlock(hmfp); 512 wirehmfp += sizeof(DWORD); 513 /* Note use (buffer_end - buffer) instead of size here, because size is an 514 * overestimate with native */ 515 ok(*(DWORD *)wirehmfp == (buffer_end - buffer - 0x28), "wirestgm + 0x20 should be size - 0x34 instead of 0x%08x\n", *(DWORD *)wirehmfp); 516 wirehmfp += sizeof(DWORD); 517 ok(*(DWORD *)wirehmfp == (buffer_end - buffer - 0x28), "wirestgm + 0x24 should be size - 0x34 instead of 0x%08x\n", *(DWORD *)wirehmfp); 518 wirehmfp += sizeof(DWORD); 519 ok(*(WORD *)wirehmfp == 1, "wirehmfp + 0x28 should be 1 instead of 0x%08x\n", *(DWORD *)wirehmfp); 520 /* ... rest of data not tested - refer to tests for GetMetaFileBits 521 * at this point */ 522 523 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE); 524 HMETAFILEPICT_UserUnmarshal(&umcb.Flags, buffer, &hmfp2); 525 ok(hmfp2 != NULL, "HMETAFILEPICT didn't unmarshal\n"); 526 HeapFree(GetProcessHeap(), 0, buffer); 527 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE); 528 HMETAFILEPICT_UserFree(&umcb.Flags, &hmfp2); 529 pmfp = GlobalLock(hmfp); 530 DeleteMetaFile(pmfp->hMF); 531 GlobalUnlock(hmfp); 532 GlobalFree(hmfp); 533 534 /* test NULL emf */ 535 hmfp = NULL; 536 537 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE); 538 size = HMETAFILEPICT_UserSize(&umcb.Flags, 0, &hmfp); 539 ok(size == 8, "size should be 8 bytes, not %d\n", size); 540 buffer = HeapAlloc(GetProcessHeap(), 0, size); 541 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE); 542 HMETAFILEPICT_UserMarshal(&umcb.Flags, buffer, &hmfp); 543 wirehmfp = buffer; 544 ok(*(DWORD *)wirehmfp == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehmfp); 545 wirehmfp += sizeof(DWORD); 546 ok(*(DWORD *)wirehmfp == (DWORD)(DWORD_PTR)hmfp, "wirestgm + 0x4 should be hmf instead of 0x%08x\n", *(DWORD *)wirehmfp); 547 wirehmfp += sizeof(DWORD); 548 549 hmfp2 = NULL; 550 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE); 551 HMETAFILEPICT_UserUnmarshal(&umcb.Flags, buffer, &hmfp2); 552 ok(hmfp2 == NULL, "NULL HMETAFILE didn't unmarshal\n"); 553 HeapFree(GetProcessHeap(), 0, buffer); 554 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE); 555 HMETAFILEPICT_UserFree(&umcb.Flags, &hmfp2); 556 } 557 558 typedef struct 559 { 560 IUnknown IUnknown_iface; 561 LONG refs; 562 } TestUnknown; 563 564 static inline TestUnknown *impl_from_IUnknown(IUnknown *iface) 565 { 566 return CONTAINING_RECORD(iface, TestUnknown, IUnknown_iface); 567 } 568 569 static HRESULT WINAPI Test_IUnknown_QueryInterface( 570 LPUNKNOWN iface, 571 REFIID riid, 572 LPVOID *ppvObj) 573 { 574 if (ppvObj == NULL) return E_POINTER; 575 576 if (IsEqualGUID(riid, &IID_IUnknown)) 577 { 578 *ppvObj = iface; 579 IUnknown_AddRef(iface); 580 return S_OK; 581 } 582 583 *ppvObj = NULL; 584 return E_NOINTERFACE; 585 } 586 587 static ULONG WINAPI Test_IUnknown_AddRef(LPUNKNOWN iface) 588 { 589 TestUnknown *This = impl_from_IUnknown(iface); 590 return InterlockedIncrement(&This->refs); 591 } 592 593 static ULONG WINAPI Test_IUnknown_Release(LPUNKNOWN iface) 594 { 595 TestUnknown *This = impl_from_IUnknown(iface); 596 return InterlockedDecrement(&This->refs); 597 } 598 599 static const IUnknownVtbl TestUnknown_Vtbl = 600 { 601 Test_IUnknown_QueryInterface, 602 Test_IUnknown_AddRef, 603 Test_IUnknown_Release, 604 }; 605 606 struct test_stream 607 { 608 IStream IStream_iface; 609 LONG refs; 610 }; 611 612 static inline struct test_stream *impl_from_IStream(IStream *iface) 613 { 614 return CONTAINING_RECORD(iface, struct test_stream, IStream_iface); 615 } 616 617 static HRESULT WINAPI Test_IStream_QueryInterface(IStream *iface, 618 REFIID riid, LPVOID *ppvObj) 619 { 620 if (ppvObj == NULL) return E_POINTER; 621 622 if (IsEqualIID(riid, &IID_IUnknown) || 623 IsEqualIID(riid, &IID_IStream)) 624 { 625 *ppvObj = iface; 626 IStream_AddRef(iface); 627 return S_OK; 628 } 629 630 *ppvObj = NULL; 631 return E_NOINTERFACE; 632 } 633 634 static ULONG WINAPI Test_IStream_AddRef(IStream *iface) 635 { 636 struct test_stream *This = impl_from_IStream(iface); 637 return InterlockedIncrement(&This->refs); 638 } 639 640 static ULONG WINAPI Test_IStream_Release(IStream *iface) 641 { 642 struct test_stream *This = impl_from_IStream(iface); 643 return InterlockedDecrement(&This->refs); 644 } 645 646 static const IStreamVtbl TestStream_Vtbl = 647 { 648 Test_IStream_QueryInterface, 649 Test_IStream_AddRef, 650 Test_IStream_Release 651 /* the rest can be NULLs */ 652 }; 653 654 static TestUnknown Test_Unknown = { {&TestUnknown_Vtbl}, 1 }; 655 static TestUnknown Test_Unknown2 = { {&TestUnknown_Vtbl}, 1 }; 656 static struct test_stream Test_Stream = { {&TestStream_Vtbl}, 1 }; 657 static struct test_stream Test_Stream2 = { {&TestStream_Vtbl}, 1 }; 658 659 ULONG __RPC_USER WdtpInterfacePointer_UserSize(ULONG *, ULONG, ULONG, IUnknown *, REFIID); 660 unsigned char * __RPC_USER WdtpInterfacePointer_UserMarshal(ULONG *, ULONG, unsigned char *, IUnknown *, REFIID); 661 unsigned char * __RPC_USER WdtpInterfacePointer_UserUnmarshal(ULONG *, unsigned char *, IUnknown **, REFIID); 662 663 static void marshal_WdtpInterfacePointer(DWORD umcb_ctx, DWORD ctx, BOOL client, BOOL in, BOOL out) 664 { 665 USER_MARSHAL_CB umcb; 666 MIDL_STUB_MESSAGE stub_msg; 667 RPC_MESSAGE rpc_msg; 668 unsigned char *buffer, *buffer_end; 669 ULONG size; 670 IUnknown *unk; 671 IUnknown *unk2; 672 unsigned char *wireip; 673 HGLOBAL h = GlobalAlloc(GMEM_MOVEABLE, 0); 674 IStream *stm; 675 void *marshal_data; 676 LARGE_INTEGER zero; 677 ULARGE_INTEGER pos; 678 DWORD marshal_size; 679 680 /* shows that the WdtpInterfacePointer functions don't marshal anything for 681 * NULL pointers, so code using these functions must handle that case 682 * itself */ 683 684 unk = NULL; 685 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, umcb_ctx); 686 size = WdtpInterfacePointer_UserSize(&umcb.Flags, ctx, 0, unk, &IID_IUnknown); 687 ok(size == 0, "size should be 0 bytes, not %d\n", size); 688 buffer = HeapAlloc(GetProcessHeap(), 0, size); 689 buffer_end = WdtpInterfacePointer_UserMarshal(&umcb.Flags, ctx, buffer, unk, &IID_IUnknown); 690 ok(buffer_end == buffer, "buffer_end %p buffer %p\n", buffer_end, buffer); 691 HeapFree(GetProcessHeap(), 0, buffer); 692 693 /* Now for a non-NULL pointer. The marshalled data are two size DWORDS and then 694 the result of CoMarshalInterface called with the LOWORD of the ctx */ 695 696 unk = &Test_Unknown.IUnknown_iface; 697 Test_Unknown.refs = 1; 698 699 CreateStreamOnHGlobal(h, TRUE, &stm); 700 CoMarshalInterface(stm, &IID_IUnknown, unk, LOWORD(ctx), NULL, MSHLFLAGS_NORMAL); 701 zero.QuadPart = 0; 702 IStream_Seek(stm, zero, STREAM_SEEK_CUR, &pos); 703 marshal_size = pos.u.LowPart; 704 marshal_data = GlobalLock(h); 705 todo_wine 706 ok(Test_Unknown.refs == 2, "got %d\n", Test_Unknown.refs); 707 708 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, umcb_ctx); 709 size = WdtpInterfacePointer_UserSize(&umcb.Flags, ctx, 0, unk, &IID_IUnknown); 710 ok(size >= marshal_size + 2 * sizeof(DWORD), "marshal size %x got %x\n", marshal_size, size); 711 buffer = HeapAlloc(GetProcessHeap(), 0, size); 712 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, umcb_ctx); 713 buffer_end = WdtpInterfacePointer_UserMarshal(&umcb.Flags, ctx, buffer, unk, &IID_IUnknown); 714 todo_wine 715 ok(Test_Unknown.refs == 2, "got %d\n", Test_Unknown.refs); 716 wireip = buffer; 717 718 ok(buffer_end == buffer + marshal_size + 2 * sizeof(DWORD), "buffer_end %p buffer %p\n", buffer_end, buffer); 719 720 ok(*(DWORD *)wireip == marshal_size, "wireip + 0x0 should be %x instead of %x\n", marshal_size, *(DWORD *)wireip); 721 wireip += sizeof(DWORD); 722 ok(*(DWORD *)wireip == marshal_size, "wireip + 0x4 should be %x instead of %x\n", marshal_size, *(DWORD *)wireip); 723 wireip += sizeof(DWORD); 724 725 ok(!memcmp(marshal_data, wireip, marshal_size), "buffer mismatch\n"); 726 GlobalUnlock(h); 727 zero.QuadPart = 0; 728 IStream_Seek(stm, zero, STREAM_SEEK_SET, NULL); 729 CoReleaseMarshalData(stm); 730 IStream_Release(stm); 731 732 Test_Unknown2.refs = 1; 733 unk2 = &Test_Unknown2.IUnknown_iface; 734 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, umcb_ctx); 735 umcb.pStubMsg->IsClient = client; 736 umcb.pStubMsg->fIsIn = in; 737 umcb.pStubMsg->fIsOut = out; 738 739 WdtpInterfacePointer_UserUnmarshal(&umcb.Flags, buffer, &unk2, &IID_IUnknown); 740 ok(unk2 != NULL, "IUnknown object didn't unmarshal properly\n"); 741 ok(Test_Unknown.refs == 2, "got %d\n", Test_Unknown.refs); 742 ok(Test_Unknown2.refs == 0, "got %d\n", Test_Unknown2.refs); 743 HeapFree(GetProcessHeap(), 0, buffer); 744 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_INPROC); 745 IUnknown_Release(unk2); 746 } 747 748 static void test_marshal_WdtpInterfacePointer(void) 749 { 750 /* 751 * There are two places where we can pass the marshalling ctx: as 752 * part of the umcb and as a separate flag. The loword of that 753 * separate flag field is what matters. 754 */ 755 756 /* All three are marshalled as inproc */ 757 marshal_WdtpInterfacePointer(MSHCTX_INPROC, MSHCTX_INPROC, 0,0,0); 758 marshal_WdtpInterfacePointer(MSHCTX_DIFFERENTMACHINE, MSHCTX_INPROC,0,0,0); 759 marshal_WdtpInterfacePointer(MSHCTX_INPROC, MAKELONG(MSHCTX_INPROC, 0xffff),0,0,0); 760 761 /* All three are marshalled as remote */ 762 marshal_WdtpInterfacePointer(MSHCTX_INPROC, MSHCTX_DIFFERENTMACHINE,0,0,0); 763 marshal_WdtpInterfacePointer(MSHCTX_DIFFERENTMACHINE, MSHCTX_DIFFERENTMACHINE,0,0,0); 764 marshal_WdtpInterfacePointer(MSHCTX_INPROC, MAKELONG(MSHCTX_DIFFERENTMACHINE, 0xffff),0,0,0); 765 766 /* Test different combinations of client, in and out */ 767 marshal_WdtpInterfacePointer(MSHCTX_INPROC, MSHCTX_DIFFERENTMACHINE,0,0,1); 768 marshal_WdtpInterfacePointer(MSHCTX_INPROC, MSHCTX_DIFFERENTMACHINE,0,1,0); 769 marshal_WdtpInterfacePointer(MSHCTX_INPROC, MSHCTX_DIFFERENTMACHINE,0,1,1); 770 marshal_WdtpInterfacePointer(MSHCTX_INPROC, MSHCTX_DIFFERENTMACHINE,1,0,0); 771 marshal_WdtpInterfacePointer(MSHCTX_INPROC, MSHCTX_DIFFERENTMACHINE,1,0,1); 772 marshal_WdtpInterfacePointer(MSHCTX_INPROC, MSHCTX_DIFFERENTMACHINE,1,1,0); 773 marshal_WdtpInterfacePointer(MSHCTX_INPROC, MSHCTX_DIFFERENTMACHINE,1,1,1); 774 } 775 776 static void marshal_STGMEDIUM(BOOL client, BOOL in, BOOL out) 777 { 778 USER_MARSHAL_CB umcb; 779 MIDL_STUB_MESSAGE stub_msg; 780 RPC_MESSAGE rpc_msg; 781 unsigned char *buffer, *buffer_end, *expect_buffer, *expect_buffer_end; 782 ULONG size, expect_size; 783 STGMEDIUM med, med2; 784 IUnknown *unk = &Test_Unknown.IUnknown_iface; 785 IStream *stm = &Test_Stream.IStream_iface; 786 787 /* TYMED_NULL with pUnkForRelease */ 788 789 Test_Unknown.refs = 1; 790 791 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE); 792 expect_size = WdtpInterfacePointer_UserSize(&umcb.Flags, umcb.Flags, 2 * sizeof(DWORD), unk, &IID_IUnknown); 793 expect_buffer = HeapAlloc(GetProcessHeap(), 0, expect_size); 794 *(DWORD*)expect_buffer = TYMED_NULL; 795 *((DWORD*)expect_buffer + 1) = 0xdeadbeef; 796 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, expect_buffer, expect_size, MSHCTX_DIFFERENTMACHINE); 797 expect_buffer_end = WdtpInterfacePointer_UserMarshal(&umcb.Flags, umcb.Flags, expect_buffer + 2 * sizeof(DWORD), unk, &IID_IUnknown); 798 799 med.tymed = TYMED_NULL; 800 U(med).pstg = NULL; 801 med.pUnkForRelease = unk; 802 803 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE); 804 size = STGMEDIUM_UserSize(&umcb.Flags, 0, &med); 805 ok(size == expect_size, "size %d should be %d bytes\n", size, expect_size); 806 807 buffer = HeapAlloc(GetProcessHeap(), 0, size); 808 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE); 809 buffer_end = STGMEDIUM_UserMarshal(&umcb.Flags, buffer, &med); 810 ok(buffer_end - buffer == expect_buffer_end - expect_buffer, "buffer size mismatch\n"); 811 ok(*(DWORD*)buffer == TYMED_NULL, "got %08x\n", *(DWORD*)buffer); 812 ok(*((DWORD*)buffer+1) != 0, "got %08x\n", *((DWORD*)buffer+1)); 813 ok(!memcmp(buffer+8, expect_buffer + 8, expect_buffer_end - expect_buffer - 8), "buffer mismatch\n"); 814 815 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE); 816 umcb.pStubMsg->IsClient = client; 817 umcb.pStubMsg->fIsIn = in; 818 umcb.pStubMsg->fIsOut = out; 819 820 Test_Unknown2.refs = 1; 821 med2.tymed = TYMED_NULL; 822 U(med2).pstm = NULL; 823 med2.pUnkForRelease = &Test_Unknown2.IUnknown_iface; 824 825 STGMEDIUM_UserUnmarshal(&umcb.Flags, buffer, &med2); 826 827 ok(med2.tymed == TYMED_NULL, "got tymed %x\n", med2.tymed); 828 ok(med2.pUnkForRelease != NULL, "Incorrectly unmarshalled\n"); 829 ok(Test_Unknown2.refs == 0, "got %d\n", Test_Unknown2.refs); 830 831 HeapFree(GetProcessHeap(), 0, buffer); 832 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE); 833 STGMEDIUM_UserFree(&umcb.Flags, &med2); 834 835 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, expect_buffer, expect_size, MSHCTX_DIFFERENTMACHINE); 836 med2.tymed = TYMED_NULL; 837 U(med2).pstm = NULL; 838 med2.pUnkForRelease = NULL; 839 STGMEDIUM_UserUnmarshal(&umcb.Flags, expect_buffer, &med2); 840 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE); 841 STGMEDIUM_UserFree(&umcb.Flags, &med2); 842 843 ok(Test_Unknown.refs == 1, "got %d\n", Test_Unknown.refs); 844 845 HeapFree(GetProcessHeap(), 0, expect_buffer); 846 847 /* TYMED_ISTREAM with pUnkForRelease */ 848 849 Test_Unknown.refs = 1; 850 Test_Stream.refs = 1; 851 852 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE); 853 expect_size = WdtpInterfacePointer_UserSize(&umcb.Flags, umcb.Flags, 3 * sizeof(DWORD), (IUnknown*)stm, &IID_IStream); 854 expect_size = WdtpInterfacePointer_UserSize(&umcb.Flags, umcb.Flags, expect_size, unk, &IID_IUnknown); 855 856 expect_buffer = HeapAlloc(GetProcessHeap(), 0, expect_size); 857 /* There may be a hole between the two interfaces so init the buffer to something */ 858 memset(expect_buffer, 0xcc, expect_size); 859 *(DWORD*)expect_buffer = TYMED_ISTREAM; 860 *((DWORD*)expect_buffer + 1) = 0xdeadbeef; 861 *((DWORD*)expect_buffer + 2) = 0xcafe; 862 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, expect_buffer, expect_size, MSHCTX_DIFFERENTMACHINE); 863 expect_buffer_end = WdtpInterfacePointer_UserMarshal(&umcb.Flags, umcb.Flags, expect_buffer + 3 * sizeof(DWORD), (IUnknown*)stm, &IID_IStream); 864 expect_buffer_end = WdtpInterfacePointer_UserMarshal(&umcb.Flags, umcb.Flags, expect_buffer_end, unk, &IID_IUnknown); 865 866 med.tymed = TYMED_ISTREAM; 867 U(med).pstm = stm; 868 med.pUnkForRelease = unk; 869 870 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE); 871 size = STGMEDIUM_UserSize(&umcb.Flags, 0, &med); 872 ok(size == expect_size, "size %d should be %d bytes\n", size, expect_size); 873 874 buffer = HeapAlloc(GetProcessHeap(), 0, size); 875 memset(buffer, 0xcc, size); 876 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE); 877 buffer_end = STGMEDIUM_UserMarshal(&umcb.Flags, buffer, &med); 878 ok(buffer_end - buffer == expect_buffer_end - expect_buffer, "buffer size mismatch\n"); 879 ok(*(DWORD*)buffer == TYMED_ISTREAM, "got %08x\n", *(DWORD*)buffer); 880 ok(*((DWORD*)buffer+1) != 0, "got %08x\n", *((DWORD*)buffer+1)); 881 ok(*((DWORD*)buffer+2) != 0, "got %08x\n", *((DWORD*)buffer+2)); 882 ok(!memcmp(buffer + 12, expect_buffer + 12, (buffer_end - buffer) - 12), "buffer mismatch\n"); 883 884 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE); 885 umcb.pStubMsg->IsClient = client; 886 umcb.pStubMsg->fIsIn = in; 887 umcb.pStubMsg->fIsOut = out; 888 889 Test_Stream2.refs = 1; 890 Test_Unknown2.refs = 1; 891 med2.tymed = TYMED_ISTREAM; 892 U(med2).pstm = &Test_Stream2.IStream_iface; 893 med2.pUnkForRelease = &Test_Unknown2.IUnknown_iface; 894 895 STGMEDIUM_UserUnmarshal(&umcb.Flags, buffer, &med2); 896 897 ok(med2.tymed == TYMED_ISTREAM, "got tymed %x\n", med2.tymed); 898 ok(U(med2).pstm != NULL, "Incorrectly unmarshalled\n"); 899 ok(med2.pUnkForRelease != NULL, "Incorrectly unmarshalled\n"); 900 ok(Test_Stream2.refs == 0, "got %d\n", Test_Stream2.refs); 901 ok(Test_Unknown2.refs == 0, "got %d\n", Test_Unknown2.refs); 902 903 HeapFree(GetProcessHeap(), 0, buffer); 904 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE); 905 STGMEDIUM_UserFree(&umcb.Flags, &med2); 906 907 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, expect_buffer, expect_size, MSHCTX_DIFFERENTMACHINE); 908 med2.tymed = TYMED_NULL; 909 U(med2).pstm = NULL; 910 med2.pUnkForRelease = NULL; 911 STGMEDIUM_UserUnmarshal(&umcb.Flags, expect_buffer, &med2); 912 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE); 913 STGMEDIUM_UserFree(&umcb.Flags, &med2); 914 915 ok(Test_Unknown.refs == 1, "got %d\n", Test_Unknown.refs); 916 ok(Test_Stream.refs == 1, "got %d\n", Test_Stream.refs); 917 918 HeapFree(GetProcessHeap(), 0, expect_buffer); 919 920 /* TYMED_ISTREAM = NULL with pUnkForRelease = NULL */ 921 922 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE); 923 expect_size = 3 * sizeof(DWORD); 924 925 med.tymed = TYMED_ISTREAM; 926 U(med).pstm = NULL; 927 med.pUnkForRelease = NULL; 928 929 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE); 930 size = STGMEDIUM_UserSize(&umcb.Flags, 0, &med); 931 ok(size == expect_size, "size %d should be %d bytes\n", size, expect_size); 932 933 buffer = HeapAlloc(GetProcessHeap(), 0, size); 934 memset(buffer, 0xcc, size); 935 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE); 936 buffer_end = STGMEDIUM_UserMarshal(&umcb.Flags, buffer, &med); 937 ok(buffer_end - buffer == expect_size, "buffer size mismatch\n"); 938 ok(*(DWORD*)buffer == TYMED_ISTREAM, "got %08x\n", *(DWORD*)buffer); 939 ok(*((DWORD*)buffer+1) == 0, "got %08x\n", *((DWORD*)buffer+1)); 940 ok(*((DWORD*)buffer+2) == 0, "got %08x\n", *((DWORD*)buffer+2)); 941 942 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE); 943 umcb.pStubMsg->IsClient = client; 944 umcb.pStubMsg->fIsIn = in; 945 umcb.pStubMsg->fIsOut = out; 946 947 Test_Stream2.refs = 1; 948 Test_Unknown2.refs = 1; 949 med2.tymed = TYMED_ISTREAM; 950 U(med2).pstm = &Test_Stream2.IStream_iface; 951 med2.pUnkForRelease = &Test_Unknown2.IUnknown_iface; 952 953 STGMEDIUM_UserUnmarshal(&umcb.Flags, buffer, &med2); 954 955 ok(med2.tymed == TYMED_ISTREAM, "got tymed %x\n", med2.tymed); 956 ok(U(med2).pstm == NULL, "Incorrectly unmarshalled\n"); 957 ok(med2.pUnkForRelease == &Test_Unknown2.IUnknown_iface, "Incorrectly unmarshalled\n"); 958 ok(Test_Stream2.refs == 0, "got %d\n", Test_Stream2.refs); 959 ok(Test_Unknown2.refs == 1, "got %d\n", Test_Unknown2.refs); 960 961 HeapFree(GetProcessHeap(), 0, buffer); 962 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE); 963 STGMEDIUM_UserFree(&umcb.Flags, &med2); 964 } 965 966 static void test_marshal_STGMEDIUM(void) 967 { 968 marshal_STGMEDIUM(0, 0, 0); 969 marshal_STGMEDIUM(0, 0, 1); 970 marshal_STGMEDIUM(0, 1, 0); 971 marshal_STGMEDIUM(0, 1, 1); 972 /* For Windows versions post 2003, client side, non-[in,out] STGMEDIUMs get zero-initialised. 973 However since inline stubs don't set fIsIn or fIsOut this behaviour would break 974 ref counting in GetDataHere_Proxy for example, as we'd end up not releasing the original 975 interface. For simplicity we don't test or implement this. */ 976 marshal_STGMEDIUM(1, 1, 1); 977 } 978 979 static void test_marshal_SNB(void) 980 { 981 static const WCHAR str1W[] = {'s','t','r','i','n','g','1',0}; 982 static const WCHAR str2W[] = {'s','t','r','2',0}; 983 unsigned char *buffer, *src, *mbuf; 984 MIDL_STUB_MESSAGE stub_msg; 985 WCHAR **ptrW, *dataW; 986 USER_MARSHAL_CB umcb; 987 RPC_MESSAGE rpc_msg; 988 RemSNB *wiresnb; 989 SNB snb, snb2; 990 ULONG size; 991 992 /* 4 bytes alignment */ 993 snb = NULL; 994 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL); 995 size = SNB_UserSize(&umcb.Flags, 3, &snb); 996 ok(size == 16, "Size should be 16, instead of %d\n", size); 997 998 /* NULL block */ 999 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL); 1000 size = SNB_UserSize(&umcb.Flags, 0, &snb); 1001 ok(size == 12, "Size should be 12, instead of %d\n", size); 1002 1003 buffer = HeapAlloc(GetProcessHeap(), 0, size); 1004 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL); 1005 mbuf = SNB_UserMarshal(&umcb.Flags, buffer, &snb); 1006 ok(mbuf == buffer + size, "got %p, %p\n", mbuf, buffer + size); 1007 1008 wiresnb = (RemSNB*)buffer; 1009 ok(wiresnb->ulCntStr == 0, "got %u\n", wiresnb->ulCntStr); 1010 ok(wiresnb->ulCntChar == 0, "got %u\n", wiresnb->ulCntChar); 1011 ok(*(ULONG*)wiresnb->rgString == 0, "got %u\n", *(ULONG*)wiresnb->rgString); 1012 1013 snb2 = NULL; 1014 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL); 1015 SNB_UserUnmarshal(&umcb.Flags, buffer, &snb2); 1016 ok(snb2 == NULL, "got %p\n", snb2); 1017 1018 HeapFree(GetProcessHeap(), 0, buffer); 1019 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL); 1020 SNB_UserFree(&umcb.Flags, &snb2); 1021 1022 /* block with actual data */ 1023 1024 /* allocate source block, n+1 pointers first, then data */ 1025 src = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR*)*3 + sizeof(str1W) + sizeof(str2W)); 1026 ptrW = (WCHAR**)src; 1027 dataW = *ptrW = (WCHAR*)(src + 3*sizeof(WCHAR*)); 1028 ptrW++; 1029 *ptrW = (WCHAR*)(src + 3*sizeof(WCHAR*) + sizeof(str1W)); 1030 ptrW++; 1031 *ptrW = NULL; 1032 lstrcpyW(dataW, str1W); 1033 dataW += lstrlenW(str1W) + 1; 1034 lstrcpyW(dataW, str2W); 1035 1036 snb = (SNB)src; 1037 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL); 1038 size = SNB_UserSize(&umcb.Flags, 0, &snb); 1039 ok(size == 38, "Size should be 38, instead of %d\n", size); 1040 1041 buffer = HeapAlloc(GetProcessHeap(), 0, size); 1042 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL); 1043 SNB_UserMarshal(&umcb.Flags, buffer, &snb); 1044 1045 wiresnb = (RemSNB*)buffer; 1046 ok(wiresnb->ulCntStr == 13, "got %u\n", wiresnb->ulCntStr); 1047 ok(wiresnb->ulCntChar == 2, "got %u\n", wiresnb->ulCntChar); 1048 /* payload length is stored one more time, as ULONG */ 1049 ok(*(ULONG*)wiresnb->rgString == wiresnb->ulCntStr, "got %u\n", *(ULONG*)wiresnb->rgString); 1050 dataW = &wiresnb->rgString[2]; 1051 ok(!lstrcmpW(dataW, str1W), "marshalled string 0: %s\n", wine_dbgstr_w(dataW)); 1052 dataW += sizeof(str1W)/sizeof(WCHAR); 1053 ok(!lstrcmpW(dataW, str2W), "marshalled string 1: %s\n", wine_dbgstr_w(dataW)); 1054 1055 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL); 1056 1057 g_expect_user_alloc = TRUE; 1058 snb2 = NULL; 1059 SNB_UserUnmarshal(&umcb.Flags, buffer, &snb2); 1060 g_expect_user_alloc = FALSE; 1061 1062 ptrW = snb2; 1063 ok(!lstrcmpW(*ptrW, str1W), "unmarshalled string 0: %s\n", wine_dbgstr_w(*ptrW)); 1064 ptrW++; 1065 ok(!lstrcmpW(*ptrW, str2W), "unmarshalled string 1: %s\n", wine_dbgstr_w(*ptrW)); 1066 ptrW++; 1067 ok(*ptrW == NULL, "expected terminating NULL ptr, got %p, start %p\n", *ptrW, snb2); 1068 1069 HeapFree(GetProcessHeap(), 0, buffer); 1070 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL); 1071 1072 g_expect_user_free = TRUE; 1073 SNB_UserFree(&umcb.Flags, &snb2); 1074 g_expect_user_free = FALSE; 1075 1076 HeapFree(GetProcessHeap(), 0, src); 1077 } 1078 1079 static void test_marshal_HDC(void) 1080 { 1081 MIDL_STUB_MESSAGE stub_msg; 1082 HDC hdc = GetDC(0), hdc2; 1083 USER_MARSHAL_CB umcb; 1084 RPC_MESSAGE rpc_msg; 1085 unsigned char *buffer; 1086 wireHDC wirehdc; 1087 ULONG size; 1088 1089 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL); 1090 size = HDC_UserSize(&umcb.Flags, 0, &hdc); 1091 ok(size == sizeof(*wirehdc), "Wrong size %d\n", size); 1092 1093 buffer = HeapAlloc(GetProcessHeap(), 0, size); 1094 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL); 1095 HDC_UserMarshal(&umcb.Flags, buffer, &hdc); 1096 wirehdc = (wireHDC)buffer; 1097 ok(wirehdc->fContext == WDT_INPROC_CALL, "Context should be WDT_INPROC_CALL instead of 0x%08x\n", wirehdc->fContext); 1098 ok(wirehdc->u.hInproc == (LONG_PTR)hdc, "Marshaled value should be %p instead of %x\n", hdc, wirehdc->u.hRemote); 1099 1100 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL); 1101 HDC_UserUnmarshal(&umcb.Flags, buffer, &hdc2); 1102 ok(hdc == hdc2, "Didn't unmarshal properly\n"); 1103 HeapFree(GetProcessHeap(), 0, buffer); 1104 1105 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL); 1106 HDC_UserFree(&umcb.Flags, &hdc2); 1107 ReleaseDC(0, hdc); 1108 } 1109 1110 static void test_marshal_HICON(void) 1111 { 1112 static const BYTE bmp_bits[1024]; 1113 MIDL_STUB_MESSAGE stub_msg; 1114 HICON hIcon, hIcon2; 1115 USER_MARSHAL_CB umcb; 1116 RPC_MESSAGE rpc_msg; 1117 unsigned char *buffer; 1118 wireHICON wirehicon; 1119 ULONG size; 1120 1121 hIcon = CreateIcon(0, 16, 16, 1, 1, bmp_bits, bmp_bits); 1122 ok(hIcon != 0, "CreateIcon failed\n"); 1123 1124 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL); 1125 size = HICON_UserSize(&umcb.Flags, 0, &hIcon); 1126 ok(size == sizeof(*wirehicon), "Wrong size %d\n", size); 1127 1128 buffer = HeapAlloc(GetProcessHeap(), 0, size); 1129 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL); 1130 HICON_UserMarshal(&umcb.Flags, buffer, &hIcon); 1131 wirehicon = (wireHICON)buffer; 1132 ok(wirehicon->fContext == WDT_INPROC_CALL, "Context should be WDT_INPROC_CALL instead of 0x%08x\n", wirehicon->fContext); 1133 ok(wirehicon->u.hInproc == (LONG_PTR)hIcon, "Marshaled value should be %p instead of %x\n", hIcon, wirehicon->u.hRemote); 1134 1135 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL); 1136 HICON_UserUnmarshal(&umcb.Flags, buffer, &hIcon2); 1137 ok(hIcon == hIcon2, "Didn't unmarshal properly\n"); 1138 HeapFree(GetProcessHeap(), 0, buffer); 1139 1140 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL); 1141 HICON_UserFree(&umcb.Flags, &hIcon2); 1142 DestroyIcon(hIcon); 1143 } 1144 1145 static void test_marshal_HBRUSH(void) 1146 { 1147 MIDL_STUB_MESSAGE stub_msg; 1148 HBRUSH hBrush, hBrush2; 1149 USER_MARSHAL_CB umcb; 1150 RPC_MESSAGE rpc_msg; 1151 unsigned char *buffer; 1152 LOGBRUSH logbrush; 1153 wireHBRUSH wirehbrush; 1154 ULONG size; 1155 1156 logbrush.lbStyle = BS_SOLID; 1157 logbrush.lbColor = RGB(0, 0, 0); 1158 logbrush.lbHatch = 0; 1159 1160 hBrush = CreateBrushIndirect(&logbrush); 1161 ok(hBrush != 0, "CreateBrushIndirect failed\n"); 1162 1163 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL); 1164 size = HBRUSH_UserSize(&umcb.Flags, 0, &hBrush); 1165 ok(size == sizeof(*wirehbrush), "Wrong size %d\n", size); 1166 1167 buffer = HeapAlloc(GetProcessHeap(), 0, size); 1168 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL); 1169 HBRUSH_UserMarshal(&umcb.Flags, buffer, &hBrush); 1170 wirehbrush = (wireHBRUSH)buffer; 1171 ok(wirehbrush->fContext == WDT_INPROC_CALL, "Context should be WDT_INPROC_CALL instead of 0x%08x\n", wirehbrush->fContext); 1172 ok(wirehbrush->u.hInproc == (LONG_PTR)hBrush, "Marshaled value should be %p instead of %x\n", hBrush, wirehbrush->u.hRemote); 1173 1174 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL); 1175 HBRUSH_UserUnmarshal(&umcb.Flags, buffer, &hBrush2); 1176 ok(hBrush == hBrush2, "Didn't unmarshal properly\n"); 1177 HeapFree(GetProcessHeap(), 0, buffer); 1178 1179 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL); 1180 HBRUSH_UserFree(&umcb.Flags, &hBrush2); 1181 DeleteObject(hBrush); 1182 } 1183 1184 struct obj 1185 { 1186 IDataObject IDataObject_iface; 1187 }; 1188 1189 static HRESULT WINAPI obj_QueryInterface(IDataObject *iface, REFIID iid, void **obj) 1190 { 1191 *obj = NULL; 1192 1193 if (IsEqualGUID(iid, &IID_IUnknown) || 1194 IsEqualGUID(iid, &IID_IDataObject)) 1195 *obj = iface; 1196 1197 if (*obj) 1198 { 1199 IDataObject_AddRef(iface); 1200 return S_OK; 1201 } 1202 1203 return E_NOINTERFACE; 1204 } 1205 1206 static ULONG WINAPI obj_AddRef(IDataObject *iface) 1207 { 1208 return 2; 1209 } 1210 1211 static ULONG WINAPI obj_Release(IDataObject *iface) 1212 { 1213 return 1; 1214 } 1215 1216 static HRESULT WINAPI obj_DO_GetDataHere(IDataObject *iface, FORMATETC *fmt, 1217 STGMEDIUM *med) 1218 { 1219 ok( med->pUnkForRelease == NULL, "got %p\n", med->pUnkForRelease ); 1220 1221 if (fmt->cfFormat == 2) 1222 { 1223 IStream_Release(U(med)->pstm); 1224 U(med)->pstm = &Test_Stream2.IStream_iface; 1225 } 1226 1227 return S_OK; 1228 } 1229 1230 static const IDataObjectVtbl obj_data_object_vtbl = 1231 { 1232 obj_QueryInterface, 1233 obj_AddRef, 1234 obj_Release, 1235 NULL, /* GetData */ 1236 obj_DO_GetDataHere, 1237 NULL, /* QueryGetData */ 1238 NULL, /* GetCanonicalFormatEtc */ 1239 NULL, /* SetData */ 1240 NULL, /* EnumFormatEtc */ 1241 NULL, /* DAdvise */ 1242 NULL, /* DUnadvise */ 1243 NULL /* EnumDAdvise */ 1244 }; 1245 1246 static struct obj obj = 1247 { 1248 {&obj_data_object_vtbl} 1249 }; 1250 1251 static void test_GetDataHere_Proxy(void) 1252 { 1253 HRESULT hr; 1254 IStream *stm; 1255 HANDLE thread; 1256 DWORD tid; 1257 static const LARGE_INTEGER zero; 1258 IDataObject *data; 1259 FORMATETC fmt; 1260 STGMEDIUM med; 1261 1262 hr = CreateStreamOnHGlobal( NULL, TRUE, &stm ); 1263 ok( hr == S_OK, "got %08x\n", hr ); 1264 tid = start_host_object2( stm, &IID_IDataObject, (IUnknown *)&obj.IDataObject_iface, MSHLFLAGS_NORMAL, NULL, &thread ); 1265 1266 IStream_Seek( stm, zero, STREAM_SEEK_SET, NULL ); 1267 hr = CoUnmarshalInterface( stm, &IID_IDataObject, (void **)&data ); 1268 ok( hr == S_OK, "got %08x\n", hr ); 1269 IStream_Release( stm ); 1270 1271 Test_Stream.refs = 1; 1272 Test_Stream2.refs = 1; 1273 Test_Unknown.refs = 1; 1274 1275 fmt.cfFormat = 1; 1276 fmt.ptd = NULL; 1277 fmt.dwAspect = DVASPECT_CONTENT; 1278 fmt.lindex = -1; 1279 U(med).pstm = NULL; 1280 med.pUnkForRelease = &Test_Unknown.IUnknown_iface; 1281 1282 fmt.tymed = med.tymed = TYMED_NULL; 1283 hr = IDataObject_GetDataHere( data, &fmt, &med ); 1284 ok( hr == DV_E_TYMED, "got %08x\n", hr ); 1285 1286 for (fmt.tymed = TYMED_HGLOBAL; fmt.tymed <= TYMED_ENHMF; fmt.tymed <<= 1) 1287 { 1288 med.tymed = fmt.tymed; 1289 hr = IDataObject_GetDataHere( data, &fmt, &med ); 1290 ok( hr == (fmt.tymed <= TYMED_ISTORAGE ? S_OK : DV_E_TYMED), "got %08x for tymed %d\n", hr, fmt.tymed ); 1291 ok( Test_Unknown.refs == 1, "got %d\n", Test_Unknown.refs ); 1292 } 1293 1294 fmt.tymed = TYMED_ISTREAM; 1295 med.tymed = TYMED_ISTORAGE; 1296 hr = IDataObject_GetDataHere( data, &fmt, &med ); 1297 ok( hr == DV_E_TYMED, "got %08x\n", hr ); 1298 1299 fmt.tymed = med.tymed = TYMED_ISTREAM; 1300 U(med).pstm = &Test_Stream.IStream_iface; 1301 med.pUnkForRelease = &Test_Unknown.IUnknown_iface; 1302 1303 hr = IDataObject_GetDataHere( data, &fmt, &med ); 1304 ok( hr == S_OK, "got %08x\n", hr ); 1305 1306 ok( U(med).pstm == &Test_Stream.IStream_iface, "stm changed\n" ); 1307 ok( med.pUnkForRelease == &Test_Unknown.IUnknown_iface, "punk changed\n" ); 1308 1309 ok( Test_Stream.refs == 1, "got %d\n", Test_Stream.refs ); 1310 ok( Test_Unknown.refs == 1, "got %d\n", Test_Unknown.refs ); 1311 1312 fmt.cfFormat = 2; 1313 fmt.tymed = med.tymed = TYMED_ISTREAM; 1314 U(med).pstm = &Test_Stream.IStream_iface; 1315 med.pUnkForRelease = &Test_Unknown.IUnknown_iface; 1316 1317 hr = IDataObject_GetDataHere( data, &fmt, &med ); 1318 ok( hr == S_OK, "got %08x\n", hr ); 1319 1320 ok( U(med).pstm == &Test_Stream.IStream_iface, "stm changed\n" ); 1321 ok( med.pUnkForRelease == &Test_Unknown.IUnknown_iface, "punk changed\n" ); 1322 1323 ok( Test_Stream.refs == 1, "got %d\n", Test_Stream.refs ); 1324 ok( Test_Unknown.refs == 1, "got %d\n", Test_Unknown.refs ); 1325 ok( Test_Stream2.refs == 0, "got %d\n", Test_Stream2.refs ); 1326 1327 IDataObject_Release( data ); 1328 end_host_object( tid, thread ); 1329 } 1330 1331 START_TEST(usrmarshal) 1332 { 1333 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 1334 1335 test_marshal_CLIPFORMAT(); 1336 test_marshal_HWND(); 1337 test_marshal_HGLOBAL(); 1338 test_marshal_HENHMETAFILE(); 1339 test_marshal_HMETAFILE(); 1340 test_marshal_HMETAFILEPICT(); 1341 test_marshal_WdtpInterfacePointer(); 1342 test_marshal_STGMEDIUM(); 1343 test_marshal_SNB(); 1344 test_marshal_HDC(); 1345 test_marshal_HICON(); 1346 test_marshal_HBRUSH(); 1347 1348 test_GetDataHere_Proxy(); 1349 1350 CoUninitialize(); 1351 } 1352