msdaps: Add server side stubs for IAccessor.
[wine] / dlls / rpcrt4 / tests / cstub.c
1 /*
2  * Unit test suite for cstubs
3  *
4  * Copyright 2006 Huw Davies
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include <stdarg.h>
22
23 #define PROXY_DELEGATION
24 #define COBJMACROS
25
26 #include "wine/test.h"
27 #include <windef.h>
28 #include <winbase.h>
29 #include <winnt.h>
30 #include <winerror.h>
31
32
33 #include "initguid.h"
34 #include "rpc.h"
35 #include "rpcdce.h"
36 #include "rpcproxy.h"
37
38 static CStdPSFactoryBuffer PSFactoryBuffer;
39
40 CSTDSTUBBUFFERRELEASE(&PSFactoryBuffer)
41 CSTDSTUBBUFFER2RELEASE(&PSFactoryBuffer)
42
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
48 static int my_alloc_called;
49 static int my_free_called;
50
51 static void * CALLBACK my_alloc(SIZE_T size)
52 {
53     my_alloc_called++;
54     return NdrOleAllocate(size);
55 }
56
57 static void CALLBACK my_free(void *ptr)
58 {
59     my_free_called++;
60     NdrOleFree(ptr);
61 }
62
63 typedef struct _MIDL_PROC_FORMAT_STRING
64 {
65     short          Pad;
66     unsigned char  Format[ 2 ];
67 } MIDL_PROC_FORMAT_STRING;
68
69 typedef struct _MIDL_TYPE_FORMAT_STRING
70 {
71     short          Pad;
72     unsigned char  Format[ 2 ];
73 } MIDL_TYPE_FORMAT_STRING;
74
75
76 static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =
77 {
78     0,
79     {
80         0, 0
81     }
82 };
83
84 static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =
85 {
86     0,
87     {
88         0, 0
89     }
90 };
91
92 static const MIDL_STUB_DESC Object_StubDesc =
93     {
94     NULL,
95     my_alloc,
96     my_free,
97     { 0 },
98     0,
99     0,
100     0,
101     0,
102     __MIDL_TypeFormatString.Format,
103     1, /* -error bounds_check flag */
104     0x20000, /* Ndr library version */
105     0,
106     0x50100a4, /* MIDL Version 5.1.164 */
107     0,
108     NULL,
109     0,  /* notify & notify_flag routine table */
110     1,  /* Flags */
111     0,  /* Reserved3 */
112     0,  /* Reserved4 */
113     0   /* Reserved5 */
114     };
115
116 static HRESULT WINAPI if1_fn1_Proxy(void *This)
117 {
118     return S_OK;
119 }
120
121 static void __RPC_STUB if1_fn1_Stub(
122     IRpcStubBuffer *This,
123     IRpcChannelBuffer *_pRpcChannelBuffer,
124     PRPC_MESSAGE _pRpcMessage,
125     DWORD *_pdwStubPhase)
126 {
127     trace("fn1 stub\n");
128 }
129
130 static HRESULT WINAPI if1_fn2_Proxy(void *This)
131 {
132     return S_OK;
133 }
134
135 static void __RPC_STUB if1_fn2_Stub(
136     IRpcStubBuffer *This,
137     IRpcChannelBuffer *_pRpcChannelBuffer,
138     PRPC_MESSAGE _pRpcMessage,
139     DWORD *_pdwStubPhase)
140 {
141     trace("fn2 stub\n");
142 }
143
144 static CINTERFACE_PROXY_VTABLE(5) if1_proxy_vtbl =
145 {
146     { &IID_if1 },
147     {   IUnknown_QueryInterface_Proxy,
148         IUnknown_AddRef_Proxy,
149         IUnknown_Release_Proxy ,
150         if1_fn1_Proxy,
151         if1_fn2_Proxy
152     }
153 };
154
155
156 static const unsigned short if1_FormatStringOffsetTable[] =
157     {
158     0,
159     0
160     };
161
162 static const MIDL_SERVER_INFO if1_server_info =
163     {
164     &Object_StubDesc,
165     0,
166     __MIDL_ProcFormatString.Format,
167     &if1_FormatStringOffsetTable[-3],
168     0,
169     0,
170     0,
171     0};
172
173
174 static const PRPC_STUB_FUNCTION if1_table[] =
175 {
176     if1_fn1_Stub,
177     if1_fn2_Stub
178 };
179
180 static CInterfaceStubVtbl if1_stub_vtbl =
181 {
182     {
183         &IID_if1,
184         &if1_server_info,
185         5,
186         &if1_table[-3]
187     },
188     { CStdStubBuffer_METHODS }
189 };
190
191 static CINTERFACE_PROXY_VTABLE(13) if2_proxy_vtbl =
192 {
193     { &IID_if2 },
194     {   IUnknown_QueryInterface_Proxy,
195         IUnknown_AddRef_Proxy,
196         IUnknown_Release_Proxy ,
197         0,
198         0,
199         0,
200         0,
201         0,
202         0,
203         0,
204         0,
205         0,
206         0
207     }
208 };
209
210 static const unsigned short if2_FormatStringOffsetTable[] =
211     {
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,
222     0
223     };
224
225 static const MIDL_SERVER_INFO if2_server_info =
226     {
227     &Object_StubDesc,
228     0,
229     __MIDL_ProcFormatString.Format,
230     &if2_FormatStringOffsetTable[-3],
231     0,
232     0,
233     0,
234     0};
235
236
237 static const PRPC_STUB_FUNCTION if2_table[] =
238 {
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
249 };
250
251 static CInterfaceStubVtbl if2_stub_vtbl =
252 {
253     {
254         &IID_if2,
255         &if2_server_info,
256         13,
257         &if2_table[-3]
258     },
259     { CStdStubBuffer_DELEGATING_METHODS }
260 };
261
262 static CINTERFACE_PROXY_VTABLE(5) if3_proxy_vtbl =
263 {
264     { &IID_if3 },
265     {   IUnknown_QueryInterface_Proxy,
266         IUnknown_AddRef_Proxy,
267         IUnknown_Release_Proxy ,
268         if1_fn1_Proxy,
269         0
270     }
271 };
272
273
274 static const unsigned short if3_FormatStringOffsetTable[] =
275     {
276     0,
277     0
278     };
279
280 static const MIDL_SERVER_INFO if3_server_info =
281     {
282     &Object_StubDesc,
283     0,
284     __MIDL_ProcFormatString.Format,
285     &if3_FormatStringOffsetTable[-3],
286     0,
287     0,
288     0,
289     0};
290
291
292 static const PRPC_STUB_FUNCTION if3_table[] =
293 {
294     if1_fn1_Stub
295 };
296
297 static CInterfaceStubVtbl if3_stub_vtbl =
298 {
299     {
300         &IID_if3,
301         &if3_server_info,
302         5,
303         &if1_table[-3]
304     },
305     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
306 };
307
308 static CINTERFACE_PROXY_VTABLE(7) if4_proxy_vtbl =
309 {
310     { &IID_if4 },
311     {   IUnknown_QueryInterface_Proxy,
312         IUnknown_AddRef_Proxy,
313         IUnknown_Release_Proxy ,
314         0,
315         0,
316         0,
317         0
318     }
319 };
320
321 static const unsigned short if4_FormatStringOffsetTable[] =
322     {
323     (unsigned short) -1,
324     (unsigned short) -1,
325     (unsigned short) -1,
326     (unsigned short) -1,
327     0
328     };
329
330 static const MIDL_SERVER_INFO if4_server_info =
331     {
332     &Object_StubDesc,
333     0,
334     __MIDL_ProcFormatString.Format,
335     &if4_FormatStringOffsetTable[-3],
336     0,
337     0,
338     0,
339     0};
340
341
342 static const PRPC_STUB_FUNCTION if4_table[] =
343 {
344     STUB_FORWARDING_FUNCTION,
345     STUB_FORWARDING_FUNCTION,
346     STUB_FORWARDING_FUNCTION,
347     STUB_FORWARDING_FUNCTION,
348 };
349
350 static CInterfaceStubVtbl if4_stub_vtbl =
351 {
352     {
353         &IID_if4,
354         &if4_server_info,
355         7,
356         &if2_table[-3]
357     },
358     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
359 };
360
361 static const CInterfaceProxyVtbl *cstub_ProxyVtblList[] =
362 {
363     (const CInterfaceProxyVtbl *) &if1_proxy_vtbl,
364     (const CInterfaceProxyVtbl *) &if2_proxy_vtbl,
365     (const CInterfaceProxyVtbl *) &if3_proxy_vtbl,
366     (const CInterfaceProxyVtbl *) &if4_proxy_vtbl,
367     NULL
368 };
369
370 static const CInterfaceStubVtbl *cstub_StubVtblList[] =
371 {
372     &if1_stub_vtbl,
373     &if2_stub_vtbl,
374     &if3_stub_vtbl,
375     &if4_stub_vtbl,
376     NULL
377 };
378
379 static PCInterfaceName const if_name_list[] =
380 {
381     "if1",
382     "if2",
383     "if3",
384     "if4",
385     NULL
386 };
387
388 static const IID *base_iid_list[] =
389 {
390     NULL,
391     &IID_ITypeLib,
392     NULL,
393     &IID_IDispatch,
394     NULL
395 };
396
397 #define cstub_CHECK_IID(n)     IID_GENERIC_CHECK_IID( cstub, pIID, n)
398
399 static int __stdcall iid_lookup( const IID * pIID, int * pIndex )
400 {
401     IID_BS_LOOKUP_SETUP
402
403     IID_BS_LOOKUP_INITIAL_TEST( cstub, 4, 4 )
404     IID_BS_LOOKUP_NEXT_TEST( cstub, 2 )
405     IID_BS_LOOKUP_NEXT_TEST( cstub, 1 )
406     IID_BS_LOOKUP_RETURN_RESULT( cstub, 4, *pIndex )
407
408 }
409
410
411 static BOOL check_address(void *actual, void *expected)
412 {
413     static void *ole32_start = NULL;
414     static void *ole32_end = NULL;
415
416     if (actual == expected)
417         return TRUE;
418
419     /* On Win7, actual can be located inside ole32.dll */
420     if (ole32_start == NULL || ole32_end == NULL)
421     {
422         PIMAGE_NT_HEADERS nt_headers;
423         ole32_start = (void *) GetModuleHandleA("ole32.dll");
424         if (ole32_start == NULL)
425             return FALSE;
426         nt_headers = (PIMAGE_NT_HEADERS)((char *) ole32_start + ((PIMAGE_DOS_HEADER) ole32_start)->e_lfanew);
427         ole32_end = (void *)((char *) ole32_start + nt_headers->OptionalHeader.SizeOfImage);
428     }
429
430     return ole32_start <= actual && actual < ole32_end;
431 }
432
433 static const ExtendedProxyFileInfo my_proxy_file_info =
434 {
435     (const PCInterfaceProxyVtblList *) &cstub_ProxyVtblList,
436     (const PCInterfaceStubVtblList *) &cstub_StubVtblList,
437     (const PCInterfaceName *) &if_name_list,
438     (const IID **) &base_iid_list,
439     &iid_lookup,
440     4,
441     1,
442     NULL,
443     0,
444     0,
445     0
446 };
447
448 static const ProxyFileInfo *proxy_file_list[] = {
449     &my_proxy_file_info,
450     NULL
451 };
452
453
454 static IPSFactoryBuffer *test_NdrDllGetClassObject(void)
455 {
456     HMODULE rpcrt4 = GetModuleHandleA("rpcrt4.dll");
457     IPSFactoryBuffer *ppsf = NULL;
458     const PCInterfaceProxyVtblList* proxy_vtbl;
459     const PCInterfaceStubVtblList* stub_vtbl;
460     const CLSID PSDispatch = {0x20420, 0, 0, {0xc0, 0, 0, 0, 0, 0, 0, 0x46}};
461     const CLSID CLSID_Unknown = {0x45678, 0x1234, 0x6666, {0xff, 0x67, 0x45, 0x98, 0x76, 0x12, 0x34, 0x56}};
462     static const GUID * const interfaces[] = { &IID_if1, &IID_if2, &IID_if3, &IID_if4 };
463     UINT i;
464     HRESULT r;
465     HMODULE hmod = GetModuleHandleA("rpcrt4.dll");
466     void *CStd_QueryInterface = GetProcAddress(hmod, "CStdStubBuffer_QueryInterface");
467     void *CStd_AddRef = GetProcAddress(hmod, "CStdStubBuffer_AddRef");
468     void *CStd_Release = GetProcAddress(hmod, "NdrCStdStubBuffer_Release");
469     void *CStd_Connect = GetProcAddress(hmod, "CStdStubBuffer_Connect");
470     void *CStd_Disconnect = GetProcAddress(hmod, "CStdStubBuffer_Disconnect");
471     void *CStd_Invoke = GetProcAddress(hmod, "CStdStubBuffer_Invoke");
472     void *CStd_IsIIDSupported = GetProcAddress(hmod, "CStdStubBuffer_IsIIDSupported");
473     void *CStd_CountRefs = GetProcAddress(hmod, "CStdStubBuffer_CountRefs");
474     void *CStd_DebugServerQueryInterface = GetProcAddress(hmod, "CStdStubBuffer_DebugServerQueryInterface");
475     void *CStd_DebugServerRelease = GetProcAddress(hmod, "CStdStubBuffer_DebugServerRelease");
476
477     r = NdrDllGetClassObject(&PSDispatch, &IID_IPSFactoryBuffer, (void**)&ppsf, proxy_file_list,
478                              &CLSID_Unknown, &PSFactoryBuffer);
479     ok(r == CLASS_E_CLASSNOTAVAILABLE, "NdrDllGetClassObject with unknown clsid should have returned CLASS_E_CLASSNOTAVAILABLE instead of 0x%x\n", r);
480     ok(ppsf == NULL, "NdrDllGetClassObject should have set ppsf to NULL on failure\n");
481
482     r = NdrDllGetClassObject(&PSDispatch, &IID_IPSFactoryBuffer, (void**)&ppsf, proxy_file_list,
483                          &PSDispatch, &PSFactoryBuffer);
484
485     ok(r == S_OK, "ret %08x\n", r);
486     ok(ppsf != NULL, "ppsf == NULL\n");
487
488     proxy_vtbl = PSFactoryBuffer.pProxyFileList[0]->pProxyVtblList;
489     stub_vtbl = PSFactoryBuffer.pProxyFileList[0]->pStubVtblList;
490     ok(PSFactoryBuffer.pProxyFileList == proxy_file_list, "pfl not the same\n");
491     ok(proxy_vtbl == (PCInterfaceProxyVtblList *) &cstub_ProxyVtblList, "proxy vtbllist not the same\n");
492     ok(stub_vtbl == (PCInterfaceStubVtblList *) &cstub_StubVtblList, "stub vtbllist not the same\n");
493
494     /* if1 is non-delegating, if2 is delegating, if3 is non-delegating
495        but I've zero'ed the vtbl entries, similarly if4 is delegating
496        with zero'ed vtbl entries */
497
498 #define VTBL_TEST_NOT_CHANGE_TO(name, i)                                  \
499     ok(stub_vtbl[i]->Vtbl.name != CStd_##name, #name "vtbl %d updated %p %p\n", \
500        i, stub_vtbl[i]->Vtbl.name, CStd_##name )
501 #define VTBL_TEST_CHANGE_TO(name, i)                                  \
502     ok(check_address(stub_vtbl[i]->Vtbl.name, CStd_##name), #name "vtbl %d not updated %p %p\n", \
503        i, stub_vtbl[i]->Vtbl.name, CStd_##name )
504 #define VTBL_TEST_ZERO(name, i)                                  \
505     ok(stub_vtbl[i]->Vtbl.name == NULL, #name "vtbl %d not null %p\n", \
506        i, stub_vtbl[i]->Vtbl.name )
507
508     VTBL_TEST_NOT_CHANGE_TO(QueryInterface, 0);
509     VTBL_TEST_NOT_CHANGE_TO(AddRef, 0);
510     VTBL_TEST_NOT_CHANGE_TO(Release, 0);
511     VTBL_TEST_NOT_CHANGE_TO(Connect, 0);
512     VTBL_TEST_NOT_CHANGE_TO(Disconnect, 0);
513     VTBL_TEST_NOT_CHANGE_TO(Invoke, 0);
514     VTBL_TEST_NOT_CHANGE_TO(IsIIDSupported, 0);
515     VTBL_TEST_NOT_CHANGE_TO(CountRefs, 0);
516     VTBL_TEST_NOT_CHANGE_TO(DebugServerQueryInterface, 0);
517     VTBL_TEST_NOT_CHANGE_TO(DebugServerRelease, 0);
518
519     VTBL_TEST_CHANGE_TO(QueryInterface, 1);
520     VTBL_TEST_CHANGE_TO(AddRef, 1);
521     VTBL_TEST_NOT_CHANGE_TO(Release, 1);
522     VTBL_TEST_NOT_CHANGE_TO(Connect, 1);
523     VTBL_TEST_NOT_CHANGE_TO(Disconnect, 1);
524     VTBL_TEST_CHANGE_TO(Invoke, 1);
525     VTBL_TEST_CHANGE_TO(IsIIDSupported, 1);
526     VTBL_TEST_NOT_CHANGE_TO(CountRefs, 1);
527     VTBL_TEST_CHANGE_TO(DebugServerQueryInterface, 1);
528     VTBL_TEST_CHANGE_TO(DebugServerRelease, 1);
529
530     VTBL_TEST_CHANGE_TO(QueryInterface, 2);
531     VTBL_TEST_CHANGE_TO(AddRef, 2);
532     VTBL_TEST_ZERO(Release, 2);
533     VTBL_TEST_CHANGE_TO(Connect, 2);
534     VTBL_TEST_CHANGE_TO(Disconnect, 2);
535     VTBL_TEST_CHANGE_TO(Invoke, 2);
536     VTBL_TEST_CHANGE_TO(IsIIDSupported, 2);
537     VTBL_TEST_CHANGE_TO(CountRefs, 2);
538     VTBL_TEST_CHANGE_TO(DebugServerQueryInterface, 2);
539     VTBL_TEST_CHANGE_TO(DebugServerRelease, 2);
540
541     VTBL_TEST_CHANGE_TO(QueryInterface, 3);
542     VTBL_TEST_CHANGE_TO(AddRef, 3);
543     VTBL_TEST_ZERO(Release, 3);
544     VTBL_TEST_NOT_CHANGE_TO(Connect, 3);
545     VTBL_TEST_NOT_CHANGE_TO(Disconnect, 3);
546     VTBL_TEST_CHANGE_TO(Invoke, 3);
547     VTBL_TEST_CHANGE_TO(IsIIDSupported, 3);
548     VTBL_TEST_NOT_CHANGE_TO(CountRefs, 3);
549     VTBL_TEST_CHANGE_TO(DebugServerQueryInterface, 3);
550     VTBL_TEST_CHANGE_TO(DebugServerRelease, 3);
551
552 #define VTBL_PROXY_TEST(i,num,ptr) \
553     ok( check_address(proxy_vtbl[i]->Vtbl[num], (ptr)), "wrong proxy %u func %u %p/%p\n", \
554         (i), (num), proxy_vtbl[i]->Vtbl[num], (ptr) )
555 #define VTBL_PROXY_TEST_NOT_ZERO(i,num) \
556     ok( proxy_vtbl[i]->Vtbl[num] != NULL, "wrong proxy %u func %u is NULL\n", (i), (num))
557
558     VTBL_PROXY_TEST(0, 0, IUnknown_QueryInterface_Proxy);
559     VTBL_PROXY_TEST(0, 1, IUnknown_AddRef_Proxy);
560     VTBL_PROXY_TEST(0, 2, IUnknown_Release_Proxy);
561     VTBL_PROXY_TEST(0, 3, if1_fn1_Proxy);
562     VTBL_PROXY_TEST(0, 4, if1_fn2_Proxy);
563
564     VTBL_PROXY_TEST(1, 0, GetProcAddress(rpcrt4,"IUnknown_QueryInterface_Proxy"));
565     VTBL_PROXY_TEST(1, 1, GetProcAddress(rpcrt4,"IUnknown_AddRef_Proxy"));
566     VTBL_PROXY_TEST(1, 2, GetProcAddress(rpcrt4,"IUnknown_Release_Proxy"));
567     VTBL_PROXY_TEST_NOT_ZERO(1, 3);
568     VTBL_PROXY_TEST_NOT_ZERO(1, 4);
569     VTBL_PROXY_TEST_NOT_ZERO(1, 5);
570     VTBL_PROXY_TEST_NOT_ZERO(1, 6);
571     VTBL_PROXY_TEST_NOT_ZERO(1, 7);
572     VTBL_PROXY_TEST_NOT_ZERO(1, 8);
573     VTBL_PROXY_TEST_NOT_ZERO(1, 9);
574     VTBL_PROXY_TEST_NOT_ZERO(1, 10);
575     VTBL_PROXY_TEST_NOT_ZERO(1, 11);
576     VTBL_PROXY_TEST_NOT_ZERO(1, 12);
577
578     VTBL_PROXY_TEST(2, 0, IUnknown_QueryInterface_Proxy);
579     VTBL_PROXY_TEST(2, 1, IUnknown_AddRef_Proxy);
580     VTBL_PROXY_TEST(2, 2, IUnknown_Release_Proxy);
581     VTBL_PROXY_TEST(2, 3, if1_fn1_Proxy);
582     todo_wine VTBL_PROXY_TEST_NOT_ZERO(2, 4);
583
584     VTBL_PROXY_TEST(3, 0, GetProcAddress(rpcrt4,"IUnknown_QueryInterface_Proxy"));
585     VTBL_PROXY_TEST(3, 1, GetProcAddress(rpcrt4,"IUnknown_AddRef_Proxy"));
586     VTBL_PROXY_TEST(3, 2, GetProcAddress(rpcrt4,"IUnknown_Release_Proxy"));
587     VTBL_PROXY_TEST_NOT_ZERO(3, 3);
588     VTBL_PROXY_TEST_NOT_ZERO(3, 4);
589     VTBL_PROXY_TEST_NOT_ZERO(3, 5);
590     VTBL_PROXY_TEST_NOT_ZERO(3, 6);
591
592 #undef VTBL_TEST_NOT_CHANGE_TO
593 #undef VTBL_TEST_CHANGE_TO
594 #undef VTBL_TEST_ZERO
595 #undef VTBL_PROXY_TEST
596 #undef VTBL_PROXY_TEST_NOT_ZERO
597
598     for (i = 0; i < sizeof(interfaces)/sizeof(interfaces[0]); i++)
599         ok( proxy_vtbl[i]->header.piid == interfaces[i],
600             "wrong proxy %u iid %p/%p\n", i, proxy_vtbl[i]->header.piid, interfaces[i] );
601
602     ok(PSFactoryBuffer.RefCount == 1, "ref count %d\n", PSFactoryBuffer.RefCount);
603     IPSFactoryBuffer_Release(ppsf);
604
605     r = NdrDllGetClassObject(&IID_if3, &IID_IPSFactoryBuffer, (void**)&ppsf, proxy_file_list,
606                              NULL, &PSFactoryBuffer);
607     ok(r == S_OK, "ret %08x\n", r);
608     ok(ppsf != NULL, "ppsf == NULL\n");
609
610     return ppsf;
611 }
612
613 static int base_buffer_invoke_called;
614 static HRESULT WINAPI base_buffer_Invoke(IRpcStubBuffer *This, RPCOLEMESSAGE *msg, IRpcChannelBuffer *channel)
615 {
616     base_buffer_invoke_called++;
617     ok(msg == (RPCOLEMESSAGE*)0xcafebabe, "msg ptr changed\n");
618     ok(channel == (IRpcChannelBuffer*)0xdeadbeef, "channel ptr changed\n");
619     return S_OK; /* returning any failure here results in an exception */
620 }
621
622 static IRpcStubBufferVtbl base_buffer_vtbl = {
623     (void*)0xcafebab0,
624     (void*)0xcafebab1,
625     (void*)0xcafebab2,
626     (void*)0xcafebab3,
627     (void*)0xcafebab4,
628     base_buffer_Invoke,
629     (void*)0xcafebab6,
630     (void*)0xcafebab7,
631     (void*)0xcafebab8,
632     (void*)0xcafebab9
633 };
634
635 static void test_NdrStubForwardingFunction(void)
636 {
637     void *This[5];
638     void *real_this;
639     IRpcChannelBuffer *channel = (IRpcChannelBuffer*)0xdeadbeef;
640     RPC_MESSAGE *msg = (RPC_MESSAGE*)0xcafebabe;
641     DWORD *phase = (DWORD*)0x12345678;
642     IRpcStubBufferVtbl *base_buffer_vtbl_ptr = &base_buffer_vtbl;
643     IRpcStubBuffer *base_stub_buffer = (IRpcStubBuffer*)&base_buffer_vtbl_ptr;
644
645     memset(This, 0xcc, sizeof(This));
646     This[0] = base_stub_buffer;
647     real_this = &This[1];
648
649     NdrStubForwardingFunction( real_this, channel, msg, phase );
650     ok(base_buffer_invoke_called == 1, "base_buffer_invoke called %d times\n", base_buffer_invoke_called);
651
652 }
653
654 static IRpcStubBuffer *create_stub(IPSFactoryBuffer *ppsf, REFIID iid, IUnknown *obj, HRESULT expected_result)
655 {
656     IRpcStubBuffer *pstub = NULL;
657     HRESULT r;
658
659     r = IPSFactoryBuffer_CreateStub(ppsf, iid, obj, &pstub);
660     ok(r == expected_result, "CreateStub returned %08x expected %08x\n", r, expected_result);
661     return pstub;
662 }
663
664 static HRESULT WINAPI create_stub_test_QI(IUnknown *This, REFIID iid, void **ppv)
665 {
666     ok(IsEqualIID(iid, &IID_if1), "incorrect iid\n");
667     *ppv = (void*)0xdeadbeef;
668     return S_OK;
669 }
670
671 static IUnknownVtbl create_stub_test_vtbl =
672 {
673     create_stub_test_QI,
674     NULL,
675     NULL
676 };
677
678 static HRESULT WINAPI create_stub_test_fail_QI(IUnknown *This, REFIID iid, void **ppv)
679 {
680     ok(IsEqualIID(iid, &IID_if1), "incorrect iid\n");
681     *ppv = NULL;
682     return E_NOINTERFACE;
683 }
684
685 static IUnknownVtbl create_stub_test_fail_vtbl =
686 {
687     create_stub_test_fail_QI,
688     NULL,
689     NULL
690 };
691
692 struct dummy_unknown
693 {
694     const IUnknownVtbl *vtbl;
695     LONG ref;
696 };
697
698 static HRESULT WINAPI dummy_QueryInterface(IUnknown *This, REFIID iid, void **ppv)
699 {
700     *ppv = NULL;
701     return E_NOINTERFACE;
702 }
703
704 static ULONG WINAPI dummy_AddRef(LPUNKNOWN iface)
705 {
706     struct dummy_unknown *this = (struct dummy_unknown *)iface;
707     return InterlockedIncrement( &this->ref );
708 }
709
710 static ULONG WINAPI dummy_Release(LPUNKNOWN iface)
711 {
712     struct dummy_unknown *this = (struct dummy_unknown *)iface;
713     return InterlockedDecrement( &this->ref );
714 }
715
716 static IUnknownVtbl dummy_unknown_vtbl =
717 {
718     dummy_QueryInterface,
719     dummy_AddRef,
720     dummy_Release
721 };
722 static struct dummy_unknown dummy_unknown = { &dummy_unknown_vtbl, 0 };
723
724 static void create_proxy_test( IPSFactoryBuffer *ppsf, REFIID iid, const void *expected_vtbl )
725 {
726     IRpcProxyBuffer *proxy = NULL;
727     IUnknown *iface = NULL;
728     HRESULT r;
729     ULONG count;
730
731     r = IPSFactoryBuffer_CreateProxy(ppsf, NULL, iid, &proxy, (void **)&iface);
732     ok( r == S_OK, "IPSFactoryBuffer_CreateProxy failed %x\n", r );
733     ok( *(void **)iface == expected_vtbl, "wrong iface pointer %p/%p\n", *(void **)iface, expected_vtbl );
734     count = IUnknown_Release( iface );
735     ok( count == 1, "wrong refcount %u\n", count );
736     count = IRpcProxyBuffer_Release( proxy );
737     ok( count == 0, "wrong refcount %u\n", count );
738
739     dummy_unknown.ref = 4;
740     r = IPSFactoryBuffer_CreateProxy(ppsf, (IUnknown *)&dummy_unknown, iid, &proxy, (void **)&iface);
741     ok( r == S_OK, "IPSFactoryBuffer_CreateProxy failed %x\n", r );
742     ok( dummy_unknown.ref == 5, "wrong refcount %u\n", dummy_unknown.ref );
743     ok( *(void **)iface == expected_vtbl, "wrong iface pointer %p/%p\n", *(void **)iface, expected_vtbl );
744     count = IUnknown_Release( iface );
745     ok( count == 4, "wrong refcount %u\n", count );
746     ok( dummy_unknown.ref == 4, "wrong refcount %u\n", dummy_unknown.ref );
747     count = IRpcProxyBuffer_Release( proxy );
748     ok( count == 0, "wrong refcount %u\n", count );
749     ok( dummy_unknown.ref == 4, "wrong refcount %u\n", dummy_unknown.ref );
750 }
751
752 static void test_CreateProxy( IPSFactoryBuffer *ppsf )
753 {
754     create_proxy_test( ppsf, &IID_if1, if1_proxy_vtbl.Vtbl );
755     create_proxy_test( ppsf, &IID_if2, if2_proxy_vtbl.Vtbl );
756     create_proxy_test( ppsf, &IID_if3, if3_proxy_vtbl.Vtbl );
757     create_proxy_test( ppsf, &IID_if4, if4_proxy_vtbl.Vtbl );
758 }
759
760 static void test_CreateStub(IPSFactoryBuffer *ppsf)
761 {
762     IUnknownVtbl *vtbl = &create_stub_test_vtbl;
763     IUnknown *obj = (IUnknown*)&vtbl;
764     IRpcStubBuffer *pstub = create_stub(ppsf, &IID_if1, obj, S_OK);
765     CStdStubBuffer *cstd_stub = (CStdStubBuffer*)pstub;
766     const CInterfaceStubHeader *header = &CONTAINING_RECORD(cstd_stub->lpVtbl, const CInterfaceStubVtbl, Vtbl)->header;
767
768     ok(IsEqualIID(header->piid, &IID_if1), "header iid differs\n");
769     ok(cstd_stub->RefCount == 1, "ref count %d\n", cstd_stub->RefCount);
770     /* 0xdeadbeef returned from create_stub_test_QI */
771     ok(cstd_stub->pvServerObject == (void*)0xdeadbeef, "pvServerObject %p\n", cstd_stub->pvServerObject);
772     ok(cstd_stub->pPSFactory != NULL, "pPSFactory was NULL\n");
773     cstd_stub->pvServerObject = NULL;
774     IRpcStubBuffer_Release(pstub);
775
776     vtbl = &create_stub_test_fail_vtbl;
777     pstub = create_stub(ppsf, &IID_if1, obj, E_NOINTERFACE);
778
779 }
780
781 static HRESULT WINAPI connect_test_orig_QI(IUnknown *This, REFIID iid, void **ppv)
782 {
783     ok(IsEqualIID(iid, &IID_if1) ||
784        IsEqualIID(iid, &IID_if2), "incorrect iid\n");
785     *ppv = (void*)This;
786     return S_OK;
787 }
788
789 static int connect_test_orig_release_called;
790 static ULONG WINAPI connect_test_orig_release(IUnknown *This)
791 {
792     connect_test_orig_release_called++;
793     return 0;
794 }
795
796 static IUnknownVtbl connect_test_orig_vtbl =
797 {
798     connect_test_orig_QI,
799     NULL,
800     connect_test_orig_release
801 };
802
803 static HRESULT WINAPI connect_test_new_QI(IUnknown *This, REFIID iid, void **ppv)
804 {
805     ok(IsEqualIID(iid, &IID_if1) ||
806        IsEqualIID(iid, &IID_if2), "incorrect iid\n");
807     *ppv = (void*)0xcafebabe;
808     return S_OK;
809 }
810
811 static IUnknownVtbl connect_test_new_vtbl =
812 {
813     connect_test_new_QI,
814     NULL,
815     NULL
816 };
817
818 static HRESULT WINAPI connect_test_new_fail_QI(IUnknown *This, REFIID iid, void **ppv)
819 {
820     ok(IsEqualIID(iid, &IID_if1), "incorrect iid\n");
821     *ppv = (void*)0xdeadbeef;
822     return E_NOINTERFACE;
823 }
824
825 static IUnknownVtbl connect_test_new_fail_vtbl =
826 {
827     connect_test_new_fail_QI,
828     NULL,
829     NULL
830 };
831
832 static int connect_test_base_Connect_called;
833 static HRESULT WINAPI connect_test_base_Connect(IRpcStubBuffer *pstub, IUnknown *obj)
834 {
835     connect_test_base_Connect_called++;
836     ok(*(void**)obj == (void*)0xbeefcafe, "unexpected obj %p\n", obj);
837     return S_OK;
838 }
839
840 static IRpcStubBufferVtbl connect_test_base_stub_buffer_vtbl =
841 {
842     (void*)0xcafebab0,
843     (void*)0xcafebab1,
844     (void*)0xcafebab2,
845     connect_test_base_Connect,
846     (void*)0xcafebab4,
847     (void*)0xcafebab5,
848     (void*)0xcafebab6,
849     (void*)0xcafebab7,
850     (void*)0xcafebab8,
851     (void*)0xcafebab9
852 };
853
854 static void test_Connect(IPSFactoryBuffer *ppsf)
855 {
856     IUnknownVtbl *orig_vtbl = &connect_test_orig_vtbl;
857     IUnknownVtbl *new_vtbl = &connect_test_new_vtbl;
858     IUnknownVtbl *new_fail_vtbl = &connect_test_new_fail_vtbl;
859     IUnknown *obj = (IUnknown*)&orig_vtbl;
860     IRpcStubBuffer *pstub = create_stub(ppsf, &IID_if1, obj, S_OK); 
861     CStdStubBuffer *cstd_stub = (CStdStubBuffer*)pstub;
862     IRpcStubBufferVtbl *base_stub_buf_vtbl = &connect_test_base_stub_buffer_vtbl;
863     HRESULT r;
864
865     obj = (IUnknown*)&new_vtbl;
866     r = IRpcStubBuffer_Connect(pstub, obj);
867     ok(r == S_OK, "r %08x\n", r);
868     ok(connect_test_orig_release_called == 1, "release called %d\n", connect_test_orig_release_called);
869     ok(cstd_stub->pvServerObject == (void*)0xcafebabe, "pvServerObject %p\n", cstd_stub->pvServerObject);
870
871     cstd_stub->pvServerObject = (IUnknown*)&orig_vtbl;
872     obj = (IUnknown*)&new_fail_vtbl;
873     r = IRpcStubBuffer_Connect(pstub, obj);
874     ok(r == E_NOINTERFACE, "r %08x\n", r);
875     ok(cstd_stub->pvServerObject == (void*)0xdeadbeef, "pvServerObject %p\n", cstd_stub->pvServerObject);
876     ok(connect_test_orig_release_called == 2, "release called %d\n", connect_test_orig_release_called);    
877
878     /* Now use a delegated stub.
879
880        We know from the NdrStubForwardFunction test that
881        (void**)pstub-1 is the base interface stub buffer.  This shows
882        that (void**)pstub-2 contains the address of a vtable that gets
883        passed to the base interface's Connect method.  Note that
884        (void**)pstub-2 itself gets passed to Connect and not
885        *((void**)pstub-2), so it should contain the vtable ptr and not
886        an interface ptr. */
887
888     obj = (IUnknown*)&orig_vtbl;
889     pstub = create_stub(ppsf, &IID_if2, obj, S_OK);
890     *((void**)pstub-1) = &base_stub_buf_vtbl;
891     *((void**)pstub-2) = (void*)0xbeefcafe;
892
893     obj = (IUnknown*)&new_vtbl;
894     r = IRpcStubBuffer_Connect(pstub, obj);
895     ok(connect_test_base_Connect_called == 1, "connect_test_bsae_Connect called %d times\n",
896        connect_test_base_Connect_called);
897     ok(connect_test_orig_release_called == 3, "release called %d\n", connect_test_orig_release_called);
898     cstd_stub = (CStdStubBuffer*)pstub;
899     ok(cstd_stub->pvServerObject == (void*)0xcafebabe, "pvServerObject %p\n", cstd_stub->pvServerObject);
900 }
901
902 static void test_Disconnect(IPSFactoryBuffer *ppsf)
903 {
904     IUnknownVtbl *orig_vtbl = &connect_test_orig_vtbl;
905     IUnknown *obj = (IUnknown*)&orig_vtbl;
906     IRpcStubBuffer *pstub = create_stub(ppsf, &IID_if1, obj, S_OK);
907     CStdStubBuffer *cstd_stub = (CStdStubBuffer*)pstub;
908
909     connect_test_orig_release_called = 0;
910     IRpcStubBuffer_Disconnect(pstub);
911     ok(connect_test_orig_release_called == 1, "release called %d\n", connect_test_orig_release_called);
912     ok(cstd_stub->pvServerObject == NULL, "pvServerObject %p\n", cstd_stub->pvServerObject);
913     IRpcStubBuffer_Release(pstub);
914 }
915
916
917 static int release_test_psfacbuf_release_called;
918 static ULONG WINAPI release_test_pretend_psfacbuf_release(IUnknown *pUnk)
919 {
920     release_test_psfacbuf_release_called++;
921     return 1;
922 }
923
924 static IUnknownVtbl release_test_pretend_psfacbuf_vtbl =
925 {
926     NULL,
927     NULL,
928     release_test_pretend_psfacbuf_release
929 };
930
931 static void test_Release(IPSFactoryBuffer *ppsf)
932 {
933     LONG facbuf_refs;
934     IUnknownVtbl *orig_vtbl = &connect_test_orig_vtbl;
935     IUnknown *obj = (IUnknown*)&orig_vtbl;
936     IUnknownVtbl *pretend_psfacbuf_vtbl = &release_test_pretend_psfacbuf_vtbl;
937     IUnknown *pretend_psfacbuf = (IUnknown *)&pretend_psfacbuf_vtbl;
938     IRpcStubBuffer *pstub = create_stub(ppsf, &IID_if1, obj, S_OK);
939     CStdStubBuffer *cstd_stub = (CStdStubBuffer*)pstub;
940
941     facbuf_refs = PSFactoryBuffer.RefCount;
942
943     /* This shows that NdrCStdStubBuffer_Release doesn't call Disconnect */
944     ok(cstd_stub->RefCount == 1, "ref count %d\n", cstd_stub->RefCount);
945     connect_test_orig_release_called = 0;
946     IRpcStubBuffer_Release(pstub);
947 todo_wine {
948     ok(connect_test_orig_release_called == 0, "release called %d\n", connect_test_orig_release_called);
949 }
950     ok(PSFactoryBuffer.RefCount == facbuf_refs - 1, "factory buffer refs %d orig %d\n", PSFactoryBuffer.RefCount, facbuf_refs);
951
952     /* This shows that NdrCStdStubBuffer_Release calls Release on its 2nd arg, rather than on This->pPSFactory
953        (which are usually the same and indeed it's odd that _Release requires this 2nd arg). */
954     pstub = create_stub(ppsf, &IID_if1, obj, S_OK);
955     ok(PSFactoryBuffer.RefCount == facbuf_refs, "factory buffer refs %d orig %d\n", PSFactoryBuffer.RefCount, facbuf_refs);
956     NdrCStdStubBuffer_Release(pstub, (IPSFactoryBuffer*)pretend_psfacbuf);
957     ok(release_test_psfacbuf_release_called == 1, "pretend_psfacbuf_release called %d\n", release_test_psfacbuf_release_called);
958     ok(PSFactoryBuffer.RefCount == facbuf_refs, "factory buffer refs %d orig %d\n", PSFactoryBuffer.RefCount, facbuf_refs);
959 }
960
961 static HRESULT WINAPI delegating_invoke_test_QI(ITypeLib *pUnk, REFIID iid, void** ppv)
962 {
963
964     *ppv = pUnk;
965     return S_OK;
966 }
967
968 static ULONG WINAPI delegating_invoke_test_addref(ITypeLib *pUnk)
969 {
970     return 1;
971 }
972
973 static ULONG WINAPI delegating_invoke_test_release(ITypeLib *pUnk)
974 {
975     return 1;
976 }
977
978 static UINT WINAPI delegating_invoke_test_get_type_info_count(ITypeLib *pUnk)
979 {
980     return 0xabcdef;
981 }
982
983 static ITypeLibVtbl delegating_invoke_test_obj_vtbl =
984 {
985     delegating_invoke_test_QI,
986     delegating_invoke_test_addref,
987     delegating_invoke_test_release,
988     delegating_invoke_test_get_type_info_count,
989     NULL,
990     NULL,
991     NULL,
992     NULL,
993     NULL,
994     NULL,
995     NULL,
996     NULL,
997     NULL
998 };
999
1000 static HRESULT WINAPI delegating_invoke_chan_query_interface(IRpcChannelBuffer *pchan,
1001                                                              REFIID iid,
1002                                                              void **ppv)
1003 {
1004     ok(0, "call to QueryInterface not expected\n");
1005     return E_NOINTERFACE;
1006 }
1007
1008 static ULONG WINAPI delegating_invoke_chan_add_ref(IRpcChannelBuffer *pchan)
1009 {
1010     return 2;
1011 }
1012
1013 static ULONG WINAPI delegating_invoke_chan_release(IRpcChannelBuffer *pchan)
1014 {
1015     return 1;
1016 }
1017
1018 static HRESULT WINAPI delegating_invoke_chan_get_buffer(IRpcChannelBuffer *pchan,
1019                                                         RPCOLEMESSAGE *msg,
1020                                                         REFIID iid)
1021 {
1022     msg->Buffer = HeapAlloc(GetProcessHeap(), 0, msg->cbBuffer);
1023     return S_OK;
1024 }
1025
1026 static HRESULT WINAPI delegating_invoke_chan_send_receive(IRpcChannelBuffer *pchan,
1027                                                           RPCOLEMESSAGE *pMessage,
1028                                                           ULONG *pStatus)
1029 {
1030     ok(0, "call to SendReceive not expected\n");
1031     return E_NOTIMPL;
1032 }
1033
1034 static HRESULT WINAPI delegating_invoke_chan_free_buffer(IRpcChannelBuffer *pchan,
1035                                                          RPCOLEMESSAGE *pMessage)
1036 {
1037     ok(0, "call to FreeBuffer not expected\n");
1038     return E_NOTIMPL;
1039 }
1040
1041 static HRESULT WINAPI delegating_invoke_chan_get_dest_ctx(IRpcChannelBuffer *pchan,
1042                                                           DWORD *pdwDestContext,
1043                                                           void **ppvDestContext)
1044 {
1045     *pdwDestContext = MSHCTX_LOCAL;
1046     *ppvDestContext = NULL;
1047     return S_OK;
1048 }
1049
1050 static HRESULT WINAPI delegating_invoke_chan_is_connected(IRpcChannelBuffer *pchan)
1051 {
1052     ok(0, "call to IsConnected not expected\n");
1053     return E_NOTIMPL;
1054 }
1055
1056 static IRpcChannelBufferVtbl delegating_invoke_test_rpc_chan_vtbl =
1057 {
1058     delegating_invoke_chan_query_interface,
1059     delegating_invoke_chan_add_ref,
1060     delegating_invoke_chan_release,
1061     delegating_invoke_chan_get_buffer,
1062     delegating_invoke_chan_send_receive,
1063     delegating_invoke_chan_free_buffer,
1064     delegating_invoke_chan_get_dest_ctx,
1065     delegating_invoke_chan_is_connected
1066 };
1067
1068 static void test_delegating_Invoke(IPSFactoryBuffer *ppsf)
1069 {
1070     ITypeLibVtbl *obj_vtbl = &delegating_invoke_test_obj_vtbl;
1071     IUnknown *obj = (IUnknown*)&obj_vtbl;
1072     IRpcStubBuffer *pstub = create_stub(ppsf, &IID_if2, obj, S_OK);
1073     IRpcChannelBufferVtbl *pchan_vtbl = &delegating_invoke_test_rpc_chan_vtbl;
1074     IRpcChannelBuffer *pchan = (IRpcChannelBuffer *)&pchan_vtbl;
1075     HRESULT r = E_FAIL;
1076     RPCOLEMESSAGE msg;
1077
1078     memset(&msg, 0, sizeof(msg));
1079     msg.dataRepresentation = NDR_LOCAL_DATA_REPRESENTATION;
1080     msg.iMethod = 3;
1081     r = IRpcStubBuffer_Invoke(pstub, &msg, pchan);
1082     ok(r == S_OK, "ret %08x\n", r);
1083     if(r == S_OK)
1084     {
1085         ok(*(DWORD*)msg.Buffer == 0xabcdef, "buf[0] %08x\n", *(DWORD*)msg.Buffer);
1086         ok(*((DWORD*)msg.Buffer + 1) == S_OK, "buf[1] %08x\n", *((DWORD*)msg.Buffer + 1));
1087     }
1088     /* free the buffer allocated by delegating_invoke_chan_get_buffer */
1089     HeapFree(GetProcessHeap(), 0, msg.Buffer);
1090     IRpcStubBuffer_Release(pstub);
1091 }
1092
1093 START_TEST( cstub )
1094 {
1095     IPSFactoryBuffer *ppsf;
1096
1097     OleInitialize(NULL);
1098
1099     ppsf = test_NdrDllGetClassObject();
1100     test_NdrStubForwardingFunction();
1101     test_CreateProxy(ppsf);
1102     test_CreateStub(ppsf);
1103     test_Connect(ppsf);
1104     test_Disconnect(ppsf);
1105     test_Release(ppsf);
1106     test_delegating_Invoke(ppsf);
1107
1108     OleUninitialize();
1109 }