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