2 * Unit test suite for cstubs
4 * Copyright 2006 Huw Davies
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.
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.
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
23 #define PROXY_DELEGATION
26 #include "wine/test.h"
38 static CStdPSFactoryBuffer PSFactoryBuffer;
40 CSTDSTUBBUFFERRELEASE(&PSFactoryBuffer)
41 CSTDSTUBBUFFER2RELEASE(&PSFactoryBuffer)
43 static GUID IID_if1 = {0x12345678, 1234, 5678, {12,34,56,78,90,0xab,0xcd,0xef}};
44 static GUID IID_if2 = {0x12345679, 1234, 5678, {12,34,56,78,90,0xab,0xcd,0xef}};
45 static GUID IID_if3 = {0x1234567a, 1234, 5678, {12,34,56,78,90,0xab,0xcd,0xef}};
46 static GUID IID_if4 = {0x1234567b, 1234, 5678, {12,34,56,78,90,0xab,0xcd,0xef}};
48 static int my_alloc_called;
49 static int my_free_called;
51 static void * CALLBACK my_alloc(SIZE_T size)
54 return NdrOleAllocate(size);
57 static void CALLBACK my_free(void *ptr)
63 typedef struct _MIDL_PROC_FORMAT_STRING
66 unsigned char Format[ 2 ];
67 } MIDL_PROC_FORMAT_STRING;
69 typedef struct _MIDL_TYPE_FORMAT_STRING
72 unsigned char Format[ 2 ];
73 } MIDL_TYPE_FORMAT_STRING;
76 static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =
84 static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =
92 static const MIDL_STUB_DESC Object_StubDesc =
102 __MIDL_TypeFormatString.Format,
103 1, /* -error bounds_check flag */
104 0x20000, /* Ndr library version */
106 0x50100a4, /* MIDL Version 5.1.164 */
109 0, /* notify & notify_flag routine table */
116 static HRESULT WINAPI if1_fn1_Proxy(void *This)
121 static void __RPC_STUB if1_fn1_Stub(
122 IRpcStubBuffer *This,
123 IRpcChannelBuffer *_pRpcChannelBuffer,
124 PRPC_MESSAGE _pRpcMessage,
125 DWORD *_pdwStubPhase)
130 static HRESULT WINAPI if1_fn2_Proxy(void *This)
135 static void __RPC_STUB if1_fn2_Stub(
136 IRpcStubBuffer *This,
137 IRpcChannelBuffer *_pRpcChannelBuffer,
138 PRPC_MESSAGE _pRpcMessage,
139 DWORD *_pdwStubPhase)
144 static CINTERFACE_PROXY_VTABLE(5) if1_proxy_vtbl =
147 { IUnknown_QueryInterface_Proxy,
148 IUnknown_AddRef_Proxy,
149 IUnknown_Release_Proxy ,
156 static const unsigned short if1_FormatStringOffsetTable[] =
162 static const MIDL_SERVER_INFO if1_server_info =
166 __MIDL_ProcFormatString.Format,
167 &if1_FormatStringOffsetTable[-3],
174 static const PRPC_STUB_FUNCTION if1_table[] =
180 static CInterfaceStubVtbl if1_stub_vtbl =
188 { CStdStubBuffer_METHODS }
191 static CINTERFACE_PROXY_VTABLE(13) if2_proxy_vtbl =
194 { IUnknown_QueryInterface_Proxy,
195 IUnknown_AddRef_Proxy,
196 IUnknown_Release_Proxy ,
210 static const unsigned short if2_FormatStringOffsetTable[] =
225 static const MIDL_SERVER_INFO if2_server_info =
229 __MIDL_ProcFormatString.Format,
230 &if2_FormatStringOffsetTable[-3],
237 static const PRPC_STUB_FUNCTION if2_table[] =
239 STUB_FORWARDING_FUNCTION,
240 STUB_FORWARDING_FUNCTION,
241 STUB_FORWARDING_FUNCTION,
242 STUB_FORWARDING_FUNCTION,
243 STUB_FORWARDING_FUNCTION,
244 STUB_FORWARDING_FUNCTION,
245 STUB_FORWARDING_FUNCTION,
246 STUB_FORWARDING_FUNCTION,
247 STUB_FORWARDING_FUNCTION,
248 STUB_FORWARDING_FUNCTION
251 static CInterfaceStubVtbl if2_stub_vtbl =
259 { CStdStubBuffer_DELEGATING_METHODS }
262 static CINTERFACE_PROXY_VTABLE(5) if3_proxy_vtbl =
265 { IUnknown_QueryInterface_Proxy,
266 IUnknown_AddRef_Proxy,
267 IUnknown_Release_Proxy ,
274 static const unsigned short if3_FormatStringOffsetTable[] =
280 static const MIDL_SERVER_INFO if3_server_info =
284 __MIDL_ProcFormatString.Format,
285 &if3_FormatStringOffsetTable[-3],
292 static const PRPC_STUB_FUNCTION if3_table[] =
297 static CInterfaceStubVtbl if3_stub_vtbl =
305 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
308 static CINTERFACE_PROXY_VTABLE(7) if4_proxy_vtbl =
311 { IUnknown_QueryInterface_Proxy,
312 IUnknown_AddRef_Proxy,
313 IUnknown_Release_Proxy ,
321 static const unsigned short if4_FormatStringOffsetTable[] =
330 static const MIDL_SERVER_INFO if4_server_info =
334 __MIDL_ProcFormatString.Format,
335 &if4_FormatStringOffsetTable[-3],
342 static const PRPC_STUB_FUNCTION if4_table[] =
344 STUB_FORWARDING_FUNCTION,
345 STUB_FORWARDING_FUNCTION,
346 STUB_FORWARDING_FUNCTION,
347 STUB_FORWARDING_FUNCTION,
350 static CInterfaceStubVtbl if4_stub_vtbl =
358 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
361 static const CInterfaceProxyVtbl *cstub_ProxyVtblList[] =
363 (const CInterfaceProxyVtbl *) &if1_proxy_vtbl,
364 (const CInterfaceProxyVtbl *) &if2_proxy_vtbl,
365 (const CInterfaceProxyVtbl *) &if3_proxy_vtbl,
366 (const CInterfaceProxyVtbl *) &if4_proxy_vtbl,
370 static const CInterfaceStubVtbl *cstub_StubVtblList[] =
379 static PCInterfaceName const if_name_list[] =
388 static const IID *base_iid_list[] =
397 #define cstub_CHECK_IID(n) IID_GENERIC_CHECK_IID( cstub, pIID, n)
399 static int __stdcall iid_lookup( const IID * pIID, int * pIndex )
403 IID_BS_LOOKUP_INITIAL_TEST( cstub, 4, 4 )
404 IID_BS_LOOKUP_NEXT_TEST( cstub, 2 )
405 IID_BS_LOOKUP_NEXT_TEST( cstub, 1 )
406 IID_BS_LOOKUP_RETURN_RESULT( cstub, 4, *pIndex )
411 static BOOL check_address(void *actual, void *expected)
413 static void *ole32_start = NULL;
414 static void *ole32_end = NULL;
416 if (actual == expected)
419 /* On Win7, actual can be located inside ole32.dll */
420 if (ole32_start == NULL || ole32_end == NULL)
422 PIMAGE_NT_HEADERS nt_headers;
423 ole32_start = (void *) GetModuleHandleA("ole32.dll");
424 if (ole32_start == NULL)
426 nt_headers = (PIMAGE_NT_HEADERS)((char *) ole32_start + ((PIMAGE_DOS_HEADER) ole32_start)->e_lfanew);
427 ole32_end = (void *)((char *) ole32_start + nt_headers->OptionalHeader.SizeOfImage);
430 return ole32_start <= actual && actual < ole32_end;
433 static const ExtendedProxyFileInfo my_proxy_file_info =
435 (const PCInterfaceProxyVtblList *) &cstub_ProxyVtblList,
436 (const PCInterfaceStubVtblList *) &cstub_StubVtblList,
437 (const PCInterfaceName *) &if_name_list,
438 (const IID **) &base_iid_list,
448 static const ProxyFileInfo *proxy_file_list[] = {
454 static IPSFactoryBuffer *test_NdrDllGetClassObject(void)
456 HMODULE rpcrt4 = GetModuleHandleA("rpcrt4.dll");
457 IPSFactoryBuffer *ppsf = NULL;
458 const PCInterfaceProxyVtblList* proxy_vtbl;
459 const PCInterfaceStubVtblList* stub_vtbl;
460 const CLSID PSDispatch = {0x20420, 0, 0, {0xc0, 0, 0, 0, 0, 0, 0, 0x46}};
461 const CLSID CLSID_Unknown = {0x45678, 0x1234, 0x6666, {0xff, 0x67, 0x45, 0x98, 0x76, 0x12, 0x34, 0x56}};
462 static const GUID * const interfaces[] = { &IID_if1, &IID_if2, &IID_if3, &IID_if4 };
465 HMODULE hmod = GetModuleHandleA("rpcrt4.dll");
466 void *CStd_QueryInterface = GetProcAddress(hmod, "CStdStubBuffer_QueryInterface");
467 void *CStd_AddRef = GetProcAddress(hmod, "CStdStubBuffer_AddRef");
468 void *CStd_Release = GetProcAddress(hmod, "NdrCStdStubBuffer_Release");
469 void *CStd_Connect = GetProcAddress(hmod, "CStdStubBuffer_Connect");
470 void *CStd_Disconnect = GetProcAddress(hmod, "CStdStubBuffer_Disconnect");
471 void *CStd_Invoke = GetProcAddress(hmod, "CStdStubBuffer_Invoke");
472 void *CStd_IsIIDSupported = GetProcAddress(hmod, "CStdStubBuffer_IsIIDSupported");
473 void *CStd_CountRefs = GetProcAddress(hmod, "CStdStubBuffer_CountRefs");
474 void *CStd_DebugServerQueryInterface = GetProcAddress(hmod, "CStdStubBuffer_DebugServerQueryInterface");
475 void *CStd_DebugServerRelease = GetProcAddress(hmod, "CStdStubBuffer_DebugServerRelease");
477 r = NdrDllGetClassObject(&PSDispatch, &IID_IPSFactoryBuffer, (void**)&ppsf, proxy_file_list,
478 &CLSID_Unknown, &PSFactoryBuffer);
479 ok(r == CLASS_E_CLASSNOTAVAILABLE, "NdrDllGetClassObject with unknown clsid should have returned CLASS_E_CLASSNOTAVAILABLE instead of 0x%x\n", r);
480 ok(ppsf == NULL, "NdrDllGetClassObject should have set ppsf to NULL on failure\n");
482 r = NdrDllGetClassObject(&PSDispatch, &IID_IPSFactoryBuffer, (void**)&ppsf, proxy_file_list,
483 &PSDispatch, &PSFactoryBuffer);
485 ok(r == S_OK, "ret %08x\n", r);
486 ok(ppsf != NULL, "ppsf == NULL\n");
488 proxy_vtbl = PSFactoryBuffer.pProxyFileList[0]->pProxyVtblList;
489 stub_vtbl = PSFactoryBuffer.pProxyFileList[0]->pStubVtblList;
490 ok(PSFactoryBuffer.pProxyFileList == proxy_file_list, "pfl not the same\n");
491 ok(proxy_vtbl == (PCInterfaceProxyVtblList *) &cstub_ProxyVtblList, "proxy vtbllist not the same\n");
492 ok(stub_vtbl == (PCInterfaceStubVtblList *) &cstub_StubVtblList, "stub vtbllist not the same\n");
494 /* if1 is non-delegating, if2 is delegating, if3 is non-delegating
495 but I've zero'ed the vtbl entries, similarly if4 is delegating
496 with zero'ed vtbl entries */
498 #define VTBL_TEST_NOT_CHANGE_TO(name, i) \
499 ok(stub_vtbl[i]->Vtbl.name != CStd_##name, #name "vtbl %d updated %p %p\n", \
500 i, stub_vtbl[i]->Vtbl.name, CStd_##name )
501 #define VTBL_TEST_CHANGE_TO(name, i) \
502 ok(check_address(stub_vtbl[i]->Vtbl.name, CStd_##name), #name "vtbl %d not updated %p %p\n", \
503 i, stub_vtbl[i]->Vtbl.name, CStd_##name )
504 #define VTBL_TEST_ZERO(name, i) \
505 ok(stub_vtbl[i]->Vtbl.name == NULL, #name "vtbl %d not null %p\n", \
506 i, stub_vtbl[i]->Vtbl.name )
508 VTBL_TEST_NOT_CHANGE_TO(QueryInterface, 0);
509 VTBL_TEST_NOT_CHANGE_TO(AddRef, 0);
510 VTBL_TEST_NOT_CHANGE_TO(Release, 0);
511 VTBL_TEST_NOT_CHANGE_TO(Connect, 0);
512 VTBL_TEST_NOT_CHANGE_TO(Disconnect, 0);
513 VTBL_TEST_NOT_CHANGE_TO(Invoke, 0);
514 VTBL_TEST_NOT_CHANGE_TO(IsIIDSupported, 0);
515 VTBL_TEST_NOT_CHANGE_TO(CountRefs, 0);
516 VTBL_TEST_NOT_CHANGE_TO(DebugServerQueryInterface, 0);
517 VTBL_TEST_NOT_CHANGE_TO(DebugServerRelease, 0);
519 VTBL_TEST_CHANGE_TO(QueryInterface, 1);
520 VTBL_TEST_CHANGE_TO(AddRef, 1);
521 VTBL_TEST_NOT_CHANGE_TO(Release, 1);
522 VTBL_TEST_NOT_CHANGE_TO(Connect, 1);
523 VTBL_TEST_NOT_CHANGE_TO(Disconnect, 1);
524 VTBL_TEST_CHANGE_TO(Invoke, 1);
525 VTBL_TEST_CHANGE_TO(IsIIDSupported, 1);
526 VTBL_TEST_NOT_CHANGE_TO(CountRefs, 1);
527 VTBL_TEST_CHANGE_TO(DebugServerQueryInterface, 1);
528 VTBL_TEST_CHANGE_TO(DebugServerRelease, 1);
530 VTBL_TEST_CHANGE_TO(QueryInterface, 2);
531 VTBL_TEST_CHANGE_TO(AddRef, 2);
532 VTBL_TEST_ZERO(Release, 2);
533 VTBL_TEST_CHANGE_TO(Connect, 2);
534 VTBL_TEST_CHANGE_TO(Disconnect, 2);
535 VTBL_TEST_CHANGE_TO(Invoke, 2);
536 VTBL_TEST_CHANGE_TO(IsIIDSupported, 2);
537 VTBL_TEST_CHANGE_TO(CountRefs, 2);
538 VTBL_TEST_CHANGE_TO(DebugServerQueryInterface, 2);
539 VTBL_TEST_CHANGE_TO(DebugServerRelease, 2);
541 VTBL_TEST_CHANGE_TO(QueryInterface, 3);
542 VTBL_TEST_CHANGE_TO(AddRef, 3);
543 VTBL_TEST_ZERO(Release, 3);
544 VTBL_TEST_NOT_CHANGE_TO(Connect, 3);
545 VTBL_TEST_NOT_CHANGE_TO(Disconnect, 3);
546 VTBL_TEST_CHANGE_TO(Invoke, 3);
547 VTBL_TEST_CHANGE_TO(IsIIDSupported, 3);
548 VTBL_TEST_NOT_CHANGE_TO(CountRefs, 3);
549 VTBL_TEST_CHANGE_TO(DebugServerQueryInterface, 3);
550 VTBL_TEST_CHANGE_TO(DebugServerRelease, 3);
552 #define VTBL_PROXY_TEST(i,num,ptr) \
553 ok( check_address(proxy_vtbl[i]->Vtbl[num], (ptr)), "wrong proxy %u func %u %p/%p\n", \
554 (i), (num), proxy_vtbl[i]->Vtbl[num], (ptr) )
555 #define VTBL_PROXY_TEST_NOT_ZERO(i,num) \
556 ok( proxy_vtbl[i]->Vtbl[num] != NULL, "wrong proxy %u func %u is NULL\n", (i), (num))
558 VTBL_PROXY_TEST(0, 0, IUnknown_QueryInterface_Proxy);
559 VTBL_PROXY_TEST(0, 1, IUnknown_AddRef_Proxy);
560 VTBL_PROXY_TEST(0, 2, IUnknown_Release_Proxy);
561 VTBL_PROXY_TEST(0, 3, if1_fn1_Proxy);
562 VTBL_PROXY_TEST(0, 4, if1_fn2_Proxy);
564 VTBL_PROXY_TEST(1, 0, GetProcAddress(rpcrt4,"IUnknown_QueryInterface_Proxy"));
565 VTBL_PROXY_TEST(1, 1, GetProcAddress(rpcrt4,"IUnknown_AddRef_Proxy"));
566 VTBL_PROXY_TEST(1, 2, GetProcAddress(rpcrt4,"IUnknown_Release_Proxy"));
567 VTBL_PROXY_TEST_NOT_ZERO(1, 3);
568 VTBL_PROXY_TEST_NOT_ZERO(1, 4);
569 VTBL_PROXY_TEST_NOT_ZERO(1, 5);
570 VTBL_PROXY_TEST_NOT_ZERO(1, 6);
571 VTBL_PROXY_TEST_NOT_ZERO(1, 7);
572 VTBL_PROXY_TEST_NOT_ZERO(1, 8);
573 VTBL_PROXY_TEST_NOT_ZERO(1, 9);
574 VTBL_PROXY_TEST_NOT_ZERO(1, 10);
575 VTBL_PROXY_TEST_NOT_ZERO(1, 11);
576 VTBL_PROXY_TEST_NOT_ZERO(1, 12);
578 VTBL_PROXY_TEST(2, 0, IUnknown_QueryInterface_Proxy);
579 VTBL_PROXY_TEST(2, 1, IUnknown_AddRef_Proxy);
580 VTBL_PROXY_TEST(2, 2, IUnknown_Release_Proxy);
581 VTBL_PROXY_TEST(2, 3, if1_fn1_Proxy);
582 todo_wine VTBL_PROXY_TEST_NOT_ZERO(2, 4);
584 VTBL_PROXY_TEST(3, 0, GetProcAddress(rpcrt4,"IUnknown_QueryInterface_Proxy"));
585 VTBL_PROXY_TEST(3, 1, GetProcAddress(rpcrt4,"IUnknown_AddRef_Proxy"));
586 VTBL_PROXY_TEST(3, 2, GetProcAddress(rpcrt4,"IUnknown_Release_Proxy"));
587 VTBL_PROXY_TEST_NOT_ZERO(3, 3);
588 VTBL_PROXY_TEST_NOT_ZERO(3, 4);
589 VTBL_PROXY_TEST_NOT_ZERO(3, 5);
590 VTBL_PROXY_TEST_NOT_ZERO(3, 6);
592 #undef VTBL_TEST_NOT_CHANGE_TO
593 #undef VTBL_TEST_CHANGE_TO
594 #undef VTBL_TEST_ZERO
595 #undef VTBL_PROXY_TEST
596 #undef VTBL_PROXY_TEST_NOT_ZERO
598 for (i = 0; i < sizeof(interfaces)/sizeof(interfaces[0]); i++)
599 ok( proxy_vtbl[i]->header.piid == interfaces[i],
600 "wrong proxy %u iid %p/%p\n", i, proxy_vtbl[i]->header.piid, interfaces[i] );
602 ok(PSFactoryBuffer.RefCount == 1, "ref count %d\n", PSFactoryBuffer.RefCount);
603 IPSFactoryBuffer_Release(ppsf);
605 r = NdrDllGetClassObject(&IID_if3, &IID_IPSFactoryBuffer, (void**)&ppsf, proxy_file_list,
606 NULL, &PSFactoryBuffer);
607 ok(r == S_OK, "ret %08x\n", r);
608 ok(ppsf != NULL, "ppsf == NULL\n");
613 static int base_buffer_invoke_called;
614 static HRESULT WINAPI base_buffer_Invoke(IRpcStubBuffer *This, RPCOLEMESSAGE *msg, IRpcChannelBuffer *channel)
616 base_buffer_invoke_called++;
617 ok(msg == (RPCOLEMESSAGE*)0xcafebabe, "msg ptr changed\n");
618 ok(channel == (IRpcChannelBuffer*)0xdeadbeef, "channel ptr changed\n");
619 return S_OK; /* returning any failure here results in an exception */
622 static IRpcStubBufferVtbl base_buffer_vtbl = {
635 static void test_NdrStubForwardingFunction(void)
639 IRpcChannelBuffer *channel = (IRpcChannelBuffer*)0xdeadbeef;
640 RPC_MESSAGE *msg = (RPC_MESSAGE*)0xcafebabe;
641 DWORD *phase = (DWORD*)0x12345678;
642 IRpcStubBufferVtbl *base_buffer_vtbl_ptr = &base_buffer_vtbl;
643 IRpcStubBuffer *base_stub_buffer = (IRpcStubBuffer*)&base_buffer_vtbl_ptr;
645 memset(This, 0xcc, sizeof(This));
646 This[0] = base_stub_buffer;
647 real_this = &This[1];
649 NdrStubForwardingFunction( real_this, channel, msg, phase );
650 ok(base_buffer_invoke_called == 1, "base_buffer_invoke called %d times\n", base_buffer_invoke_called);
654 static IRpcStubBuffer *create_stub(IPSFactoryBuffer *ppsf, REFIID iid, IUnknown *obj, HRESULT expected_result)
656 IRpcStubBuffer *pstub = NULL;
659 r = IPSFactoryBuffer_CreateStub(ppsf, iid, obj, &pstub);
660 ok(r == expected_result, "CreateStub returned %08x expected %08x\n", r, expected_result);
664 static HRESULT WINAPI create_stub_test_QI(IUnknown *This, REFIID iid, void **ppv)
666 ok(IsEqualIID(iid, &IID_if1), "incorrect iid\n");
667 *ppv = (void*)0xdeadbeef;
671 static IUnknownVtbl create_stub_test_vtbl =
678 static HRESULT WINAPI create_stub_test_fail_QI(IUnknown *This, REFIID iid, void **ppv)
680 ok(IsEqualIID(iid, &IID_if1), "incorrect iid\n");
682 return E_NOINTERFACE;
685 static IUnknownVtbl create_stub_test_fail_vtbl =
687 create_stub_test_fail_QI,
694 const IUnknownVtbl *vtbl;
698 static HRESULT WINAPI dummy_QueryInterface(IUnknown *This, REFIID iid, void **ppv)
701 return E_NOINTERFACE;
704 static ULONG WINAPI dummy_AddRef(LPUNKNOWN iface)
706 struct dummy_unknown *this = (struct dummy_unknown *)iface;
707 return InterlockedIncrement( &this->ref );
710 static ULONG WINAPI dummy_Release(LPUNKNOWN iface)
712 struct dummy_unknown *this = (struct dummy_unknown *)iface;
713 return InterlockedDecrement( &this->ref );
716 static IUnknownVtbl dummy_unknown_vtbl =
718 dummy_QueryInterface,
722 static struct dummy_unknown dummy_unknown = { &dummy_unknown_vtbl, 0 };
724 static void create_proxy_test( IPSFactoryBuffer *ppsf, REFIID iid, const void *expected_vtbl )
726 IRpcProxyBuffer *proxy = NULL;
727 IUnknown *iface = NULL;
731 r = IPSFactoryBuffer_CreateProxy(ppsf, NULL, iid, &proxy, (void **)&iface);
732 ok( r == S_OK, "IPSFactoryBuffer_CreateProxy failed %x\n", r );
733 ok( *(void **)iface == expected_vtbl, "wrong iface pointer %p/%p\n", *(void **)iface, expected_vtbl );
734 count = IUnknown_Release( iface );
735 ok( count == 1, "wrong refcount %u\n", count );
736 count = IRpcProxyBuffer_Release( proxy );
737 ok( count == 0, "wrong refcount %u\n", count );
739 dummy_unknown.ref = 4;
740 r = IPSFactoryBuffer_CreateProxy(ppsf, (IUnknown *)&dummy_unknown, iid, &proxy, (void **)&iface);
741 ok( r == S_OK, "IPSFactoryBuffer_CreateProxy failed %x\n", r );
742 ok( dummy_unknown.ref == 5, "wrong refcount %u\n", dummy_unknown.ref );
743 ok( *(void **)iface == expected_vtbl, "wrong iface pointer %p/%p\n", *(void **)iface, expected_vtbl );
744 count = IUnknown_Release( iface );
745 ok( count == 4, "wrong refcount %u\n", count );
746 ok( dummy_unknown.ref == 4, "wrong refcount %u\n", dummy_unknown.ref );
747 count = IRpcProxyBuffer_Release( proxy );
748 ok( count == 0, "wrong refcount %u\n", count );
749 ok( dummy_unknown.ref == 4, "wrong refcount %u\n", dummy_unknown.ref );
752 static void test_CreateProxy( IPSFactoryBuffer *ppsf )
754 create_proxy_test( ppsf, &IID_if1, if1_proxy_vtbl.Vtbl );
755 create_proxy_test( ppsf, &IID_if2, if2_proxy_vtbl.Vtbl );
756 create_proxy_test( ppsf, &IID_if3, if3_proxy_vtbl.Vtbl );
757 create_proxy_test( ppsf, &IID_if4, if4_proxy_vtbl.Vtbl );
760 static void test_CreateStub(IPSFactoryBuffer *ppsf)
762 IUnknownVtbl *vtbl = &create_stub_test_vtbl;
763 IUnknown *obj = (IUnknown*)&vtbl;
764 IRpcStubBuffer *pstub = create_stub(ppsf, &IID_if1, obj, S_OK);
765 CStdStubBuffer *cstd_stub = (CStdStubBuffer*)pstub;
766 const CInterfaceStubHeader *header = &CONTAINING_RECORD(cstd_stub->lpVtbl, const CInterfaceStubVtbl, Vtbl)->header;
768 ok(IsEqualIID(header->piid, &IID_if1), "header iid differs\n");
769 ok(cstd_stub->RefCount == 1, "ref count %d\n", cstd_stub->RefCount);
770 /* 0xdeadbeef returned from create_stub_test_QI */
771 ok(cstd_stub->pvServerObject == (void*)0xdeadbeef, "pvServerObject %p\n", cstd_stub->pvServerObject);
772 ok(cstd_stub->pPSFactory != NULL, "pPSFactory was NULL\n");
773 cstd_stub->pvServerObject = NULL;
774 IRpcStubBuffer_Release(pstub);
776 vtbl = &create_stub_test_fail_vtbl;
777 pstub = create_stub(ppsf, &IID_if1, obj, E_NOINTERFACE);
778 ok(pstub == S_OK, "create_stub failed: %u\n", GetLastError());
782 static HRESULT WINAPI connect_test_orig_QI(IUnknown *This, REFIID iid, void **ppv)
784 ok(IsEqualIID(iid, &IID_if1) ||
785 IsEqualIID(iid, &IID_if2), "incorrect iid\n");
790 static int connect_test_orig_release_called;
791 static ULONG WINAPI connect_test_orig_release(IUnknown *This)
793 connect_test_orig_release_called++;
797 static IUnknownVtbl connect_test_orig_vtbl =
799 connect_test_orig_QI,
801 connect_test_orig_release
804 static HRESULT WINAPI connect_test_new_QI(IUnknown *This, REFIID iid, void **ppv)
806 ok(IsEqualIID(iid, &IID_if1) ||
807 IsEqualIID(iid, &IID_if2), "incorrect iid\n");
808 *ppv = (void*)0xcafebabe;
812 static IUnknownVtbl connect_test_new_vtbl =
819 static HRESULT WINAPI connect_test_new_fail_QI(IUnknown *This, REFIID iid, void **ppv)
821 ok(IsEqualIID(iid, &IID_if1), "incorrect iid\n");
822 *ppv = (void*)0xdeadbeef;
823 return E_NOINTERFACE;
826 static IUnknownVtbl connect_test_new_fail_vtbl =
828 connect_test_new_fail_QI,
833 static int connect_test_base_Connect_called;
834 static HRESULT WINAPI connect_test_base_Connect(IRpcStubBuffer *pstub, IUnknown *obj)
836 connect_test_base_Connect_called++;
837 ok(*(void**)obj == (void*)0xbeefcafe, "unexpected obj %p\n", obj);
841 static IRpcStubBufferVtbl connect_test_base_stub_buffer_vtbl =
846 connect_test_base_Connect,
855 static void test_Connect(IPSFactoryBuffer *ppsf)
857 IUnknownVtbl *orig_vtbl = &connect_test_orig_vtbl;
858 IUnknownVtbl *new_vtbl = &connect_test_new_vtbl;
859 IUnknownVtbl *new_fail_vtbl = &connect_test_new_fail_vtbl;
860 IUnknown *obj = (IUnknown*)&orig_vtbl;
861 IRpcStubBuffer *pstub = create_stub(ppsf, &IID_if1, obj, S_OK);
862 CStdStubBuffer *cstd_stub = (CStdStubBuffer*)pstub;
863 IRpcStubBufferVtbl *base_stub_buf_vtbl = &connect_test_base_stub_buffer_vtbl;
866 obj = (IUnknown*)&new_vtbl;
867 r = IRpcStubBuffer_Connect(pstub, obj);
868 ok(r == S_OK, "r %08x\n", r);
869 ok(connect_test_orig_release_called == 1, "release called %d\n", connect_test_orig_release_called);
870 ok(cstd_stub->pvServerObject == (void*)0xcafebabe, "pvServerObject %p\n", cstd_stub->pvServerObject);
872 cstd_stub->pvServerObject = (IUnknown*)&orig_vtbl;
873 obj = (IUnknown*)&new_fail_vtbl;
874 r = IRpcStubBuffer_Connect(pstub, obj);
875 ok(r == E_NOINTERFACE, "r %08x\n", r);
876 ok(cstd_stub->pvServerObject == (void*)0xdeadbeef, "pvServerObject %p\n", cstd_stub->pvServerObject);
877 ok(connect_test_orig_release_called == 2, "release called %d\n", connect_test_orig_release_called);
879 /* Now use a delegated stub.
881 We know from the NdrStubForwardFunction test that
882 (void**)pstub-1 is the base interface stub buffer. This shows
883 that (void**)pstub-2 contains the address of a vtable that gets
884 passed to the base interface's Connect method. Note that
885 (void**)pstub-2 itself gets passed to Connect and not
886 *((void**)pstub-2), so it should contain the vtable ptr and not
889 obj = (IUnknown*)&orig_vtbl;
890 pstub = create_stub(ppsf, &IID_if2, obj, S_OK);
891 *((void**)pstub-1) = &base_stub_buf_vtbl;
892 *((void**)pstub-2) = (void*)0xbeefcafe;
894 obj = (IUnknown*)&new_vtbl;
895 r = IRpcStubBuffer_Connect(pstub, obj);
896 ok(r == S_OK, "r %08x\n", r);
897 ok(connect_test_base_Connect_called == 1, "connect_test_bsae_Connect called %d times\n",
898 connect_test_base_Connect_called);
899 ok(connect_test_orig_release_called == 3, "release called %d\n", connect_test_orig_release_called);
900 cstd_stub = (CStdStubBuffer*)pstub;
901 ok(cstd_stub->pvServerObject == (void*)0xcafebabe, "pvServerObject %p\n", cstd_stub->pvServerObject);
904 static void test_Disconnect(IPSFactoryBuffer *ppsf)
906 IUnknownVtbl *orig_vtbl = &connect_test_orig_vtbl;
907 IUnknown *obj = (IUnknown*)&orig_vtbl;
908 IRpcStubBuffer *pstub = create_stub(ppsf, &IID_if1, obj, S_OK);
909 CStdStubBuffer *cstd_stub = (CStdStubBuffer*)pstub;
911 connect_test_orig_release_called = 0;
912 IRpcStubBuffer_Disconnect(pstub);
913 ok(connect_test_orig_release_called == 1, "release called %d\n", connect_test_orig_release_called);
914 ok(cstd_stub->pvServerObject == NULL, "pvServerObject %p\n", cstd_stub->pvServerObject);
915 IRpcStubBuffer_Release(pstub);
919 static int release_test_psfacbuf_release_called;
920 static ULONG WINAPI release_test_pretend_psfacbuf_release(IUnknown *pUnk)
922 release_test_psfacbuf_release_called++;
926 static IUnknownVtbl release_test_pretend_psfacbuf_vtbl =
930 release_test_pretend_psfacbuf_release
933 static void test_Release(IPSFactoryBuffer *ppsf)
936 IUnknownVtbl *orig_vtbl = &connect_test_orig_vtbl;
937 IUnknown *obj = (IUnknown*)&orig_vtbl;
938 IUnknownVtbl *pretend_psfacbuf_vtbl = &release_test_pretend_psfacbuf_vtbl;
939 IUnknown *pretend_psfacbuf = (IUnknown *)&pretend_psfacbuf_vtbl;
940 IRpcStubBuffer *pstub = create_stub(ppsf, &IID_if1, obj, S_OK);
941 CStdStubBuffer *cstd_stub = (CStdStubBuffer*)pstub;
943 facbuf_refs = PSFactoryBuffer.RefCount;
945 /* This shows that NdrCStdStubBuffer_Release doesn't call Disconnect */
946 ok(cstd_stub->RefCount == 1, "ref count %d\n", cstd_stub->RefCount);
947 connect_test_orig_release_called = 0;
948 IRpcStubBuffer_Release(pstub);
950 ok(connect_test_orig_release_called == 0, "release called %d\n", connect_test_orig_release_called);
952 ok(PSFactoryBuffer.RefCount == facbuf_refs - 1, "factory buffer refs %d orig %d\n", PSFactoryBuffer.RefCount, facbuf_refs);
954 /* This shows that NdrCStdStubBuffer_Release calls Release on its 2nd arg, rather than on This->pPSFactory
955 (which are usually the same and indeed it's odd that _Release requires this 2nd arg). */
956 pstub = create_stub(ppsf, &IID_if1, obj, S_OK);
957 ok(PSFactoryBuffer.RefCount == facbuf_refs, "factory buffer refs %d orig %d\n", PSFactoryBuffer.RefCount, facbuf_refs);
958 NdrCStdStubBuffer_Release(pstub, (IPSFactoryBuffer*)pretend_psfacbuf);
959 ok(release_test_psfacbuf_release_called == 1, "pretend_psfacbuf_release called %d\n", release_test_psfacbuf_release_called);
960 ok(PSFactoryBuffer.RefCount == facbuf_refs, "factory buffer refs %d orig %d\n", PSFactoryBuffer.RefCount, facbuf_refs);
963 static HRESULT WINAPI delegating_invoke_test_QI(ITypeLib *pUnk, REFIID iid, void** ppv)
970 static ULONG WINAPI delegating_invoke_test_addref(ITypeLib *pUnk)
975 static ULONG WINAPI delegating_invoke_test_release(ITypeLib *pUnk)
980 static UINT WINAPI delegating_invoke_test_get_type_info_count(ITypeLib *pUnk)
985 static ITypeLibVtbl delegating_invoke_test_obj_vtbl =
987 delegating_invoke_test_QI,
988 delegating_invoke_test_addref,
989 delegating_invoke_test_release,
990 delegating_invoke_test_get_type_info_count,
1002 static HRESULT WINAPI delegating_invoke_chan_query_interface(IRpcChannelBuffer *pchan,
1006 ok(0, "call to QueryInterface not expected\n");
1007 return E_NOINTERFACE;
1010 static ULONG WINAPI delegating_invoke_chan_add_ref(IRpcChannelBuffer *pchan)
1015 static ULONG WINAPI delegating_invoke_chan_release(IRpcChannelBuffer *pchan)
1020 static HRESULT WINAPI delegating_invoke_chan_get_buffer(IRpcChannelBuffer *pchan,
1024 msg->Buffer = HeapAlloc(GetProcessHeap(), 0, msg->cbBuffer);
1028 static HRESULT WINAPI delegating_invoke_chan_send_receive(IRpcChannelBuffer *pchan,
1029 RPCOLEMESSAGE *pMessage,
1032 ok(0, "call to SendReceive not expected\n");
1036 static HRESULT WINAPI delegating_invoke_chan_free_buffer(IRpcChannelBuffer *pchan,
1037 RPCOLEMESSAGE *pMessage)
1039 ok(0, "call to FreeBuffer not expected\n");
1043 static HRESULT WINAPI delegating_invoke_chan_get_dest_ctx(IRpcChannelBuffer *pchan,
1044 DWORD *pdwDestContext,
1045 void **ppvDestContext)
1047 *pdwDestContext = MSHCTX_LOCAL;
1048 *ppvDestContext = NULL;
1052 static HRESULT WINAPI delegating_invoke_chan_is_connected(IRpcChannelBuffer *pchan)
1054 ok(0, "call to IsConnected not expected\n");
1058 static IRpcChannelBufferVtbl delegating_invoke_test_rpc_chan_vtbl =
1060 delegating_invoke_chan_query_interface,
1061 delegating_invoke_chan_add_ref,
1062 delegating_invoke_chan_release,
1063 delegating_invoke_chan_get_buffer,
1064 delegating_invoke_chan_send_receive,
1065 delegating_invoke_chan_free_buffer,
1066 delegating_invoke_chan_get_dest_ctx,
1067 delegating_invoke_chan_is_connected
1070 static void test_delegating_Invoke(IPSFactoryBuffer *ppsf)
1072 ITypeLibVtbl *obj_vtbl = &delegating_invoke_test_obj_vtbl;
1073 IUnknown *obj = (IUnknown*)&obj_vtbl;
1074 IRpcStubBuffer *pstub = create_stub(ppsf, &IID_if2, obj, S_OK);
1075 IRpcChannelBufferVtbl *pchan_vtbl = &delegating_invoke_test_rpc_chan_vtbl;
1076 IRpcChannelBuffer *pchan = (IRpcChannelBuffer *)&pchan_vtbl;
1080 memset(&msg, 0, sizeof(msg));
1081 msg.dataRepresentation = NDR_LOCAL_DATA_REPRESENTATION;
1083 r = IRpcStubBuffer_Invoke(pstub, &msg, pchan);
1084 ok(r == S_OK, "ret %08x\n", r);
1087 ok(*(DWORD*)msg.Buffer == 0xabcdef, "buf[0] %08x\n", *(DWORD*)msg.Buffer);
1088 ok(*((DWORD*)msg.Buffer + 1) == S_OK, "buf[1] %08x\n", *((DWORD*)msg.Buffer + 1));
1090 /* free the buffer allocated by delegating_invoke_chan_get_buffer */
1091 HeapFree(GetProcessHeap(), 0, msg.Buffer);
1092 IRpcStubBuffer_Release(pstub);
1094 static const CInterfaceProxyVtbl *cstub_ProxyVtblList2[] =
1099 static const CInterfaceStubVtbl *cstub_StubVtblList2[] =
1104 static PCInterfaceName const if_name_list2[] =
1109 static const IID *base_iid_list2[] =
1114 static const ExtendedProxyFileInfo my_proxy_file_info2 =
1116 (const PCInterfaceProxyVtblList *) &cstub_ProxyVtblList2,
1117 (const PCInterfaceStubVtblList *) &cstub_StubVtblList2,
1118 (const PCInterfaceName *) &if_name_list2,
1119 (const IID **) &base_iid_list2,
1129 static const ProxyFileInfo *proxy_file_list2[] = {
1130 &my_proxy_file_info2,
1134 static void test_NdrDllRegisterProxy( void )
1137 const ExtendedProxyFileInfo *pf;
1138 HMODULE hmod = GetModuleHandleA(NULL);
1141 res = NdrDllRegisterProxy(NULL, NULL, NULL);
1142 ok(res == E_HANDLE, "Incorrect return code %x\n",res);
1144 res = NdrDllRegisterProxy(hmod, &pf, NULL);
1145 ok(res == E_NOINTERFACE, "Incorrect return code %x\n",res);
1146 res = NdrDllRegisterProxy(hmod, proxy_file_list2, NULL);
1147 ok(res == E_NOINTERFACE, "Incorrect return code %x\n",res);
1148 /* This fails on Vista and Windows 7 due to permissions */
1149 res = NdrDllRegisterProxy(hmod, proxy_file_list, NULL);
1150 ok(res == S_OK || res == E_ACCESSDENIED, "NdrDllRegisterProxy failed %x\n",res);
1153 res = NdrDllUnregisterProxy(hmod,proxy_file_list, NULL);
1154 ok(res == S_OK, "NdrDllUnregisterProxy failed %x\n",res);
1160 IPSFactoryBuffer *ppsf;
1162 OleInitialize(NULL);
1164 ppsf = test_NdrDllGetClassObject();
1165 test_NdrStubForwardingFunction();
1166 test_CreateProxy(ppsf);
1167 test_CreateStub(ppsf);
1169 test_Disconnect(ppsf);
1171 test_delegating_Invoke(ppsf);
1172 test_NdrDllRegisterProxy();