push 43f03fe87c2254c6df67b2de3c08b5b20fd64327
[wine/hacks.git] / dlls / rpcrt4 / tests / cstub.c
blob69d5ea70e2e527ef7047f6903f72c57ba8273018
1 /*
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
21 #include <stdarg.h>
23 #define PROXY_DELEGATION
24 #define COBJMACROS
26 #include "wine/test.h"
27 #include <windef.h>
28 #include <winbase.h>
29 #include <winnt.h>
30 #include <winerror.h>
33 #include "initguid.h"
34 #include "rpc.h"
35 #include "rpcdce.h"
36 #include "rpcproxy.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)
53 my_alloc_called++;
54 return NdrOleAllocate(size);
57 static void CALLBACK my_free(void *ptr)
59 my_free_called++;
60 NdrOleFree(ptr);
63 typedef struct _MIDL_PROC_FORMAT_STRING
65 short Pad;
66 unsigned char Format[ 2 ];
67 } MIDL_PROC_FORMAT_STRING;
69 typedef struct _MIDL_TYPE_FORMAT_STRING
71 short Pad;
72 unsigned char Format[ 2 ];
73 } MIDL_TYPE_FORMAT_STRING;
76 static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =
80 0, 0
84 static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =
88 0, 0
92 static const MIDL_STUB_DESC Object_StubDesc =
94 NULL,
95 my_alloc,
96 my_free,
97 { 0 },
102 __MIDL_TypeFormatString.Format,
103 1, /* -error bounds_check flag */
104 0x20000, /* Ndr library version */
106 0x50100a4, /* MIDL Version 5.1.164 */
108 NULL,
109 0, /* notify & notify_flag routine table */
110 1, /* Flags */
111 0, /* Reserved3 */
112 0, /* Reserved4 */
113 0 /* Reserved5 */
116 static HRESULT WINAPI if1_fn1_Proxy(void *This)
118 return S_OK;
121 static void __RPC_STUB if1_fn1_Stub(
122 IRpcStubBuffer *This,
123 IRpcChannelBuffer *_pRpcChannelBuffer,
124 PRPC_MESSAGE _pRpcMessage,
125 DWORD *_pdwStubPhase)
127 trace("fn1 stub\n");
130 static HRESULT WINAPI if1_fn2_Proxy(void *This)
132 return S_OK;
135 static void __RPC_STUB if1_fn2_Stub(
136 IRpcStubBuffer *This,
137 IRpcChannelBuffer *_pRpcChannelBuffer,
138 PRPC_MESSAGE _pRpcMessage,
139 DWORD *_pdwStubPhase)
141 trace("fn2 stub\n");
144 static CINTERFACE_PROXY_VTABLE(5) if1_proxy_vtbl =
146 { &IID_if1 },
147 { IUnknown_QueryInterface_Proxy,
148 IUnknown_AddRef_Proxy,
149 IUnknown_Release_Proxy ,
150 if1_fn1_Proxy,
151 if1_fn2_Proxy
156 static const unsigned short if1_FormatStringOffsetTable[] =
162 static const MIDL_SERVER_INFO if1_server_info =
164 &Object_StubDesc,
166 __MIDL_ProcFormatString.Format,
167 &if1_FormatStringOffsetTable[-3],
174 static const PRPC_STUB_FUNCTION if1_table[] =
176 if1_fn1_Stub,
177 if1_fn2_Stub
180 static CInterfaceStubVtbl if1_stub_vtbl =
183 &IID_if1,
184 &if1_server_info,
186 &if1_table[-3]
188 { CStdStubBuffer_METHODS }
191 static CINTERFACE_PROXY_VTABLE(13) if2_proxy_vtbl =
193 { &IID_if2 },
194 { IUnknown_QueryInterface_Proxy,
195 IUnknown_AddRef_Proxy,
196 IUnknown_Release_Proxy ,
210 static const unsigned short if2_FormatStringOffsetTable[] =
212 (unsigned short) -1,
213 (unsigned short) -1,
214 (unsigned short) -1,
215 (unsigned short) -1,
216 (unsigned short) -1,
217 (unsigned short) -1,
218 (unsigned short) -1,
219 (unsigned short) -1,
220 (unsigned short) -1,
221 (unsigned short) -1,
225 static const MIDL_SERVER_INFO if2_server_info =
227 &Object_StubDesc,
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 =
254 &IID_if2,
255 &if2_server_info,
257 &if2_table[-3]
259 { CStdStubBuffer_DELEGATING_METHODS }
262 static CINTERFACE_PROXY_VTABLE(4) if3_proxy_vtbl =
264 { &IID_if3 },
265 { IUnknown_QueryInterface_Proxy,
266 IUnknown_AddRef_Proxy,
267 IUnknown_Release_Proxy ,
268 if1_fn1_Proxy
273 static const unsigned short if3_FormatStringOffsetTable[] =
279 static const MIDL_SERVER_INFO if3_server_info =
281 &Object_StubDesc,
283 __MIDL_ProcFormatString.Format,
284 &if3_FormatStringOffsetTable[-3],
291 static const PRPC_STUB_FUNCTION if3_table[] =
293 if1_fn1_Stub
296 static CInterfaceStubVtbl if3_stub_vtbl =
299 &IID_if3,
300 &if3_server_info,
302 &if1_table[-3]
304 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
307 static CINTERFACE_PROXY_VTABLE(7) if4_proxy_vtbl =
309 { &IID_if4 },
310 { IUnknown_QueryInterface_Proxy,
311 IUnknown_AddRef_Proxy,
312 IUnknown_Release_Proxy ,
320 static const unsigned short if4_FormatStringOffsetTable[] =
322 (unsigned short) -1,
323 (unsigned short) -1,
324 (unsigned short) -1,
325 (unsigned short) -1,
329 static const MIDL_SERVER_INFO if4_server_info =
331 &Object_StubDesc,
333 __MIDL_ProcFormatString.Format,
334 &if4_FormatStringOffsetTable[-3],
341 static const PRPC_STUB_FUNCTION if4_table[] =
343 STUB_FORWARDING_FUNCTION,
344 STUB_FORWARDING_FUNCTION,
345 STUB_FORWARDING_FUNCTION,
346 STUB_FORWARDING_FUNCTION,
349 static CInterfaceStubVtbl if4_stub_vtbl =
352 &IID_if4,
353 &if4_server_info,
355 &if2_table[-3]
357 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
360 static const CInterfaceProxyVtbl *cstub_ProxyVtblList[] =
362 (const CInterfaceProxyVtbl *) &if1_proxy_vtbl,
363 (const CInterfaceProxyVtbl *) &if2_proxy_vtbl,
364 (const CInterfaceProxyVtbl *) &if3_proxy_vtbl,
365 (const CInterfaceProxyVtbl *) &if4_proxy_vtbl,
366 NULL
369 static const CInterfaceStubVtbl *cstub_StubVtblList[] =
371 &if1_stub_vtbl,
372 &if2_stub_vtbl,
373 &if3_stub_vtbl,
374 &if4_stub_vtbl,
375 NULL
378 static PCInterfaceName const if_name_list[] =
380 "if1",
381 "if2",
382 "if3",
383 "if4",
384 NULL
387 static const IID *base_iid_list[] =
389 NULL,
390 &IID_ITypeLib,
391 NULL,
392 &IID_IDispatch,
393 NULL
396 #define cstub_CHECK_IID(n) IID_GENERIC_CHECK_IID( cstub, pIID, n)
398 static int __stdcall iid_lookup( const IID * pIID, int * pIndex )
400 IID_BS_LOOKUP_SETUP
402 IID_BS_LOOKUP_INITIAL_TEST( cstub, 4, 4 )
403 IID_BS_LOOKUP_NEXT_TEST( cstub, 2 )
404 IID_BS_LOOKUP_NEXT_TEST( cstub, 1 )
405 IID_BS_LOOKUP_RETURN_RESULT( cstub, 4, *pIndex )
410 static const ExtendedProxyFileInfo my_proxy_file_info =
412 (const PCInterfaceProxyVtblList *) &cstub_ProxyVtblList,
413 (const PCInterfaceStubVtblList *) &cstub_StubVtblList,
414 (const PCInterfaceName *) &if_name_list,
415 (const IID **) &base_iid_list,
416 &iid_lookup,
419 NULL,
425 static const ProxyFileInfo *proxy_file_list[] = {
426 &my_proxy_file_info,
427 NULL
431 static IPSFactoryBuffer *test_NdrDllGetClassObject(void)
433 IPSFactoryBuffer *ppsf = NULL;
434 const CLSID PSDispatch = {0x20420, 0, 0, {0xc0, 0, 0, 0, 0, 0, 0, 0x46}};
435 const CLSID CLSID_Unknown = {0x45678, 0x1234, 0x6666, {0xff, 0x67, 0x45, 0x98, 0x76, 0x12, 0x34, 0x56}};
436 HRESULT r;
437 HMODULE hmod = GetModuleHandleA("rpcrt4.dll");
438 void *CStd_QueryInterface = GetProcAddress(hmod, "CStdStubBuffer_QueryInterface");
439 void *CStd_AddRef = GetProcAddress(hmod, "CStdStubBuffer_AddRef");
440 void *CStd_Release = GetProcAddress(hmod, "NdrCStdStubBuffer_Release");
441 void *CStd_Connect = GetProcAddress(hmod, "CStdStubBuffer_Connect");
442 void *CStd_Disconnect = GetProcAddress(hmod, "CStdStubBuffer_Disconnect");
443 void *CStd_Invoke = GetProcAddress(hmod, "CStdStubBuffer_Invoke");
444 void *CStd_IsIIDSupported = GetProcAddress(hmod, "CStdStubBuffer_IsIIDSupported");
445 void *CStd_CountRefs = GetProcAddress(hmod, "CStdStubBuffer_CountRefs");
446 void *CStd_DebugServerQueryInterface = GetProcAddress(hmod, "CStdStubBuffer_DebugServerQueryInterface");
447 void *CStd_DebugServerRelease = GetProcAddress(hmod, "CStdStubBuffer_DebugServerRelease");
449 r = NdrDllGetClassObject(&PSDispatch, &IID_IPSFactoryBuffer, (void**)&ppsf, proxy_file_list,
450 &CLSID_Unknown, &PSFactoryBuffer);
451 ok(r == CLASS_E_CLASSNOTAVAILABLE, "NdrDllGetClassObject with unknown clsid should have returned CLASS_E_CLASSNOTAVAILABLE instead of 0x%x\n", r);
452 ok(ppsf == NULL, "NdrDllGetClassObject should have set ppsf to NULL on failure\n");
454 r = NdrDllGetClassObject(&PSDispatch, &IID_IPSFactoryBuffer, (void**)&ppsf, proxy_file_list,
455 &PSDispatch, &PSFactoryBuffer);
457 ok(r == S_OK, "ret %08x\n", r);
458 ok(ppsf != NULL, "ppsf == NULL\n");
460 ok(PSFactoryBuffer.pProxyFileList == proxy_file_list, "pfl not the same\n");
461 ok(PSFactoryBuffer.pProxyFileList[0]->pStubVtblList == (PCInterfaceStubVtblList *) &cstub_StubVtblList, "stub vtbllist not the same\n");
463 /* if1 is non-delegating, if2 is delegating, if3 is non-delegating
464 but I've zero'ed the vtbl entries, similarly if4 is delegating
465 with zero'ed vtbl entries */
467 #define VTBL_TEST_NOT_CHANGE_TO(name, i) \
468 ok(PSFactoryBuffer.pProxyFileList[0]->pStubVtblList[i]->Vtbl.name != CStd_##name, #name "vtbl %d updated %p %p\n", \
469 i, PSFactoryBuffer.pProxyFileList[0]->pStubVtblList[i]->Vtbl.name, CStd_##name );
470 #define VTBL_TEST_CHANGE_TO(name, i) \
471 ok(PSFactoryBuffer.pProxyFileList[0]->pStubVtblList[i]->Vtbl.name == CStd_##name, #name "vtbl %d not updated %p %p\n", \
472 i, PSFactoryBuffer.pProxyFileList[0]->pStubVtblList[i]->Vtbl.name, CStd_##name );
473 #define VTBL_TEST_ZERO(name, i) \
474 ok(PSFactoryBuffer.pProxyFileList[0]->pStubVtblList[i]->Vtbl.name == NULL, #name "vtbl %d not null %p\n", \
475 i, PSFactoryBuffer.pProxyFileList[0]->pStubVtblList[i]->Vtbl.name );
476 VTBL_TEST_NOT_CHANGE_TO(QueryInterface, 0);
477 VTBL_TEST_NOT_CHANGE_TO(AddRef, 0);
478 VTBL_TEST_NOT_CHANGE_TO(Release, 0);
479 VTBL_TEST_NOT_CHANGE_TO(Connect, 0);
480 VTBL_TEST_NOT_CHANGE_TO(Disconnect, 0);
481 VTBL_TEST_NOT_CHANGE_TO(Invoke, 0);
482 VTBL_TEST_NOT_CHANGE_TO(IsIIDSupported, 0);
483 VTBL_TEST_NOT_CHANGE_TO(CountRefs, 0);
484 VTBL_TEST_NOT_CHANGE_TO(DebugServerQueryInterface, 0);
485 VTBL_TEST_NOT_CHANGE_TO(DebugServerRelease, 0);
487 VTBL_TEST_CHANGE_TO(QueryInterface, 1);
488 VTBL_TEST_CHANGE_TO(AddRef, 1);
489 VTBL_TEST_NOT_CHANGE_TO(Release, 1);
490 VTBL_TEST_NOT_CHANGE_TO(Connect, 1);
491 VTBL_TEST_NOT_CHANGE_TO(Disconnect, 1);
492 VTBL_TEST_CHANGE_TO(Invoke, 1);
493 VTBL_TEST_CHANGE_TO(IsIIDSupported, 1);
494 VTBL_TEST_NOT_CHANGE_TO(CountRefs, 1);
495 VTBL_TEST_CHANGE_TO(DebugServerQueryInterface, 1);
496 VTBL_TEST_CHANGE_TO(DebugServerRelease, 1);
498 VTBL_TEST_CHANGE_TO(QueryInterface, 2);
499 VTBL_TEST_CHANGE_TO(AddRef, 2);
500 VTBL_TEST_ZERO(Release, 2);
501 VTBL_TEST_CHANGE_TO(Connect, 2);
502 VTBL_TEST_CHANGE_TO(Disconnect, 2);
503 VTBL_TEST_CHANGE_TO(Invoke, 2);
504 VTBL_TEST_CHANGE_TO(IsIIDSupported, 2);
505 VTBL_TEST_CHANGE_TO(CountRefs, 2);
506 VTBL_TEST_CHANGE_TO(DebugServerQueryInterface, 2);
507 VTBL_TEST_CHANGE_TO(DebugServerRelease, 2);
509 VTBL_TEST_CHANGE_TO(QueryInterface, 3);
510 VTBL_TEST_CHANGE_TO(AddRef, 3);
511 VTBL_TEST_ZERO(Release, 3);
512 VTBL_TEST_NOT_CHANGE_TO(Connect, 3);
513 VTBL_TEST_NOT_CHANGE_TO(Disconnect, 3);
514 VTBL_TEST_CHANGE_TO(Invoke, 3);
515 VTBL_TEST_CHANGE_TO(IsIIDSupported, 3);
516 VTBL_TEST_NOT_CHANGE_TO(CountRefs, 3);
517 VTBL_TEST_CHANGE_TO(DebugServerQueryInterface, 3);
518 VTBL_TEST_CHANGE_TO(DebugServerRelease, 3);
522 #undef VTBL_TEST_NOT_CHANGE_TO
523 #undef VTBL_TEST_CHANGE_TO
524 #undef VTBL_TEST_ZERO
526 ok(PSFactoryBuffer.RefCount == 1, "ref count %d\n", PSFactoryBuffer.RefCount);
527 IPSFactoryBuffer_Release(ppsf);
529 r = NdrDllGetClassObject(&IID_if3, &IID_IPSFactoryBuffer, (void**)&ppsf, proxy_file_list,
530 NULL, &PSFactoryBuffer);
531 ok(r == S_OK, "ret %08x\n", r);
532 ok(ppsf != NULL, "ppsf == NULL\n");
534 return ppsf;
537 static int base_buffer_invoke_called;
538 static HRESULT WINAPI base_buffer_Invoke(IRpcStubBuffer *This, RPCOLEMESSAGE *msg, IRpcChannelBuffer *channel)
540 base_buffer_invoke_called++;
541 ok(msg == (RPCOLEMESSAGE*)0xcafebabe, "msg ptr changed\n");
542 ok(channel == (IRpcChannelBuffer*)0xdeadbeef, "channel ptr changed\n");
543 return S_OK; /* returning any failure here results in an exception */
546 static IRpcStubBufferVtbl base_buffer_vtbl = {
547 (void*)0xcafebab0,
548 (void*)0xcafebab1,
549 (void*)0xcafebab2,
550 (void*)0xcafebab3,
551 (void*)0xcafebab4,
552 base_buffer_Invoke,
553 (void*)0xcafebab6,
554 (void*)0xcafebab7,
555 (void*)0xcafebab8,
556 (void*)0xcafebab9
559 static void test_NdrStubForwardingFunction(void)
561 void *This[5];
562 void *real_this;
563 IRpcChannelBuffer *channel = (IRpcChannelBuffer*)0xdeadbeef;
564 RPC_MESSAGE *msg = (RPC_MESSAGE*)0xcafebabe;
565 DWORD *phase = (DWORD*)0x12345678;
566 IRpcStubBufferVtbl *base_buffer_vtbl_ptr = &base_buffer_vtbl;
567 IRpcStubBuffer *base_stub_buffer = (IRpcStubBuffer*)&base_buffer_vtbl_ptr;
569 memset(This, 0xcc, sizeof(This));
570 This[0] = base_stub_buffer;
571 real_this = &This[1];
573 NdrStubForwardingFunction( real_this, channel, msg, phase );
574 ok(base_buffer_invoke_called == 1, "base_buffer_invoke called %d times\n", base_buffer_invoke_called);
578 static IRpcStubBuffer *create_stub(IPSFactoryBuffer *ppsf, REFIID iid, IUnknown *obj, HRESULT expected_result)
580 IRpcStubBuffer *pstub = NULL;
581 HRESULT r;
583 r = IPSFactoryBuffer_CreateStub(ppsf, iid, obj, &pstub);
584 ok(r == expected_result, "CreateStub returned %08x expected %08x\n", r, expected_result);
585 return pstub;
588 static HRESULT WINAPI create_stub_test_QI(IUnknown *This, REFIID iid, void **ppv)
590 ok(IsEqualIID(iid, &IID_if1), "incorrect iid\n");
591 *ppv = (void*)0xdeadbeef;
592 return S_OK;
595 static IUnknownVtbl create_stub_test_vtbl =
597 create_stub_test_QI,
598 NULL,
599 NULL
602 static HRESULT WINAPI create_stub_test_fail_QI(IUnknown *This, REFIID iid, void **ppv)
604 ok(IsEqualIID(iid, &IID_if1), "incorrect iid\n");
605 *ppv = NULL;
606 return E_NOINTERFACE;
609 static IUnknownVtbl create_stub_test_fail_vtbl =
611 create_stub_test_fail_QI,
612 NULL,
613 NULL
616 static void test_CreateStub(IPSFactoryBuffer *ppsf)
618 IUnknownVtbl *vtbl = &create_stub_test_vtbl;
619 IUnknown *obj = (IUnknown*)&vtbl;
620 IRpcStubBuffer *pstub = create_stub(ppsf, &IID_if1, obj, S_OK);
621 CStdStubBuffer *cstd_stub = (CStdStubBuffer*)pstub;
622 const CInterfaceStubHeader *header = &CONTAINING_RECORD(cstd_stub->lpVtbl, const CInterfaceStubVtbl, Vtbl)->header;
624 ok(IsEqualIID(header->piid, &IID_if1), "header iid differs\n");
625 ok(cstd_stub->RefCount == 1, "ref count %d\n", cstd_stub->RefCount);
626 /* 0xdeadbeef returned from create_stub_test_QI */
627 ok(cstd_stub->pvServerObject == (void*)0xdeadbeef, "pvServerObject %p\n", cstd_stub->pvServerObject);
628 ok(cstd_stub->pPSFactory != NULL, "pPSFactory was NULL\n");
630 vtbl = &create_stub_test_fail_vtbl;
631 pstub = create_stub(ppsf, &IID_if1, obj, E_NOINTERFACE);
635 static HRESULT WINAPI connect_test_orig_QI(IUnknown *This, REFIID iid, void **ppv)
637 ok(IsEqualIID(iid, &IID_if1) ||
638 IsEqualIID(iid, &IID_if2), "incorrect iid\n");
639 *ppv = (void*)This;
640 return S_OK;
643 static int connect_test_orig_release_called;
644 static ULONG WINAPI connect_test_orig_release(IUnknown *This)
646 connect_test_orig_release_called++;
647 return 0;
650 static IUnknownVtbl connect_test_orig_vtbl =
652 connect_test_orig_QI,
653 NULL,
654 connect_test_orig_release
657 static HRESULT WINAPI connect_test_new_QI(IUnknown *This, REFIID iid, void **ppv)
659 ok(IsEqualIID(iid, &IID_if1) ||
660 IsEqualIID(iid, &IID_if2), "incorrect iid\n");
661 *ppv = (void*)0xcafebabe;
662 return S_OK;
665 static IUnknownVtbl connect_test_new_vtbl =
667 connect_test_new_QI,
668 NULL,
669 NULL
672 static HRESULT WINAPI connect_test_new_fail_QI(IUnknown *This, REFIID iid, void **ppv)
674 ok(IsEqualIID(iid, &IID_if1), "incorrect iid\n");
675 *ppv = (void*)0xdeadbeef;
676 return E_NOINTERFACE;
679 static IUnknownVtbl connect_test_new_fail_vtbl =
681 connect_test_new_fail_QI,
682 NULL,
683 NULL
686 static int connect_test_base_Connect_called;
687 static HRESULT WINAPI connect_test_base_Connect(IRpcStubBuffer *pstub, IUnknown *obj)
689 connect_test_base_Connect_called++;
690 ok(*(void**)obj == (void*)0xbeefcafe, "unexpected obj %p\n", obj);
691 return S_OK;
694 static IRpcStubBufferVtbl connect_test_base_stub_buffer_vtbl =
696 (void*)0xcafebab0,
697 (void*)0xcafebab1,
698 (void*)0xcafebab2,
699 connect_test_base_Connect,
700 (void*)0xcafebab4,
701 (void*)0xcafebab5,
702 (void*)0xcafebab6,
703 (void*)0xcafebab7,
704 (void*)0xcafebab8,
705 (void*)0xcafebab9
708 static void test_Connect(IPSFactoryBuffer *ppsf)
710 IUnknownVtbl *orig_vtbl = &connect_test_orig_vtbl;
711 IUnknownVtbl *new_vtbl = &connect_test_new_vtbl;
712 IUnknownVtbl *new_fail_vtbl = &connect_test_new_fail_vtbl;
713 IUnknown *obj = (IUnknown*)&orig_vtbl;
714 IRpcStubBuffer *pstub = create_stub(ppsf, &IID_if1, obj, S_OK);
715 CStdStubBuffer *cstd_stub = (CStdStubBuffer*)pstub;
716 IRpcStubBufferVtbl *base_stub_buf_vtbl = &connect_test_base_stub_buffer_vtbl;
717 HRESULT r;
719 obj = (IUnknown*)&new_vtbl;
720 r = IRpcStubBuffer_Connect(pstub, obj);
721 ok(r == S_OK, "r %08x\n", r);
722 ok(connect_test_orig_release_called == 1, "release called %d\n", connect_test_orig_release_called);
723 ok(cstd_stub->pvServerObject == (void*)0xcafebabe, "pvServerObject %p\n", cstd_stub->pvServerObject);
725 cstd_stub->pvServerObject = (IUnknown*)&orig_vtbl;
726 obj = (IUnknown*)&new_fail_vtbl;
727 r = IRpcStubBuffer_Connect(pstub, obj);
728 ok(r == E_NOINTERFACE, "r %08x\n", r);
729 ok(cstd_stub->pvServerObject == (void*)0xdeadbeef, "pvServerObject %p\n", cstd_stub->pvServerObject);
730 ok(connect_test_orig_release_called == 2, "release called %d\n", connect_test_orig_release_called);
732 /* Now use a delegated stub.
734 We know from the NdrStubForwardFunction test that
735 (void**)pstub-1 is the base interface stub buffer. This shows
736 that (void**)pstub-2 contains the address of a vtable that gets
737 passed to the base interface's Connect method. Note that
738 (void**)pstub-2 itself gets passed to Connect and not
739 *((void**)pstub-2), so it should contain the vtable ptr and not
740 an interface ptr. */
742 obj = (IUnknown*)&orig_vtbl;
743 pstub = create_stub(ppsf, &IID_if2, obj, S_OK);
744 *((void**)pstub-1) = &base_stub_buf_vtbl;
745 *((void**)pstub-2) = (void*)0xbeefcafe;
747 obj = (IUnknown*)&new_vtbl;
748 r = IRpcStubBuffer_Connect(pstub, obj);
749 ok(connect_test_base_Connect_called == 1, "connect_test_bsae_Connect called %d times\n",
750 connect_test_base_Connect_called);
751 ok(connect_test_orig_release_called == 3, "release called %d\n", connect_test_orig_release_called);
752 cstd_stub = (CStdStubBuffer*)pstub;
753 ok(cstd_stub->pvServerObject == (void*)0xcafebabe, "pvServerObject %p\n", cstd_stub->pvServerObject);
756 static void test_Disconnect(IPSFactoryBuffer *ppsf)
758 IUnknownVtbl *orig_vtbl = &connect_test_orig_vtbl;
759 IUnknown *obj = (IUnknown*)&orig_vtbl;
760 IRpcStubBuffer *pstub = create_stub(ppsf, &IID_if1, obj, S_OK);
761 CStdStubBuffer *cstd_stub = (CStdStubBuffer*)pstub;
763 connect_test_orig_release_called = 0;
764 IRpcStubBuffer_Disconnect(pstub);
765 ok(connect_test_orig_release_called == 1, "release called %d\n", connect_test_orig_release_called);
766 ok(cstd_stub->pvServerObject == NULL, "pvServerObject %p\n", cstd_stub->pvServerObject);
770 static int release_test_psfacbuf_release_called;
771 static ULONG WINAPI release_test_pretend_psfacbuf_release(IUnknown *pUnk)
773 release_test_psfacbuf_release_called++;
774 return 1;
777 static IUnknownVtbl release_test_pretend_psfacbuf_vtbl =
779 NULL,
780 NULL,
781 release_test_pretend_psfacbuf_release
784 static void test_Release(IPSFactoryBuffer *ppsf)
786 LONG facbuf_refs;
787 IUnknownVtbl *orig_vtbl = &connect_test_orig_vtbl;
788 IUnknown *obj = (IUnknown*)&orig_vtbl;
789 IUnknownVtbl *pretend_psfacbuf_vtbl = &release_test_pretend_psfacbuf_vtbl;
790 IUnknown *pretend_psfacbuf = (IUnknown *)&pretend_psfacbuf_vtbl;
791 IRpcStubBuffer *pstub = create_stub(ppsf, &IID_if1, obj, S_OK);
792 CStdStubBuffer *cstd_stub = (CStdStubBuffer*)pstub;
794 facbuf_refs = PSFactoryBuffer.RefCount;
796 /* This shows that NdrCStdStubBuffer_Release doesn't call Disconnect */
797 ok(cstd_stub->RefCount == 1, "ref count %d\n", cstd_stub->RefCount);
798 connect_test_orig_release_called = 0;
799 IRpcStubBuffer_Release(pstub);
800 todo_wine {
801 ok(connect_test_orig_release_called == 0, "release called %d\n", connect_test_orig_release_called);
803 ok(PSFactoryBuffer.RefCount == facbuf_refs - 1, "factory buffer refs %d orig %d\n", PSFactoryBuffer.RefCount, facbuf_refs);
805 /* This shows that NdrCStdStubBuffer_Release calls Release on its 2nd arg, rather than on This->pPSFactory
806 (which are usually the same and indeed it's odd that _Release requires this 2nd arg). */
807 pstub = create_stub(ppsf, &IID_if1, obj, S_OK);
808 ok(PSFactoryBuffer.RefCount == facbuf_refs, "factory buffer refs %d orig %d\n", PSFactoryBuffer.RefCount, facbuf_refs);
809 NdrCStdStubBuffer_Release(pstub, (IPSFactoryBuffer*)pretend_psfacbuf);
810 ok(release_test_psfacbuf_release_called == 1, "pretend_psfacbuf_release called %d\n", release_test_psfacbuf_release_called);
811 ok(PSFactoryBuffer.RefCount == facbuf_refs, "factory buffer refs %d orig %d\n", PSFactoryBuffer.RefCount, facbuf_refs);
814 static HRESULT WINAPI delegating_invoke_test_QI(ITypeLib *pUnk, REFIID iid, void** ppv)
817 *ppv = pUnk;
818 return S_OK;
821 static ULONG WINAPI delegating_invoke_test_addref(ITypeLib *pUnk)
823 return 1;
826 static ULONG WINAPI delegating_invoke_test_release(ITypeLib *pUnk)
828 return 1;
831 static UINT WINAPI delegating_invoke_test_get_type_info_count(ITypeLib *pUnk)
833 return 0xabcdef;
836 static ITypeLibVtbl delegating_invoke_test_obj_vtbl =
838 delegating_invoke_test_QI,
839 delegating_invoke_test_addref,
840 delegating_invoke_test_release,
841 delegating_invoke_test_get_type_info_count,
842 NULL,
843 NULL,
844 NULL,
845 NULL,
846 NULL,
847 NULL,
848 NULL,
849 NULL,
850 NULL
853 static HRESULT WINAPI delegating_invoke_chan_query_interface(IRpcChannelBuffer *pchan,
854 REFIID iid,
855 void **ppv)
857 ok(0, "call to QueryInterface not expected\n");
858 return E_NOINTERFACE;
861 static ULONG WINAPI delegating_invoke_chan_add_ref(IRpcChannelBuffer *pchan)
863 return 2;
866 static ULONG WINAPI delegating_invoke_chan_release(IRpcChannelBuffer *pchan)
868 return 1;
871 static HRESULT WINAPI delegating_invoke_chan_get_buffer(IRpcChannelBuffer *pchan,
872 RPCOLEMESSAGE *msg,
873 REFIID iid)
875 msg->Buffer = HeapAlloc(GetProcessHeap(), 0, msg->cbBuffer);
876 return S_OK;
879 static HRESULT WINAPI delegating_invoke_chan_send_receive(IRpcChannelBuffer *pchan,
880 RPCOLEMESSAGE *pMessage,
881 ULONG *pStatus)
883 ok(0, "call to SendReceive not expected\n");
884 return E_NOTIMPL;
887 static HRESULT WINAPI delegating_invoke_chan_free_buffer(IRpcChannelBuffer *pchan,
888 RPCOLEMESSAGE *pMessage)
890 ok(0, "call to FreeBuffer not expected\n");
891 return E_NOTIMPL;
894 static HRESULT WINAPI delegating_invoke_chan_get_dest_ctx(IRpcChannelBuffer *pchan,
895 DWORD *pdwDestContext,
896 void **ppvDestContext)
898 *pdwDestContext = MSHCTX_LOCAL;
899 *ppvDestContext = NULL;
900 return S_OK;
903 static HRESULT WINAPI delegating_invoke_chan_is_connected(IRpcChannelBuffer *pchan)
905 ok(0, "call to IsConnected not expected\n");
906 return E_NOTIMPL;
909 static IRpcChannelBufferVtbl delegating_invoke_test_rpc_chan_vtbl =
911 delegating_invoke_chan_query_interface,
912 delegating_invoke_chan_add_ref,
913 delegating_invoke_chan_release,
914 delegating_invoke_chan_get_buffer,
915 delegating_invoke_chan_send_receive,
916 delegating_invoke_chan_free_buffer,
917 delegating_invoke_chan_get_dest_ctx,
918 delegating_invoke_chan_is_connected
921 static void test_delegating_Invoke(IPSFactoryBuffer *ppsf)
923 ITypeLibVtbl *obj_vtbl = &delegating_invoke_test_obj_vtbl;
924 IUnknown *obj = (IUnknown*)&obj_vtbl;
925 IRpcStubBuffer *pstub = create_stub(ppsf, &IID_if2, obj, S_OK);
926 IRpcChannelBufferVtbl *pchan_vtbl = &delegating_invoke_test_rpc_chan_vtbl;
927 IRpcChannelBuffer *pchan = (IRpcChannelBuffer *)&pchan_vtbl;
928 HRESULT r = E_FAIL;
929 RPCOLEMESSAGE msg;
931 memset(&msg, 0, sizeof(msg));
932 msg.dataRepresentation = NDR_LOCAL_DATA_REPRESENTATION;
933 msg.iMethod = 3;
934 r = IRpcStubBuffer_Invoke(pstub, &msg, pchan);
935 ok(r == S_OK, "ret %08x\n", r);
936 if(r == S_OK)
938 ok(*(DWORD*)msg.Buffer == 0xabcdef, "buf[0] %08x\n", *(DWORD*)msg.Buffer);
939 ok(*((DWORD*)msg.Buffer + 1) == S_OK, "buf[1] %08x\n", *((DWORD*)msg.Buffer + 1));
941 /* free the buffer allocated by delegating_invoke_chan_get_buffer */
942 HeapFree(GetProcessHeap(), 0, msg.Buffer);
943 IRpcStubBuffer_Release(pstub);
946 START_TEST( cstub )
948 IPSFactoryBuffer *ppsf;
950 OleInitialize(NULL);
952 ppsf = test_NdrDllGetClassObject();
953 test_NdrStubForwardingFunction();
954 test_CreateStub(ppsf);
955 test_Connect(ppsf);
956 test_Disconnect(ppsf);
957 test_Release(ppsf);
958 test_delegating_Invoke(ppsf);
960 OleUninitialize();