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