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
37 #include "wine/heap.h"
38 #include "wine/test.h"
42 static CStdPSFactoryBuffer PSFactoryBuffer
;
44 static ULONG WINAPI
test_CStdStubBuffer_Release(IRpcStubBuffer
*This
)
46 return NdrCStdStubBuffer_Release(This
, (IPSFactoryBuffer
*)&PSFactoryBuffer
);
49 static ULONG WINAPI
test_CStdStubBuffer2_Release(IRpcStubBuffer
*This
)
51 return NdrCStdStubBuffer2_Release(This
, (IPSFactoryBuffer
*)&PSFactoryBuffer
);
54 static GUID IID_if1
= {0x12345678, 1234, 5678, {12,34,56,78,90,0xab,0xcd,0xef}};
55 static GUID IID_if2
= {0x12345679, 1234, 5678, {12,34,56,78,90,0xab,0xcd,0xef}};
56 static GUID IID_if3
= {0x1234567a, 1234, 5678, {12,34,56,78,90,0xab,0xcd,0xef}};
57 static GUID IID_if4
= {0x1234567b, 1234, 5678, {12,34,56,78,90,0xab,0xcd,0xef}};
58 static CLSID CLSID_psfact
= {0x1234567c, 1234, 5678, {12,34,56,78,90,0xab,0xcd,0xef}};
60 static int my_alloc_called
;
61 static int my_free_called
;
63 static void * CALLBACK
my_alloc(SIZE_T size
)
66 return NdrOleAllocate(size
);
69 static void CALLBACK
my_free(void *ptr
)
75 typedef struct _MIDL_PROC_FORMAT_STRING
78 unsigned char Format
[ 2 ];
79 } MIDL_PROC_FORMAT_STRING
;
81 typedef struct _MIDL_TYPE_FORMAT_STRING
84 unsigned char Format
[ 2 ];
85 } MIDL_TYPE_FORMAT_STRING
;
88 static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString
=
96 static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString
=
104 static const MIDL_STUB_DESC Object_StubDesc
=
114 __MIDL_TypeFormatString
.Format
,
115 1, /* -error bounds_check flag */
116 0x20000, /* Ndr library version */
118 0x50100a4, /* MIDL Version 5.1.164 */
121 0, /* notify & notify_flag routine table */
128 static HRESULT WINAPI
if1_fn1_Proxy(void *This
)
133 static void __RPC_STUB
if1_fn1_Stub(
134 IRpcStubBuffer
*This
,
135 IRpcChannelBuffer
*_pRpcChannelBuffer
,
136 PRPC_MESSAGE _pRpcMessage
,
137 DWORD
*_pdwStubPhase
)
142 static HRESULT WINAPI
if1_fn2_Proxy(void *This
)
147 static void __RPC_STUB
if1_fn2_Stub(
148 IRpcStubBuffer
*This
,
149 IRpcChannelBuffer
*_pRpcChannelBuffer
,
150 PRPC_MESSAGE _pRpcMessage
,
151 DWORD
*_pdwStubPhase
)
156 static CINTERFACE_PROXY_VTABLE(5) if1_proxy_vtbl
=
159 { IUnknown_QueryInterface_Proxy
,
160 IUnknown_AddRef_Proxy
,
161 IUnknown_Release_Proxy
,
168 static const unsigned short if1_FormatStringOffsetTable
[] =
174 static const MIDL_SERVER_INFO if1_server_info
=
178 __MIDL_ProcFormatString
.Format
,
179 &if1_FormatStringOffsetTable
[-3],
186 static const PRPC_STUB_FUNCTION if1_table
[] =
192 static CInterfaceStubVtbl if1_stub_vtbl
=
201 CStdStubBuffer_QueryInterface
,
202 CStdStubBuffer_AddRef
,
203 test_CStdStubBuffer_Release
,
204 CStdStubBuffer_Connect
,
205 CStdStubBuffer_Disconnect
,
206 CStdStubBuffer_Invoke
,
207 CStdStubBuffer_IsIIDSupported
,
208 CStdStubBuffer_CountRefs
,
209 CStdStubBuffer_DebugServerQueryInterface
,
210 CStdStubBuffer_DebugServerRelease
214 static CINTERFACE_PROXY_VTABLE(13) if2_proxy_vtbl
=
217 { IUnknown_QueryInterface_Proxy
,
218 IUnknown_AddRef_Proxy
,
219 IUnknown_Release_Proxy
,
233 static const unsigned short if2_FormatStringOffsetTable
[] =
248 static const MIDL_SERVER_INFO if2_server_info
=
252 __MIDL_ProcFormatString
.Format
,
253 &if2_FormatStringOffsetTable
[-3],
260 static const PRPC_STUB_FUNCTION if2_table
[] =
262 STUB_FORWARDING_FUNCTION
,
263 STUB_FORWARDING_FUNCTION
,
264 STUB_FORWARDING_FUNCTION
,
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
274 static CInterfaceStubVtbl if2_stub_vtbl
=
282 { 0, 0, test_CStdStubBuffer2_Release
, 0, 0, 0, 0, 0, 0, 0 }
285 static CINTERFACE_PROXY_VTABLE(5) if3_proxy_vtbl
=
288 { IUnknown_QueryInterface_Proxy
,
289 IUnknown_AddRef_Proxy
,
290 IUnknown_Release_Proxy
,
297 static const unsigned short if3_FormatStringOffsetTable
[] =
303 static const MIDL_SERVER_INFO if3_server_info
=
307 __MIDL_ProcFormatString
.Format
,
308 &if3_FormatStringOffsetTable
[-3],
314 static CInterfaceStubVtbl if3_stub_vtbl
=
322 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
325 static CINTERFACE_PROXY_VTABLE(7) if4_proxy_vtbl
=
328 { IUnknown_QueryInterface_Proxy
,
329 IUnknown_AddRef_Proxy
,
330 IUnknown_Release_Proxy
,
338 static const unsigned short if4_FormatStringOffsetTable
[] =
347 static const MIDL_SERVER_INFO if4_server_info
=
351 __MIDL_ProcFormatString
.Format
,
352 &if4_FormatStringOffsetTable
[-3],
358 static CInterfaceStubVtbl if4_stub_vtbl
=
366 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
369 static const CInterfaceProxyVtbl
*cstub_ProxyVtblList
[] =
371 (const CInterfaceProxyVtbl
*) &if1_proxy_vtbl
,
372 (const CInterfaceProxyVtbl
*) &if2_proxy_vtbl
,
373 (const CInterfaceProxyVtbl
*) &if3_proxy_vtbl
,
374 (const CInterfaceProxyVtbl
*) &if4_proxy_vtbl
,
378 static const CInterfaceStubVtbl
*cstub_StubVtblList
[] =
387 static PCInterfaceName
const if_name_list
[] =
396 static const IID
*base_iid_list
[] =
405 #define cstub_CHECK_IID(n) IID_GENERIC_CHECK_IID( cstub, pIID, n)
407 static int __stdcall
iid_lookup( const IID
* pIID
, int * pIndex
)
411 IID_BS_LOOKUP_INITIAL_TEST( cstub
, 4, 4 )
412 IID_BS_LOOKUP_NEXT_TEST( cstub
, 2 )
413 IID_BS_LOOKUP_NEXT_TEST( cstub
, 1 )
414 IID_BS_LOOKUP_RETURN_RESULT( cstub
, 4, *pIndex
)
419 static BOOL
check_address(void *actual
, void *expected
)
421 static void *ole32_start
= NULL
;
422 static void *ole32_end
= NULL
;
423 static void *combase_start
= NULL
;
424 static void *combase_end
= NULL
;
426 if (actual
== expected
)
429 /* On Win7, actual can be located inside ole32.dll */
430 if (ole32_start
== NULL
|| ole32_end
== NULL
)
432 PIMAGE_NT_HEADERS nt_headers
;
433 ole32_start
= (void *) GetModuleHandleA("ole32.dll");
434 if (ole32_start
== NULL
)
436 nt_headers
= (PIMAGE_NT_HEADERS
)((char *) ole32_start
+ ((PIMAGE_DOS_HEADER
) ole32_start
)->e_lfanew
);
437 ole32_end
= (void *)((char *) ole32_start
+ nt_headers
->OptionalHeader
.SizeOfImage
);
440 if (ole32_start
<= actual
&& actual
< ole32_end
)
443 /* On Win8, actual can be located inside combase.dll */
444 if (combase_start
== NULL
|| combase_end
== NULL
)
446 PIMAGE_NT_HEADERS nt_headers
;
447 combase_start
= (void *) GetModuleHandleA("combase.dll");
448 if (combase_start
== NULL
)
450 nt_headers
= (PIMAGE_NT_HEADERS
)((char *) combase_start
+ ((PIMAGE_DOS_HEADER
) combase_start
)->e_lfanew
);
451 combase_end
= (void *)((char *) combase_start
+ nt_headers
->OptionalHeader
.SizeOfImage
);
454 return (combase_start
<= actual
&& actual
< combase_end
);
457 static const ExtendedProxyFileInfo my_proxy_file_info
=
459 (const PCInterfaceProxyVtblList
*) &cstub_ProxyVtblList
,
460 (const PCInterfaceStubVtblList
*) &cstub_StubVtblList
,
461 (const PCInterfaceName
*) &if_name_list
,
462 (const IID
**) &base_iid_list
,
472 static const ProxyFileInfo
*proxy_file_list
[] = {
478 static IPSFactoryBuffer
*test_NdrDllGetClassObject(void)
480 HMODULE rpcrt4
= GetModuleHandleA("rpcrt4.dll");
481 IPSFactoryBuffer
*ppsf
= NULL
;
482 const PCInterfaceProxyVtblList
* proxy_vtbl
;
483 const PCInterfaceStubVtblList
* stub_vtbl
;
484 const CLSID CLSID_Unknown
= {0x45678, 0x1234, 0x6666, {0xff, 0x67, 0x45, 0x98, 0x76, 0x12, 0x34, 0x56}};
485 static const GUID
* const interfaces
[] = { &IID_if1
, &IID_if2
, &IID_if3
, &IID_if4
};
488 HMODULE hmod
= GetModuleHandleA("rpcrt4.dll");
489 void *CStd_QueryInterface
= GetProcAddress(hmod
, "CStdStubBuffer_QueryInterface");
490 void *CStd_AddRef
= GetProcAddress(hmod
, "CStdStubBuffer_AddRef");
491 void *CStd_Release
= GetProcAddress(hmod
, "NdrCStdStubBuffer_Release");
492 void *CStd_Connect
= GetProcAddress(hmod
, "CStdStubBuffer_Connect");
493 void *CStd_Disconnect
= GetProcAddress(hmod
, "CStdStubBuffer_Disconnect");
494 void *CStd_Invoke
= GetProcAddress(hmod
, "CStdStubBuffer_Invoke");
495 void *CStd_IsIIDSupported
= GetProcAddress(hmod
, "CStdStubBuffer_IsIIDSupported");
496 void *CStd_CountRefs
= GetProcAddress(hmod
, "CStdStubBuffer_CountRefs");
497 void *CStd_DebugServerQueryInterface
= GetProcAddress(hmod
, "CStdStubBuffer_DebugServerQueryInterface");
498 void *CStd_DebugServerRelease
= GetProcAddress(hmod
, "CStdStubBuffer_DebugServerRelease");
500 r
= NdrDllGetClassObject(&CLSID_Unknown
, &IID_IPSFactoryBuffer
, (void**)&ppsf
, proxy_file_list
,
501 &CLSID_psfact
, &PSFactoryBuffer
);
502 ok(r
== CLASS_E_CLASSNOTAVAILABLE
, "NdrDllGetClassObject with unknown clsid should have returned CLASS_E_CLASSNOTAVAILABLE instead of 0x%lx\n", r
);
503 ok(ppsf
== NULL
, "NdrDllGetClassObject should have set ppsf to NULL on failure\n");
505 r
= NdrDllGetClassObject(&CLSID_psfact
, &IID_IPSFactoryBuffer
, (void**)&ppsf
, proxy_file_list
,
506 &CLSID_psfact
, &PSFactoryBuffer
);
508 ok(r
== S_OK
, "ret %08lx\n", r
);
509 ok(ppsf
!= NULL
, "ppsf == NULL\n");
511 proxy_vtbl
= PSFactoryBuffer
.pProxyFileList
[0]->pProxyVtblList
;
512 stub_vtbl
= PSFactoryBuffer
.pProxyFileList
[0]->pStubVtblList
;
513 ok(PSFactoryBuffer
.pProxyFileList
== proxy_file_list
, "pfl not the same\n");
514 ok(proxy_vtbl
== (PCInterfaceProxyVtblList
*) &cstub_ProxyVtblList
, "proxy vtbllist not the same\n");
515 ok(stub_vtbl
== (PCInterfaceStubVtblList
*) &cstub_StubVtblList
, "stub vtbllist not the same\n");
517 /* if1 is non-delegating, if2 is delegating, if3 is non-delegating
518 but I've zero'ed the vtbl entries, similarly if4 is delegating
519 with zero'ed vtbl entries */
521 #define VTBL_TEST_NOT_CHANGE_TO(name, i) \
522 ok(stub_vtbl[i]->Vtbl.name != CStd_##name, #name "vtbl %d updated %p %p\n", \
523 i, stub_vtbl[i]->Vtbl.name, CStd_##name )
524 #define VTBL_TEST_CHANGE_TO(name, i) \
525 ok(check_address(stub_vtbl[i]->Vtbl.name, CStd_##name), #name "vtbl %d not updated %p %p\n", \
526 i, stub_vtbl[i]->Vtbl.name, CStd_##name )
527 #define VTBL_TEST_ZERO(name, i) \
528 ok(stub_vtbl[i]->Vtbl.name == NULL, #name "vtbl %d not null %p\n", \
529 i, stub_vtbl[i]->Vtbl.name )
531 VTBL_TEST_NOT_CHANGE_TO(QueryInterface
, 0);
532 VTBL_TEST_NOT_CHANGE_TO(AddRef
, 0);
533 VTBL_TEST_NOT_CHANGE_TO(Release
, 0);
534 VTBL_TEST_NOT_CHANGE_TO(Connect
, 0);
535 VTBL_TEST_NOT_CHANGE_TO(Disconnect
, 0);
536 VTBL_TEST_NOT_CHANGE_TO(Invoke
, 0);
537 VTBL_TEST_NOT_CHANGE_TO(IsIIDSupported
, 0);
538 VTBL_TEST_NOT_CHANGE_TO(CountRefs
, 0);
539 VTBL_TEST_NOT_CHANGE_TO(DebugServerQueryInterface
, 0);
540 VTBL_TEST_NOT_CHANGE_TO(DebugServerRelease
, 0);
542 VTBL_TEST_CHANGE_TO(QueryInterface
, 1);
543 VTBL_TEST_CHANGE_TO(AddRef
, 1);
544 VTBL_TEST_NOT_CHANGE_TO(Release
, 1);
545 VTBL_TEST_NOT_CHANGE_TO(Connect
, 1);
546 VTBL_TEST_NOT_CHANGE_TO(Disconnect
, 1);
547 VTBL_TEST_CHANGE_TO(Invoke
, 1);
548 VTBL_TEST_CHANGE_TO(IsIIDSupported
, 1);
549 VTBL_TEST_NOT_CHANGE_TO(CountRefs
, 1);
550 VTBL_TEST_CHANGE_TO(DebugServerQueryInterface
, 1);
551 VTBL_TEST_CHANGE_TO(DebugServerRelease
, 1);
553 VTBL_TEST_CHANGE_TO(QueryInterface
, 2);
554 VTBL_TEST_CHANGE_TO(AddRef
, 2);
555 VTBL_TEST_ZERO(Release
, 2);
556 VTBL_TEST_CHANGE_TO(Connect
, 2);
557 VTBL_TEST_CHANGE_TO(Disconnect
, 2);
558 VTBL_TEST_CHANGE_TO(Invoke
, 2);
559 VTBL_TEST_CHANGE_TO(IsIIDSupported
, 2);
560 VTBL_TEST_CHANGE_TO(CountRefs
, 2);
561 VTBL_TEST_CHANGE_TO(DebugServerQueryInterface
, 2);
562 VTBL_TEST_CHANGE_TO(DebugServerRelease
, 2);
564 VTBL_TEST_CHANGE_TO(QueryInterface
, 3);
565 VTBL_TEST_CHANGE_TO(AddRef
, 3);
566 VTBL_TEST_ZERO(Release
, 3);
567 VTBL_TEST_NOT_CHANGE_TO(Connect
, 3);
568 VTBL_TEST_NOT_CHANGE_TO(Disconnect
, 3);
569 VTBL_TEST_CHANGE_TO(Invoke
, 3);
570 VTBL_TEST_CHANGE_TO(IsIIDSupported
, 3);
571 VTBL_TEST_NOT_CHANGE_TO(CountRefs
, 3);
572 VTBL_TEST_CHANGE_TO(DebugServerQueryInterface
, 3);
573 VTBL_TEST_CHANGE_TO(DebugServerRelease
, 3);
575 #define VTBL_PROXY_TEST(i,num,ptr) \
576 ok( check_address(proxy_vtbl[i]->Vtbl[num], (ptr)), "wrong proxy %u func %u %p/%p\n", \
577 (i), (num), proxy_vtbl[i]->Vtbl[num], (ptr) )
578 #define VTBL_PROXY_TEST_NOT_ZERO(i,num) \
579 ok( proxy_vtbl[i]->Vtbl[num] != NULL, "wrong proxy %u func %u is NULL\n", (i), (num))
581 VTBL_PROXY_TEST(0, 0, IUnknown_QueryInterface_Proxy
);
582 VTBL_PROXY_TEST(0, 1, IUnknown_AddRef_Proxy
);
583 VTBL_PROXY_TEST(0, 2, IUnknown_Release_Proxy
);
584 VTBL_PROXY_TEST(0, 3, if1_fn1_Proxy
);
585 VTBL_PROXY_TEST(0, 4, if1_fn2_Proxy
);
587 VTBL_PROXY_TEST(1, 0, GetProcAddress(rpcrt4
,"IUnknown_QueryInterface_Proxy"));
588 VTBL_PROXY_TEST(1, 1, GetProcAddress(rpcrt4
,"IUnknown_AddRef_Proxy"));
589 VTBL_PROXY_TEST(1, 2, GetProcAddress(rpcrt4
,"IUnknown_Release_Proxy"));
590 VTBL_PROXY_TEST_NOT_ZERO(1, 3);
591 VTBL_PROXY_TEST_NOT_ZERO(1, 4);
592 VTBL_PROXY_TEST_NOT_ZERO(1, 5);
593 VTBL_PROXY_TEST_NOT_ZERO(1, 6);
594 VTBL_PROXY_TEST_NOT_ZERO(1, 7);
595 VTBL_PROXY_TEST_NOT_ZERO(1, 8);
596 VTBL_PROXY_TEST_NOT_ZERO(1, 9);
597 VTBL_PROXY_TEST_NOT_ZERO(1, 10);
598 VTBL_PROXY_TEST_NOT_ZERO(1, 11);
599 VTBL_PROXY_TEST_NOT_ZERO(1, 12);
601 VTBL_PROXY_TEST(2, 0, IUnknown_QueryInterface_Proxy
);
602 VTBL_PROXY_TEST(2, 1, IUnknown_AddRef_Proxy
);
603 VTBL_PROXY_TEST(2, 2, IUnknown_Release_Proxy
);
604 VTBL_PROXY_TEST(2, 3, if1_fn1_Proxy
);
605 todo_wine
VTBL_PROXY_TEST_NOT_ZERO(2, 4);
607 VTBL_PROXY_TEST(3, 0, GetProcAddress(rpcrt4
,"IUnknown_QueryInterface_Proxy"));
608 VTBL_PROXY_TEST(3, 1, GetProcAddress(rpcrt4
,"IUnknown_AddRef_Proxy"));
609 VTBL_PROXY_TEST(3, 2, GetProcAddress(rpcrt4
,"IUnknown_Release_Proxy"));
610 VTBL_PROXY_TEST_NOT_ZERO(3, 3);
611 VTBL_PROXY_TEST_NOT_ZERO(3, 4);
612 VTBL_PROXY_TEST_NOT_ZERO(3, 5);
613 VTBL_PROXY_TEST_NOT_ZERO(3, 6);
615 #undef VTBL_TEST_NOT_CHANGE_TO
616 #undef VTBL_TEST_CHANGE_TO
617 #undef VTBL_TEST_ZERO
618 #undef VTBL_PROXY_TEST
619 #undef VTBL_PROXY_TEST_NOT_ZERO
621 for (i
= 0; i
< ARRAY_SIZE(interfaces
); i
++)
622 ok( proxy_vtbl
[i
]->header
.piid
== interfaces
[i
],
623 "wrong proxy %u iid %p/%p\n", i
, proxy_vtbl
[i
]->header
.piid
, interfaces
[i
] );
625 ok(PSFactoryBuffer
.RefCount
== 1, "ref count %ld\n", PSFactoryBuffer
.RefCount
);
626 IPSFactoryBuffer_Release(ppsf
);
628 /* One can also search by IID */
629 r
= NdrDllGetClassObject(&IID_if3
, &IID_IPSFactoryBuffer
, (void**)&ppsf
, proxy_file_list
,
630 &CLSID_psfact
, &PSFactoryBuffer
);
631 ok(r
== S_OK
, "ret %08lx\n", r
);
632 ok(ppsf
!= NULL
, "ppsf == NULL\n");
633 IPSFactoryBuffer_Release(ppsf
);
635 r
= NdrDllGetClassObject(&IID_if3
, &IID_IPSFactoryBuffer
, (void**)&ppsf
, proxy_file_list
,
636 NULL
, &PSFactoryBuffer
);
637 ok(r
== S_OK
, "ret %08lx\n", r
);
638 ok(ppsf
!= NULL
, "ppsf == NULL\n");
639 IPSFactoryBuffer_Release(ppsf
);
641 /* but only if the PS factory implements it */
642 r
= NdrDllGetClassObject(&IID_IDispatch
, &IID_IPSFactoryBuffer
, (void**)&ppsf
, proxy_file_list
,
643 &CLSID_psfact
, &PSFactoryBuffer
);
644 ok(r
== CLASS_E_CLASSNOTAVAILABLE
, "ret %08lx\n", r
);
646 /* Create it again to return */
647 r
= NdrDllGetClassObject(&CLSID_psfact
, &IID_IPSFactoryBuffer
, (void**)&ppsf
, proxy_file_list
,
648 &CLSID_psfact
, &PSFactoryBuffer
);
649 ok(r
== S_OK
, "ret %08lx\n", r
);
650 ok(ppsf
!= NULL
, "ppsf == NULL\n");
652 /* Because this PS factory is not loaded as a dll in the normal way, Windows 8 / 10
653 get confused and will crash when one of the proxies for the delegated ifaces is created.
654 Registering the ifaces fixes this (in fact calling CoRegisterPSClsid() with any IID / CLSID is enough). */
656 r
= CoRegisterPSClsid(&IID_if1
, &CLSID_psfact
);
657 ok(r
== S_OK
, "ret %08lx\n", r
);
658 r
= CoRegisterPSClsid(&IID_if2
, &CLSID_psfact
);
659 ok(r
== S_OK
, "ret %08lx\n", r
);
660 r
= CoRegisterPSClsid(&IID_if3
, &CLSID_psfact
);
661 ok(r
== S_OK
, "ret %08lx\n", r
);
662 r
= CoRegisterPSClsid(&IID_if4
, &CLSID_psfact
);
663 ok(r
== S_OK
, "ret %08lx\n", r
);
668 static int base_buffer_invoke_called
;
669 static HRESULT WINAPI
base_buffer_Invoke(IRpcStubBuffer
*This
, RPCOLEMESSAGE
*msg
, IRpcChannelBuffer
*channel
)
671 base_buffer_invoke_called
++;
672 ok(msg
== (RPCOLEMESSAGE
*)0xcafebabe, "msg ptr changed\n");
673 ok(channel
== (IRpcChannelBuffer
*)0xdeadbeef, "channel ptr changed\n");
674 return S_OK
; /* returning any failure here results in an exception */
677 static IRpcStubBufferVtbl base_buffer_vtbl
= {
690 static void test_NdrStubForwardingFunction(void)
694 IRpcChannelBuffer
*channel
= (IRpcChannelBuffer
*)0xdeadbeef;
695 RPC_MESSAGE
*msg
= (RPC_MESSAGE
*)0xcafebabe;
696 DWORD
*phase
= (DWORD
*)0x12345678;
697 IRpcStubBufferVtbl
*base_buffer_vtbl_ptr
= &base_buffer_vtbl
;
698 IRpcStubBuffer
*base_stub_buffer
= (IRpcStubBuffer
*)&base_buffer_vtbl_ptr
;
700 memset(This
, 0xcc, sizeof(This
));
701 This
[0] = base_stub_buffer
;
702 real_this
= &This
[1];
704 NdrStubForwardingFunction( real_this
, channel
, msg
, phase
);
705 ok(base_buffer_invoke_called
== 1, "base_buffer_invoke called %d times\n", base_buffer_invoke_called
);
709 static IRpcStubBuffer
*create_stub(IPSFactoryBuffer
*ppsf
, REFIID iid
, IUnknown
*obj
, HRESULT expected_result
)
711 IRpcStubBuffer
*pstub
= NULL
;
714 r
= IPSFactoryBuffer_CreateStub(ppsf
, iid
, obj
, &pstub
);
715 ok(r
== expected_result
, "CreateStub returned %08lx expected %08lx\n", r
, expected_result
);
719 static HRESULT WINAPI
create_stub_test_QI(IUnknown
*This
, REFIID iid
, void **ppv
)
721 ok(IsEqualIID(iid
, &IID_if1
), "incorrect iid\n");
722 *ppv
= (void*)0xdeadbeef;
726 static IUnknownVtbl create_stub_test_vtbl
=
733 static HRESULT WINAPI
create_stub_test_fail_QI(IUnknown
*This
, REFIID iid
, void **ppv
)
735 ok(IsEqualIID(iid
, &IID_if1
), "incorrect iid\n");
737 return E_NOINTERFACE
;
740 static IUnknownVtbl create_stub_test_fail_vtbl
=
742 create_stub_test_fail_QI
,
749 IUnknown IUnknown_iface
;
753 static inline struct dummy_unknown
*impl_from_IUnknown(IUnknown
*iface
)
755 return CONTAINING_RECORD(iface
, struct dummy_unknown
, IUnknown_iface
);
758 static HRESULT WINAPI
dummy_QueryInterface(IUnknown
*This
, REFIID iid
, void **ppv
)
761 return E_NOINTERFACE
;
764 static ULONG WINAPI
dummy_AddRef(LPUNKNOWN iface
)
766 struct dummy_unknown
*this = impl_from_IUnknown(iface
);
767 return InterlockedIncrement( &this->ref
);
770 static ULONG WINAPI
dummy_Release(LPUNKNOWN iface
)
772 struct dummy_unknown
*this = impl_from_IUnknown(iface
);
773 return InterlockedDecrement( &this->ref
);
776 static IUnknownVtbl dummy_unknown_vtbl
=
778 dummy_QueryInterface
,
782 static struct dummy_unknown dummy_unknown
= { { &dummy_unknown_vtbl
}, 0 };
784 static void create_proxy_test( IPSFactoryBuffer
*ppsf
, REFIID iid
, const void *expected_vtbl
)
786 IRpcProxyBuffer
*proxy
= NULL
;
787 IUnknown
*iface
= NULL
;
791 r
= IPSFactoryBuffer_CreateProxy(ppsf
, NULL
, iid
, &proxy
, (void **)&iface
);
792 ok( r
== S_OK
, "IPSFactoryBuffer_CreateProxy failed %lx\n", r
);
793 ok( *(void **)iface
== expected_vtbl
, "wrong iface pointer %p/%p\n", *(void **)iface
, expected_vtbl
);
794 count
= IUnknown_Release( iface
);
795 ok( count
== 1, "wrong refcount %lu\n", count
);
796 count
= IRpcProxyBuffer_Release( proxy
);
797 ok( count
== 0, "wrong refcount %lu\n", count
);
799 dummy_unknown
.ref
= 4;
800 r
= IPSFactoryBuffer_CreateProxy(ppsf
, &dummy_unknown
.IUnknown_iface
, iid
, &proxy
,
802 ok( r
== S_OK
, "IPSFactoryBuffer_CreateProxy failed %lx\n", r
);
803 ok( dummy_unknown
.ref
== 5, "wrong refcount %lu\n", dummy_unknown
.ref
);
804 ok( *(void **)iface
== expected_vtbl
, "wrong iface pointer %p/%p\n", *(void **)iface
, expected_vtbl
);
805 count
= IUnknown_Release( iface
);
806 ok( count
== 4, "wrong refcount %lu\n", count
);
807 ok( dummy_unknown
.ref
== 4, "wrong refcount %lu\n", dummy_unknown
.ref
);
808 count
= IRpcProxyBuffer_Release( proxy
);
809 ok( count
== 0, "wrong refcount %lu\n", count
);
810 ok( dummy_unknown
.ref
== 4, "wrong refcount %lu\n", dummy_unknown
.ref
);
813 static void test_CreateProxy( IPSFactoryBuffer
*ppsf
)
815 create_proxy_test( ppsf
, &IID_if1
, if1_proxy_vtbl
.Vtbl
);
816 create_proxy_test( ppsf
, &IID_if2
, if2_proxy_vtbl
.Vtbl
);
817 create_proxy_test( ppsf
, &IID_if3
, if3_proxy_vtbl
.Vtbl
);
818 create_proxy_test( ppsf
, &IID_if4
, if4_proxy_vtbl
.Vtbl
);
821 static void test_CreateStub(IPSFactoryBuffer
*ppsf
)
823 IUnknownVtbl
*vtbl
= &create_stub_test_vtbl
;
824 IUnknown
*obj
= (IUnknown
*)&vtbl
;
825 IRpcStubBuffer
*pstub
= create_stub(ppsf
, &IID_if1
, obj
, S_OK
);
826 CStdStubBuffer
*cstd_stub
= (CStdStubBuffer
*)pstub
;
827 const CInterfaceStubHeader
*header
= &CONTAINING_RECORD(cstd_stub
->lpVtbl
, const CInterfaceStubVtbl
, Vtbl
)->header
;
829 ok(IsEqualIID(header
->piid
, &IID_if1
), "header iid differs\n");
830 ok(cstd_stub
->RefCount
== 1, "ref count %ld\n", cstd_stub
->RefCount
);
831 /* 0xdeadbeef returned from create_stub_test_QI */
832 ok(cstd_stub
->pvServerObject
== (void*)0xdeadbeef, "pvServerObject %p\n", cstd_stub
->pvServerObject
);
833 ok(cstd_stub
->pPSFactory
!= NULL
, "pPSFactory was NULL\n");
834 cstd_stub
->pvServerObject
= NULL
;
835 IRpcStubBuffer_Release(pstub
);
837 vtbl
= &create_stub_test_fail_vtbl
;
838 pstub
= create_stub(ppsf
, &IID_if1
, obj
, E_NOINTERFACE
);
839 ok(pstub
== S_OK
, "create_stub failed: %lu\n", GetLastError());
843 static HRESULT WINAPI
connect_test_orig_QI(IUnknown
*This
, REFIID iid
, void **ppv
)
845 ok(IsEqualIID(iid
, &IID_if1
) ||
846 IsEqualIID(iid
, &IID_if2
), "incorrect iid\n");
851 static int connect_test_orig_release_called
;
852 static ULONG WINAPI
connect_test_orig_release(IUnknown
*This
)
854 connect_test_orig_release_called
++;
858 static IUnknownVtbl connect_test_orig_vtbl
=
860 connect_test_orig_QI
,
862 connect_test_orig_release
865 static HRESULT WINAPI
connect_test_new_QI(IUnknown
*This
, REFIID iid
, void **ppv
)
867 ok(IsEqualIID(iid
, &IID_if1
) ||
868 IsEqualIID(iid
, &IID_if2
), "incorrect iid\n");
869 *ppv
= (void*)0xcafebabe;
873 static IUnknownVtbl connect_test_new_vtbl
=
880 static HRESULT WINAPI
connect_test_new_fail_QI(IUnknown
*This
, REFIID iid
, void **ppv
)
882 ok(IsEqualIID(iid
, &IID_if1
), "incorrect iid\n");
883 *ppv
= (void*)0xdeadbeef;
884 return E_NOINTERFACE
;
887 static IUnknownVtbl connect_test_new_fail_vtbl
=
889 connect_test_new_fail_QI
,
894 static int connect_test_base_Connect_called
;
895 static HRESULT WINAPI
connect_test_base_Connect(IRpcStubBuffer
*pstub
, IUnknown
*obj
)
897 connect_test_base_Connect_called
++;
898 ok(*(void**)obj
== (void*)0xbeefcafe, "unexpected obj %p\n", obj
);
902 static IRpcStubBufferVtbl connect_test_base_stub_buffer_vtbl
=
907 connect_test_base_Connect
,
916 static void test_Connect(IPSFactoryBuffer
*ppsf
)
918 IUnknownVtbl
*orig_vtbl
= &connect_test_orig_vtbl
;
919 IUnknownVtbl
*new_vtbl
= &connect_test_new_vtbl
;
920 IUnknownVtbl
*new_fail_vtbl
= &connect_test_new_fail_vtbl
;
921 IUnknown
*obj
= (IUnknown
*)&orig_vtbl
;
922 IRpcStubBuffer
*pstub
= create_stub(ppsf
, &IID_if1
, obj
, S_OK
);
923 CStdStubBuffer
*cstd_stub
= (CStdStubBuffer
*)pstub
;
924 IRpcStubBufferVtbl
*base_stub_buf_vtbl
= &connect_test_base_stub_buffer_vtbl
;
927 obj
= (IUnknown
*)&new_vtbl
;
928 r
= IRpcStubBuffer_Connect(pstub
, obj
);
929 ok(r
== S_OK
, "r %08lx\n", r
);
930 ok(connect_test_orig_release_called
== 1, "release called %d\n", connect_test_orig_release_called
);
931 ok(cstd_stub
->pvServerObject
== (void*)0xcafebabe, "pvServerObject %p\n", cstd_stub
->pvServerObject
);
933 cstd_stub
->pvServerObject
= (IUnknown
*)&orig_vtbl
;
934 obj
= (IUnknown
*)&new_fail_vtbl
;
935 r
= IRpcStubBuffer_Connect(pstub
, obj
);
936 ok(r
== E_NOINTERFACE
, "r %08lx\n", r
);
937 ok(cstd_stub
->pvServerObject
== (void*)0xdeadbeef, "pvServerObject %p\n", cstd_stub
->pvServerObject
);
938 ok(connect_test_orig_release_called
== 2, "release called %d\n", connect_test_orig_release_called
);
940 /* Now use a delegated stub.
942 We know from the NdrStubForwardFunction test that
943 (void**)pstub-1 is the base interface stub buffer. This shows
944 that (void**)pstub-2 contains the address of a vtable that gets
945 passed to the base interface's Connect method. Note that
946 (void**)pstub-2 itself gets passed to Connect and not
947 *((void**)pstub-2), so it should contain the vtable ptr and not
950 obj
= (IUnknown
*)&orig_vtbl
;
951 pstub
= create_stub(ppsf
, &IID_if2
, obj
, S_OK
);
952 *((void**)pstub
-1) = &base_stub_buf_vtbl
;
953 *((void**)pstub
-2) = (void*)0xbeefcafe;
955 obj
= (IUnknown
*)&new_vtbl
;
956 r
= IRpcStubBuffer_Connect(pstub
, obj
);
957 ok(r
== S_OK
, "r %08lx\n", r
);
958 ok(connect_test_base_Connect_called
== 1, "connect_test_bsae_Connect called %d times\n",
959 connect_test_base_Connect_called
);
960 ok(connect_test_orig_release_called
== 3, "release called %d\n", connect_test_orig_release_called
);
961 cstd_stub
= (CStdStubBuffer
*)pstub
;
962 ok(cstd_stub
->pvServerObject
== (void*)0xcafebabe, "pvServerObject %p\n", cstd_stub
->pvServerObject
);
965 static void test_Disconnect(IPSFactoryBuffer
*ppsf
)
967 IUnknownVtbl
*orig_vtbl
= &connect_test_orig_vtbl
;
968 IUnknown
*obj
= (IUnknown
*)&orig_vtbl
;
969 IRpcStubBuffer
*pstub
= create_stub(ppsf
, &IID_if1
, obj
, S_OK
);
970 CStdStubBuffer
*cstd_stub
= (CStdStubBuffer
*)pstub
;
972 connect_test_orig_release_called
= 0;
973 IRpcStubBuffer_Disconnect(pstub
);
974 ok(connect_test_orig_release_called
== 1, "release called %d\n", connect_test_orig_release_called
);
975 ok(cstd_stub
->pvServerObject
== NULL
, "pvServerObject %p\n", cstd_stub
->pvServerObject
);
976 IRpcStubBuffer_Release(pstub
);
980 static int release_test_psfacbuf_release_called
;
981 static ULONG WINAPI
release_test_pretend_psfacbuf_release(IUnknown
*pUnk
)
983 release_test_psfacbuf_release_called
++;
987 static IUnknownVtbl release_test_pretend_psfacbuf_vtbl
=
991 release_test_pretend_psfacbuf_release
994 static void test_Release(IPSFactoryBuffer
*ppsf
)
997 IUnknownVtbl
*orig_vtbl
= &connect_test_orig_vtbl
;
998 IUnknown
*obj
= (IUnknown
*)&orig_vtbl
;
999 IUnknownVtbl
*pretend_psfacbuf_vtbl
= &release_test_pretend_psfacbuf_vtbl
;
1000 IUnknown
*pretend_psfacbuf
= (IUnknown
*)&pretend_psfacbuf_vtbl
;
1001 IRpcStubBuffer
*pstub
= create_stub(ppsf
, &IID_if1
, obj
, S_OK
);
1002 CStdStubBuffer
*cstd_stub
= (CStdStubBuffer
*)pstub
;
1004 facbuf_refs
= PSFactoryBuffer
.RefCount
;
1006 /* This shows that NdrCStdStubBuffer_Release doesn't call Disconnect */
1007 ok(cstd_stub
->RefCount
== 1, "ref count %ld\n", cstd_stub
->RefCount
);
1008 connect_test_orig_release_called
= 0;
1009 IRpcStubBuffer_Release(pstub
);
1011 ok(connect_test_orig_release_called
== 0, "release called %d\n", connect_test_orig_release_called
);
1013 ok(PSFactoryBuffer
.RefCount
== facbuf_refs
- 1, "factory buffer refs %ld orig %ld\n", PSFactoryBuffer
.RefCount
, facbuf_refs
);
1015 /* This shows that NdrCStdStubBuffer_Release calls Release on its 2nd arg, rather than on This->pPSFactory
1016 (which are usually the same and indeed it's odd that _Release requires this 2nd arg). */
1017 pstub
= create_stub(ppsf
, &IID_if1
, obj
, S_OK
);
1018 ok(PSFactoryBuffer
.RefCount
== facbuf_refs
, "factory buffer refs %ld orig %ld\n", PSFactoryBuffer
.RefCount
, facbuf_refs
);
1019 NdrCStdStubBuffer_Release(pstub
, (IPSFactoryBuffer
*)pretend_psfacbuf
);
1020 ok(release_test_psfacbuf_release_called
== 1, "pretend_psfacbuf_release called %d\n", release_test_psfacbuf_release_called
);
1021 ok(PSFactoryBuffer
.RefCount
== facbuf_refs
, "factory buffer refs %ld orig %ld\n", PSFactoryBuffer
.RefCount
, facbuf_refs
);
1024 static HRESULT WINAPI
delegating_invoke_test_QI(ITypeLib
*pUnk
, REFIID iid
, void** ppv
)
1031 static ULONG WINAPI
delegating_invoke_test_addref(ITypeLib
*pUnk
)
1036 static ULONG WINAPI
delegating_invoke_test_release(ITypeLib
*pUnk
)
1041 static UINT WINAPI
delegating_invoke_test_get_type_info_count(ITypeLib
*pUnk
)
1046 static ITypeLibVtbl delegating_invoke_test_obj_vtbl
=
1048 delegating_invoke_test_QI
,
1049 delegating_invoke_test_addref
,
1050 delegating_invoke_test_release
,
1051 delegating_invoke_test_get_type_info_count
,
1063 static HRESULT WINAPI
delegating_invoke_chan_query_interface(IRpcChannelBuffer
*pchan
,
1067 ok(0, "call to QueryInterface not expected\n");
1068 return E_NOINTERFACE
;
1071 static ULONG WINAPI
delegating_invoke_chan_add_ref(IRpcChannelBuffer
*pchan
)
1076 static ULONG WINAPI
delegating_invoke_chan_release(IRpcChannelBuffer
*pchan
)
1081 static HRESULT WINAPI
delegating_invoke_chan_get_buffer(IRpcChannelBuffer
*pchan
,
1085 msg
->Buffer
= HeapAlloc(GetProcessHeap(), 0, msg
->cbBuffer
);
1089 static HRESULT WINAPI
delegating_invoke_chan_send_receive(IRpcChannelBuffer
*pchan
,
1090 RPCOLEMESSAGE
*pMessage
,
1093 ok(0, "call to SendReceive not expected\n");
1097 static HRESULT WINAPI
delegating_invoke_chan_free_buffer(IRpcChannelBuffer
*pchan
,
1098 RPCOLEMESSAGE
*pMessage
)
1100 ok(0, "call to FreeBuffer not expected\n");
1104 static HRESULT WINAPI
delegating_invoke_chan_get_dest_ctx(IRpcChannelBuffer
*pchan
,
1105 DWORD
*pdwDestContext
,
1106 void **ppvDestContext
)
1108 *pdwDestContext
= MSHCTX_LOCAL
;
1109 *ppvDestContext
= NULL
;
1113 static HRESULT WINAPI
delegating_invoke_chan_is_connected(IRpcChannelBuffer
*pchan
)
1115 ok(0, "call to IsConnected not expected\n");
1119 static IRpcChannelBufferVtbl delegating_invoke_test_rpc_chan_vtbl
=
1121 delegating_invoke_chan_query_interface
,
1122 delegating_invoke_chan_add_ref
,
1123 delegating_invoke_chan_release
,
1124 delegating_invoke_chan_get_buffer
,
1125 delegating_invoke_chan_send_receive
,
1126 delegating_invoke_chan_free_buffer
,
1127 delegating_invoke_chan_get_dest_ctx
,
1128 delegating_invoke_chan_is_connected
1131 static void test_delegating_Invoke(IPSFactoryBuffer
*ppsf
)
1133 ITypeLibVtbl
*obj_vtbl
= &delegating_invoke_test_obj_vtbl
;
1134 IUnknown
*obj
= (IUnknown
*)&obj_vtbl
;
1135 IRpcStubBuffer
*pstub
= create_stub(ppsf
, &IID_if2
, obj
, S_OK
);
1136 IRpcChannelBufferVtbl
*pchan_vtbl
= &delegating_invoke_test_rpc_chan_vtbl
;
1137 IRpcChannelBuffer
*pchan
= (IRpcChannelBuffer
*)&pchan_vtbl
;
1141 memset(&msg
, 0, sizeof(msg
));
1142 msg
.dataRepresentation
= NDR_LOCAL_DATA_REPRESENTATION
;
1144 r
= IRpcStubBuffer_Invoke(pstub
, &msg
, pchan
);
1145 ok(r
== S_OK
, "ret %08lx\n", r
);
1148 ok(*(DWORD
*)msg
.Buffer
== 0xabcdef, "buf[0] %08lx\n", *(DWORD
*)msg
.Buffer
);
1149 ok(*((DWORD
*)msg
.Buffer
+ 1) == S_OK
, "buf[1] %08lx\n", *((DWORD
*)msg
.Buffer
+ 1));
1151 /* free the buffer allocated by delegating_invoke_chan_get_buffer */
1152 HeapFree(GetProcessHeap(), 0, msg
.Buffer
);
1153 IRpcStubBuffer_Release(pstub
);
1155 static const CInterfaceProxyVtbl
*cstub_ProxyVtblList2
[] =
1160 static const CInterfaceStubVtbl
*cstub_StubVtblList2
[] =
1165 static PCInterfaceName
const if_name_list2
[] =
1170 static const IID
*base_iid_list2
[] =
1175 static const ExtendedProxyFileInfo my_proxy_file_info2
=
1177 (const PCInterfaceProxyVtblList
*) &cstub_ProxyVtblList2
,
1178 (const PCInterfaceStubVtblList
*) &cstub_StubVtblList2
,
1179 (const PCInterfaceName
*) &if_name_list2
,
1180 (const IID
**) &base_iid_list2
,
1190 static const ProxyFileInfo
*proxy_file_list2
[] = {
1191 &my_proxy_file_info2
,
1195 static void test_NdrDllRegisterProxy( void )
1198 const ExtendedProxyFileInfo
*pf
;
1199 HMODULE hmod
= GetModuleHandleA(NULL
);
1202 res
= NdrDllRegisterProxy(NULL
, NULL
, NULL
);
1203 ok(res
== E_HANDLE
, "Incorrect return code %lx\n",res
);
1205 res
= NdrDllRegisterProxy(hmod
, &pf
, NULL
);
1206 ok(res
== E_NOINTERFACE
, "Incorrect return code %lx\n",res
);
1207 res
= NdrDllRegisterProxy(hmod
, proxy_file_list2
, NULL
);
1208 ok(res
== E_NOINTERFACE
, "Incorrect return code %lx\n",res
);
1209 /* This fails on Vista and Windows 7 due to permissions */
1210 res
= NdrDllRegisterProxy(hmod
, proxy_file_list
, NULL
);
1211 ok(res
== S_OK
|| res
== E_ACCESSDENIED
, "NdrDllRegisterProxy failed %lx\n",res
);
1214 res
= NdrDllUnregisterProxy(hmod
,proxy_file_list
, NULL
);
1215 ok(res
== S_OK
, "NdrDllUnregisterProxy failed %lx\n",res
);
1219 static HANDLE
create_process(const char *arg
)
1221 PROCESS_INFORMATION pi
;
1222 STARTUPINFOA si
= {0};
1228 winetest_get_mainargs(&argv
);
1229 sprintf(cmdline
, "\"%s\" %s %s", argv
[0], argv
[1], arg
);
1230 ret
= CreateProcessA(argv
[0], cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
1231 ok(ret
, "CreateProcess failed: %lu\n", GetLastError());
1232 CloseHandle(pi
.hThread
);
1236 DEFINE_GUID(CLSID_test1
,0xdeadf00d,0x0001,0x44c7,0x85,0x0f,0x2a,0x0f,0x46,0x5c,0x0c,0x6c);
1238 static HRESULT WINAPI
test1_QueryInterface(ITest1
*iface
, REFIID iid
, void **out
)
1240 if (winetest_debug
> 1) trace("%s\n", wine_dbgstr_guid(iid
));
1241 if (IsEqualGUID(iid
, &IID_IUnknown
) || IsEqualGUID(iid
, &IID_ITest1
))
1247 return E_NOINTERFACE
;
1250 static ULONG WINAPI
test1_AddRef(ITest1
*iface
)
1255 static ULONG WINAPI
test1_Release(ITest1
*iface
)
1260 static HRESULT WINAPI
test1_GetClassID(ITest1
*iface
, CLSID
*clsid
)
1262 *clsid
= CLSID_test1
;
1266 static int WINAPI
test1_square(ITest1
*iface
, int x
)
1271 static const ITest1Vtbl test1_vtbl
=
1273 test1_QueryInterface
,
1280 static HRESULT WINAPI
test_cf_QueryInterface(IClassFactory
*iface
, REFIID iid
, void **out
)
1282 if (IsEqualGUID(iid
, &IID_IUnknown
) || IsEqualGUID(iid
, &IID_IClassFactory
))
1288 return E_NOINTERFACE
;
1291 static ULONG WINAPI
test_cf_AddRef(IClassFactory
*iface
)
1296 static ULONG WINAPI
test_cf_Release(IClassFactory
*iface
)
1301 static HRESULT WINAPI
test_cf_CreateInstance(IClassFactory
*iface
, IUnknown
*outer
, REFIID iid
, void **out
)
1303 ITest1
*obj
= heap_alloc(sizeof(*obj
));
1305 obj
->lpVtbl
= &test1_vtbl
;
1307 return ITest1_QueryInterface(obj
, iid
, out
);
1310 static HRESULT WINAPI
test_cf_LockServer(IClassFactory
*iface
, BOOL lock
)
1315 static const IClassFactoryVtbl test_cf_vtbl
=
1317 test_cf_QueryInterface
,
1320 test_cf_CreateInstance
,
1324 static IClassFactory test_cf
= { &test_cf_vtbl
};
1326 extern CStdPSFactoryBuffer gPFactory
;
1327 extern const ProxyFileInfo
* aProxyFileList
;
1329 static void local_server_proc(void)
1331 DWORD obj_cookie
, ps_cookie
, index
;
1332 HANDLE stop_event
, ready_event
;
1333 IPSFactoryBuffer
*ps
;
1336 stop_event
= OpenEventA(EVENT_ALL_ACCESS
, FALSE
, "wine_cstub_test_server_stop");
1337 ready_event
= OpenEventA(EVENT_ALL_ACCESS
, FALSE
, "wine_cstub_test_server_ready");
1341 hr
= CoRegisterClassObject(&CLSID_test1
, (IUnknown
*)&test_cf
,
1342 CLSCTX_LOCAL_SERVER
, REGCLS_MULTIPLEUSE
, &obj_cookie
);
1343 ok(hr
== S_OK
, "got %#lx\n", hr
);
1345 hr
= NdrDllGetClassObject(&CLSID_test_ps
, &IID_IPSFactoryBuffer
, (void **)&ps
,
1346 &aProxyFileList
, &CLSID_test_ps
, &gPFactory
);
1347 ok(hr
== S_OK
, "got %#lx\n", hr
);
1349 hr
= CoRegisterClassObject(&CLSID_test_ps
, (IUnknown
*)ps
,
1350 CLSCTX_INPROC_SERVER
, REGCLS_MULTIPLEUSE
, &ps_cookie
);
1351 ok(hr
== S_OK
, "got %#lx\n", hr
);
1353 hr
= CoRegisterPSClsid(&IID_ITest1
, &CLSID_test_ps
);
1354 ok(hr
== S_OK
, "got %#lx\n", hr
);
1356 SetEvent(ready_event
);
1358 hr
= CoWaitForMultipleHandles(0, 1000, 1, &stop_event
, &index
);
1359 ok(hr
== S_OK
, "got %#lx\n", hr
);
1360 ok(!index
, "got %lu\n", index
);
1362 hr
= CoRevokeClassObject(ps_cookie
);
1363 ok(hr
== S_OK
, "got %#lx\n", hr
);
1365 hr
= CoRevokeClassObject(obj_cookie
);
1366 ok(hr
== S_OK
, "got %#lx\n", hr
);
1372 static void test_delegated_methods(void)
1374 HANDLE process
, stop_event
, ready_event
;
1375 IPSFactoryBuffer
*ps
;
1382 stop_event
= CreateEventA(NULL
, TRUE
, FALSE
, "wine_cstub_test_server_stop");
1383 ready_event
= CreateEventA(NULL
, TRUE
, FALSE
, "wine_cstub_test_server_ready");
1385 process
= create_process("server");
1386 ok(!WaitForSingleObject(ready_event
, 5000), "wait failed\n");
1388 hr
= NdrDllGetClassObject(&CLSID_test_ps
, &IID_IPSFactoryBuffer
, (void **)&ps
,
1389 &aProxyFileList
, &CLSID_test_ps
, &gPFactory
);
1390 ok(hr
== S_OK
, "got %#lx\n", hr
);
1392 hr
= CoRegisterClassObject(&CLSID_test_ps
, (IUnknown
*)ps
,
1393 CLSCTX_INPROC_SERVER
, REGCLS_MULTIPLEUSE
, &ps_cookie
);
1394 ok(hr
== S_OK
, "got %#lx\n", hr
);
1396 hr
= CoRegisterPSClsid(&IID_ITest1
, &CLSID_test_ps
);
1397 ok(hr
== S_OK
, "got %#lx\n", hr
);
1399 hr
= CoCreateInstance(&CLSID_test1
, NULL
, CLSCTX_LOCAL_SERVER
, &IID_ITest1
, (void **)&test_obj
);
1400 ok(hr
== S_OK
, "got %#lx\n", hr
);
1402 ret
= ITest1_square(test_obj
, 3);
1403 ok(ret
== 9, "got %d\n", ret
);
1405 hr
= ITest1_GetClassID(test_obj
, &clsid
);
1406 ok(hr
== S_OK
, "got %#lx\n", hr
);
1407 ok(IsEqualGUID(&clsid
, &CLSID_test1
), "got %s\n", wine_dbgstr_guid(&clsid
));
1409 ITest1_Release(test_obj
);
1411 SetEvent(stop_event
);
1412 ok(!WaitForSingleObject(process
, 1000), "wait failed\n");
1414 hr
= CoRevokeClassObject(ps_cookie
);
1415 ok(hr
== S_OK
, "got %#lx\n", hr
);
1418 typedef struct tagChannelBufferRefCount
1420 IRpcChannelBuffer IRpcChannelBuffer_iface
;
1422 } CChannelBufferRefCount
;
1424 static CChannelBufferRefCount
* impl_from_IRpcChannelBuffer(IRpcChannelBuffer
* iface
)
1426 return CONTAINING_RECORD(iface
, CChannelBufferRefCount
, IRpcChannelBuffer_iface
);
1429 static HRESULT WINAPI
test_chanbuf_refcount_chan_query_interface(IRpcChannelBuffer
* pchan
,
1433 if (IsEqualGUID(&IID_IRpcChannelBuffer
, iid
))
1436 IRpcChannelBuffer_AddRef(pchan
);
1439 return E_NOINTERFACE
;
1442 static ULONG WINAPI
test_chanbuf_refcount_chan_add_ref(IRpcChannelBuffer
* pchan
)
1444 CChannelBufferRefCount
* This
= impl_from_IRpcChannelBuffer(pchan
);
1445 return InterlockedIncrement(&This
->RefCount
);
1448 static ULONG WINAPI
test_chanbuf_refcount_chan_release(IRpcChannelBuffer
* pchan
)
1450 CChannelBufferRefCount
* This
= impl_from_IRpcChannelBuffer(pchan
);
1451 return InterlockedDecrement(&This
->RefCount
);
1454 static HRESULT WINAPI
test_chanbuf_refcount_chan_get_buffer(IRpcChannelBuffer
* pchan
,
1458 ok(0, "call to GetBuffer not expected\n");
1462 static HRESULT WINAPI
test_chanbuf_refcount_chan_send_receive(IRpcChannelBuffer
* pchan
,
1463 RPCOLEMESSAGE
* pMessage
,
1466 ok(0, "call to SendReceive not expected\n");
1470 static HRESULT WINAPI
test_chanbuf_refcount_chan_free_buffer(IRpcChannelBuffer
* pchan
,
1471 RPCOLEMESSAGE
* pMessage
)
1473 ok(0, "call to FreeBuffer not expected\n");
1477 static HRESULT WINAPI
test_chanbuf_refcount_chan_get_dest_ctx(IRpcChannelBuffer
* pchan
,
1478 DWORD
* pdwDestContext
,
1479 void** ppvDestContext
)
1481 *pdwDestContext
= MSHCTX_LOCAL
;
1482 *ppvDestContext
= NULL
;
1486 static HRESULT WINAPI
test_chanbuf_refcount_chan_is_connected(IRpcChannelBuffer
* pchan
)
1488 ok(0, "call to IsConnected not expected\n");
1492 static IRpcChannelBufferVtbl test_chanbuf_refcount_test_rpc_chan_vtbl
=
1494 test_chanbuf_refcount_chan_query_interface
,
1495 test_chanbuf_refcount_chan_add_ref
,
1496 test_chanbuf_refcount_chan_release
,
1497 test_chanbuf_refcount_chan_get_buffer
,
1498 test_chanbuf_refcount_chan_send_receive
,
1499 test_chanbuf_refcount_chan_free_buffer
,
1500 test_chanbuf_refcount_chan_get_dest_ctx
,
1501 test_chanbuf_refcount_chan_is_connected
1504 static void test_ChannelBufferRefCount(IPSFactoryBuffer
*ppsf
)
1506 IRpcProxyBuffer
* proxy_buffer
= NULL
;
1507 IUnknown
* proxy_if1
= NULL
;
1508 CChannelBufferRefCount test_chanbuf
= {{&test_chanbuf_refcount_test_rpc_chan_vtbl
}, 1};
1510 RPC_MESSAGE rpcMessage
= {0};
1511 MIDL_STUB_MESSAGE stubMessage
= {0};
1512 MIDL_STUB_DESC stubDesc
= {0};
1515 HRESULT hr
= IPSFactoryBuffer_CreateProxy(ppsf
, NULL
, &IID_if1
, &proxy_buffer
, (void**)&proxy_if1
);
1516 ok(hr
== S_OK
, "got %#lx\n", hr
);
1518 ok(test_chanbuf
.RefCount
== 1, "got %ld\n", test_chanbuf
.RefCount
);
1519 hr
= IRpcProxyBuffer_Connect(proxy_buffer
, &test_chanbuf
.IRpcChannelBuffer_iface
);
1520 ok(hr
== S_OK
, "got %#lx\n", hr
);
1521 /* proxy_buffer should have acquired its own refcount on test_chanbuf */
1522 ok(test_chanbuf
.RefCount
== 2, "got %ld\n", test_chanbuf
.RefCount
);
1524 /* which therefore survives releasing the initial one */
1525 refs
= IRpcChannelBuffer_Release(&test_chanbuf
.IRpcChannelBuffer_iface
);
1526 ok(refs
== 1, "got %ld\n", refs
);
1528 NdrProxyInitialize(proxy_if1
, &rpcMessage
, &stubMessage
, &stubDesc
, 0);
1529 /* stubMessage should add its own refcount on test_chanbuf */
1530 ok(test_chanbuf
.RefCount
== 2, "got %ld\n", test_chanbuf
.RefCount
);
1531 ok(stubMessage
.pRpcChannelBuffer
!= NULL
, "NULL pRocChannelBuffer\n");
1533 /* stubMessage doesn't add its own refcounts on proxy_if1 or proxy_buffer,
1534 * so it's possible these are freed out from under it.
1535 * E.g. an event sink might unadvise upon receiving the event it was waiting for;
1536 * this unadvise could be reentrant to Invoke because SendReceive pumps STA messages.
1537 * The source would then erase that connection point entry and Release the proxy. */
1538 IRpcProxyBuffer_Disconnect(proxy_buffer
);
1539 ok(test_chanbuf
.RefCount
== 1, "got %ld\n", test_chanbuf
.RefCount
);
1540 IRpcProxyBuffer_Release(proxy_buffer
);
1541 refs
= IUnknown_Release(proxy_if1
);
1542 ok(refs
== 0, "got %ld\n", refs
);
1543 ok(test_chanbuf
.RefCount
== 1, "got %ld\n", test_chanbuf
.RefCount
);
1545 /* NdrProxyFreeBuffer must not dereference the now-freed proxy_if1,
1546 * yet should still free the remaining reference on test_chanbuf */
1547 NdrProxyFreeBuffer(proxy_if1
, &stubMessage
);
1548 ok(test_chanbuf
.RefCount
== 0, "got %ld\n", test_chanbuf
.RefCount
);
1549 ok(!stubMessage
.pRpcChannelBuffer
, "dangling pRpcChannelBuffer = %p\n", stubMessage
.pRpcChannelBuffer
);
1554 IPSFactoryBuffer
*ppsf
;
1558 argc
= winetest_get_mainargs( &argv
);
1559 if (argc
> 2 && !strcmp(argv
[2], "server"))
1561 local_server_proc();
1565 OleInitialize(NULL
);
1567 ppsf
= test_NdrDllGetClassObject();
1568 test_NdrStubForwardingFunction();
1569 test_CreateProxy(ppsf
);
1570 test_CreateStub(ppsf
);
1572 test_Disconnect(ppsf
);
1574 test_delegating_Invoke(ppsf
);
1575 test_NdrDllRegisterProxy();
1576 test_delegated_methods();
1577 test_ChannelBufferRefCount(ppsf
);