1 /* 2 * Unit test suite for cstubs 3 * 4 * Copyright 2006 Huw Davies 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 <stdarg.h> 22 #include <stdio.h> 23 24 #define COBJMACROS 25 #ifdef __REACTOS__ 26 #define CONST_VTABLE 27 #endif 28 29 #include <windef.h> 30 #include <winbase.h> 31 #include <winnt.h> 32 #include <winerror.h> 33 34 #include "initguid.h" 35 #include <ole2.h> 36 #include "rpc.h" 37 #include "rpcdce.h" 38 #include "rpcproxy.h" 39 40 #include "wine/heap.h" 41 #include "wine/test.h" 42 43 #include "cstub_p.h" 44 45 static CStdPSFactoryBuffer PSFactoryBuffer; 46 47 static ULONG WINAPI test_CStdStubBuffer_Release(IRpcStubBuffer *This) 48 { 49 return NdrCStdStubBuffer_Release(This, (IPSFactoryBuffer *)&PSFactoryBuffer); 50 } 51 52 static ULONG WINAPI test_CStdStubBuffer2_Release(IRpcStubBuffer *This) 53 { 54 return NdrCStdStubBuffer2_Release(This, (IPSFactoryBuffer *)&PSFactoryBuffer); 55 } 56 57 static GUID IID_if1 = {0x12345678, 1234, 5678, {12,34,56,78,90,0xab,0xcd,0xef}}; 58 static GUID IID_if2 = {0x12345679, 1234, 5678, {12,34,56,78,90,0xab,0xcd,0xef}}; 59 static GUID IID_if3 = {0x1234567a, 1234, 5678, {12,34,56,78,90,0xab,0xcd,0xef}}; 60 static GUID IID_if4 = {0x1234567b, 1234, 5678, {12,34,56,78,90,0xab,0xcd,0xef}}; 61 static CLSID CLSID_psfact = {0x1234567c, 1234, 5678, {12,34,56,78,90,0xab,0xcd,0xef}}; 62 63 static int my_alloc_called; 64 static int my_free_called; 65 66 static void * CALLBACK my_alloc(SIZE_T size) 67 { 68 my_alloc_called++; 69 return NdrOleAllocate(size); 70 } 71 72 static void CALLBACK my_free(void *ptr) 73 { 74 my_free_called++; 75 NdrOleFree(ptr); 76 } 77 78 typedef struct _MIDL_PROC_FORMAT_STRING 79 { 80 short Pad; 81 unsigned char Format[ 2 ]; 82 } MIDL_PROC_FORMAT_STRING; 83 84 typedef struct _MIDL_TYPE_FORMAT_STRING 85 { 86 short Pad; 87 unsigned char Format[ 2 ]; 88 } MIDL_TYPE_FORMAT_STRING; 89 90 91 static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString = 92 { 93 0, 94 { 95 0, 0 96 } 97 }; 98 99 static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString = 100 { 101 0, 102 { 103 0, 0 104 } 105 }; 106 107 static const MIDL_STUB_DESC Object_StubDesc = 108 { 109 NULL, 110 my_alloc, 111 my_free, 112 { 0 }, 113 0, 114 0, 115 0, 116 0, 117 __MIDL_TypeFormatString.Format, 118 1, /* -error bounds_check flag */ 119 0x20000, /* Ndr library version */ 120 0, 121 0x50100a4, /* MIDL Version 5.1.164 */ 122 0, 123 NULL, 124 0, /* notify & notify_flag routine table */ 125 1, /* Flags */ 126 0, /* Reserved3 */ 127 0, /* Reserved4 */ 128 0 /* Reserved5 */ 129 }; 130 131 static HRESULT WINAPI if1_fn1_Proxy(void *This) 132 { 133 return S_OK; 134 } 135 136 static void __RPC_STUB if1_fn1_Stub( 137 IRpcStubBuffer *This, 138 IRpcChannelBuffer *_pRpcChannelBuffer, 139 PRPC_MESSAGE _pRpcMessage, 140 DWORD *_pdwStubPhase) 141 { 142 trace("fn1 stub\n"); 143 } 144 145 static HRESULT WINAPI if1_fn2_Proxy(void *This) 146 { 147 return S_OK; 148 } 149 150 static void __RPC_STUB if1_fn2_Stub( 151 IRpcStubBuffer *This, 152 IRpcChannelBuffer *_pRpcChannelBuffer, 153 PRPC_MESSAGE _pRpcMessage, 154 DWORD *_pdwStubPhase) 155 { 156 trace("fn2 stub\n"); 157 } 158 159 static CINTERFACE_PROXY_VTABLE(5) if1_proxy_vtbl = 160 { 161 { &IID_if1 }, 162 { IUnknown_QueryInterface_Proxy, 163 IUnknown_AddRef_Proxy, 164 IUnknown_Release_Proxy , 165 if1_fn1_Proxy, 166 if1_fn2_Proxy 167 } 168 }; 169 170 171 static const unsigned short if1_FormatStringOffsetTable[] = 172 { 173 0, 174 0 175 }; 176 177 static const MIDL_SERVER_INFO if1_server_info = 178 { 179 &Object_StubDesc, 180 0, 181 __MIDL_ProcFormatString.Format, 182 &if1_FormatStringOffsetTable[-3], 183 0, 184 0, 185 0, 186 0}; 187 188 189 static const PRPC_STUB_FUNCTION if1_table[] = 190 { 191 if1_fn1_Stub, 192 if1_fn2_Stub 193 }; 194 195 static CInterfaceStubVtbl if1_stub_vtbl = 196 { 197 { 198 &IID_if1, 199 &if1_server_info, 200 5, 201 &if1_table[-3] 202 }, 203 { 204 CStdStubBuffer_QueryInterface, 205 CStdStubBuffer_AddRef, 206 test_CStdStubBuffer_Release, 207 CStdStubBuffer_Connect, 208 CStdStubBuffer_Disconnect, 209 CStdStubBuffer_Invoke, 210 CStdStubBuffer_IsIIDSupported, 211 CStdStubBuffer_CountRefs, 212 CStdStubBuffer_DebugServerQueryInterface, 213 CStdStubBuffer_DebugServerRelease 214 } 215 }; 216 217 static CINTERFACE_PROXY_VTABLE(13) if2_proxy_vtbl = 218 { 219 { &IID_if2 }, 220 { IUnknown_QueryInterface_Proxy, 221 IUnknown_AddRef_Proxy, 222 IUnknown_Release_Proxy , 223 0, 224 0, 225 0, 226 0, 227 0, 228 0, 229 0, 230 0, 231 0, 232 0 233 } 234 }; 235 236 static const unsigned short if2_FormatStringOffsetTable[] = 237 { 238 (unsigned short) -1, 239 (unsigned short) -1, 240 (unsigned short) -1, 241 (unsigned short) -1, 242 (unsigned short) -1, 243 (unsigned short) -1, 244 (unsigned short) -1, 245 (unsigned short) -1, 246 (unsigned short) -1, 247 (unsigned short) -1, 248 0 249 }; 250 251 static const MIDL_SERVER_INFO if2_server_info = 252 { 253 &Object_StubDesc, 254 0, 255 __MIDL_ProcFormatString.Format, 256 &if2_FormatStringOffsetTable[-3], 257 0, 258 0, 259 0, 260 0}; 261 262 263 static const PRPC_STUB_FUNCTION if2_table[] = 264 { 265 STUB_FORWARDING_FUNCTION, 266 STUB_FORWARDING_FUNCTION, 267 STUB_FORWARDING_FUNCTION, 268 STUB_FORWARDING_FUNCTION, 269 STUB_FORWARDING_FUNCTION, 270 STUB_FORWARDING_FUNCTION, 271 STUB_FORWARDING_FUNCTION, 272 STUB_FORWARDING_FUNCTION, 273 STUB_FORWARDING_FUNCTION, 274 STUB_FORWARDING_FUNCTION 275 }; 276 277 static CInterfaceStubVtbl if2_stub_vtbl = 278 { 279 { 280 &IID_if2, 281 &if2_server_info, 282 13, 283 &if2_table[-3] 284 }, 285 { 0, 0, test_CStdStubBuffer2_Release, 0, 0, 0, 0, 0, 0, 0 } 286 }; 287 288 static CINTERFACE_PROXY_VTABLE(5) if3_proxy_vtbl = 289 { 290 { &IID_if3 }, 291 { IUnknown_QueryInterface_Proxy, 292 IUnknown_AddRef_Proxy, 293 IUnknown_Release_Proxy , 294 if1_fn1_Proxy, 295 0 296 } 297 }; 298 299 300 static const unsigned short if3_FormatStringOffsetTable[] = 301 { 302 0, 303 0 304 }; 305 306 static const MIDL_SERVER_INFO if3_server_info = 307 { 308 &Object_StubDesc, 309 0, 310 __MIDL_ProcFormatString.Format, 311 &if3_FormatStringOffsetTable[-3], 312 0, 313 0, 314 0, 315 0}; 316 317 static CInterfaceStubVtbl if3_stub_vtbl = 318 { 319 { 320 &IID_if3, 321 &if3_server_info, 322 5, 323 &if1_table[-3] 324 }, 325 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } 326 }; 327 328 static CINTERFACE_PROXY_VTABLE(7) if4_proxy_vtbl = 329 { 330 { &IID_if4 }, 331 { IUnknown_QueryInterface_Proxy, 332 IUnknown_AddRef_Proxy, 333 IUnknown_Release_Proxy , 334 0, 335 0, 336 0, 337 0 338 } 339 }; 340 341 static const unsigned short if4_FormatStringOffsetTable[] = 342 { 343 (unsigned short) -1, 344 (unsigned short) -1, 345 (unsigned short) -1, 346 (unsigned short) -1, 347 0 348 }; 349 350 static const MIDL_SERVER_INFO if4_server_info = 351 { 352 &Object_StubDesc, 353 0, 354 __MIDL_ProcFormatString.Format, 355 &if4_FormatStringOffsetTable[-3], 356 0, 357 0, 358 0, 359 0}; 360 361 static CInterfaceStubVtbl if4_stub_vtbl = 362 { 363 { 364 &IID_if4, 365 &if4_server_info, 366 7, 367 &if2_table[-3] 368 }, 369 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } 370 }; 371 372 static const CInterfaceProxyVtbl *cstub_ProxyVtblList[] = 373 { 374 (const CInterfaceProxyVtbl *) &if1_proxy_vtbl, 375 (const CInterfaceProxyVtbl *) &if2_proxy_vtbl, 376 (const CInterfaceProxyVtbl *) &if3_proxy_vtbl, 377 (const CInterfaceProxyVtbl *) &if4_proxy_vtbl, 378 NULL 379 }; 380 381 static const CInterfaceStubVtbl *cstub_StubVtblList[] = 382 { 383 &if1_stub_vtbl, 384 &if2_stub_vtbl, 385 &if3_stub_vtbl, 386 &if4_stub_vtbl, 387 NULL 388 }; 389 390 static PCInterfaceName const if_name_list[] = 391 { 392 "if1", 393 "if2", 394 "if3", 395 "if4", 396 NULL 397 }; 398 399 static const IID *base_iid_list[] = 400 { 401 NULL, 402 &IID_ITypeLib, 403 NULL, 404 &IID_IDispatch, 405 NULL 406 }; 407 408 #define cstub_CHECK_IID(n) IID_GENERIC_CHECK_IID( cstub, pIID, n) 409 410 static int __stdcall iid_lookup( const IID * pIID, int * pIndex ) 411 { 412 IID_BS_LOOKUP_SETUP 413 414 IID_BS_LOOKUP_INITIAL_TEST( cstub, 4, 4 ) 415 IID_BS_LOOKUP_NEXT_TEST( cstub, 2 ) 416 IID_BS_LOOKUP_NEXT_TEST( cstub, 1 ) 417 IID_BS_LOOKUP_RETURN_RESULT( cstub, 4, *pIndex ) 418 419 } 420 421 422 static BOOL check_address(void *actual, void *expected) 423 { 424 static void *ole32_start = NULL; 425 static void *ole32_end = NULL; 426 static void *combase_start = NULL; 427 static void *combase_end = NULL; 428 429 if (actual == expected) 430 return TRUE; 431 432 /* On Win7, actual can be located inside ole32.dll */ 433 if (ole32_start == NULL || ole32_end == NULL) 434 { 435 PIMAGE_NT_HEADERS nt_headers; 436 ole32_start = (void *) GetModuleHandleA("ole32.dll"); 437 if (ole32_start == NULL) 438 return FALSE; 439 nt_headers = (PIMAGE_NT_HEADERS)((char *) ole32_start + ((PIMAGE_DOS_HEADER) ole32_start)->e_lfanew); 440 ole32_end = (void *)((char *) ole32_start + nt_headers->OptionalHeader.SizeOfImage); 441 } 442 443 if (ole32_start <= actual && actual < ole32_end) 444 return TRUE; 445 446 /* On Win8, actual can be located inside combase.dll */ 447 if (combase_start == NULL || combase_end == NULL) 448 { 449 PIMAGE_NT_HEADERS nt_headers; 450 combase_start = (void *) GetModuleHandleA("combase.dll"); 451 if (combase_start == NULL) 452 return FALSE; 453 nt_headers = (PIMAGE_NT_HEADERS)((char *) combase_start + ((PIMAGE_DOS_HEADER) combase_start)->e_lfanew); 454 combase_end = (void *)((char *) combase_start + nt_headers->OptionalHeader.SizeOfImage); 455 } 456 457 return (combase_start <= actual && actual < combase_end); 458 } 459 460 static const ExtendedProxyFileInfo my_proxy_file_info = 461 { 462 (const PCInterfaceProxyVtblList *) &cstub_ProxyVtblList, 463 (const PCInterfaceStubVtblList *) &cstub_StubVtblList, 464 (const PCInterfaceName *) &if_name_list, 465 (const IID **) &base_iid_list, 466 &iid_lookup, 467 4, 468 1, 469 NULL, 470 0, 471 0, 472 0 473 }; 474 475 static const ProxyFileInfo *proxy_file_list[] = { 476 &my_proxy_file_info, 477 NULL 478 }; 479 480 481 static IPSFactoryBuffer *test_NdrDllGetClassObject(void) 482 { 483 HMODULE rpcrt4 = GetModuleHandleA("rpcrt4.dll"); 484 IPSFactoryBuffer *ppsf = NULL; 485 const PCInterfaceProxyVtblList* proxy_vtbl; 486 const PCInterfaceStubVtblList* stub_vtbl; 487 const CLSID CLSID_Unknown = {0x45678, 0x1234, 0x6666, {0xff, 0x67, 0x45, 0x98, 0x76, 0x12, 0x34, 0x56}}; 488 static const GUID * const interfaces[] = { &IID_if1, &IID_if2, &IID_if3, &IID_if4 }; 489 UINT i; 490 HRESULT r; 491 HMODULE hmod = GetModuleHandleA("rpcrt4.dll"); 492 void *CStd_QueryInterface = GetProcAddress(hmod, "CStdStubBuffer_QueryInterface"); 493 void *CStd_AddRef = GetProcAddress(hmod, "CStdStubBuffer_AddRef"); 494 void *CStd_Release = GetProcAddress(hmod, "NdrCStdStubBuffer_Release"); 495 void *CStd_Connect = GetProcAddress(hmod, "CStdStubBuffer_Connect"); 496 void *CStd_Disconnect = GetProcAddress(hmod, "CStdStubBuffer_Disconnect"); 497 void *CStd_Invoke = GetProcAddress(hmod, "CStdStubBuffer_Invoke"); 498 void *CStd_IsIIDSupported = GetProcAddress(hmod, "CStdStubBuffer_IsIIDSupported"); 499 void *CStd_CountRefs = GetProcAddress(hmod, "CStdStubBuffer_CountRefs"); 500 void *CStd_DebugServerQueryInterface = GetProcAddress(hmod, "CStdStubBuffer_DebugServerQueryInterface"); 501 void *CStd_DebugServerRelease = GetProcAddress(hmod, "CStdStubBuffer_DebugServerRelease"); 502 503 r = NdrDllGetClassObject(&CLSID_Unknown, &IID_IPSFactoryBuffer, (void**)&ppsf, proxy_file_list, 504 &CLSID_psfact, &PSFactoryBuffer); 505 ok(r == CLASS_E_CLASSNOTAVAILABLE, "NdrDllGetClassObject with unknown clsid should have returned CLASS_E_CLASSNOTAVAILABLE instead of 0x%x\n", r); 506 ok(ppsf == NULL, "NdrDllGetClassObject should have set ppsf to NULL on failure\n"); 507 508 r = NdrDllGetClassObject(&CLSID_psfact, &IID_IPSFactoryBuffer, (void**)&ppsf, proxy_file_list, 509 &CLSID_psfact, &PSFactoryBuffer); 510 511 ok(r == S_OK, "ret %08x\n", r); 512 ok(ppsf != NULL, "ppsf == NULL\n"); 513 514 proxy_vtbl = PSFactoryBuffer.pProxyFileList[0]->pProxyVtblList; 515 stub_vtbl = PSFactoryBuffer.pProxyFileList[0]->pStubVtblList; 516 ok(PSFactoryBuffer.pProxyFileList == proxy_file_list, "pfl not the same\n"); 517 ok(proxy_vtbl == (PCInterfaceProxyVtblList *) &cstub_ProxyVtblList, "proxy vtbllist not the same\n"); 518 ok(stub_vtbl == (PCInterfaceStubVtblList *) &cstub_StubVtblList, "stub vtbllist not the same\n"); 519 520 /* if1 is non-delegating, if2 is delegating, if3 is non-delegating 521 but I've zero'ed the vtbl entries, similarly if4 is delegating 522 with zero'ed vtbl entries */ 523 524 #define VTBL_TEST_NOT_CHANGE_TO(name, i) \ 525 ok(stub_vtbl[i]->Vtbl.name != CStd_##name, #name "vtbl %d updated %p %p\n", \ 526 i, stub_vtbl[i]->Vtbl.name, CStd_##name ) 527 #define VTBL_TEST_CHANGE_TO(name, i) \ 528 ok(check_address(stub_vtbl[i]->Vtbl.name, CStd_##name), #name "vtbl %d not updated %p %p\n", \ 529 i, stub_vtbl[i]->Vtbl.name, CStd_##name ) 530 #define VTBL_TEST_ZERO(name, i) \ 531 ok(stub_vtbl[i]->Vtbl.name == NULL, #name "vtbl %d not null %p\n", \ 532 i, stub_vtbl[i]->Vtbl.name ) 533 534 VTBL_TEST_NOT_CHANGE_TO(QueryInterface, 0); 535 VTBL_TEST_NOT_CHANGE_TO(AddRef, 0); 536 VTBL_TEST_NOT_CHANGE_TO(Release, 0); 537 VTBL_TEST_NOT_CHANGE_TO(Connect, 0); 538 VTBL_TEST_NOT_CHANGE_TO(Disconnect, 0); 539 VTBL_TEST_NOT_CHANGE_TO(Invoke, 0); 540 VTBL_TEST_NOT_CHANGE_TO(IsIIDSupported, 0); 541 VTBL_TEST_NOT_CHANGE_TO(CountRefs, 0); 542 VTBL_TEST_NOT_CHANGE_TO(DebugServerQueryInterface, 0); 543 VTBL_TEST_NOT_CHANGE_TO(DebugServerRelease, 0); 544 545 VTBL_TEST_CHANGE_TO(QueryInterface, 1); 546 VTBL_TEST_CHANGE_TO(AddRef, 1); 547 VTBL_TEST_NOT_CHANGE_TO(Release, 1); 548 VTBL_TEST_NOT_CHANGE_TO(Connect, 1); 549 VTBL_TEST_NOT_CHANGE_TO(Disconnect, 1); 550 VTBL_TEST_CHANGE_TO(Invoke, 1); 551 VTBL_TEST_CHANGE_TO(IsIIDSupported, 1); 552 VTBL_TEST_NOT_CHANGE_TO(CountRefs, 1); 553 VTBL_TEST_CHANGE_TO(DebugServerQueryInterface, 1); 554 VTBL_TEST_CHANGE_TO(DebugServerRelease, 1); 555 556 VTBL_TEST_CHANGE_TO(QueryInterface, 2); 557 VTBL_TEST_CHANGE_TO(AddRef, 2); 558 VTBL_TEST_ZERO(Release, 2); 559 VTBL_TEST_CHANGE_TO(Connect, 2); 560 VTBL_TEST_CHANGE_TO(Disconnect, 2); 561 VTBL_TEST_CHANGE_TO(Invoke, 2); 562 VTBL_TEST_CHANGE_TO(IsIIDSupported, 2); 563 VTBL_TEST_CHANGE_TO(CountRefs, 2); 564 VTBL_TEST_CHANGE_TO(DebugServerQueryInterface, 2); 565 VTBL_TEST_CHANGE_TO(DebugServerRelease, 2); 566 567 VTBL_TEST_CHANGE_TO(QueryInterface, 3); 568 VTBL_TEST_CHANGE_TO(AddRef, 3); 569 VTBL_TEST_ZERO(Release, 3); 570 VTBL_TEST_NOT_CHANGE_TO(Connect, 3); 571 VTBL_TEST_NOT_CHANGE_TO(Disconnect, 3); 572 VTBL_TEST_CHANGE_TO(Invoke, 3); 573 VTBL_TEST_CHANGE_TO(IsIIDSupported, 3); 574 VTBL_TEST_NOT_CHANGE_TO(CountRefs, 3); 575 VTBL_TEST_CHANGE_TO(DebugServerQueryInterface, 3); 576 VTBL_TEST_CHANGE_TO(DebugServerRelease, 3); 577 578 #define VTBL_PROXY_TEST(i,num,ptr) \ 579 ok( check_address(proxy_vtbl[i]->Vtbl[num], (ptr)), "wrong proxy %u func %u %p/%p\n", \ 580 (i), (num), proxy_vtbl[i]->Vtbl[num], (ptr) ) 581 #define VTBL_PROXY_TEST_NOT_ZERO(i,num) \ 582 ok( proxy_vtbl[i]->Vtbl[num] != NULL, "wrong proxy %u func %u is NULL\n", (i), (num)) 583 584 VTBL_PROXY_TEST(0, 0, IUnknown_QueryInterface_Proxy); 585 VTBL_PROXY_TEST(0, 1, IUnknown_AddRef_Proxy); 586 VTBL_PROXY_TEST(0, 2, IUnknown_Release_Proxy); 587 VTBL_PROXY_TEST(0, 3, if1_fn1_Proxy); 588 VTBL_PROXY_TEST(0, 4, if1_fn2_Proxy); 589 590 VTBL_PROXY_TEST(1, 0, GetProcAddress(rpcrt4,"IUnknown_QueryInterface_Proxy")); 591 VTBL_PROXY_TEST(1, 1, GetProcAddress(rpcrt4,"IUnknown_AddRef_Proxy")); 592 VTBL_PROXY_TEST(1, 2, GetProcAddress(rpcrt4,"IUnknown_Release_Proxy")); 593 VTBL_PROXY_TEST_NOT_ZERO(1, 3); 594 VTBL_PROXY_TEST_NOT_ZERO(1, 4); 595 VTBL_PROXY_TEST_NOT_ZERO(1, 5); 596 VTBL_PROXY_TEST_NOT_ZERO(1, 6); 597 VTBL_PROXY_TEST_NOT_ZERO(1, 7); 598 VTBL_PROXY_TEST_NOT_ZERO(1, 8); 599 VTBL_PROXY_TEST_NOT_ZERO(1, 9); 600 VTBL_PROXY_TEST_NOT_ZERO(1, 10); 601 VTBL_PROXY_TEST_NOT_ZERO(1, 11); 602 VTBL_PROXY_TEST_NOT_ZERO(1, 12); 603 604 VTBL_PROXY_TEST(2, 0, IUnknown_QueryInterface_Proxy); 605 VTBL_PROXY_TEST(2, 1, IUnknown_AddRef_Proxy); 606 VTBL_PROXY_TEST(2, 2, IUnknown_Release_Proxy); 607 VTBL_PROXY_TEST(2, 3, if1_fn1_Proxy); 608 todo_wine VTBL_PROXY_TEST_NOT_ZERO(2, 4); 609 610 VTBL_PROXY_TEST(3, 0, GetProcAddress(rpcrt4,"IUnknown_QueryInterface_Proxy")); 611 VTBL_PROXY_TEST(3, 1, GetProcAddress(rpcrt4,"IUnknown_AddRef_Proxy")); 612 VTBL_PROXY_TEST(3, 2, GetProcAddress(rpcrt4,"IUnknown_Release_Proxy")); 613 VTBL_PROXY_TEST_NOT_ZERO(3, 3); 614 VTBL_PROXY_TEST_NOT_ZERO(3, 4); 615 VTBL_PROXY_TEST_NOT_ZERO(3, 5); 616 VTBL_PROXY_TEST_NOT_ZERO(3, 6); 617 618 #undef VTBL_TEST_NOT_CHANGE_TO 619 #undef VTBL_TEST_CHANGE_TO 620 #undef VTBL_TEST_ZERO 621 #undef VTBL_PROXY_TEST 622 #undef VTBL_PROXY_TEST_NOT_ZERO 623 624 for (i = 0; i < ARRAY_SIZE(interfaces); i++) 625 ok( proxy_vtbl[i]->header.piid == interfaces[i], 626 "wrong proxy %u iid %p/%p\n", i, proxy_vtbl[i]->header.piid, interfaces[i] ); 627 628 ok(PSFactoryBuffer.RefCount == 1, "ref count %d\n", PSFactoryBuffer.RefCount); 629 IPSFactoryBuffer_Release(ppsf); 630 631 /* One can also search by IID */ 632 r = NdrDllGetClassObject(&IID_if3, &IID_IPSFactoryBuffer, (void**)&ppsf, proxy_file_list, 633 &CLSID_psfact, &PSFactoryBuffer); 634 ok(r == S_OK, "ret %08x\n", r); 635 ok(ppsf != NULL, "ppsf == NULL\n"); 636 IPSFactoryBuffer_Release(ppsf); 637 638 r = NdrDllGetClassObject(&IID_if3, &IID_IPSFactoryBuffer, (void**)&ppsf, proxy_file_list, 639 NULL, &PSFactoryBuffer); 640 ok(r == S_OK, "ret %08x\n", r); 641 ok(ppsf != NULL, "ppsf == NULL\n"); 642 IPSFactoryBuffer_Release(ppsf); 643 644 /* but only if the PS factory implements it */ 645 r = NdrDllGetClassObject(&IID_IDispatch, &IID_IPSFactoryBuffer, (void**)&ppsf, proxy_file_list, 646 &CLSID_psfact, &PSFactoryBuffer); 647 ok(r == CLASS_E_CLASSNOTAVAILABLE, "ret %08x\n", r); 648 649 /* Create it again to return */ 650 r = NdrDllGetClassObject(&CLSID_psfact, &IID_IPSFactoryBuffer, (void**)&ppsf, proxy_file_list, 651 &CLSID_psfact, &PSFactoryBuffer); 652 ok(r == S_OK, "ret %08x\n", r); 653 ok(ppsf != NULL, "ppsf == NULL\n"); 654 655 /* Because this PS factory is not loaded as a dll in the normal way, Windows 8 / 10 656 get confused and will crash when one of the proxies for the delegated ifaces is created. 657 Registering the ifaces fixes this (in fact calling CoRegisterPSClsid() with any IID / CLSID is enough). */ 658 659 r = CoRegisterPSClsid(&IID_if1, &CLSID_psfact); 660 ok(r == S_OK, "ret %08x\n", r); 661 r = CoRegisterPSClsid(&IID_if2, &CLSID_psfact); 662 ok(r == S_OK, "ret %08x\n", r); 663 r = CoRegisterPSClsid(&IID_if3, &CLSID_psfact); 664 ok(r == S_OK, "ret %08x\n", r); 665 r = CoRegisterPSClsid(&IID_if4, &CLSID_psfact); 666 ok(r == S_OK, "ret %08x\n", r); 667 668 return ppsf; 669 } 670 671 static int base_buffer_invoke_called; 672 static HRESULT WINAPI base_buffer_Invoke(IRpcStubBuffer *This, RPCOLEMESSAGE *msg, IRpcChannelBuffer *channel) 673 { 674 base_buffer_invoke_called++; 675 ok(msg == (RPCOLEMESSAGE*)0xcafebabe, "msg ptr changed\n"); 676 ok(channel == (IRpcChannelBuffer*)0xdeadbeef, "channel ptr changed\n"); 677 return S_OK; /* returning any failure here results in an exception */ 678 } 679 680 static IRpcStubBufferVtbl base_buffer_vtbl = { 681 (void*)0xcafebab0, 682 (void*)0xcafebab1, 683 (void*)0xcafebab2, 684 (void*)0xcafebab3, 685 (void*)0xcafebab4, 686 base_buffer_Invoke, 687 (void*)0xcafebab6, 688 (void*)0xcafebab7, 689 (void*)0xcafebab8, 690 (void*)0xcafebab9 691 }; 692 693 static void test_NdrStubForwardingFunction(void) 694 { 695 void *This[5]; 696 void *real_this; 697 IRpcChannelBuffer *channel = (IRpcChannelBuffer*)0xdeadbeef; 698 RPC_MESSAGE *msg = (RPC_MESSAGE*)0xcafebabe; 699 DWORD *phase = (DWORD*)0x12345678; 700 IRpcStubBufferVtbl *base_buffer_vtbl_ptr = &base_buffer_vtbl; 701 IRpcStubBuffer *base_stub_buffer = (IRpcStubBuffer*)&base_buffer_vtbl_ptr; 702 703 memset(This, 0xcc, sizeof(This)); 704 This[0] = base_stub_buffer; 705 real_this = &This[1]; 706 707 NdrStubForwardingFunction( real_this, channel, msg, phase ); 708 ok(base_buffer_invoke_called == 1, "base_buffer_invoke called %d times\n", base_buffer_invoke_called); 709 710 } 711 712 static IRpcStubBuffer *create_stub(IPSFactoryBuffer *ppsf, REFIID iid, IUnknown *obj, HRESULT expected_result) 713 { 714 IRpcStubBuffer *pstub = NULL; 715 HRESULT r; 716 717 r = IPSFactoryBuffer_CreateStub(ppsf, iid, obj, &pstub); 718 ok(r == expected_result, "CreateStub returned %08x expected %08x\n", r, expected_result); 719 return pstub; 720 } 721 722 static HRESULT WINAPI create_stub_test_QI(IUnknown *This, REFIID iid, void **ppv) 723 { 724 ok(IsEqualIID(iid, &IID_if1), "incorrect iid\n"); 725 *ppv = (void*)0xdeadbeef; 726 return S_OK; 727 } 728 729 static IUnknownVtbl create_stub_test_vtbl = 730 { 731 create_stub_test_QI, 732 NULL, 733 NULL 734 }; 735 736 static HRESULT WINAPI create_stub_test_fail_QI(IUnknown *This, REFIID iid, void **ppv) 737 { 738 ok(IsEqualIID(iid, &IID_if1), "incorrect iid\n"); 739 *ppv = NULL; 740 return E_NOINTERFACE; 741 } 742 743 static IUnknownVtbl create_stub_test_fail_vtbl = 744 { 745 create_stub_test_fail_QI, 746 NULL, 747 NULL 748 }; 749 750 struct dummy_unknown 751 { 752 IUnknown IUnknown_iface; 753 LONG ref; 754 }; 755 756 static inline struct dummy_unknown *impl_from_IUnknown(IUnknown *iface) 757 { 758 return CONTAINING_RECORD(iface, struct dummy_unknown, IUnknown_iface); 759 } 760 761 static HRESULT WINAPI dummy_QueryInterface(IUnknown *This, REFIID iid, void **ppv) 762 { 763 *ppv = NULL; 764 return E_NOINTERFACE; 765 } 766 767 static ULONG WINAPI dummy_AddRef(LPUNKNOWN iface) 768 { 769 struct dummy_unknown *this = impl_from_IUnknown(iface); 770 return InterlockedIncrement( &this->ref ); 771 } 772 773 static ULONG WINAPI dummy_Release(LPUNKNOWN iface) 774 { 775 struct dummy_unknown *this = impl_from_IUnknown(iface); 776 return InterlockedDecrement( &this->ref ); 777 } 778 779 static IUnknownVtbl dummy_unknown_vtbl = 780 { 781 dummy_QueryInterface, 782 dummy_AddRef, 783 dummy_Release 784 }; 785 static struct dummy_unknown dummy_unknown = { { &dummy_unknown_vtbl }, 0 }; 786 787 static void create_proxy_test( IPSFactoryBuffer *ppsf, REFIID iid, const void *expected_vtbl ) 788 { 789 IRpcProxyBuffer *proxy = NULL; 790 IUnknown *iface = NULL; 791 HRESULT r; 792 ULONG count; 793 794 r = IPSFactoryBuffer_CreateProxy(ppsf, NULL, iid, &proxy, (void **)&iface); 795 ok( r == S_OK, "IPSFactoryBuffer_CreateProxy failed %x\n", r ); 796 ok( *(void **)iface == expected_vtbl, "wrong iface pointer %p/%p\n", *(void **)iface, expected_vtbl ); 797 count = IUnknown_Release( iface ); 798 ok( count == 1, "wrong refcount %u\n", count ); 799 count = IRpcProxyBuffer_Release( proxy ); 800 ok( count == 0, "wrong refcount %u\n", count ); 801 802 dummy_unknown.ref = 4; 803 r = IPSFactoryBuffer_CreateProxy(ppsf, &dummy_unknown.IUnknown_iface, iid, &proxy, 804 (void **)&iface); 805 ok( r == S_OK, "IPSFactoryBuffer_CreateProxy failed %x\n", r ); 806 ok( dummy_unknown.ref == 5, "wrong refcount %u\n", dummy_unknown.ref ); 807 ok( *(void **)iface == expected_vtbl, "wrong iface pointer %p/%p\n", *(void **)iface, expected_vtbl ); 808 count = IUnknown_Release( iface ); 809 ok( count == 4, "wrong refcount %u\n", count ); 810 ok( dummy_unknown.ref == 4, "wrong refcount %u\n", dummy_unknown.ref ); 811 count = IRpcProxyBuffer_Release( proxy ); 812 ok( count == 0, "wrong refcount %u\n", count ); 813 ok( dummy_unknown.ref == 4, "wrong refcount %u\n", dummy_unknown.ref ); 814 } 815 816 static void test_CreateProxy( IPSFactoryBuffer *ppsf ) 817 { 818 create_proxy_test( ppsf, &IID_if1, if1_proxy_vtbl.Vtbl ); 819 create_proxy_test( ppsf, &IID_if2, if2_proxy_vtbl.Vtbl ); 820 create_proxy_test( ppsf, &IID_if3, if3_proxy_vtbl.Vtbl ); 821 create_proxy_test( ppsf, &IID_if4, if4_proxy_vtbl.Vtbl ); 822 } 823 824 static void test_CreateStub(IPSFactoryBuffer *ppsf) 825 { 826 IUnknownVtbl *vtbl = &create_stub_test_vtbl; 827 IUnknown *obj = (IUnknown*)&vtbl; 828 IRpcStubBuffer *pstub = create_stub(ppsf, &IID_if1, obj, S_OK); 829 CStdStubBuffer *cstd_stub = (CStdStubBuffer*)pstub; 830 const CInterfaceStubHeader *header = &CONTAINING_RECORD(cstd_stub->lpVtbl, const CInterfaceStubVtbl, Vtbl)->header; 831 832 ok(IsEqualIID(header->piid, &IID_if1), "header iid differs\n"); 833 ok(cstd_stub->RefCount == 1, "ref count %d\n", cstd_stub->RefCount); 834 /* 0xdeadbeef returned from create_stub_test_QI */ 835 ok(cstd_stub->pvServerObject == (void*)0xdeadbeef, "pvServerObject %p\n", cstd_stub->pvServerObject); 836 ok(cstd_stub->pPSFactory != NULL, "pPSFactory was NULL\n"); 837 cstd_stub->pvServerObject = NULL; 838 IRpcStubBuffer_Release(pstub); 839 840 vtbl = &create_stub_test_fail_vtbl; 841 pstub = create_stub(ppsf, &IID_if1, obj, E_NOINTERFACE); 842 ok(pstub == S_OK, "create_stub failed: %u\n", GetLastError()); 843 844 } 845 846 static HRESULT WINAPI connect_test_orig_QI(IUnknown *This, REFIID iid, void **ppv) 847 { 848 ok(IsEqualIID(iid, &IID_if1) || 849 IsEqualIID(iid, &IID_if2), "incorrect iid\n"); 850 *ppv = (void*)This; 851 return S_OK; 852 } 853 854 static int connect_test_orig_release_called; 855 static ULONG WINAPI connect_test_orig_release(IUnknown *This) 856 { 857 connect_test_orig_release_called++; 858 return 0; 859 } 860 861 static IUnknownVtbl connect_test_orig_vtbl = 862 { 863 connect_test_orig_QI, 864 NULL, 865 connect_test_orig_release 866 }; 867 868 static HRESULT WINAPI connect_test_new_QI(IUnknown *This, REFIID iid, void **ppv) 869 { 870 ok(IsEqualIID(iid, &IID_if1) || 871 IsEqualIID(iid, &IID_if2), "incorrect iid\n"); 872 *ppv = (void*)0xcafebabe; 873 return S_OK; 874 } 875 876 static IUnknownVtbl connect_test_new_vtbl = 877 { 878 connect_test_new_QI, 879 NULL, 880 NULL 881 }; 882 883 static HRESULT WINAPI connect_test_new_fail_QI(IUnknown *This, REFIID iid, void **ppv) 884 { 885 ok(IsEqualIID(iid, &IID_if1), "incorrect iid\n"); 886 *ppv = (void*)0xdeadbeef; 887 return E_NOINTERFACE; 888 } 889 890 static IUnknownVtbl connect_test_new_fail_vtbl = 891 { 892 connect_test_new_fail_QI, 893 NULL, 894 NULL 895 }; 896 897 static int connect_test_base_Connect_called; 898 static HRESULT WINAPI connect_test_base_Connect(IRpcStubBuffer *pstub, IUnknown *obj) 899 { 900 connect_test_base_Connect_called++; 901 ok(*(void**)obj == (void*)0xbeefcafe, "unexpected obj %p\n", obj); 902 return S_OK; 903 } 904 905 static IRpcStubBufferVtbl connect_test_base_stub_buffer_vtbl = 906 { 907 (void*)0xcafebab0, 908 (void*)0xcafebab1, 909 (void*)0xcafebab2, 910 connect_test_base_Connect, 911 (void*)0xcafebab4, 912 (void*)0xcafebab5, 913 (void*)0xcafebab6, 914 (void*)0xcafebab7, 915 (void*)0xcafebab8, 916 (void*)0xcafebab9 917 }; 918 919 static void test_Connect(IPSFactoryBuffer *ppsf) 920 { 921 IUnknownVtbl *orig_vtbl = &connect_test_orig_vtbl; 922 IUnknownVtbl *new_vtbl = &connect_test_new_vtbl; 923 IUnknownVtbl *new_fail_vtbl = &connect_test_new_fail_vtbl; 924 IUnknown *obj = (IUnknown*)&orig_vtbl; 925 IRpcStubBuffer *pstub = create_stub(ppsf, &IID_if1, obj, S_OK); 926 CStdStubBuffer *cstd_stub = (CStdStubBuffer*)pstub; 927 IRpcStubBufferVtbl *base_stub_buf_vtbl = &connect_test_base_stub_buffer_vtbl; 928 HRESULT r; 929 930 obj = (IUnknown*)&new_vtbl; 931 r = IRpcStubBuffer_Connect(pstub, obj); 932 ok(r == S_OK, "r %08x\n", r); 933 ok(connect_test_orig_release_called == 1, "release called %d\n", connect_test_orig_release_called); 934 ok(cstd_stub->pvServerObject == (void*)0xcafebabe, "pvServerObject %p\n", cstd_stub->pvServerObject); 935 936 cstd_stub->pvServerObject = (IUnknown*)&orig_vtbl; 937 obj = (IUnknown*)&new_fail_vtbl; 938 r = IRpcStubBuffer_Connect(pstub, obj); 939 ok(r == E_NOINTERFACE, "r %08x\n", r); 940 ok(cstd_stub->pvServerObject == (void*)0xdeadbeef, "pvServerObject %p\n", cstd_stub->pvServerObject); 941 ok(connect_test_orig_release_called == 2, "release called %d\n", connect_test_orig_release_called); 942 943 /* Now use a delegated stub. 944 945 We know from the NdrStubForwardFunction test that 946 (void**)pstub-1 is the base interface stub buffer. This shows 947 that (void**)pstub-2 contains the address of a vtable that gets 948 passed to the base interface's Connect method. Note that 949 (void**)pstub-2 itself gets passed to Connect and not 950 *((void**)pstub-2), so it should contain the vtable ptr and not 951 an interface ptr. */ 952 953 obj = (IUnknown*)&orig_vtbl; 954 pstub = create_stub(ppsf, &IID_if2, obj, S_OK); 955 *((void**)pstub-1) = &base_stub_buf_vtbl; 956 *((void**)pstub-2) = (void*)0xbeefcafe; 957 958 obj = (IUnknown*)&new_vtbl; 959 r = IRpcStubBuffer_Connect(pstub, obj); 960 ok(r == S_OK, "r %08x\n", r); 961 ok(connect_test_base_Connect_called == 1, "connect_test_bsae_Connect called %d times\n", 962 connect_test_base_Connect_called); 963 ok(connect_test_orig_release_called == 3, "release called %d\n", connect_test_orig_release_called); 964 cstd_stub = (CStdStubBuffer*)pstub; 965 ok(cstd_stub->pvServerObject == (void*)0xcafebabe, "pvServerObject %p\n", cstd_stub->pvServerObject); 966 } 967 968 static void test_Disconnect(IPSFactoryBuffer *ppsf) 969 { 970 IUnknownVtbl *orig_vtbl = &connect_test_orig_vtbl; 971 IUnknown *obj = (IUnknown*)&orig_vtbl; 972 IRpcStubBuffer *pstub = create_stub(ppsf, &IID_if1, obj, S_OK); 973 CStdStubBuffer *cstd_stub = (CStdStubBuffer*)pstub; 974 975 connect_test_orig_release_called = 0; 976 IRpcStubBuffer_Disconnect(pstub); 977 ok(connect_test_orig_release_called == 1, "release called %d\n", connect_test_orig_release_called); 978 ok(cstd_stub->pvServerObject == NULL, "pvServerObject %p\n", cstd_stub->pvServerObject); 979 IRpcStubBuffer_Release(pstub); 980 } 981 982 983 static int release_test_psfacbuf_release_called; 984 static ULONG WINAPI release_test_pretend_psfacbuf_release(IUnknown *pUnk) 985 { 986 release_test_psfacbuf_release_called++; 987 return 1; 988 } 989 990 static IUnknownVtbl release_test_pretend_psfacbuf_vtbl = 991 { 992 NULL, 993 NULL, 994 release_test_pretend_psfacbuf_release 995 }; 996 997 static void test_Release(IPSFactoryBuffer *ppsf) 998 { 999 LONG facbuf_refs; 1000 IUnknownVtbl *orig_vtbl = &connect_test_orig_vtbl; 1001 IUnknown *obj = (IUnknown*)&orig_vtbl; 1002 IUnknownVtbl *pretend_psfacbuf_vtbl = &release_test_pretend_psfacbuf_vtbl; 1003 IUnknown *pretend_psfacbuf = (IUnknown *)&pretend_psfacbuf_vtbl; 1004 IRpcStubBuffer *pstub = create_stub(ppsf, &IID_if1, obj, S_OK); 1005 CStdStubBuffer *cstd_stub = (CStdStubBuffer*)pstub; 1006 1007 facbuf_refs = PSFactoryBuffer.RefCount; 1008 1009 /* This shows that NdrCStdStubBuffer_Release doesn't call Disconnect */ 1010 ok(cstd_stub->RefCount == 1, "ref count %d\n", cstd_stub->RefCount); 1011 connect_test_orig_release_called = 0; 1012 IRpcStubBuffer_Release(pstub); 1013 todo_wine { 1014 ok(connect_test_orig_release_called == 0, "release called %d\n", connect_test_orig_release_called); 1015 } 1016 ok(PSFactoryBuffer.RefCount == facbuf_refs - 1, "factory buffer refs %d orig %d\n", PSFactoryBuffer.RefCount, facbuf_refs); 1017 1018 /* This shows that NdrCStdStubBuffer_Release calls Release on its 2nd arg, rather than on This->pPSFactory 1019 (which are usually the same and indeed it's odd that _Release requires this 2nd arg). */ 1020 pstub = create_stub(ppsf, &IID_if1, obj, S_OK); 1021 ok(PSFactoryBuffer.RefCount == facbuf_refs, "factory buffer refs %d orig %d\n", PSFactoryBuffer.RefCount, facbuf_refs); 1022 NdrCStdStubBuffer_Release(pstub, (IPSFactoryBuffer*)pretend_psfacbuf); 1023 ok(release_test_psfacbuf_release_called == 1, "pretend_psfacbuf_release called %d\n", release_test_psfacbuf_release_called); 1024 ok(PSFactoryBuffer.RefCount == facbuf_refs, "factory buffer refs %d orig %d\n", PSFactoryBuffer.RefCount, facbuf_refs); 1025 } 1026 1027 static HRESULT WINAPI delegating_invoke_test_QI(ITypeLib *pUnk, REFIID iid, void** ppv) 1028 { 1029 1030 *ppv = pUnk; 1031 return S_OK; 1032 } 1033 1034 static ULONG WINAPI delegating_invoke_test_addref(ITypeLib *pUnk) 1035 { 1036 return 1; 1037 } 1038 1039 static ULONG WINAPI delegating_invoke_test_release(ITypeLib *pUnk) 1040 { 1041 return 1; 1042 } 1043 1044 static UINT WINAPI delegating_invoke_test_get_type_info_count(ITypeLib *pUnk) 1045 { 1046 return 0xabcdef; 1047 } 1048 1049 static ITypeLibVtbl delegating_invoke_test_obj_vtbl = 1050 { 1051 delegating_invoke_test_QI, 1052 delegating_invoke_test_addref, 1053 delegating_invoke_test_release, 1054 delegating_invoke_test_get_type_info_count, 1055 NULL, 1056 NULL, 1057 NULL, 1058 NULL, 1059 NULL, 1060 NULL, 1061 NULL, 1062 NULL, 1063 NULL 1064 }; 1065 1066 static HRESULT WINAPI delegating_invoke_chan_query_interface(IRpcChannelBuffer *pchan, 1067 REFIID iid, 1068 void **ppv) 1069 { 1070 ok(0, "call to QueryInterface not expected\n"); 1071 return E_NOINTERFACE; 1072 } 1073 1074 static ULONG WINAPI delegating_invoke_chan_add_ref(IRpcChannelBuffer *pchan) 1075 { 1076 return 2; 1077 } 1078 1079 static ULONG WINAPI delegating_invoke_chan_release(IRpcChannelBuffer *pchan) 1080 { 1081 return 1; 1082 } 1083 1084 static HRESULT WINAPI delegating_invoke_chan_get_buffer(IRpcChannelBuffer *pchan, 1085 RPCOLEMESSAGE *msg, 1086 REFIID iid) 1087 { 1088 msg->Buffer = HeapAlloc(GetProcessHeap(), 0, msg->cbBuffer); 1089 return S_OK; 1090 } 1091 1092 static HRESULT WINAPI delegating_invoke_chan_send_receive(IRpcChannelBuffer *pchan, 1093 RPCOLEMESSAGE *pMessage, 1094 ULONG *pStatus) 1095 { 1096 ok(0, "call to SendReceive not expected\n"); 1097 return E_NOTIMPL; 1098 } 1099 1100 static HRESULT WINAPI delegating_invoke_chan_free_buffer(IRpcChannelBuffer *pchan, 1101 RPCOLEMESSAGE *pMessage) 1102 { 1103 ok(0, "call to FreeBuffer not expected\n"); 1104 return E_NOTIMPL; 1105 } 1106 1107 static HRESULT WINAPI delegating_invoke_chan_get_dest_ctx(IRpcChannelBuffer *pchan, 1108 DWORD *pdwDestContext, 1109 void **ppvDestContext) 1110 { 1111 *pdwDestContext = MSHCTX_LOCAL; 1112 *ppvDestContext = NULL; 1113 return S_OK; 1114 } 1115 1116 static HRESULT WINAPI delegating_invoke_chan_is_connected(IRpcChannelBuffer *pchan) 1117 { 1118 ok(0, "call to IsConnected not expected\n"); 1119 return E_NOTIMPL; 1120 } 1121 1122 static IRpcChannelBufferVtbl delegating_invoke_test_rpc_chan_vtbl = 1123 { 1124 delegating_invoke_chan_query_interface, 1125 delegating_invoke_chan_add_ref, 1126 delegating_invoke_chan_release, 1127 delegating_invoke_chan_get_buffer, 1128 delegating_invoke_chan_send_receive, 1129 delegating_invoke_chan_free_buffer, 1130 delegating_invoke_chan_get_dest_ctx, 1131 delegating_invoke_chan_is_connected 1132 }; 1133 1134 static void test_delegating_Invoke(IPSFactoryBuffer *ppsf) 1135 { 1136 ITypeLibVtbl *obj_vtbl = &delegating_invoke_test_obj_vtbl; 1137 IUnknown *obj = (IUnknown*)&obj_vtbl; 1138 IRpcStubBuffer *pstub = create_stub(ppsf, &IID_if2, obj, S_OK); 1139 IRpcChannelBufferVtbl *pchan_vtbl = &delegating_invoke_test_rpc_chan_vtbl; 1140 IRpcChannelBuffer *pchan = (IRpcChannelBuffer *)&pchan_vtbl; 1141 HRESULT r = E_FAIL; 1142 RPCOLEMESSAGE msg; 1143 1144 memset(&msg, 0, sizeof(msg)); 1145 msg.dataRepresentation = NDR_LOCAL_DATA_REPRESENTATION; 1146 msg.iMethod = 3; 1147 r = IRpcStubBuffer_Invoke(pstub, &msg, pchan); 1148 ok(r == S_OK, "ret %08x\n", r); 1149 if(r == S_OK) 1150 { 1151 ok(*(DWORD*)msg.Buffer == 0xabcdef, "buf[0] %08x\n", *(DWORD*)msg.Buffer); 1152 ok(*((DWORD*)msg.Buffer + 1) == S_OK, "buf[1] %08x\n", *((DWORD*)msg.Buffer + 1)); 1153 } 1154 /* free the buffer allocated by delegating_invoke_chan_get_buffer */ 1155 HeapFree(GetProcessHeap(), 0, msg.Buffer); 1156 IRpcStubBuffer_Release(pstub); 1157 } 1158 static const CInterfaceProxyVtbl *cstub_ProxyVtblList2[] = 1159 { 1160 NULL 1161 }; 1162 1163 static const CInterfaceStubVtbl *cstub_StubVtblList2[] = 1164 { 1165 NULL 1166 }; 1167 1168 static PCInterfaceName const if_name_list2[] = 1169 { 1170 NULL 1171 }; 1172 1173 static const IID *base_iid_list2[] = 1174 { 1175 NULL, 1176 }; 1177 1178 static const ExtendedProxyFileInfo my_proxy_file_info2 = 1179 { 1180 (const PCInterfaceProxyVtblList *) &cstub_ProxyVtblList2, 1181 (const PCInterfaceStubVtblList *) &cstub_StubVtblList2, 1182 (const PCInterfaceName *) &if_name_list2, 1183 (const IID **) &base_iid_list2, 1184 &iid_lookup, 1185 0, 1186 1, 1187 NULL, 1188 0, 1189 0, 1190 0 1191 }; 1192 1193 static const ProxyFileInfo *proxy_file_list2[] = { 1194 &my_proxy_file_info2, 1195 NULL 1196 }; 1197 1198 static void test_NdrDllRegisterProxy( void ) 1199 { 1200 HRESULT res; 1201 const ExtendedProxyFileInfo *pf; 1202 HMODULE hmod = GetModuleHandleA(NULL); 1203 1204 1205 res = NdrDllRegisterProxy(NULL, NULL, NULL); 1206 ok(res == E_HANDLE, "Incorrect return code %x\n",res); 1207 pf = NULL; 1208 res = NdrDllRegisterProxy(hmod, &pf, NULL); 1209 ok(res == E_NOINTERFACE, "Incorrect return code %x\n",res); 1210 res = NdrDllRegisterProxy(hmod, proxy_file_list2, NULL); 1211 ok(res == E_NOINTERFACE, "Incorrect return code %x\n",res); 1212 /* This fails on Vista and Windows 7 due to permissions */ 1213 res = NdrDllRegisterProxy(hmod, proxy_file_list, NULL); 1214 ok(res == S_OK || res == E_ACCESSDENIED, "NdrDllRegisterProxy failed %x\n",res); 1215 if (res == S_OK) 1216 { 1217 res = NdrDllUnregisterProxy(hmod,proxy_file_list, NULL); 1218 ok(res == S_OK, "NdrDllUnregisterProxy failed %x\n",res); 1219 } 1220 } 1221 1222 static HANDLE create_process(const char *arg) 1223 { 1224 PROCESS_INFORMATION pi; 1225 STARTUPINFOA si = {0}; 1226 char cmdline[200]; 1227 char **argv; 1228 BOOL ret; 1229 1230 si.cb = sizeof(si); 1231 winetest_get_mainargs(&argv); 1232 sprintf(cmdline, "\"%s\" %s %s", argv[0], argv[1], arg); 1233 ret = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); 1234 ok(ret, "CreateProcess failed: %u\n", GetLastError()); 1235 CloseHandle(pi.hThread); 1236 return pi.hProcess; 1237 } 1238 1239 DEFINE_GUID(CLSID_test1,0xdeadf00d,0x0001,0x44c7,0x85,0x0f,0x2a,0x0f,0x46,0x5c,0x0c,0x6c); 1240 1241 static HRESULT WINAPI test1_QueryInterface(ITest1 *iface, REFIID iid, void **out) 1242 { 1243 if (winetest_debug > 1) trace("%s\n", wine_dbgstr_guid(iid)); 1244 if (IsEqualGUID(iid, &IID_IUnknown) || IsEqualGUID(iid, &IID_ITest1)) 1245 { 1246 *out = iface; 1247 return S_OK; 1248 } 1249 *out = NULL; 1250 return E_NOINTERFACE; 1251 } 1252 1253 static ULONG WINAPI test1_AddRef(ITest1 *iface) 1254 { 1255 return 2; 1256 } 1257 1258 static ULONG WINAPI test1_Release(ITest1 *iface) 1259 { 1260 return 1; 1261 } 1262 1263 static HRESULT WINAPI test1_GetClassID(ITest1 *iface, CLSID *clsid) 1264 { 1265 *clsid = CLSID_test1; 1266 return S_OK; 1267 } 1268 1269 static int WINAPI test1_square(ITest1 *iface, int x) 1270 { 1271 return x * x; 1272 } 1273 1274 static const ITest1Vtbl test1_vtbl = 1275 { 1276 test1_QueryInterface, 1277 test1_AddRef, 1278 test1_Release, 1279 test1_GetClassID, 1280 test1_square, 1281 }; 1282 1283 static HRESULT WINAPI test_cf_QueryInterface(IClassFactory *iface, REFIID iid, void **out) 1284 { 1285 if (IsEqualGUID(iid, &IID_IUnknown) || IsEqualGUID(iid, &IID_IClassFactory)) 1286 { 1287 *out = iface; 1288 return S_OK; 1289 } 1290 *out = NULL; 1291 return E_NOINTERFACE; 1292 } 1293 1294 static ULONG WINAPI test_cf_AddRef(IClassFactory *iface) 1295 { 1296 return 2; 1297 } 1298 1299 static ULONG WINAPI test_cf_Release(IClassFactory *iface) 1300 { 1301 return 1; 1302 } 1303 1304 static HRESULT WINAPI test_cf_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID iid, void **out) 1305 { 1306 ITest1 *obj = heap_alloc(sizeof(*obj)); 1307 1308 obj->lpVtbl = &test1_vtbl; 1309 1310 return ITest1_QueryInterface(obj, iid, out); 1311 } 1312 1313 static HRESULT WINAPI test_cf_LockServer(IClassFactory *iface, BOOL lock) 1314 { 1315 return S_OK; 1316 } 1317 1318 static const IClassFactoryVtbl test_cf_vtbl = 1319 { 1320 test_cf_QueryInterface, 1321 test_cf_AddRef, 1322 test_cf_Release, 1323 test_cf_CreateInstance, 1324 test_cf_LockServer, 1325 }; 1326 1327 static IClassFactory test_cf = { &test_cf_vtbl }; 1328 1329 extern CStdPSFactoryBuffer gPFactory; 1330 extern const ProxyFileInfo * aProxyFileList; 1331 1332 static void local_server_proc(void) 1333 { 1334 DWORD obj_cookie, ps_cookie, index; 1335 HANDLE stop_event, ready_event; 1336 IPSFactoryBuffer *ps; 1337 HRESULT hr; 1338 1339 stop_event = OpenEventA(EVENT_ALL_ACCESS, FALSE, "wine_cstub_test_server_stop"); 1340 ready_event = OpenEventA(EVENT_ALL_ACCESS, FALSE, "wine_cstub_test_server_ready"); 1341 1342 CoInitialize(NULL); 1343 1344 hr = CoRegisterClassObject(&CLSID_test1, (IUnknown *)&test_cf, 1345 CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &obj_cookie); 1346 ok(hr == S_OK, "got %#x\n", hr); 1347 1348 hr = NdrDllGetClassObject(&CLSID_test_ps, &IID_IPSFactoryBuffer, (void **)&ps, 1349 &aProxyFileList, &CLSID_test_ps, &gPFactory); 1350 ok(hr == S_OK, "got %#x\n", hr); 1351 1352 hr = CoRegisterClassObject(&CLSID_test_ps, (IUnknown *)ps, 1353 CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &ps_cookie); 1354 ok(hr == S_OK, "got %#x\n", hr); 1355 1356 hr = CoRegisterPSClsid(&IID_ITest1, &CLSID_test_ps); 1357 ok(hr == S_OK, "got %#x\n", hr); 1358 1359 SetEvent(ready_event); 1360 1361 hr = CoWaitForMultipleHandles(0, 1000, 1, &stop_event, &index); 1362 ok(hr == S_OK, "got %#x\n", hr); 1363 ok(!index, "got %u\n", index); 1364 1365 hr = CoRevokeClassObject(ps_cookie); 1366 ok(hr == S_OK, "got %#x\n", hr); 1367 1368 hr = CoRevokeClassObject(obj_cookie); 1369 ok(hr == S_OK, "got %#x\n", hr); 1370 1371 CoUninitialize(); 1372 ExitProcess(0); 1373 } 1374 1375 static void test_delegated_methods(void) 1376 { 1377 HANDLE process, stop_event, ready_event; 1378 IPSFactoryBuffer *ps; 1379 ITest1 *test_obj; 1380 DWORD ps_cookie; 1381 CLSID clsid; 1382 HRESULT hr; 1383 int ret; 1384 1385 stop_event = CreateEventA(NULL, TRUE, FALSE, "wine_cstub_test_server_stop"); 1386 ready_event = CreateEventA(NULL, TRUE, FALSE, "wine_cstub_test_server_ready"); 1387 1388 process = create_process("server"); 1389 ok(!WaitForSingleObject(ready_event, 1000), "wait failed\n"); 1390 1391 hr = NdrDllGetClassObject(&CLSID_test_ps, &IID_IPSFactoryBuffer, (void **)&ps, 1392 &aProxyFileList, &CLSID_test_ps, &gPFactory); 1393 ok(hr == S_OK, "got %#x\n", hr); 1394 1395 hr = CoRegisterClassObject(&CLSID_test_ps, (IUnknown *)ps, 1396 CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &ps_cookie); 1397 ok(hr == S_OK, "got %#x\n", hr); 1398 1399 hr = CoRegisterPSClsid(&IID_ITest1, &CLSID_test_ps); 1400 ok(hr == S_OK, "got %#x\n", hr); 1401 1402 hr = CoCreateInstance(&CLSID_test1, NULL, CLSCTX_LOCAL_SERVER, &IID_ITest1, (void **)&test_obj); 1403 ok(hr == S_OK, "got %#x\n", hr); 1404 1405 ret = ITest1_square(test_obj, 3); 1406 ok(ret == 9, "got %d\n", ret); 1407 1408 hr = ITest1_GetClassID(test_obj, &clsid); 1409 ok(hr == S_OK, "got %#x\n", hr); 1410 ok(IsEqualGUID(&clsid, &CLSID_test1), "got %s\n", wine_dbgstr_guid(&clsid)); 1411 1412 ITest1_Release(test_obj); 1413 1414 SetEvent(stop_event); 1415 ok(!WaitForSingleObject(process, 1000), "wait failed\n"); 1416 1417 hr = CoRevokeClassObject(ps_cookie); 1418 ok(hr == S_OK, "got %#x\n", hr); 1419 } 1420 1421 START_TEST( cstub ) 1422 { 1423 IPSFactoryBuffer *ppsf; 1424 int argc; 1425 char **argv; 1426 1427 argc = winetest_get_mainargs( &argv ); 1428 if (argc > 2 && !strcmp(argv[2], "server")) 1429 { 1430 local_server_proc(); 1431 return; 1432 } 1433 1434 OleInitialize(NULL); 1435 1436 ppsf = test_NdrDllGetClassObject(); 1437 test_NdrStubForwardingFunction(); 1438 test_CreateProxy(ppsf); 1439 test_CreateStub(ppsf); 1440 test_Connect(ppsf); 1441 test_Disconnect(ppsf); 1442 test_Release(ppsf); 1443 test_delegating_Invoke(ppsf); 1444 test_NdrDllRegisterProxy(); 1445 test_delegated_methods(); 1446 1447 OleUninitialize(); 1448 } 1449