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