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}};
47 static CLSID CLSID_psfact
= {0x1234567c, 1234, 5678, {12,34,56,78,90,0xab,0xcd,0xef}};
49 static int my_alloc_called
;
50 static int my_free_called
;
52 static void * CALLBACK
my_alloc(SIZE_T size
)
55 return NdrOleAllocate(size
);
58 static void CALLBACK
my_free(void *ptr
)
64 typedef struct _MIDL_PROC_FORMAT_STRING
67 unsigned char Format
[ 2 ];
68 } MIDL_PROC_FORMAT_STRING
;
70 typedef struct _MIDL_TYPE_FORMAT_STRING
73 unsigned char Format
[ 2 ];
74 } MIDL_TYPE_FORMAT_STRING
;
77 static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString
=
85 static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString
=
93 static const MIDL_STUB_DESC Object_StubDesc
=
103 __MIDL_TypeFormatString
.Format
,
104 1, /* -error bounds_check flag */
105 0x20000, /* Ndr library version */
107 0x50100a4, /* MIDL Version 5.1.164 */
110 0, /* notify & notify_flag routine table */
117 static HRESULT WINAPI
if1_fn1_Proxy(void *This
)
122 static void __RPC_STUB
if1_fn1_Stub(
123 IRpcStubBuffer
*This
,
124 IRpcChannelBuffer
*_pRpcChannelBuffer
,
125 PRPC_MESSAGE _pRpcMessage
,
126 DWORD
*_pdwStubPhase
)
131 static HRESULT WINAPI
if1_fn2_Proxy(void *This
)
136 static void __RPC_STUB
if1_fn2_Stub(
137 IRpcStubBuffer
*This
,
138 IRpcChannelBuffer
*_pRpcChannelBuffer
,
139 PRPC_MESSAGE _pRpcMessage
,
140 DWORD
*_pdwStubPhase
)
145 static CINTERFACE_PROXY_VTABLE(5) if1_proxy_vtbl
=
148 { IUnknown_QueryInterface_Proxy
,
149 IUnknown_AddRef_Proxy
,
150 IUnknown_Release_Proxy
,
157 static const unsigned short if1_FormatStringOffsetTable
[] =
163 static const MIDL_SERVER_INFO if1_server_info
=
167 __MIDL_ProcFormatString
.Format
,
168 &if1_FormatStringOffsetTable
[-3],
175 static const PRPC_STUB_FUNCTION if1_table
[] =
181 static CInterfaceStubVtbl if1_stub_vtbl
=
189 { CStdStubBuffer_METHODS
}
192 static CINTERFACE_PROXY_VTABLE(13) if2_proxy_vtbl
=
195 { IUnknown_QueryInterface_Proxy
,
196 IUnknown_AddRef_Proxy
,
197 IUnknown_Release_Proxy
,
211 static const unsigned short if2_FormatStringOffsetTable
[] =
226 static const MIDL_SERVER_INFO if2_server_info
=
230 __MIDL_ProcFormatString
.Format
,
231 &if2_FormatStringOffsetTable
[-3],
238 static const PRPC_STUB_FUNCTION if2_table
[] =
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
,
249 STUB_FORWARDING_FUNCTION
252 static CInterfaceStubVtbl if2_stub_vtbl
=
260 { CStdStubBuffer_DELEGATING_METHODS
}
263 static CINTERFACE_PROXY_VTABLE(5) if3_proxy_vtbl
=
266 { IUnknown_QueryInterface_Proxy
,
267 IUnknown_AddRef_Proxy
,
268 IUnknown_Release_Proxy
,
275 static const unsigned short if3_FormatStringOffsetTable
[] =
281 static const MIDL_SERVER_INFO if3_server_info
=
285 __MIDL_ProcFormatString
.Format
,
286 &if3_FormatStringOffsetTable
[-3],
292 static CInterfaceStubVtbl if3_stub_vtbl
=
300 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
303 static CINTERFACE_PROXY_VTABLE(7) if4_proxy_vtbl
=
306 { IUnknown_QueryInterface_Proxy
,
307 IUnknown_AddRef_Proxy
,
308 IUnknown_Release_Proxy
,
316 static const unsigned short if4_FormatStringOffsetTable
[] =
325 static const MIDL_SERVER_INFO if4_server_info
=
329 __MIDL_ProcFormatString
.Format
,
330 &if4_FormatStringOffsetTable
[-3],
336 static CInterfaceStubVtbl if4_stub_vtbl
=
344 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
347 static const CInterfaceProxyVtbl
*cstub_ProxyVtblList
[] =
349 (const CInterfaceProxyVtbl
*) &if1_proxy_vtbl
,
350 (const CInterfaceProxyVtbl
*) &if2_proxy_vtbl
,
351 (const CInterfaceProxyVtbl
*) &if3_proxy_vtbl
,
352 (const CInterfaceProxyVtbl
*) &if4_proxy_vtbl
,
356 static const CInterfaceStubVtbl
*cstub_StubVtblList
[] =
365 static PCInterfaceName
const if_name_list
[] =
374 static const IID
*base_iid_list
[] =
383 #define cstub_CHECK_IID(n) IID_GENERIC_CHECK_IID( cstub, pIID, n)
385 static int __stdcall
iid_lookup( const IID
* pIID
, int * pIndex
)
389 IID_BS_LOOKUP_INITIAL_TEST( cstub
, 4, 4 )
390 IID_BS_LOOKUP_NEXT_TEST( cstub
, 2 )
391 IID_BS_LOOKUP_NEXT_TEST( cstub
, 1 )
392 IID_BS_LOOKUP_RETURN_RESULT( cstub
, 4, *pIndex
)
397 static BOOL
check_address(void *actual
, void *expected
)
399 static void *ole32_start
= NULL
;
400 static void *ole32_end
= NULL
;
401 static void *combase_start
= NULL
;
402 static void *combase_end
= NULL
;
404 if (actual
== expected
)
407 /* On Win7, actual can be located inside ole32.dll */
408 if (ole32_start
== NULL
|| ole32_end
== NULL
)
410 PIMAGE_NT_HEADERS nt_headers
;
411 ole32_start
= (void *) GetModuleHandleA("ole32.dll");
412 if (ole32_start
== NULL
)
414 nt_headers
= (PIMAGE_NT_HEADERS
)((char *) ole32_start
+ ((PIMAGE_DOS_HEADER
) ole32_start
)->e_lfanew
);
415 ole32_end
= (void *)((char *) ole32_start
+ nt_headers
->OptionalHeader
.SizeOfImage
);
418 if (ole32_start
<= actual
&& actual
< ole32_end
)
421 /* On Win8, actual can be located inside combase.dll */
422 if (combase_start
== NULL
|| combase_end
== NULL
)
424 PIMAGE_NT_HEADERS nt_headers
;
425 combase_start
= (void *) GetModuleHandleA("combase.dll");
426 if (combase_start
== NULL
)
428 nt_headers
= (PIMAGE_NT_HEADERS
)((char *) combase_start
+ ((PIMAGE_DOS_HEADER
) combase_start
)->e_lfanew
);
429 combase_end
= (void *)((char *) combase_start
+ nt_headers
->OptionalHeader
.SizeOfImage
);
432 return (combase_start
<= actual
&& actual
< combase_end
);
435 static const ExtendedProxyFileInfo my_proxy_file_info
=
437 (const PCInterfaceProxyVtblList
*) &cstub_ProxyVtblList
,
438 (const PCInterfaceStubVtblList
*) &cstub_StubVtblList
,
439 (const PCInterfaceName
*) &if_name_list
,
440 (const IID
**) &base_iid_list
,
450 static const ProxyFileInfo
*proxy_file_list
[] = {
456 static IPSFactoryBuffer
*test_NdrDllGetClassObject(void)
458 HMODULE rpcrt4
= GetModuleHandleA("rpcrt4.dll");
459 IPSFactoryBuffer
*ppsf
= NULL
;
460 const PCInterfaceProxyVtblList
* proxy_vtbl
;
461 const PCInterfaceStubVtblList
* stub_vtbl
;
462 const CLSID CLSID_Unknown
= {0x45678, 0x1234, 0x6666, {0xff, 0x67, 0x45, 0x98, 0x76, 0x12, 0x34, 0x56}};
463 static const GUID
* const interfaces
[] = { &IID_if1
, &IID_if2
, &IID_if3
, &IID_if4
};
466 HMODULE hmod
= GetModuleHandleA("rpcrt4.dll");
467 void *CStd_QueryInterface
= GetProcAddress(hmod
, "CStdStubBuffer_QueryInterface");
468 void *CStd_AddRef
= GetProcAddress(hmod
, "CStdStubBuffer_AddRef");
469 void *CStd_Release
= GetProcAddress(hmod
, "NdrCStdStubBuffer_Release");
470 void *CStd_Connect
= GetProcAddress(hmod
, "CStdStubBuffer_Connect");
471 void *CStd_Disconnect
= GetProcAddress(hmod
, "CStdStubBuffer_Disconnect");
472 void *CStd_Invoke
= GetProcAddress(hmod
, "CStdStubBuffer_Invoke");
473 void *CStd_IsIIDSupported
= GetProcAddress(hmod
, "CStdStubBuffer_IsIIDSupported");
474 void *CStd_CountRefs
= GetProcAddress(hmod
, "CStdStubBuffer_CountRefs");
475 void *CStd_DebugServerQueryInterface
= GetProcAddress(hmod
, "CStdStubBuffer_DebugServerQueryInterface");
476 void *CStd_DebugServerRelease
= GetProcAddress(hmod
, "CStdStubBuffer_DebugServerRelease");
478 r
= NdrDllGetClassObject(&CLSID_Unknown
, &IID_IPSFactoryBuffer
, (void**)&ppsf
, proxy_file_list
,
479 &CLSID_psfact
, &PSFactoryBuffer
);
480 ok(r
== CLASS_E_CLASSNOTAVAILABLE
, "NdrDllGetClassObject with unknown clsid should have returned CLASS_E_CLASSNOTAVAILABLE instead of 0x%x\n", r
);
481 ok(ppsf
== NULL
, "NdrDllGetClassObject should have set ppsf to NULL on failure\n");
483 r
= NdrDllGetClassObject(&CLSID_psfact
, &IID_IPSFactoryBuffer
, (void**)&ppsf
, proxy_file_list
,
484 &CLSID_psfact
, &PSFactoryBuffer
);
486 ok(r
== S_OK
, "ret %08x\n", r
);
487 ok(ppsf
!= NULL
, "ppsf == NULL\n");
489 proxy_vtbl
= PSFactoryBuffer
.pProxyFileList
[0]->pProxyVtblList
;
490 stub_vtbl
= PSFactoryBuffer
.pProxyFileList
[0]->pStubVtblList
;
491 ok(PSFactoryBuffer
.pProxyFileList
== proxy_file_list
, "pfl not the same\n");
492 ok(proxy_vtbl
== (PCInterfaceProxyVtblList
*) &cstub_ProxyVtblList
, "proxy vtbllist not the same\n");
493 ok(stub_vtbl
== (PCInterfaceStubVtblList
*) &cstub_StubVtblList
, "stub vtbllist not the same\n");
495 /* if1 is non-delegating, if2 is delegating, if3 is non-delegating
496 but I've zero'ed the vtbl entries, similarly if4 is delegating
497 with zero'ed vtbl entries */
499 #define VTBL_TEST_NOT_CHANGE_TO(name, i) \
500 ok(stub_vtbl[i]->Vtbl.name != CStd_##name, #name "vtbl %d updated %p %p\n", \
501 i, stub_vtbl[i]->Vtbl.name, CStd_##name )
502 #define VTBL_TEST_CHANGE_TO(name, i) \
503 ok(check_address(stub_vtbl[i]->Vtbl.name, CStd_##name), #name "vtbl %d not updated %p %p\n", \
504 i, stub_vtbl[i]->Vtbl.name, CStd_##name )
505 #define VTBL_TEST_ZERO(name, i) \
506 ok(stub_vtbl[i]->Vtbl.name == NULL, #name "vtbl %d not null %p\n", \
507 i, stub_vtbl[i]->Vtbl.name )
509 VTBL_TEST_NOT_CHANGE_TO(QueryInterface
, 0);
510 VTBL_TEST_NOT_CHANGE_TO(AddRef
, 0);
511 VTBL_TEST_NOT_CHANGE_TO(Release
, 0);
512 VTBL_TEST_NOT_CHANGE_TO(Connect
, 0);
513 VTBL_TEST_NOT_CHANGE_TO(Disconnect
, 0);
514 VTBL_TEST_NOT_CHANGE_TO(Invoke
, 0);
515 VTBL_TEST_NOT_CHANGE_TO(IsIIDSupported
, 0);
516 VTBL_TEST_NOT_CHANGE_TO(CountRefs
, 0);
517 VTBL_TEST_NOT_CHANGE_TO(DebugServerQueryInterface
, 0);
518 VTBL_TEST_NOT_CHANGE_TO(DebugServerRelease
, 0);
520 VTBL_TEST_CHANGE_TO(QueryInterface
, 1);
521 VTBL_TEST_CHANGE_TO(AddRef
, 1);
522 VTBL_TEST_NOT_CHANGE_TO(Release
, 1);
523 VTBL_TEST_NOT_CHANGE_TO(Connect
, 1);
524 VTBL_TEST_NOT_CHANGE_TO(Disconnect
, 1);
525 VTBL_TEST_CHANGE_TO(Invoke
, 1);
526 VTBL_TEST_CHANGE_TO(IsIIDSupported
, 1);
527 VTBL_TEST_NOT_CHANGE_TO(CountRefs
, 1);
528 VTBL_TEST_CHANGE_TO(DebugServerQueryInterface
, 1);
529 VTBL_TEST_CHANGE_TO(DebugServerRelease
, 1);
531 VTBL_TEST_CHANGE_TO(QueryInterface
, 2);
532 VTBL_TEST_CHANGE_TO(AddRef
, 2);
533 VTBL_TEST_ZERO(Release
, 2);
534 VTBL_TEST_CHANGE_TO(Connect
, 2);
535 VTBL_TEST_CHANGE_TO(Disconnect
, 2);
536 VTBL_TEST_CHANGE_TO(Invoke
, 2);
537 VTBL_TEST_CHANGE_TO(IsIIDSupported
, 2);
538 VTBL_TEST_CHANGE_TO(CountRefs
, 2);
539 VTBL_TEST_CHANGE_TO(DebugServerQueryInterface
, 2);
540 VTBL_TEST_CHANGE_TO(DebugServerRelease
, 2);
542 VTBL_TEST_CHANGE_TO(QueryInterface
, 3);
543 VTBL_TEST_CHANGE_TO(AddRef
, 3);
544 VTBL_TEST_ZERO(Release
, 3);
545 VTBL_TEST_NOT_CHANGE_TO(Connect
, 3);
546 VTBL_TEST_NOT_CHANGE_TO(Disconnect
, 3);
547 VTBL_TEST_CHANGE_TO(Invoke
, 3);
548 VTBL_TEST_CHANGE_TO(IsIIDSupported
, 3);
549 VTBL_TEST_NOT_CHANGE_TO(CountRefs
, 3);
550 VTBL_TEST_CHANGE_TO(DebugServerQueryInterface
, 3);
551 VTBL_TEST_CHANGE_TO(DebugServerRelease
, 3);
553 #define VTBL_PROXY_TEST(i,num,ptr) \
554 ok( check_address(proxy_vtbl[i]->Vtbl[num], (ptr)), "wrong proxy %u func %u %p/%p\n", \
555 (i), (num), proxy_vtbl[i]->Vtbl[num], (ptr) )
556 #define VTBL_PROXY_TEST_NOT_ZERO(i,num) \
557 ok( proxy_vtbl[i]->Vtbl[num] != NULL, "wrong proxy %u func %u is NULL\n", (i), (num))
559 VTBL_PROXY_TEST(0, 0, IUnknown_QueryInterface_Proxy
);
560 VTBL_PROXY_TEST(0, 1, IUnknown_AddRef_Proxy
);
561 VTBL_PROXY_TEST(0, 2, IUnknown_Release_Proxy
);
562 VTBL_PROXY_TEST(0, 3, if1_fn1_Proxy
);
563 VTBL_PROXY_TEST(0, 4, if1_fn2_Proxy
);
565 VTBL_PROXY_TEST(1, 0, GetProcAddress(rpcrt4
,"IUnknown_QueryInterface_Proxy"));
566 VTBL_PROXY_TEST(1, 1, GetProcAddress(rpcrt4
,"IUnknown_AddRef_Proxy"));
567 VTBL_PROXY_TEST(1, 2, GetProcAddress(rpcrt4
,"IUnknown_Release_Proxy"));
568 VTBL_PROXY_TEST_NOT_ZERO(1, 3);
569 VTBL_PROXY_TEST_NOT_ZERO(1, 4);
570 VTBL_PROXY_TEST_NOT_ZERO(1, 5);
571 VTBL_PROXY_TEST_NOT_ZERO(1, 6);
572 VTBL_PROXY_TEST_NOT_ZERO(1, 7);
573 VTBL_PROXY_TEST_NOT_ZERO(1, 8);
574 VTBL_PROXY_TEST_NOT_ZERO(1, 9);
575 VTBL_PROXY_TEST_NOT_ZERO(1, 10);
576 VTBL_PROXY_TEST_NOT_ZERO(1, 11);
577 VTBL_PROXY_TEST_NOT_ZERO(1, 12);
579 VTBL_PROXY_TEST(2, 0, IUnknown_QueryInterface_Proxy
);
580 VTBL_PROXY_TEST(2, 1, IUnknown_AddRef_Proxy
);
581 VTBL_PROXY_TEST(2, 2, IUnknown_Release_Proxy
);
582 VTBL_PROXY_TEST(2, 3, if1_fn1_Proxy
);
583 todo_wine
VTBL_PROXY_TEST_NOT_ZERO(2, 4);
585 VTBL_PROXY_TEST(3, 0, GetProcAddress(rpcrt4
,"IUnknown_QueryInterface_Proxy"));
586 VTBL_PROXY_TEST(3, 1, GetProcAddress(rpcrt4
,"IUnknown_AddRef_Proxy"));
587 VTBL_PROXY_TEST(3, 2, GetProcAddress(rpcrt4
,"IUnknown_Release_Proxy"));
588 VTBL_PROXY_TEST_NOT_ZERO(3, 3);
589 VTBL_PROXY_TEST_NOT_ZERO(3, 4);
590 VTBL_PROXY_TEST_NOT_ZERO(3, 5);
591 VTBL_PROXY_TEST_NOT_ZERO(3, 6);
593 #undef VTBL_TEST_NOT_CHANGE_TO
594 #undef VTBL_TEST_CHANGE_TO
595 #undef VTBL_TEST_ZERO
596 #undef VTBL_PROXY_TEST
597 #undef VTBL_PROXY_TEST_NOT_ZERO
599 for (i
= 0; i
< sizeof(interfaces
)/sizeof(interfaces
[0]); i
++)
600 ok( proxy_vtbl
[i
]->header
.piid
== interfaces
[i
],
601 "wrong proxy %u iid %p/%p\n", i
, proxy_vtbl
[i
]->header
.piid
, interfaces
[i
] );
603 ok(PSFactoryBuffer
.RefCount
== 1, "ref count %d\n", PSFactoryBuffer
.RefCount
);
604 IPSFactoryBuffer_Release(ppsf
);
606 /* One can also search by IID */
607 r
= NdrDllGetClassObject(&IID_if3
, &IID_IPSFactoryBuffer
, (void**)&ppsf
, proxy_file_list
,
608 &CLSID_psfact
, &PSFactoryBuffer
);
609 ok(r
== S_OK
, "ret %08x\n", r
);
610 ok(ppsf
!= NULL
, "ppsf == NULL\n");
611 IPSFactoryBuffer_Release(ppsf
);
613 r
= NdrDllGetClassObject(&IID_if3
, &IID_IPSFactoryBuffer
, (void**)&ppsf
, proxy_file_list
,
614 NULL
, &PSFactoryBuffer
);
615 ok(r
== S_OK
, "ret %08x\n", r
);
616 ok(ppsf
!= NULL
, "ppsf == NULL\n");
617 IPSFactoryBuffer_Release(ppsf
);
619 /* but only if the PS factory implements it */
620 r
= NdrDllGetClassObject(&IID_IDispatch
, &IID_IPSFactoryBuffer
, (void**)&ppsf
, proxy_file_list
,
621 &CLSID_psfact
, &PSFactoryBuffer
);
622 ok(r
== CLASS_E_CLASSNOTAVAILABLE
, "ret %08x\n", r
);
624 /* Create it again to return */
625 r
= NdrDllGetClassObject(&CLSID_psfact
, &IID_IPSFactoryBuffer
, (void**)&ppsf
, proxy_file_list
,
626 &CLSID_psfact
, &PSFactoryBuffer
);
627 ok(r
== S_OK
, "ret %08x\n", r
);
628 ok(ppsf
!= NULL
, "ppsf == NULL\n");
630 /* Because this PS factory is not loaded as a dll in the normal way, Windows 8 / 10
631 get confused and will crash when one of the proxies for the delegated ifaces is created.
632 Registering the ifaces fixes this (in fact calling CoRegisterPSClsid() with any IID / CLSID is enough). */
634 r
= CoRegisterPSClsid(&IID_if1
, &CLSID_psfact
);
635 ok(r
== S_OK
, "ret %08x\n", r
);
636 r
= CoRegisterPSClsid(&IID_if2
, &CLSID_psfact
);
637 ok(r
== S_OK
, "ret %08x\n", r
);
638 r
= CoRegisterPSClsid(&IID_if3
, &CLSID_psfact
);
639 ok(r
== S_OK
, "ret %08x\n", r
);
640 r
= CoRegisterPSClsid(&IID_if4
, &CLSID_psfact
);
641 ok(r
== S_OK
, "ret %08x\n", r
);
646 static int base_buffer_invoke_called
;
647 static HRESULT WINAPI
base_buffer_Invoke(IRpcStubBuffer
*This
, RPCOLEMESSAGE
*msg
, IRpcChannelBuffer
*channel
)
649 base_buffer_invoke_called
++;
650 ok(msg
== (RPCOLEMESSAGE
*)0xcafebabe, "msg ptr changed\n");
651 ok(channel
== (IRpcChannelBuffer
*)0xdeadbeef, "channel ptr changed\n");
652 return S_OK
; /* returning any failure here results in an exception */
655 static IRpcStubBufferVtbl base_buffer_vtbl
= {
668 static void test_NdrStubForwardingFunction(void)
672 IRpcChannelBuffer
*channel
= (IRpcChannelBuffer
*)0xdeadbeef;
673 RPC_MESSAGE
*msg
= (RPC_MESSAGE
*)0xcafebabe;
674 DWORD
*phase
= (DWORD
*)0x12345678;
675 IRpcStubBufferVtbl
*base_buffer_vtbl_ptr
= &base_buffer_vtbl
;
676 IRpcStubBuffer
*base_stub_buffer
= (IRpcStubBuffer
*)&base_buffer_vtbl_ptr
;
678 memset(This
, 0xcc, sizeof(This
));
679 This
[0] = base_stub_buffer
;
680 real_this
= &This
[1];
682 NdrStubForwardingFunction( real_this
, channel
, msg
, phase
);
683 ok(base_buffer_invoke_called
== 1, "base_buffer_invoke called %d times\n", base_buffer_invoke_called
);
687 static IRpcStubBuffer
*create_stub(IPSFactoryBuffer
*ppsf
, REFIID iid
, IUnknown
*obj
, HRESULT expected_result
)
689 IRpcStubBuffer
*pstub
= NULL
;
692 r
= IPSFactoryBuffer_CreateStub(ppsf
, iid
, obj
, &pstub
);
693 ok(r
== expected_result
, "CreateStub returned %08x expected %08x\n", r
, expected_result
);
697 static HRESULT WINAPI
create_stub_test_QI(IUnknown
*This
, REFIID iid
, void **ppv
)
699 ok(IsEqualIID(iid
, &IID_if1
), "incorrect iid\n");
700 *ppv
= (void*)0xdeadbeef;
704 static IUnknownVtbl create_stub_test_vtbl
=
711 static HRESULT WINAPI
create_stub_test_fail_QI(IUnknown
*This
, REFIID iid
, void **ppv
)
713 ok(IsEqualIID(iid
, &IID_if1
), "incorrect iid\n");
715 return E_NOINTERFACE
;
718 static IUnknownVtbl create_stub_test_fail_vtbl
=
720 create_stub_test_fail_QI
,
727 IUnknown IUnknown_iface
;
731 static inline struct dummy_unknown
*impl_from_IUnknown(IUnknown
*iface
)
733 return CONTAINING_RECORD(iface
, struct dummy_unknown
, IUnknown_iface
);
736 static HRESULT WINAPI
dummy_QueryInterface(IUnknown
*This
, REFIID iid
, void **ppv
)
739 return E_NOINTERFACE
;
742 static ULONG WINAPI
dummy_AddRef(LPUNKNOWN iface
)
744 struct dummy_unknown
*this = impl_from_IUnknown(iface
);
745 return InterlockedIncrement( &this->ref
);
748 static ULONG WINAPI
dummy_Release(LPUNKNOWN iface
)
750 struct dummy_unknown
*this = impl_from_IUnknown(iface
);
751 return InterlockedDecrement( &this->ref
);
754 static IUnknownVtbl dummy_unknown_vtbl
=
756 dummy_QueryInterface
,
760 static struct dummy_unknown dummy_unknown
= { { &dummy_unknown_vtbl
}, 0 };
762 static void create_proxy_test( IPSFactoryBuffer
*ppsf
, REFIID iid
, const void *expected_vtbl
)
764 IRpcProxyBuffer
*proxy
= NULL
;
765 IUnknown
*iface
= NULL
;
769 r
= IPSFactoryBuffer_CreateProxy(ppsf
, NULL
, iid
, &proxy
, (void **)&iface
);
770 ok( r
== S_OK
, "IPSFactoryBuffer_CreateProxy failed %x\n", r
);
771 ok( *(void **)iface
== expected_vtbl
, "wrong iface pointer %p/%p\n", *(void **)iface
, expected_vtbl
);
772 count
= IUnknown_Release( iface
);
773 ok( count
== 1, "wrong refcount %u\n", count
);
774 count
= IRpcProxyBuffer_Release( proxy
);
775 ok( count
== 0, "wrong refcount %u\n", count
);
777 dummy_unknown
.ref
= 4;
778 r
= IPSFactoryBuffer_CreateProxy(ppsf
, &dummy_unknown
.IUnknown_iface
, iid
, &proxy
,
780 ok( r
== S_OK
, "IPSFactoryBuffer_CreateProxy failed %x\n", r
);
781 ok( dummy_unknown
.ref
== 5, "wrong refcount %u\n", dummy_unknown
.ref
);
782 ok( *(void **)iface
== expected_vtbl
, "wrong iface pointer %p/%p\n", *(void **)iface
, expected_vtbl
);
783 count
= IUnknown_Release( iface
);
784 ok( count
== 4, "wrong refcount %u\n", count
);
785 ok( dummy_unknown
.ref
== 4, "wrong refcount %u\n", dummy_unknown
.ref
);
786 count
= IRpcProxyBuffer_Release( proxy
);
787 ok( count
== 0, "wrong refcount %u\n", count
);
788 ok( dummy_unknown
.ref
== 4, "wrong refcount %u\n", dummy_unknown
.ref
);
791 static void test_CreateProxy( IPSFactoryBuffer
*ppsf
)
793 create_proxy_test( ppsf
, &IID_if1
, if1_proxy_vtbl
.Vtbl
);
794 create_proxy_test( ppsf
, &IID_if2
, if2_proxy_vtbl
.Vtbl
);
795 create_proxy_test( ppsf
, &IID_if3
, if3_proxy_vtbl
.Vtbl
);
796 create_proxy_test( ppsf
, &IID_if4
, if4_proxy_vtbl
.Vtbl
);
799 static void test_CreateStub(IPSFactoryBuffer
*ppsf
)
801 IUnknownVtbl
*vtbl
= &create_stub_test_vtbl
;
802 IUnknown
*obj
= (IUnknown
*)&vtbl
;
803 IRpcStubBuffer
*pstub
= create_stub(ppsf
, &IID_if1
, obj
, S_OK
);
804 CStdStubBuffer
*cstd_stub
= (CStdStubBuffer
*)pstub
;
805 const CInterfaceStubHeader
*header
= &CONTAINING_RECORD(cstd_stub
->lpVtbl
, const CInterfaceStubVtbl
, Vtbl
)->header
;
807 ok(IsEqualIID(header
->piid
, &IID_if1
), "header iid differs\n");
808 ok(cstd_stub
->RefCount
== 1, "ref count %d\n", cstd_stub
->RefCount
);
809 /* 0xdeadbeef returned from create_stub_test_QI */
810 ok(cstd_stub
->pvServerObject
== (void*)0xdeadbeef, "pvServerObject %p\n", cstd_stub
->pvServerObject
);
811 ok(cstd_stub
->pPSFactory
!= NULL
, "pPSFactory was NULL\n");
812 cstd_stub
->pvServerObject
= NULL
;
813 IRpcStubBuffer_Release(pstub
);
815 vtbl
= &create_stub_test_fail_vtbl
;
816 pstub
= create_stub(ppsf
, &IID_if1
, obj
, E_NOINTERFACE
);
817 ok(pstub
== S_OK
, "create_stub failed: %u\n", GetLastError());
821 static HRESULT WINAPI
connect_test_orig_QI(IUnknown
*This
, REFIID iid
, void **ppv
)
823 ok(IsEqualIID(iid
, &IID_if1
) ||
824 IsEqualIID(iid
, &IID_if2
), "incorrect iid\n");
829 static int connect_test_orig_release_called
;
830 static ULONG WINAPI
connect_test_orig_release(IUnknown
*This
)
832 connect_test_orig_release_called
++;
836 static IUnknownVtbl connect_test_orig_vtbl
=
838 connect_test_orig_QI
,
840 connect_test_orig_release
843 static HRESULT WINAPI
connect_test_new_QI(IUnknown
*This
, REFIID iid
, void **ppv
)
845 ok(IsEqualIID(iid
, &IID_if1
) ||
846 IsEqualIID(iid
, &IID_if2
), "incorrect iid\n");
847 *ppv
= (void*)0xcafebabe;
851 static IUnknownVtbl connect_test_new_vtbl
=
858 static HRESULT WINAPI
connect_test_new_fail_QI(IUnknown
*This
, REFIID iid
, void **ppv
)
860 ok(IsEqualIID(iid
, &IID_if1
), "incorrect iid\n");
861 *ppv
= (void*)0xdeadbeef;
862 return E_NOINTERFACE
;
865 static IUnknownVtbl connect_test_new_fail_vtbl
=
867 connect_test_new_fail_QI
,
872 static int connect_test_base_Connect_called
;
873 static HRESULT WINAPI
connect_test_base_Connect(IRpcStubBuffer
*pstub
, IUnknown
*obj
)
875 connect_test_base_Connect_called
++;
876 ok(*(void**)obj
== (void*)0xbeefcafe, "unexpected obj %p\n", obj
);
880 static IRpcStubBufferVtbl connect_test_base_stub_buffer_vtbl
=
885 connect_test_base_Connect
,
894 static void test_Connect(IPSFactoryBuffer
*ppsf
)
896 IUnknownVtbl
*orig_vtbl
= &connect_test_orig_vtbl
;
897 IUnknownVtbl
*new_vtbl
= &connect_test_new_vtbl
;
898 IUnknownVtbl
*new_fail_vtbl
= &connect_test_new_fail_vtbl
;
899 IUnknown
*obj
= (IUnknown
*)&orig_vtbl
;
900 IRpcStubBuffer
*pstub
= create_stub(ppsf
, &IID_if1
, obj
, S_OK
);
901 CStdStubBuffer
*cstd_stub
= (CStdStubBuffer
*)pstub
;
902 IRpcStubBufferVtbl
*base_stub_buf_vtbl
= &connect_test_base_stub_buffer_vtbl
;
905 obj
= (IUnknown
*)&new_vtbl
;
906 r
= IRpcStubBuffer_Connect(pstub
, obj
);
907 ok(r
== S_OK
, "r %08x\n", r
);
908 ok(connect_test_orig_release_called
== 1, "release called %d\n", connect_test_orig_release_called
);
909 ok(cstd_stub
->pvServerObject
== (void*)0xcafebabe, "pvServerObject %p\n", cstd_stub
->pvServerObject
);
911 cstd_stub
->pvServerObject
= (IUnknown
*)&orig_vtbl
;
912 obj
= (IUnknown
*)&new_fail_vtbl
;
913 r
= IRpcStubBuffer_Connect(pstub
, obj
);
914 ok(r
== E_NOINTERFACE
, "r %08x\n", r
);
915 ok(cstd_stub
->pvServerObject
== (void*)0xdeadbeef, "pvServerObject %p\n", cstd_stub
->pvServerObject
);
916 ok(connect_test_orig_release_called
== 2, "release called %d\n", connect_test_orig_release_called
);
918 /* Now use a delegated stub.
920 We know from the NdrStubForwardFunction test that
921 (void**)pstub-1 is the base interface stub buffer. This shows
922 that (void**)pstub-2 contains the address of a vtable that gets
923 passed to the base interface's Connect method. Note that
924 (void**)pstub-2 itself gets passed to Connect and not
925 *((void**)pstub-2), so it should contain the vtable ptr and not
928 obj
= (IUnknown
*)&orig_vtbl
;
929 pstub
= create_stub(ppsf
, &IID_if2
, obj
, S_OK
);
930 *((void**)pstub
-1) = &base_stub_buf_vtbl
;
931 *((void**)pstub
-2) = (void*)0xbeefcafe;
933 obj
= (IUnknown
*)&new_vtbl
;
934 r
= IRpcStubBuffer_Connect(pstub
, obj
);
935 ok(r
== S_OK
, "r %08x\n", r
);
936 ok(connect_test_base_Connect_called
== 1, "connect_test_bsae_Connect called %d times\n",
937 connect_test_base_Connect_called
);
938 ok(connect_test_orig_release_called
== 3, "release called %d\n", connect_test_orig_release_called
);
939 cstd_stub
= (CStdStubBuffer
*)pstub
;
940 ok(cstd_stub
->pvServerObject
== (void*)0xcafebabe, "pvServerObject %p\n", cstd_stub
->pvServerObject
);
943 static void test_Disconnect(IPSFactoryBuffer
*ppsf
)
945 IUnknownVtbl
*orig_vtbl
= &connect_test_orig_vtbl
;
946 IUnknown
*obj
= (IUnknown
*)&orig_vtbl
;
947 IRpcStubBuffer
*pstub
= create_stub(ppsf
, &IID_if1
, obj
, S_OK
);
948 CStdStubBuffer
*cstd_stub
= (CStdStubBuffer
*)pstub
;
950 connect_test_orig_release_called
= 0;
951 IRpcStubBuffer_Disconnect(pstub
);
952 ok(connect_test_orig_release_called
== 1, "release called %d\n", connect_test_orig_release_called
);
953 ok(cstd_stub
->pvServerObject
== NULL
, "pvServerObject %p\n", cstd_stub
->pvServerObject
);
954 IRpcStubBuffer_Release(pstub
);
958 static int release_test_psfacbuf_release_called
;
959 static ULONG WINAPI
release_test_pretend_psfacbuf_release(IUnknown
*pUnk
)
961 release_test_psfacbuf_release_called
++;
965 static IUnknownVtbl release_test_pretend_psfacbuf_vtbl
=
969 release_test_pretend_psfacbuf_release
972 static void test_Release(IPSFactoryBuffer
*ppsf
)
975 IUnknownVtbl
*orig_vtbl
= &connect_test_orig_vtbl
;
976 IUnknown
*obj
= (IUnknown
*)&orig_vtbl
;
977 IUnknownVtbl
*pretend_psfacbuf_vtbl
= &release_test_pretend_psfacbuf_vtbl
;
978 IUnknown
*pretend_psfacbuf
= (IUnknown
*)&pretend_psfacbuf_vtbl
;
979 IRpcStubBuffer
*pstub
= create_stub(ppsf
, &IID_if1
, obj
, S_OK
);
980 CStdStubBuffer
*cstd_stub
= (CStdStubBuffer
*)pstub
;
982 facbuf_refs
= PSFactoryBuffer
.RefCount
;
984 /* This shows that NdrCStdStubBuffer_Release doesn't call Disconnect */
985 ok(cstd_stub
->RefCount
== 1, "ref count %d\n", cstd_stub
->RefCount
);
986 connect_test_orig_release_called
= 0;
987 IRpcStubBuffer_Release(pstub
);
989 ok(connect_test_orig_release_called
== 0, "release called %d\n", connect_test_orig_release_called
);
991 ok(PSFactoryBuffer
.RefCount
== facbuf_refs
- 1, "factory buffer refs %d orig %d\n", PSFactoryBuffer
.RefCount
, facbuf_refs
);
993 /* This shows that NdrCStdStubBuffer_Release calls Release on its 2nd arg, rather than on This->pPSFactory
994 (which are usually the same and indeed it's odd that _Release requires this 2nd arg). */
995 pstub
= create_stub(ppsf
, &IID_if1
, obj
, S_OK
);
996 ok(PSFactoryBuffer
.RefCount
== facbuf_refs
, "factory buffer refs %d orig %d\n", PSFactoryBuffer
.RefCount
, facbuf_refs
);
997 NdrCStdStubBuffer_Release(pstub
, (IPSFactoryBuffer
*)pretend_psfacbuf
);
998 ok(release_test_psfacbuf_release_called
== 1, "pretend_psfacbuf_release called %d\n", release_test_psfacbuf_release_called
);
999 ok(PSFactoryBuffer
.RefCount
== facbuf_refs
, "factory buffer refs %d orig %d\n", PSFactoryBuffer
.RefCount
, facbuf_refs
);
1002 static HRESULT WINAPI
delegating_invoke_test_QI(ITypeLib
*pUnk
, REFIID iid
, void** ppv
)
1009 static ULONG WINAPI
delegating_invoke_test_addref(ITypeLib
*pUnk
)
1014 static ULONG WINAPI
delegating_invoke_test_release(ITypeLib
*pUnk
)
1019 static UINT WINAPI
delegating_invoke_test_get_type_info_count(ITypeLib
*pUnk
)
1024 static ITypeLibVtbl delegating_invoke_test_obj_vtbl
=
1026 delegating_invoke_test_QI
,
1027 delegating_invoke_test_addref
,
1028 delegating_invoke_test_release
,
1029 delegating_invoke_test_get_type_info_count
,
1041 static HRESULT WINAPI
delegating_invoke_chan_query_interface(IRpcChannelBuffer
*pchan
,
1045 ok(0, "call to QueryInterface not expected\n");
1046 return E_NOINTERFACE
;
1049 static ULONG WINAPI
delegating_invoke_chan_add_ref(IRpcChannelBuffer
*pchan
)
1054 static ULONG WINAPI
delegating_invoke_chan_release(IRpcChannelBuffer
*pchan
)
1059 static HRESULT WINAPI
delegating_invoke_chan_get_buffer(IRpcChannelBuffer
*pchan
,
1063 msg
->Buffer
= HeapAlloc(GetProcessHeap(), 0, msg
->cbBuffer
);
1067 static HRESULT WINAPI
delegating_invoke_chan_send_receive(IRpcChannelBuffer
*pchan
,
1068 RPCOLEMESSAGE
*pMessage
,
1071 ok(0, "call to SendReceive not expected\n");
1075 static HRESULT WINAPI
delegating_invoke_chan_free_buffer(IRpcChannelBuffer
*pchan
,
1076 RPCOLEMESSAGE
*pMessage
)
1078 ok(0, "call to FreeBuffer not expected\n");
1082 static HRESULT WINAPI
delegating_invoke_chan_get_dest_ctx(IRpcChannelBuffer
*pchan
,
1083 DWORD
*pdwDestContext
,
1084 void **ppvDestContext
)
1086 *pdwDestContext
= MSHCTX_LOCAL
;
1087 *ppvDestContext
= NULL
;
1091 static HRESULT WINAPI
delegating_invoke_chan_is_connected(IRpcChannelBuffer
*pchan
)
1093 ok(0, "call to IsConnected not expected\n");
1097 static IRpcChannelBufferVtbl delegating_invoke_test_rpc_chan_vtbl
=
1099 delegating_invoke_chan_query_interface
,
1100 delegating_invoke_chan_add_ref
,
1101 delegating_invoke_chan_release
,
1102 delegating_invoke_chan_get_buffer
,
1103 delegating_invoke_chan_send_receive
,
1104 delegating_invoke_chan_free_buffer
,
1105 delegating_invoke_chan_get_dest_ctx
,
1106 delegating_invoke_chan_is_connected
1109 static void test_delegating_Invoke(IPSFactoryBuffer
*ppsf
)
1111 ITypeLibVtbl
*obj_vtbl
= &delegating_invoke_test_obj_vtbl
;
1112 IUnknown
*obj
= (IUnknown
*)&obj_vtbl
;
1113 IRpcStubBuffer
*pstub
= create_stub(ppsf
, &IID_if2
, obj
, S_OK
);
1114 IRpcChannelBufferVtbl
*pchan_vtbl
= &delegating_invoke_test_rpc_chan_vtbl
;
1115 IRpcChannelBuffer
*pchan
= (IRpcChannelBuffer
*)&pchan_vtbl
;
1119 memset(&msg
, 0, sizeof(msg
));
1120 msg
.dataRepresentation
= NDR_LOCAL_DATA_REPRESENTATION
;
1122 r
= IRpcStubBuffer_Invoke(pstub
, &msg
, pchan
);
1123 ok(r
== S_OK
, "ret %08x\n", r
);
1126 ok(*(DWORD
*)msg
.Buffer
== 0xabcdef, "buf[0] %08x\n", *(DWORD
*)msg
.Buffer
);
1127 ok(*((DWORD
*)msg
.Buffer
+ 1) == S_OK
, "buf[1] %08x\n", *((DWORD
*)msg
.Buffer
+ 1));
1129 /* free the buffer allocated by delegating_invoke_chan_get_buffer */
1130 HeapFree(GetProcessHeap(), 0, msg
.Buffer
);
1131 IRpcStubBuffer_Release(pstub
);
1133 static const CInterfaceProxyVtbl
*cstub_ProxyVtblList2
[] =
1138 static const CInterfaceStubVtbl
*cstub_StubVtblList2
[] =
1143 static PCInterfaceName
const if_name_list2
[] =
1148 static const IID
*base_iid_list2
[] =
1153 static const ExtendedProxyFileInfo my_proxy_file_info2
=
1155 (const PCInterfaceProxyVtblList
*) &cstub_ProxyVtblList2
,
1156 (const PCInterfaceStubVtblList
*) &cstub_StubVtblList2
,
1157 (const PCInterfaceName
*) &if_name_list2
,
1158 (const IID
**) &base_iid_list2
,
1168 static const ProxyFileInfo
*proxy_file_list2
[] = {
1169 &my_proxy_file_info2
,
1173 static void test_NdrDllRegisterProxy( void )
1176 const ExtendedProxyFileInfo
*pf
;
1177 HMODULE hmod
= GetModuleHandleA(NULL
);
1180 res
= NdrDllRegisterProxy(NULL
, NULL
, NULL
);
1181 ok(res
== E_HANDLE
, "Incorrect return code %x\n",res
);
1183 res
= NdrDllRegisterProxy(hmod
, &pf
, NULL
);
1184 ok(res
== E_NOINTERFACE
, "Incorrect return code %x\n",res
);
1185 res
= NdrDllRegisterProxy(hmod
, proxy_file_list2
, NULL
);
1186 ok(res
== E_NOINTERFACE
, "Incorrect return code %x\n",res
);
1187 /* This fails on Vista and Windows 7 due to permissions */
1188 res
= NdrDllRegisterProxy(hmod
, proxy_file_list
, NULL
);
1189 ok(res
== S_OK
|| res
== E_ACCESSDENIED
, "NdrDllRegisterProxy failed %x\n",res
);
1192 res
= NdrDllUnregisterProxy(hmod
,proxy_file_list
, NULL
);
1193 ok(res
== S_OK
, "NdrDllUnregisterProxy failed %x\n",res
);
1199 IPSFactoryBuffer
*ppsf
;
1201 OleInitialize(NULL
);
1203 ppsf
= test_NdrDllGetClassObject();
1204 test_NdrStubForwardingFunction();
1205 test_CreateProxy(ppsf
);
1206 test_CreateStub(ppsf
);
1208 test_Disconnect(ppsf
);
1210 test_delegating_Invoke(ppsf
);
1211 test_NdrDllRegisterProxy();