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 #include <stdio.h>
23 
24 #define COBJMACROS
25 #ifdef __REACTOS__
26 #define CONST_VTABLE
27 #endif
28 
29 #include <windef.h>
30 #include <winbase.h>
31 #include <winnt.h>
32 #include <winerror.h>
33 
34 #include "initguid.h"
35 #include <ole2.h>
36 #include "rpc.h"
37 #include "rpcdce.h"
38 #include "rpcproxy.h"
39 
40 #include "wine/heap.h"
41 #include "wine/test.h"
42 
43 #include "cstub_p.h"
44 
45 static CStdPSFactoryBuffer PSFactoryBuffer;
46 
test_CStdStubBuffer_Release(IRpcStubBuffer * This)47 static ULONG WINAPI test_CStdStubBuffer_Release(IRpcStubBuffer *This)
48 {
49     return NdrCStdStubBuffer_Release(This, (IPSFactoryBuffer *)&PSFactoryBuffer);
50 }
51 
test_CStdStubBuffer2_Release(IRpcStubBuffer * This)52 static ULONG WINAPI test_CStdStubBuffer2_Release(IRpcStubBuffer *This)
53 {
54     return NdrCStdStubBuffer2_Release(This, (IPSFactoryBuffer *)&PSFactoryBuffer);
55 }
56 
57 static GUID IID_if1 = {0x12345678, 1234, 5678, {12,34,56,78,90,0xab,0xcd,0xef}};
58 static GUID IID_if2 = {0x12345679, 1234, 5678, {12,34,56,78,90,0xab,0xcd,0xef}};
59 static GUID IID_if3 = {0x1234567a, 1234, 5678, {12,34,56,78,90,0xab,0xcd,0xef}};
60 static GUID IID_if4 = {0x1234567b, 1234, 5678, {12,34,56,78,90,0xab,0xcd,0xef}};
61 static CLSID CLSID_psfact = {0x1234567c, 1234, 5678, {12,34,56,78,90,0xab,0xcd,0xef}};
62 
63 static int my_alloc_called;
64 static int my_free_called;
65 
my_alloc(SIZE_T size)66 static void * CALLBACK my_alloc(SIZE_T size)
67 {
68     my_alloc_called++;
69     return NdrOleAllocate(size);
70 }
71 
my_free(void * ptr)72 static void CALLBACK my_free(void *ptr)
73 {
74     my_free_called++;
75     NdrOleFree(ptr);
76 }
77 
78 typedef struct _MIDL_PROC_FORMAT_STRING
79 {
80     short          Pad;
81     unsigned char  Format[ 2 ];
82 } MIDL_PROC_FORMAT_STRING;
83 
84 typedef struct _MIDL_TYPE_FORMAT_STRING
85 {
86     short          Pad;
87     unsigned char  Format[ 2 ];
88 } MIDL_TYPE_FORMAT_STRING;
89 
90 
91 static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =
92 {
93     0,
94     {
95         0, 0
96     }
97 };
98 
99 static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =
100 {
101     0,
102     {
103         0, 0
104     }
105 };
106 
107 static const MIDL_STUB_DESC Object_StubDesc =
108     {
109     NULL,
110     my_alloc,
111     my_free,
112     { 0 },
113     0,
114     0,
115     0,
116     0,
117     __MIDL_TypeFormatString.Format,
118     1, /* -error bounds_check flag */
119     0x20000, /* Ndr library version */
120     0,
121     0x50100a4, /* MIDL Version 5.1.164 */
122     0,
123     NULL,
124     0,  /* notify & notify_flag routine table */
125     1,  /* Flags */
126     0,  /* Reserved3 */
127     0,  /* Reserved4 */
128     0   /* Reserved5 */
129     };
130 
if1_fn1_Proxy(void * This)131 static HRESULT WINAPI if1_fn1_Proxy(void *This)
132 {
133     return S_OK;
134 }
135 
if1_fn1_Stub(IRpcStubBuffer * This,IRpcChannelBuffer * _pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD * _pdwStubPhase)136 static void __RPC_STUB if1_fn1_Stub(
137     IRpcStubBuffer *This,
138     IRpcChannelBuffer *_pRpcChannelBuffer,
139     PRPC_MESSAGE _pRpcMessage,
140     DWORD *_pdwStubPhase)
141 {
142     trace("fn1 stub\n");
143 }
144 
if1_fn2_Proxy(void * This)145 static HRESULT WINAPI if1_fn2_Proxy(void *This)
146 {
147     return S_OK;
148 }
149 
if1_fn2_Stub(IRpcStubBuffer * This,IRpcChannelBuffer * _pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD * _pdwStubPhase)150 static void __RPC_STUB if1_fn2_Stub(
151     IRpcStubBuffer *This,
152     IRpcChannelBuffer *_pRpcChannelBuffer,
153     PRPC_MESSAGE _pRpcMessage,
154     DWORD *_pdwStubPhase)
155 {
156     trace("fn2 stub\n");
157 }
158 
159 static CINTERFACE_PROXY_VTABLE(5) if1_proxy_vtbl =
160 {
161     { &IID_if1 },
162     {   IUnknown_QueryInterface_Proxy,
163         IUnknown_AddRef_Proxy,
164         IUnknown_Release_Proxy ,
165         if1_fn1_Proxy,
166         if1_fn2_Proxy
167     }
168 };
169 
170 
171 static const unsigned short if1_FormatStringOffsetTable[] =
172     {
173     0,
174     0
175     };
176 
177 static const MIDL_SERVER_INFO if1_server_info =
178     {
179     &Object_StubDesc,
180     0,
181     __MIDL_ProcFormatString.Format,
182     &if1_FormatStringOffsetTable[-3],
183     0,
184     0,
185     0,
186     0};
187 
188 
189 static const PRPC_STUB_FUNCTION if1_table[] =
190 {
191     if1_fn1_Stub,
192     if1_fn2_Stub
193 };
194 
195 static CInterfaceStubVtbl if1_stub_vtbl =
196 {
197     {
198         &IID_if1,
199         &if1_server_info,
200         5,
201         &if1_table[-3]
202     },
203     {
204         CStdStubBuffer_QueryInterface,
205         CStdStubBuffer_AddRef,
206         test_CStdStubBuffer_Release,
207         CStdStubBuffer_Connect,
208         CStdStubBuffer_Disconnect,
209         CStdStubBuffer_Invoke,
210         CStdStubBuffer_IsIIDSupported,
211         CStdStubBuffer_CountRefs,
212         CStdStubBuffer_DebugServerQueryInterface,
213         CStdStubBuffer_DebugServerRelease
214     }
215 };
216 
217 static CINTERFACE_PROXY_VTABLE(13) if2_proxy_vtbl =
218 {
219     { &IID_if2 },
220     {   IUnknown_QueryInterface_Proxy,
221         IUnknown_AddRef_Proxy,
222         IUnknown_Release_Proxy ,
223         0,
224         0,
225         0,
226         0,
227         0,
228         0,
229         0,
230         0,
231         0,
232         0
233     }
234 };
235 
236 static const unsigned short if2_FormatStringOffsetTable[] =
237     {
238     (unsigned short) -1,
239     (unsigned short) -1,
240     (unsigned short) -1,
241     (unsigned short) -1,
242     (unsigned short) -1,
243     (unsigned short) -1,
244     (unsigned short) -1,
245     (unsigned short) -1,
246     (unsigned short) -1,
247     (unsigned short) -1,
248     0
249     };
250 
251 static const MIDL_SERVER_INFO if2_server_info =
252     {
253     &Object_StubDesc,
254     0,
255     __MIDL_ProcFormatString.Format,
256     &if2_FormatStringOffsetTable[-3],
257     0,
258     0,
259     0,
260     0};
261 
262 
263 static const PRPC_STUB_FUNCTION if2_table[] =
264 {
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,
272     STUB_FORWARDING_FUNCTION,
273     STUB_FORWARDING_FUNCTION,
274     STUB_FORWARDING_FUNCTION
275 };
276 
277 static CInterfaceStubVtbl if2_stub_vtbl =
278 {
279     {
280         &IID_if2,
281         &if2_server_info,
282         13,
283         &if2_table[-3]
284     },
285     { 0, 0, test_CStdStubBuffer2_Release, 0, 0, 0, 0, 0, 0, 0 }
286 };
287 
288 static CINTERFACE_PROXY_VTABLE(5) if3_proxy_vtbl =
289 {
290     { &IID_if3 },
291     {   IUnknown_QueryInterface_Proxy,
292         IUnknown_AddRef_Proxy,
293         IUnknown_Release_Proxy ,
294         if1_fn1_Proxy,
295         0
296     }
297 };
298 
299 
300 static const unsigned short if3_FormatStringOffsetTable[] =
301     {
302     0,
303     0
304     };
305 
306 static const MIDL_SERVER_INFO if3_server_info =
307     {
308     &Object_StubDesc,
309     0,
310     __MIDL_ProcFormatString.Format,
311     &if3_FormatStringOffsetTable[-3],
312     0,
313     0,
314     0,
315     0};
316 
317 static CInterfaceStubVtbl if3_stub_vtbl =
318 {
319     {
320         &IID_if3,
321         &if3_server_info,
322         5,
323         &if1_table[-3]
324     },
325     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
326 };
327 
328 static CINTERFACE_PROXY_VTABLE(7) if4_proxy_vtbl =
329 {
330     { &IID_if4 },
331     {   IUnknown_QueryInterface_Proxy,
332         IUnknown_AddRef_Proxy,
333         IUnknown_Release_Proxy ,
334         0,
335         0,
336         0,
337         0
338     }
339 };
340 
341 static const unsigned short if4_FormatStringOffsetTable[] =
342     {
343     (unsigned short) -1,
344     (unsigned short) -1,
345     (unsigned short) -1,
346     (unsigned short) -1,
347     0
348     };
349 
350 static const MIDL_SERVER_INFO if4_server_info =
351     {
352     &Object_StubDesc,
353     0,
354     __MIDL_ProcFormatString.Format,
355     &if4_FormatStringOffsetTable[-3],
356     0,
357     0,
358     0,
359     0};
360 
361 static CInterfaceStubVtbl if4_stub_vtbl =
362 {
363     {
364         &IID_if4,
365         &if4_server_info,
366         7,
367         &if2_table[-3]
368     },
369     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
370 };
371 
372 static const CInterfaceProxyVtbl *cstub_ProxyVtblList[] =
373 {
374     (const CInterfaceProxyVtbl *) &if1_proxy_vtbl,
375     (const CInterfaceProxyVtbl *) &if2_proxy_vtbl,
376     (const CInterfaceProxyVtbl *) &if3_proxy_vtbl,
377     (const CInterfaceProxyVtbl *) &if4_proxy_vtbl,
378     NULL
379 };
380 
381 static const CInterfaceStubVtbl *cstub_StubVtblList[] =
382 {
383     &if1_stub_vtbl,
384     &if2_stub_vtbl,
385     &if3_stub_vtbl,
386     &if4_stub_vtbl,
387     NULL
388 };
389 
390 static PCInterfaceName const if_name_list[] =
391 {
392     "if1",
393     "if2",
394     "if3",
395     "if4",
396     NULL
397 };
398 
399 static const IID *base_iid_list[] =
400 {
401     NULL,
402     &IID_ITypeLib,
403     NULL,
404     &IID_IDispatch,
405     NULL
406 };
407 
408 #define cstub_CHECK_IID(n)     IID_GENERIC_CHECK_IID( cstub, pIID, n)
409 
iid_lookup(const IID * pIID,int * pIndex)410 static int __stdcall iid_lookup( const IID * pIID, int * pIndex )
411 {
412     IID_BS_LOOKUP_SETUP
413 
414     IID_BS_LOOKUP_INITIAL_TEST( cstub, 4, 4 )
415     IID_BS_LOOKUP_NEXT_TEST( cstub, 2 )
416     IID_BS_LOOKUP_NEXT_TEST( cstub, 1 )
417     IID_BS_LOOKUP_RETURN_RESULT( cstub, 4, *pIndex )
418 
419 }
420 
421 
check_address(void * actual,void * expected)422 static BOOL check_address(void *actual, void *expected)
423 {
424     static void *ole32_start = NULL;
425     static void *ole32_end = NULL;
426     static void *combase_start = NULL;
427     static void *combase_end = NULL;
428 
429     if (actual == expected)
430         return TRUE;
431 
432     /* On Win7, actual can be located inside ole32.dll */
433     if (ole32_start == NULL || ole32_end == NULL)
434     {
435         PIMAGE_NT_HEADERS nt_headers;
436         ole32_start = (void *) GetModuleHandleA("ole32.dll");
437         if (ole32_start == NULL)
438             return FALSE;
439         nt_headers = (PIMAGE_NT_HEADERS)((char *) ole32_start + ((PIMAGE_DOS_HEADER) ole32_start)->e_lfanew);
440         ole32_end = (void *)((char *) ole32_start + nt_headers->OptionalHeader.SizeOfImage);
441     }
442 
443     if (ole32_start <= actual && actual < ole32_end)
444         return TRUE;
445 
446     /* On Win8, actual can be located inside combase.dll */
447     if (combase_start == NULL || combase_end == NULL)
448     {
449         PIMAGE_NT_HEADERS nt_headers;
450         combase_start = (void *) GetModuleHandleA("combase.dll");
451         if (combase_start == NULL)
452             return FALSE;
453         nt_headers = (PIMAGE_NT_HEADERS)((char *) combase_start + ((PIMAGE_DOS_HEADER) combase_start)->e_lfanew);
454         combase_end = (void *)((char *) combase_start + nt_headers->OptionalHeader.SizeOfImage);
455     }
456 
457     return (combase_start <= actual && actual < combase_end);
458 }
459 
460 static const ExtendedProxyFileInfo my_proxy_file_info =
461 {
462     (const PCInterfaceProxyVtblList *) &cstub_ProxyVtblList,
463     (const PCInterfaceStubVtblList *) &cstub_StubVtblList,
464     (const PCInterfaceName *) &if_name_list,
465     (const IID **) &base_iid_list,
466     &iid_lookup,
467     4,
468     1,
469     NULL,
470     0,
471     0,
472     0
473 };
474 
475 static const ProxyFileInfo *proxy_file_list[] = {
476     &my_proxy_file_info,
477     NULL
478 };
479 
480 
test_NdrDllGetClassObject(void)481 static IPSFactoryBuffer *test_NdrDllGetClassObject(void)
482 {
483     HMODULE rpcrt4 = GetModuleHandleA("rpcrt4.dll");
484     IPSFactoryBuffer *ppsf = NULL;
485     const PCInterfaceProxyVtblList* proxy_vtbl;
486     const PCInterfaceStubVtblList* stub_vtbl;
487     const CLSID CLSID_Unknown = {0x45678, 0x1234, 0x6666, {0xff, 0x67, 0x45, 0x98, 0x76, 0x12, 0x34, 0x56}};
488     static const GUID * const interfaces[] = { &IID_if1, &IID_if2, &IID_if3, &IID_if4 };
489     UINT i;
490     HRESULT r;
491     HMODULE hmod = GetModuleHandleA("rpcrt4.dll");
492     void *CStd_QueryInterface = GetProcAddress(hmod, "CStdStubBuffer_QueryInterface");
493     void *CStd_AddRef = GetProcAddress(hmod, "CStdStubBuffer_AddRef");
494     void *CStd_Release = GetProcAddress(hmod, "NdrCStdStubBuffer_Release");
495     void *CStd_Connect = GetProcAddress(hmod, "CStdStubBuffer_Connect");
496     void *CStd_Disconnect = GetProcAddress(hmod, "CStdStubBuffer_Disconnect");
497     void *CStd_Invoke = GetProcAddress(hmod, "CStdStubBuffer_Invoke");
498     void *CStd_IsIIDSupported = GetProcAddress(hmod, "CStdStubBuffer_IsIIDSupported");
499     void *CStd_CountRefs = GetProcAddress(hmod, "CStdStubBuffer_CountRefs");
500     void *CStd_DebugServerQueryInterface = GetProcAddress(hmod, "CStdStubBuffer_DebugServerQueryInterface");
501     void *CStd_DebugServerRelease = GetProcAddress(hmod, "CStdStubBuffer_DebugServerRelease");
502 
503     r = NdrDllGetClassObject(&CLSID_Unknown, &IID_IPSFactoryBuffer, (void**)&ppsf, proxy_file_list,
504                              &CLSID_psfact, &PSFactoryBuffer);
505     ok(r == CLASS_E_CLASSNOTAVAILABLE, "NdrDllGetClassObject with unknown clsid should have returned CLASS_E_CLASSNOTAVAILABLE instead of 0x%x\n", r);
506     ok(ppsf == NULL, "NdrDllGetClassObject should have set ppsf to NULL on failure\n");
507 
508     r = NdrDllGetClassObject(&CLSID_psfact, &IID_IPSFactoryBuffer, (void**)&ppsf, proxy_file_list,
509                              &CLSID_psfact, &PSFactoryBuffer);
510 
511     ok(r == S_OK, "ret %08x\n", r);
512     ok(ppsf != NULL, "ppsf == NULL\n");
513 
514     proxy_vtbl = PSFactoryBuffer.pProxyFileList[0]->pProxyVtblList;
515     stub_vtbl = PSFactoryBuffer.pProxyFileList[0]->pStubVtblList;
516     ok(PSFactoryBuffer.pProxyFileList == proxy_file_list, "pfl not the same\n");
517     ok(proxy_vtbl == (PCInterfaceProxyVtblList *) &cstub_ProxyVtblList, "proxy vtbllist not the same\n");
518     ok(stub_vtbl == (PCInterfaceStubVtblList *) &cstub_StubVtblList, "stub vtbllist not the same\n");
519 
520     /* if1 is non-delegating, if2 is delegating, if3 is non-delegating
521        but I've zero'ed the vtbl entries, similarly if4 is delegating
522        with zero'ed vtbl entries */
523 
524 #define VTBL_TEST_NOT_CHANGE_TO(name, i)                                  \
525     ok(stub_vtbl[i]->Vtbl.name != CStd_##name, #name "vtbl %d updated %p %p\n", \
526        i, stub_vtbl[i]->Vtbl.name, CStd_##name )
527 #define VTBL_TEST_CHANGE_TO(name, i)                                  \
528     ok(check_address(stub_vtbl[i]->Vtbl.name, CStd_##name), #name "vtbl %d not updated %p %p\n", \
529        i, stub_vtbl[i]->Vtbl.name, CStd_##name )
530 #define VTBL_TEST_ZERO(name, i)                                  \
531     ok(stub_vtbl[i]->Vtbl.name == NULL, #name "vtbl %d not null %p\n", \
532        i, stub_vtbl[i]->Vtbl.name )
533 
534     VTBL_TEST_NOT_CHANGE_TO(QueryInterface, 0);
535     VTBL_TEST_NOT_CHANGE_TO(AddRef, 0);
536     VTBL_TEST_NOT_CHANGE_TO(Release, 0);
537     VTBL_TEST_NOT_CHANGE_TO(Connect, 0);
538     VTBL_TEST_NOT_CHANGE_TO(Disconnect, 0);
539     VTBL_TEST_NOT_CHANGE_TO(Invoke, 0);
540     VTBL_TEST_NOT_CHANGE_TO(IsIIDSupported, 0);
541     VTBL_TEST_NOT_CHANGE_TO(CountRefs, 0);
542     VTBL_TEST_NOT_CHANGE_TO(DebugServerQueryInterface, 0);
543     VTBL_TEST_NOT_CHANGE_TO(DebugServerRelease, 0);
544 
545     VTBL_TEST_CHANGE_TO(QueryInterface, 1);
546     VTBL_TEST_CHANGE_TO(AddRef, 1);
547     VTBL_TEST_NOT_CHANGE_TO(Release, 1);
548     VTBL_TEST_NOT_CHANGE_TO(Connect, 1);
549     VTBL_TEST_NOT_CHANGE_TO(Disconnect, 1);
550     VTBL_TEST_CHANGE_TO(Invoke, 1);
551     VTBL_TEST_CHANGE_TO(IsIIDSupported, 1);
552     VTBL_TEST_NOT_CHANGE_TO(CountRefs, 1);
553     VTBL_TEST_CHANGE_TO(DebugServerQueryInterface, 1);
554     VTBL_TEST_CHANGE_TO(DebugServerRelease, 1);
555 
556     VTBL_TEST_CHANGE_TO(QueryInterface, 2);
557     VTBL_TEST_CHANGE_TO(AddRef, 2);
558     VTBL_TEST_ZERO(Release, 2);
559     VTBL_TEST_CHANGE_TO(Connect, 2);
560     VTBL_TEST_CHANGE_TO(Disconnect, 2);
561     VTBL_TEST_CHANGE_TO(Invoke, 2);
562     VTBL_TEST_CHANGE_TO(IsIIDSupported, 2);
563     VTBL_TEST_CHANGE_TO(CountRefs, 2);
564     VTBL_TEST_CHANGE_TO(DebugServerQueryInterface, 2);
565     VTBL_TEST_CHANGE_TO(DebugServerRelease, 2);
566 
567     VTBL_TEST_CHANGE_TO(QueryInterface, 3);
568     VTBL_TEST_CHANGE_TO(AddRef, 3);
569     VTBL_TEST_ZERO(Release, 3);
570     VTBL_TEST_NOT_CHANGE_TO(Connect, 3);
571     VTBL_TEST_NOT_CHANGE_TO(Disconnect, 3);
572     VTBL_TEST_CHANGE_TO(Invoke, 3);
573     VTBL_TEST_CHANGE_TO(IsIIDSupported, 3);
574     VTBL_TEST_NOT_CHANGE_TO(CountRefs, 3);
575     VTBL_TEST_CHANGE_TO(DebugServerQueryInterface, 3);
576     VTBL_TEST_CHANGE_TO(DebugServerRelease, 3);
577 
578 #define VTBL_PROXY_TEST(i,num,ptr) \
579     ok( check_address(proxy_vtbl[i]->Vtbl[num], (ptr)), "wrong proxy %u func %u %p/%p\n", \
580         (i), (num), proxy_vtbl[i]->Vtbl[num], (ptr) )
581 #define VTBL_PROXY_TEST_NOT_ZERO(i,num) \
582     ok( proxy_vtbl[i]->Vtbl[num] != NULL, "wrong proxy %u func %u is NULL\n", (i), (num))
583 
584     VTBL_PROXY_TEST(0, 0, IUnknown_QueryInterface_Proxy);
585     VTBL_PROXY_TEST(0, 1, IUnknown_AddRef_Proxy);
586     VTBL_PROXY_TEST(0, 2, IUnknown_Release_Proxy);
587     VTBL_PROXY_TEST(0, 3, if1_fn1_Proxy);
588     VTBL_PROXY_TEST(0, 4, if1_fn2_Proxy);
589 
590     VTBL_PROXY_TEST(1, 0, GetProcAddress(rpcrt4,"IUnknown_QueryInterface_Proxy"));
591     VTBL_PROXY_TEST(1, 1, GetProcAddress(rpcrt4,"IUnknown_AddRef_Proxy"));
592     VTBL_PROXY_TEST(1, 2, GetProcAddress(rpcrt4,"IUnknown_Release_Proxy"));
593     VTBL_PROXY_TEST_NOT_ZERO(1, 3);
594     VTBL_PROXY_TEST_NOT_ZERO(1, 4);
595     VTBL_PROXY_TEST_NOT_ZERO(1, 5);
596     VTBL_PROXY_TEST_NOT_ZERO(1, 6);
597     VTBL_PROXY_TEST_NOT_ZERO(1, 7);
598     VTBL_PROXY_TEST_NOT_ZERO(1, 8);
599     VTBL_PROXY_TEST_NOT_ZERO(1, 9);
600     VTBL_PROXY_TEST_NOT_ZERO(1, 10);
601     VTBL_PROXY_TEST_NOT_ZERO(1, 11);
602     VTBL_PROXY_TEST_NOT_ZERO(1, 12);
603 
604     VTBL_PROXY_TEST(2, 0, IUnknown_QueryInterface_Proxy);
605     VTBL_PROXY_TEST(2, 1, IUnknown_AddRef_Proxy);
606     VTBL_PROXY_TEST(2, 2, IUnknown_Release_Proxy);
607     VTBL_PROXY_TEST(2, 3, if1_fn1_Proxy);
608     todo_wine VTBL_PROXY_TEST_NOT_ZERO(2, 4);
609 
610     VTBL_PROXY_TEST(3, 0, GetProcAddress(rpcrt4,"IUnknown_QueryInterface_Proxy"));
611     VTBL_PROXY_TEST(3, 1, GetProcAddress(rpcrt4,"IUnknown_AddRef_Proxy"));
612     VTBL_PROXY_TEST(3, 2, GetProcAddress(rpcrt4,"IUnknown_Release_Proxy"));
613     VTBL_PROXY_TEST_NOT_ZERO(3, 3);
614     VTBL_PROXY_TEST_NOT_ZERO(3, 4);
615     VTBL_PROXY_TEST_NOT_ZERO(3, 5);
616     VTBL_PROXY_TEST_NOT_ZERO(3, 6);
617 
618 #undef VTBL_TEST_NOT_CHANGE_TO
619 #undef VTBL_TEST_CHANGE_TO
620 #undef VTBL_TEST_ZERO
621 #undef VTBL_PROXY_TEST
622 #undef VTBL_PROXY_TEST_NOT_ZERO
623 
624     for (i = 0; i < ARRAY_SIZE(interfaces); i++)
625         ok( proxy_vtbl[i]->header.piid == interfaces[i],
626             "wrong proxy %u iid %p/%p\n", i, proxy_vtbl[i]->header.piid, interfaces[i] );
627 
628     ok(PSFactoryBuffer.RefCount == 1, "ref count %d\n", PSFactoryBuffer.RefCount);
629     IPSFactoryBuffer_Release(ppsf);
630 
631     /* One can also search by IID */
632     r = NdrDllGetClassObject(&IID_if3, &IID_IPSFactoryBuffer, (void**)&ppsf, proxy_file_list,
633                              &CLSID_psfact, &PSFactoryBuffer);
634     ok(r == S_OK, "ret %08x\n", r);
635     ok(ppsf != NULL, "ppsf == NULL\n");
636     IPSFactoryBuffer_Release(ppsf);
637 
638     r = NdrDllGetClassObject(&IID_if3, &IID_IPSFactoryBuffer, (void**)&ppsf, proxy_file_list,
639                              NULL, &PSFactoryBuffer);
640     ok(r == S_OK, "ret %08x\n", r);
641     ok(ppsf != NULL, "ppsf == NULL\n");
642     IPSFactoryBuffer_Release(ppsf);
643 
644     /* but only if the PS factory implements it */
645     r = NdrDllGetClassObject(&IID_IDispatch, &IID_IPSFactoryBuffer, (void**)&ppsf, proxy_file_list,
646                              &CLSID_psfact, &PSFactoryBuffer);
647     ok(r == CLASS_E_CLASSNOTAVAILABLE, "ret %08x\n", r);
648 
649     /* Create it again to return */
650     r = NdrDllGetClassObject(&CLSID_psfact, &IID_IPSFactoryBuffer, (void**)&ppsf, proxy_file_list,
651                              &CLSID_psfact, &PSFactoryBuffer);
652     ok(r == S_OK, "ret %08x\n", r);
653     ok(ppsf != NULL, "ppsf == NULL\n");
654 
655     /* Because this PS factory is not loaded as a dll in the normal way, Windows 8 / 10
656        get confused and will crash when one of the proxies for the delegated ifaces is created.
657        Registering the ifaces fixes this (in fact calling CoRegisterPSClsid() with any IID / CLSID is enough). */
658 
659     r = CoRegisterPSClsid(&IID_if1, &CLSID_psfact);
660     ok(r == S_OK, "ret %08x\n", r);
661     r = CoRegisterPSClsid(&IID_if2, &CLSID_psfact);
662     ok(r == S_OK, "ret %08x\n", r);
663     r = CoRegisterPSClsid(&IID_if3, &CLSID_psfact);
664     ok(r == S_OK, "ret %08x\n", r);
665     r = CoRegisterPSClsid(&IID_if4, &CLSID_psfact);
666     ok(r == S_OK, "ret %08x\n", r);
667 
668     return ppsf;
669 }
670 
671 static int base_buffer_invoke_called;
base_buffer_Invoke(IRpcStubBuffer * This,RPCOLEMESSAGE * msg,IRpcChannelBuffer * channel)672 static HRESULT WINAPI base_buffer_Invoke(IRpcStubBuffer *This, RPCOLEMESSAGE *msg, IRpcChannelBuffer *channel)
673 {
674     base_buffer_invoke_called++;
675     ok(msg == (RPCOLEMESSAGE*)0xcafebabe, "msg ptr changed\n");
676     ok(channel == (IRpcChannelBuffer*)0xdeadbeef, "channel ptr changed\n");
677     return S_OK; /* returning any failure here results in an exception */
678 }
679 
680 static IRpcStubBufferVtbl base_buffer_vtbl = {
681     (void*)0xcafebab0,
682     (void*)0xcafebab1,
683     (void*)0xcafebab2,
684     (void*)0xcafebab3,
685     (void*)0xcafebab4,
686     base_buffer_Invoke,
687     (void*)0xcafebab6,
688     (void*)0xcafebab7,
689     (void*)0xcafebab8,
690     (void*)0xcafebab9
691 };
692 
test_NdrStubForwardingFunction(void)693 static void test_NdrStubForwardingFunction(void)
694 {
695     void *This[5];
696     void *real_this;
697     IRpcChannelBuffer *channel = (IRpcChannelBuffer*)0xdeadbeef;
698     RPC_MESSAGE *msg = (RPC_MESSAGE*)0xcafebabe;
699     DWORD *phase = (DWORD*)0x12345678;
700     IRpcStubBufferVtbl *base_buffer_vtbl_ptr = &base_buffer_vtbl;
701     IRpcStubBuffer *base_stub_buffer = (IRpcStubBuffer*)&base_buffer_vtbl_ptr;
702 
703     memset(This, 0xcc, sizeof(This));
704     This[0] = base_stub_buffer;
705     real_this = &This[1];
706 
707     NdrStubForwardingFunction( real_this, channel, msg, phase );
708     ok(base_buffer_invoke_called == 1, "base_buffer_invoke called %d times\n", base_buffer_invoke_called);
709 
710 }
711 
create_stub(IPSFactoryBuffer * ppsf,REFIID iid,IUnknown * obj,HRESULT expected_result)712 static IRpcStubBuffer *create_stub(IPSFactoryBuffer *ppsf, REFIID iid, IUnknown *obj, HRESULT expected_result)
713 {
714     IRpcStubBuffer *pstub = NULL;
715     HRESULT r;
716 
717     r = IPSFactoryBuffer_CreateStub(ppsf, iid, obj, &pstub);
718     ok(r == expected_result, "CreateStub returned %08x expected %08x\n", r, expected_result);
719     return pstub;
720 }
721 
create_stub_test_QI(IUnknown * This,REFIID iid,void ** ppv)722 static HRESULT WINAPI create_stub_test_QI(IUnknown *This, REFIID iid, void **ppv)
723 {
724     ok(IsEqualIID(iid, &IID_if1), "incorrect iid\n");
725     *ppv = (void*)0xdeadbeef;
726     return S_OK;
727 }
728 
729 static IUnknownVtbl create_stub_test_vtbl =
730 {
731     create_stub_test_QI,
732     NULL,
733     NULL
734 };
735 
create_stub_test_fail_QI(IUnknown * This,REFIID iid,void ** ppv)736 static HRESULT WINAPI create_stub_test_fail_QI(IUnknown *This, REFIID iid, void **ppv)
737 {
738     ok(IsEqualIID(iid, &IID_if1), "incorrect iid\n");
739     *ppv = NULL;
740     return E_NOINTERFACE;
741 }
742 
743 static IUnknownVtbl create_stub_test_fail_vtbl =
744 {
745     create_stub_test_fail_QI,
746     NULL,
747     NULL
748 };
749 
750 struct dummy_unknown
751 {
752     IUnknown IUnknown_iface;
753     LONG ref;
754 };
755 
impl_from_IUnknown(IUnknown * iface)756 static inline struct dummy_unknown *impl_from_IUnknown(IUnknown *iface)
757 {
758     return CONTAINING_RECORD(iface, struct dummy_unknown, IUnknown_iface);
759 }
760 
dummy_QueryInterface(IUnknown * This,REFIID iid,void ** ppv)761 static HRESULT WINAPI dummy_QueryInterface(IUnknown *This, REFIID iid, void **ppv)
762 {
763     *ppv = NULL;
764     return E_NOINTERFACE;
765 }
766 
dummy_AddRef(LPUNKNOWN iface)767 static ULONG WINAPI dummy_AddRef(LPUNKNOWN iface)
768 {
769     struct dummy_unknown *this = impl_from_IUnknown(iface);
770     return InterlockedIncrement( &this->ref );
771 }
772 
dummy_Release(LPUNKNOWN iface)773 static ULONG WINAPI dummy_Release(LPUNKNOWN iface)
774 {
775     struct dummy_unknown *this = impl_from_IUnknown(iface);
776     return InterlockedDecrement( &this->ref );
777 }
778 
779 static IUnknownVtbl dummy_unknown_vtbl =
780 {
781     dummy_QueryInterface,
782     dummy_AddRef,
783     dummy_Release
784 };
785 static struct dummy_unknown dummy_unknown = { { &dummy_unknown_vtbl }, 0 };
786 
create_proxy_test(IPSFactoryBuffer * ppsf,REFIID iid,const void * expected_vtbl)787 static void create_proxy_test( IPSFactoryBuffer *ppsf, REFIID iid, const void *expected_vtbl )
788 {
789     IRpcProxyBuffer *proxy = NULL;
790     IUnknown *iface = NULL;
791     HRESULT r;
792     ULONG count;
793 
794     r = IPSFactoryBuffer_CreateProxy(ppsf, NULL, iid, &proxy, (void **)&iface);
795     ok( r == S_OK, "IPSFactoryBuffer_CreateProxy failed %x\n", r );
796     ok( *(void **)iface == expected_vtbl, "wrong iface pointer %p/%p\n", *(void **)iface, expected_vtbl );
797     count = IUnknown_Release( iface );
798     ok( count == 1, "wrong refcount %u\n", count );
799     count = IRpcProxyBuffer_Release( proxy );
800     ok( count == 0, "wrong refcount %u\n", count );
801 
802     dummy_unknown.ref = 4;
803     r = IPSFactoryBuffer_CreateProxy(ppsf, &dummy_unknown.IUnknown_iface, iid, &proxy,
804             (void **)&iface);
805     ok( r == S_OK, "IPSFactoryBuffer_CreateProxy failed %x\n", r );
806     ok( dummy_unknown.ref == 5, "wrong refcount %u\n", dummy_unknown.ref );
807     ok( *(void **)iface == expected_vtbl, "wrong iface pointer %p/%p\n", *(void **)iface, expected_vtbl );
808     count = IUnknown_Release( iface );
809     ok( count == 4, "wrong refcount %u\n", count );
810     ok( dummy_unknown.ref == 4, "wrong refcount %u\n", dummy_unknown.ref );
811     count = IRpcProxyBuffer_Release( proxy );
812     ok( count == 0, "wrong refcount %u\n", count );
813     ok( dummy_unknown.ref == 4, "wrong refcount %u\n", dummy_unknown.ref );
814 }
815 
test_CreateProxy(IPSFactoryBuffer * ppsf)816 static void test_CreateProxy( IPSFactoryBuffer *ppsf )
817 {
818     create_proxy_test( ppsf, &IID_if1, if1_proxy_vtbl.Vtbl );
819     create_proxy_test( ppsf, &IID_if2, if2_proxy_vtbl.Vtbl );
820     create_proxy_test( ppsf, &IID_if3, if3_proxy_vtbl.Vtbl );
821     create_proxy_test( ppsf, &IID_if4, if4_proxy_vtbl.Vtbl );
822 }
823 
test_CreateStub(IPSFactoryBuffer * ppsf)824 static void test_CreateStub(IPSFactoryBuffer *ppsf)
825 {
826     IUnknownVtbl *vtbl = &create_stub_test_vtbl;
827     IUnknown *obj = (IUnknown*)&vtbl;
828     IRpcStubBuffer *pstub = create_stub(ppsf, &IID_if1, obj, S_OK);
829     CStdStubBuffer *cstd_stub = (CStdStubBuffer*)pstub;
830     const CInterfaceStubHeader *header = &CONTAINING_RECORD(cstd_stub->lpVtbl, const CInterfaceStubVtbl, Vtbl)->header;
831 
832     ok(IsEqualIID(header->piid, &IID_if1), "header iid differs\n");
833     ok(cstd_stub->RefCount == 1, "ref count %d\n", cstd_stub->RefCount);
834     /* 0xdeadbeef returned from create_stub_test_QI */
835     ok(cstd_stub->pvServerObject == (void*)0xdeadbeef, "pvServerObject %p\n", cstd_stub->pvServerObject);
836     ok(cstd_stub->pPSFactory != NULL, "pPSFactory was NULL\n");
837     cstd_stub->pvServerObject = NULL;
838     IRpcStubBuffer_Release(pstub);
839 
840     vtbl = &create_stub_test_fail_vtbl;
841     pstub = create_stub(ppsf, &IID_if1, obj, E_NOINTERFACE);
842     ok(pstub == S_OK, "create_stub failed: %u\n", GetLastError());
843 
844 }
845 
connect_test_orig_QI(IUnknown * This,REFIID iid,void ** ppv)846 static HRESULT WINAPI connect_test_orig_QI(IUnknown *This, REFIID iid, void **ppv)
847 {
848     ok(IsEqualIID(iid, &IID_if1) ||
849        IsEqualIID(iid, &IID_if2), "incorrect iid\n");
850     *ppv = (void*)This;
851     return S_OK;
852 }
853 
854 static int connect_test_orig_release_called;
connect_test_orig_release(IUnknown * This)855 static ULONG WINAPI connect_test_orig_release(IUnknown *This)
856 {
857     connect_test_orig_release_called++;
858     return 0;
859 }
860 
861 static IUnknownVtbl connect_test_orig_vtbl =
862 {
863     connect_test_orig_QI,
864     NULL,
865     connect_test_orig_release
866 };
867 
connect_test_new_QI(IUnknown * This,REFIID iid,void ** ppv)868 static HRESULT WINAPI connect_test_new_QI(IUnknown *This, REFIID iid, void **ppv)
869 {
870     ok(IsEqualIID(iid, &IID_if1) ||
871        IsEqualIID(iid, &IID_if2), "incorrect iid\n");
872     *ppv = (void*)0xcafebabe;
873     return S_OK;
874 }
875 
876 static IUnknownVtbl connect_test_new_vtbl =
877 {
878     connect_test_new_QI,
879     NULL,
880     NULL
881 };
882 
connect_test_new_fail_QI(IUnknown * This,REFIID iid,void ** ppv)883 static HRESULT WINAPI connect_test_new_fail_QI(IUnknown *This, REFIID iid, void **ppv)
884 {
885     ok(IsEqualIID(iid, &IID_if1), "incorrect iid\n");
886     *ppv = (void*)0xdeadbeef;
887     return E_NOINTERFACE;
888 }
889 
890 static IUnknownVtbl connect_test_new_fail_vtbl =
891 {
892     connect_test_new_fail_QI,
893     NULL,
894     NULL
895 };
896 
897 static int connect_test_base_Connect_called;
connect_test_base_Connect(IRpcStubBuffer * pstub,IUnknown * obj)898 static HRESULT WINAPI connect_test_base_Connect(IRpcStubBuffer *pstub, IUnknown *obj)
899 {
900     connect_test_base_Connect_called++;
901     ok(*(void**)obj == (void*)0xbeefcafe, "unexpected obj %p\n", obj);
902     return S_OK;
903 }
904 
905 static IRpcStubBufferVtbl connect_test_base_stub_buffer_vtbl =
906 {
907     (void*)0xcafebab0,
908     (void*)0xcafebab1,
909     (void*)0xcafebab2,
910     connect_test_base_Connect,
911     (void*)0xcafebab4,
912     (void*)0xcafebab5,
913     (void*)0xcafebab6,
914     (void*)0xcafebab7,
915     (void*)0xcafebab8,
916     (void*)0xcafebab9
917 };
918 
test_Connect(IPSFactoryBuffer * ppsf)919 static void test_Connect(IPSFactoryBuffer *ppsf)
920 {
921     IUnknownVtbl *orig_vtbl = &connect_test_orig_vtbl;
922     IUnknownVtbl *new_vtbl = &connect_test_new_vtbl;
923     IUnknownVtbl *new_fail_vtbl = &connect_test_new_fail_vtbl;
924     IUnknown *obj = (IUnknown*)&orig_vtbl;
925     IRpcStubBuffer *pstub = create_stub(ppsf, &IID_if1, obj, S_OK);
926     CStdStubBuffer *cstd_stub = (CStdStubBuffer*)pstub;
927     IRpcStubBufferVtbl *base_stub_buf_vtbl = &connect_test_base_stub_buffer_vtbl;
928     HRESULT r;
929 
930     obj = (IUnknown*)&new_vtbl;
931     r = IRpcStubBuffer_Connect(pstub, obj);
932     ok(r == S_OK, "r %08x\n", r);
933     ok(connect_test_orig_release_called == 1, "release called %d\n", connect_test_orig_release_called);
934     ok(cstd_stub->pvServerObject == (void*)0xcafebabe, "pvServerObject %p\n", cstd_stub->pvServerObject);
935 
936     cstd_stub->pvServerObject = (IUnknown*)&orig_vtbl;
937     obj = (IUnknown*)&new_fail_vtbl;
938     r = IRpcStubBuffer_Connect(pstub, obj);
939     ok(r == E_NOINTERFACE, "r %08x\n", r);
940     ok(cstd_stub->pvServerObject == (void*)0xdeadbeef, "pvServerObject %p\n", cstd_stub->pvServerObject);
941     ok(connect_test_orig_release_called == 2, "release called %d\n", connect_test_orig_release_called);
942 
943     /* Now use a delegated stub.
944 
945        We know from the NdrStubForwardFunction test that
946        (void**)pstub-1 is the base interface stub buffer.  This shows
947        that (void**)pstub-2 contains the address of a vtable that gets
948        passed to the base interface's Connect method.  Note that
949        (void**)pstub-2 itself gets passed to Connect and not
950        *((void**)pstub-2), so it should contain the vtable ptr and not
951        an interface ptr. */
952 
953     obj = (IUnknown*)&orig_vtbl;
954     pstub = create_stub(ppsf, &IID_if2, obj, S_OK);
955     *((void**)pstub-1) = &base_stub_buf_vtbl;
956     *((void**)pstub-2) = (void*)0xbeefcafe;
957 
958     obj = (IUnknown*)&new_vtbl;
959     r = IRpcStubBuffer_Connect(pstub, obj);
960     ok(r == S_OK, "r %08x\n", r);
961     ok(connect_test_base_Connect_called == 1, "connect_test_bsae_Connect called %d times\n",
962        connect_test_base_Connect_called);
963     ok(connect_test_orig_release_called == 3, "release called %d\n", connect_test_orig_release_called);
964     cstd_stub = (CStdStubBuffer*)pstub;
965     ok(cstd_stub->pvServerObject == (void*)0xcafebabe, "pvServerObject %p\n", cstd_stub->pvServerObject);
966 }
967 
test_Disconnect(IPSFactoryBuffer * ppsf)968 static void test_Disconnect(IPSFactoryBuffer *ppsf)
969 {
970     IUnknownVtbl *orig_vtbl = &connect_test_orig_vtbl;
971     IUnknown *obj = (IUnknown*)&orig_vtbl;
972     IRpcStubBuffer *pstub = create_stub(ppsf, &IID_if1, obj, S_OK);
973     CStdStubBuffer *cstd_stub = (CStdStubBuffer*)pstub;
974 
975     connect_test_orig_release_called = 0;
976     IRpcStubBuffer_Disconnect(pstub);
977     ok(connect_test_orig_release_called == 1, "release called %d\n", connect_test_orig_release_called);
978     ok(cstd_stub->pvServerObject == NULL, "pvServerObject %p\n", cstd_stub->pvServerObject);
979     IRpcStubBuffer_Release(pstub);
980 }
981 
982 
983 static int release_test_psfacbuf_release_called;
release_test_pretend_psfacbuf_release(IUnknown * pUnk)984 static ULONG WINAPI release_test_pretend_psfacbuf_release(IUnknown *pUnk)
985 {
986     release_test_psfacbuf_release_called++;
987     return 1;
988 }
989 
990 static IUnknownVtbl release_test_pretend_psfacbuf_vtbl =
991 {
992     NULL,
993     NULL,
994     release_test_pretend_psfacbuf_release
995 };
996 
test_Release(IPSFactoryBuffer * ppsf)997 static void test_Release(IPSFactoryBuffer *ppsf)
998 {
999     LONG facbuf_refs;
1000     IUnknownVtbl *orig_vtbl = &connect_test_orig_vtbl;
1001     IUnknown *obj = (IUnknown*)&orig_vtbl;
1002     IUnknownVtbl *pretend_psfacbuf_vtbl = &release_test_pretend_psfacbuf_vtbl;
1003     IUnknown *pretend_psfacbuf = (IUnknown *)&pretend_psfacbuf_vtbl;
1004     IRpcStubBuffer *pstub = create_stub(ppsf, &IID_if1, obj, S_OK);
1005     CStdStubBuffer *cstd_stub = (CStdStubBuffer*)pstub;
1006 
1007     facbuf_refs = PSFactoryBuffer.RefCount;
1008 
1009     /* This shows that NdrCStdStubBuffer_Release doesn't call Disconnect */
1010     ok(cstd_stub->RefCount == 1, "ref count %d\n", cstd_stub->RefCount);
1011     connect_test_orig_release_called = 0;
1012     IRpcStubBuffer_Release(pstub);
1013 todo_wine {
1014     ok(connect_test_orig_release_called == 0, "release called %d\n", connect_test_orig_release_called);
1015 }
1016     ok(PSFactoryBuffer.RefCount == facbuf_refs - 1, "factory buffer refs %d orig %d\n", PSFactoryBuffer.RefCount, facbuf_refs);
1017 
1018     /* This shows that NdrCStdStubBuffer_Release calls Release on its 2nd arg, rather than on This->pPSFactory
1019        (which are usually the same and indeed it's odd that _Release requires this 2nd arg). */
1020     pstub = create_stub(ppsf, &IID_if1, obj, S_OK);
1021     ok(PSFactoryBuffer.RefCount == facbuf_refs, "factory buffer refs %d orig %d\n", PSFactoryBuffer.RefCount, facbuf_refs);
1022     NdrCStdStubBuffer_Release(pstub, (IPSFactoryBuffer*)pretend_psfacbuf);
1023     ok(release_test_psfacbuf_release_called == 1, "pretend_psfacbuf_release called %d\n", release_test_psfacbuf_release_called);
1024     ok(PSFactoryBuffer.RefCount == facbuf_refs, "factory buffer refs %d orig %d\n", PSFactoryBuffer.RefCount, facbuf_refs);
1025 }
1026 
delegating_invoke_test_QI(ITypeLib * pUnk,REFIID iid,void ** ppv)1027 static HRESULT WINAPI delegating_invoke_test_QI(ITypeLib *pUnk, REFIID iid, void** ppv)
1028 {
1029 
1030     *ppv = pUnk;
1031     return S_OK;
1032 }
1033 
delegating_invoke_test_addref(ITypeLib * pUnk)1034 static ULONG WINAPI delegating_invoke_test_addref(ITypeLib *pUnk)
1035 {
1036     return 1;
1037 }
1038 
delegating_invoke_test_release(ITypeLib * pUnk)1039 static ULONG WINAPI delegating_invoke_test_release(ITypeLib *pUnk)
1040 {
1041     return 1;
1042 }
1043 
delegating_invoke_test_get_type_info_count(ITypeLib * pUnk)1044 static UINT WINAPI delegating_invoke_test_get_type_info_count(ITypeLib *pUnk)
1045 {
1046     return 0xabcdef;
1047 }
1048 
1049 static ITypeLibVtbl delegating_invoke_test_obj_vtbl =
1050 {
1051     delegating_invoke_test_QI,
1052     delegating_invoke_test_addref,
1053     delegating_invoke_test_release,
1054     delegating_invoke_test_get_type_info_count,
1055     NULL,
1056     NULL,
1057     NULL,
1058     NULL,
1059     NULL,
1060     NULL,
1061     NULL,
1062     NULL,
1063     NULL
1064 };
1065 
delegating_invoke_chan_query_interface(IRpcChannelBuffer * pchan,REFIID iid,void ** ppv)1066 static HRESULT WINAPI delegating_invoke_chan_query_interface(IRpcChannelBuffer *pchan,
1067                                                              REFIID iid,
1068                                                              void **ppv)
1069 {
1070     ok(0, "call to QueryInterface not expected\n");
1071     return E_NOINTERFACE;
1072 }
1073 
delegating_invoke_chan_add_ref(IRpcChannelBuffer * pchan)1074 static ULONG WINAPI delegating_invoke_chan_add_ref(IRpcChannelBuffer *pchan)
1075 {
1076     return 2;
1077 }
1078 
delegating_invoke_chan_release(IRpcChannelBuffer * pchan)1079 static ULONG WINAPI delegating_invoke_chan_release(IRpcChannelBuffer *pchan)
1080 {
1081     return 1;
1082 }
1083 
delegating_invoke_chan_get_buffer(IRpcChannelBuffer * pchan,RPCOLEMESSAGE * msg,REFIID iid)1084 static HRESULT WINAPI delegating_invoke_chan_get_buffer(IRpcChannelBuffer *pchan,
1085                                                         RPCOLEMESSAGE *msg,
1086                                                         REFIID iid)
1087 {
1088     msg->Buffer = HeapAlloc(GetProcessHeap(), 0, msg->cbBuffer);
1089     return S_OK;
1090 }
1091 
delegating_invoke_chan_send_receive(IRpcChannelBuffer * pchan,RPCOLEMESSAGE * pMessage,ULONG * pStatus)1092 static HRESULT WINAPI delegating_invoke_chan_send_receive(IRpcChannelBuffer *pchan,
1093                                                           RPCOLEMESSAGE *pMessage,
1094                                                           ULONG *pStatus)
1095 {
1096     ok(0, "call to SendReceive not expected\n");
1097     return E_NOTIMPL;
1098 }
1099 
delegating_invoke_chan_free_buffer(IRpcChannelBuffer * pchan,RPCOLEMESSAGE * pMessage)1100 static HRESULT WINAPI delegating_invoke_chan_free_buffer(IRpcChannelBuffer *pchan,
1101                                                          RPCOLEMESSAGE *pMessage)
1102 {
1103     ok(0, "call to FreeBuffer not expected\n");
1104     return E_NOTIMPL;
1105 }
1106 
delegating_invoke_chan_get_dest_ctx(IRpcChannelBuffer * pchan,DWORD * pdwDestContext,void ** ppvDestContext)1107 static HRESULT WINAPI delegating_invoke_chan_get_dest_ctx(IRpcChannelBuffer *pchan,
1108                                                           DWORD *pdwDestContext,
1109                                                           void **ppvDestContext)
1110 {
1111     *pdwDestContext = MSHCTX_LOCAL;
1112     *ppvDestContext = NULL;
1113     return S_OK;
1114 }
1115 
delegating_invoke_chan_is_connected(IRpcChannelBuffer * pchan)1116 static HRESULT WINAPI delegating_invoke_chan_is_connected(IRpcChannelBuffer *pchan)
1117 {
1118     ok(0, "call to IsConnected not expected\n");
1119     return E_NOTIMPL;
1120 }
1121 
1122 static IRpcChannelBufferVtbl delegating_invoke_test_rpc_chan_vtbl =
1123 {
1124     delegating_invoke_chan_query_interface,
1125     delegating_invoke_chan_add_ref,
1126     delegating_invoke_chan_release,
1127     delegating_invoke_chan_get_buffer,
1128     delegating_invoke_chan_send_receive,
1129     delegating_invoke_chan_free_buffer,
1130     delegating_invoke_chan_get_dest_ctx,
1131     delegating_invoke_chan_is_connected
1132 };
1133 
test_delegating_Invoke(IPSFactoryBuffer * ppsf)1134 static void test_delegating_Invoke(IPSFactoryBuffer *ppsf)
1135 {
1136     ITypeLibVtbl *obj_vtbl = &delegating_invoke_test_obj_vtbl;
1137     IUnknown *obj = (IUnknown*)&obj_vtbl;
1138     IRpcStubBuffer *pstub = create_stub(ppsf, &IID_if2, obj, S_OK);
1139     IRpcChannelBufferVtbl *pchan_vtbl = &delegating_invoke_test_rpc_chan_vtbl;
1140     IRpcChannelBuffer *pchan = (IRpcChannelBuffer *)&pchan_vtbl;
1141     HRESULT r = E_FAIL;
1142     RPCOLEMESSAGE msg;
1143 
1144     memset(&msg, 0, sizeof(msg));
1145     msg.dataRepresentation = NDR_LOCAL_DATA_REPRESENTATION;
1146     msg.iMethod = 3;
1147     r = IRpcStubBuffer_Invoke(pstub, &msg, pchan);
1148     ok(r == S_OK, "ret %08x\n", r);
1149     if(r == S_OK)
1150     {
1151         ok(*(DWORD*)msg.Buffer == 0xabcdef, "buf[0] %08x\n", *(DWORD*)msg.Buffer);
1152         ok(*((DWORD*)msg.Buffer + 1) == S_OK, "buf[1] %08x\n", *((DWORD*)msg.Buffer + 1));
1153     }
1154     /* free the buffer allocated by delegating_invoke_chan_get_buffer */
1155     HeapFree(GetProcessHeap(), 0, msg.Buffer);
1156     IRpcStubBuffer_Release(pstub);
1157 }
1158 static const CInterfaceProxyVtbl *cstub_ProxyVtblList2[] =
1159 {
1160     NULL
1161 };
1162 
1163 static const CInterfaceStubVtbl *cstub_StubVtblList2[] =
1164 {
1165     NULL
1166 };
1167 
1168 static PCInterfaceName const if_name_list2[] =
1169 {
1170     NULL
1171 };
1172 
1173 static const IID *base_iid_list2[] =
1174 {
1175     NULL,
1176 };
1177 
1178 static const ExtendedProxyFileInfo my_proxy_file_info2 =
1179 {
1180     (const PCInterfaceProxyVtblList *) &cstub_ProxyVtblList2,
1181     (const PCInterfaceStubVtblList *) &cstub_StubVtblList2,
1182     (const PCInterfaceName *) &if_name_list2,
1183     (const IID **) &base_iid_list2,
1184     &iid_lookup,
1185     0,
1186     1,
1187     NULL,
1188     0,
1189     0,
1190     0
1191 };
1192 
1193 static const ProxyFileInfo *proxy_file_list2[] = {
1194     &my_proxy_file_info2,
1195     NULL
1196 };
1197 
test_NdrDllRegisterProxy(void)1198 static void test_NdrDllRegisterProxy( void )
1199 {
1200     HRESULT res;
1201     const ExtendedProxyFileInfo *pf;
1202     HMODULE hmod = GetModuleHandleA(NULL);
1203 
1204 
1205     res = NdrDllRegisterProxy(NULL, NULL, NULL);
1206     ok(res == E_HANDLE, "Incorrect return code %x\n",res);
1207     pf = NULL;
1208     res = NdrDllRegisterProxy(hmod, &pf, NULL);
1209     ok(res == E_NOINTERFACE, "Incorrect return code %x\n",res);
1210     res = NdrDllRegisterProxy(hmod, proxy_file_list2, NULL);
1211     ok(res == E_NOINTERFACE, "Incorrect return code %x\n",res);
1212     /* This fails on Vista and Windows 7 due to permissions */
1213     res = NdrDllRegisterProxy(hmod, proxy_file_list, NULL);
1214     ok(res == S_OK || res == E_ACCESSDENIED, "NdrDllRegisterProxy failed %x\n",res);
1215     if (res == S_OK)
1216     {
1217         res = NdrDllUnregisterProxy(hmod,proxy_file_list, NULL);
1218         ok(res == S_OK, "NdrDllUnregisterProxy failed %x\n",res);
1219     }
1220 }
1221 
create_process(const char * arg)1222 static HANDLE create_process(const char *arg)
1223 {
1224     PROCESS_INFORMATION pi;
1225     STARTUPINFOA si = {0};
1226     char cmdline[200];
1227     char **argv;
1228     BOOL ret;
1229 
1230     si.cb = sizeof(si);
1231     winetest_get_mainargs(&argv);
1232     sprintf(cmdline, "\"%s\" %s %s", argv[0], argv[1], arg);
1233     ret = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
1234     ok(ret, "CreateProcess failed: %u\n", GetLastError());
1235     CloseHandle(pi.hThread);
1236     return pi.hProcess;
1237 }
1238 
1239 DEFINE_GUID(CLSID_test1,0xdeadf00d,0x0001,0x44c7,0x85,0x0f,0x2a,0x0f,0x46,0x5c,0x0c,0x6c);
1240 
test1_QueryInterface(ITest1 * iface,REFIID iid,void ** out)1241 static HRESULT WINAPI test1_QueryInterface(ITest1 *iface, REFIID iid, void **out)
1242 {
1243     if (winetest_debug > 1) trace("%s\n", wine_dbgstr_guid(iid));
1244     if (IsEqualGUID(iid, &IID_IUnknown) || IsEqualGUID(iid, &IID_ITest1))
1245     {
1246         *out = iface;
1247         return S_OK;
1248     }
1249     *out = NULL;
1250     return E_NOINTERFACE;
1251 }
1252 
test1_AddRef(ITest1 * iface)1253 static ULONG WINAPI test1_AddRef(ITest1 *iface)
1254 {
1255     return 2;
1256 }
1257 
test1_Release(ITest1 * iface)1258 static ULONG WINAPI test1_Release(ITest1 *iface)
1259 {
1260     return 1;
1261 }
1262 
test1_GetClassID(ITest1 * iface,CLSID * clsid)1263 static HRESULT WINAPI test1_GetClassID(ITest1 *iface, CLSID *clsid)
1264 {
1265     *clsid = CLSID_test1;
1266     return S_OK;
1267 }
1268 
test1_square(ITest1 * iface,int x)1269 static int WINAPI test1_square(ITest1 *iface, int x)
1270 {
1271     return x * x;
1272 }
1273 
1274 static const ITest1Vtbl test1_vtbl =
1275 {
1276     test1_QueryInterface,
1277     test1_AddRef,
1278     test1_Release,
1279     test1_GetClassID,
1280     test1_square,
1281 };
1282 
test_cf_QueryInterface(IClassFactory * iface,REFIID iid,void ** out)1283 static HRESULT WINAPI test_cf_QueryInterface(IClassFactory *iface, REFIID iid, void **out)
1284 {
1285     if (IsEqualGUID(iid, &IID_IUnknown) || IsEqualGUID(iid, &IID_IClassFactory))
1286     {
1287         *out = iface;
1288         return S_OK;
1289     }
1290     *out = NULL;
1291     return E_NOINTERFACE;
1292 }
1293 
test_cf_AddRef(IClassFactory * iface)1294 static ULONG WINAPI test_cf_AddRef(IClassFactory *iface)
1295 {
1296     return 2;
1297 }
1298 
test_cf_Release(IClassFactory * iface)1299 static ULONG WINAPI test_cf_Release(IClassFactory *iface)
1300 {
1301     return 1;
1302 }
1303 
test_cf_CreateInstance(IClassFactory * iface,IUnknown * outer,REFIID iid,void ** out)1304 static HRESULT WINAPI test_cf_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID iid, void **out)
1305 {
1306     ITest1 *obj = heap_alloc(sizeof(*obj));
1307 
1308     obj->lpVtbl = &test1_vtbl;
1309 
1310     return ITest1_QueryInterface(obj, iid, out);
1311 }
1312 
test_cf_LockServer(IClassFactory * iface,BOOL lock)1313 static HRESULT WINAPI test_cf_LockServer(IClassFactory *iface, BOOL lock)
1314 {
1315     return S_OK;
1316 }
1317 
1318 static const IClassFactoryVtbl test_cf_vtbl =
1319 {
1320     test_cf_QueryInterface,
1321     test_cf_AddRef,
1322     test_cf_Release,
1323     test_cf_CreateInstance,
1324     test_cf_LockServer,
1325 };
1326 
1327 static IClassFactory test_cf = { &test_cf_vtbl };
1328 
1329 extern CStdPSFactoryBuffer gPFactory;
1330 extern const ProxyFileInfo * aProxyFileList;
1331 
local_server_proc(void)1332 static void local_server_proc(void)
1333 {
1334     DWORD obj_cookie, ps_cookie, index;
1335     HANDLE stop_event, ready_event;
1336     IPSFactoryBuffer *ps;
1337     HRESULT hr;
1338 
1339     stop_event = OpenEventA(EVENT_ALL_ACCESS, FALSE, "wine_cstub_test_server_stop");
1340     ready_event = OpenEventA(EVENT_ALL_ACCESS, FALSE, "wine_cstub_test_server_ready");
1341 
1342     CoInitialize(NULL);
1343 
1344     hr = CoRegisterClassObject(&CLSID_test1, (IUnknown *)&test_cf,
1345         CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &obj_cookie);
1346     ok(hr == S_OK, "got %#x\n", hr);
1347 
1348     hr = NdrDllGetClassObject(&CLSID_test_ps, &IID_IPSFactoryBuffer, (void **)&ps,
1349         &aProxyFileList, &CLSID_test_ps, &gPFactory);
1350     ok(hr == S_OK, "got %#x\n", hr);
1351 
1352     hr = CoRegisterClassObject(&CLSID_test_ps, (IUnknown *)ps,
1353         CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &ps_cookie);
1354     ok(hr == S_OK, "got %#x\n", hr);
1355 
1356     hr = CoRegisterPSClsid(&IID_ITest1, &CLSID_test_ps);
1357     ok(hr == S_OK, "got %#x\n", hr);
1358 
1359     SetEvent(ready_event);
1360 
1361     hr = CoWaitForMultipleHandles(0, 1000, 1, &stop_event, &index);
1362     ok(hr == S_OK, "got %#x\n", hr);
1363     ok(!index, "got %u\n", index);
1364 
1365     hr = CoRevokeClassObject(ps_cookie);
1366     ok(hr == S_OK, "got %#x\n", hr);
1367 
1368     hr = CoRevokeClassObject(obj_cookie);
1369     ok(hr == S_OK, "got %#x\n", hr);
1370 
1371     CoUninitialize();
1372     ExitProcess(0);
1373 }
1374 
test_delegated_methods(void)1375 static void test_delegated_methods(void)
1376 {
1377     HANDLE process, stop_event, ready_event;
1378     IPSFactoryBuffer *ps;
1379     ITest1 *test_obj;
1380     DWORD ps_cookie;
1381     CLSID clsid;
1382     HRESULT hr;
1383     int ret;
1384 
1385     stop_event = CreateEventA(NULL, TRUE, FALSE, "wine_cstub_test_server_stop");
1386     ready_event = CreateEventA(NULL, TRUE, FALSE, "wine_cstub_test_server_ready");
1387 
1388     process = create_process("server");
1389     ok(!WaitForSingleObject(ready_event, 1000), "wait failed\n");
1390 
1391     hr = NdrDllGetClassObject(&CLSID_test_ps, &IID_IPSFactoryBuffer, (void **)&ps,
1392         &aProxyFileList, &CLSID_test_ps, &gPFactory);
1393     ok(hr == S_OK, "got %#x\n", hr);
1394 
1395     hr = CoRegisterClassObject(&CLSID_test_ps, (IUnknown *)ps,
1396         CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &ps_cookie);
1397     ok(hr == S_OK, "got %#x\n", hr);
1398 
1399     hr = CoRegisterPSClsid(&IID_ITest1, &CLSID_test_ps);
1400     ok(hr == S_OK, "got %#x\n", hr);
1401 
1402     hr = CoCreateInstance(&CLSID_test1, NULL, CLSCTX_LOCAL_SERVER, &IID_ITest1, (void **)&test_obj);
1403     ok(hr == S_OK, "got %#x\n", hr);
1404 
1405     ret = ITest1_square(test_obj, 3);
1406     ok(ret == 9, "got %d\n", ret);
1407 
1408     hr = ITest1_GetClassID(test_obj, &clsid);
1409     ok(hr == S_OK, "got %#x\n", hr);
1410     ok(IsEqualGUID(&clsid, &CLSID_test1), "got %s\n", wine_dbgstr_guid(&clsid));
1411 
1412     ITest1_Release(test_obj);
1413 
1414     SetEvent(stop_event);
1415     ok(!WaitForSingleObject(process, 1000), "wait failed\n");
1416 
1417     hr = CoRevokeClassObject(ps_cookie);
1418     ok(hr == S_OK, "got %#x\n", hr);
1419 }
1420 
START_TEST(cstub)1421 START_TEST( cstub )
1422 {
1423     IPSFactoryBuffer *ppsf;
1424     int argc;
1425     char **argv;
1426 
1427     argc = winetest_get_mainargs( &argv );
1428     if (argc > 2 && !strcmp(argv[2], "server"))
1429     {
1430         local_server_proc();
1431         return;
1432     }
1433 
1434     OleInitialize(NULL);
1435 
1436     ppsf = test_NdrDllGetClassObject();
1437     test_NdrStubForwardingFunction();
1438     test_CreateProxy(ppsf);
1439     test_CreateStub(ppsf);
1440     test_Connect(ppsf);
1441     test_Disconnect(ppsf);
1442     test_Release(ppsf);
1443     test_delegating_Invoke(ppsf);
1444     test_NdrDllRegisterProxy();
1445     test_delegated_methods();
1446 
1447     OleUninitialize();
1448 }
1449