diff --git a/dlls/rpcrt4/tests/Makefile.in b/dlls/rpcrt4/tests/Makefile.in index 5b80bc3c0af..d8353b6d780 100644 --- a/dlls/rpcrt4/tests/Makefile.in +++ b/dlls/rpcrt4/tests/Makefile.in @@ -1,6 +1,7 @@ TESTDLL = rpcrt4.dll IMPORTS = oleaut32 ole32 rpcrt4 secur32 advapi32 EXTRAIDLFLAGS = --prefix-server=s_ +EXTRADEFS = -DPROXY_DELEGATION C_SRCS = \ cstub.c \ @@ -10,4 +11,6 @@ C_SRCS = \ rpc_async.c \ server.c -IDL_SRCS = server.idl +IDL_SRCS = \ + cstub.idl \ + server.idl diff --git a/dlls/rpcrt4/tests/cstub.c b/dlls/rpcrt4/tests/cstub.c index 7bed308807e..22d45699f98 100644 --- a/dlls/rpcrt4/tests/cstub.c +++ b/dlls/rpcrt4/tests/cstub.c @@ -19,11 +19,10 @@ */ #include +#include -#define PROXY_DELEGATION #define COBJMACROS -#include "wine/test.h" #include #include #include @@ -35,10 +34,22 @@ #include "rpcdce.h" #include "rpcproxy.h" +#include "wine/heap.h" +#include "wine/test.h" + +#include "cstub.h" + static CStdPSFactoryBuffer PSFactoryBuffer; -CSTDSTUBBUFFERRELEASE(&PSFactoryBuffer) -CSTDSTUBBUFFER2RELEASE(&PSFactoryBuffer) +static ULONG WINAPI test_CStdStubBuffer_Release(IRpcStubBuffer *This) +{ + return NdrCStdStubBuffer_Release(This, (IPSFactoryBuffer *)&PSFactoryBuffer); +} + +static ULONG WINAPI test_CStdStubBuffer2_Release(IRpcStubBuffer *This) +{ + return NdrCStdStubBuffer2_Release(This, (IPSFactoryBuffer *)&PSFactoryBuffer); +} static GUID IID_if1 = {0x12345678, 1234, 5678, {12,34,56,78,90,0xab,0xcd,0xef}}; static GUID IID_if2 = {0x12345679, 1234, 5678, {12,34,56,78,90,0xab,0xcd,0xef}}; @@ -186,7 +197,18 @@ static CInterfaceStubVtbl if1_stub_vtbl = 5, &if1_table[-3] }, - { CStdStubBuffer_METHODS } + { + CStdStubBuffer_QueryInterface, + CStdStubBuffer_AddRef, + test_CStdStubBuffer_Release, + CStdStubBuffer_Connect, + CStdStubBuffer_Disconnect, + CStdStubBuffer_Invoke, + CStdStubBuffer_IsIIDSupported, + CStdStubBuffer_CountRefs, + CStdStubBuffer_DebugServerQueryInterface, + CStdStubBuffer_DebugServerRelease + } }; static CINTERFACE_PROXY_VTABLE(13) if2_proxy_vtbl = @@ -257,7 +279,7 @@ static CInterfaceStubVtbl if2_stub_vtbl = 13, &if2_table[-3] }, - { CStdStubBuffer_DELEGATING_METHODS } + { 0, 0, test_CStdStubBuffer2_Release, 0, 0, 0, 0, 0, 0, 0 } }; static CINTERFACE_PROXY_VTABLE(5) if3_proxy_vtbl = @@ -1194,9 +1216,219 @@ static void test_NdrDllRegisterProxy( void ) } } +static HANDLE create_process(const char *arg) +{ + PROCESS_INFORMATION pi; + STARTUPINFOA si = {0}; + char cmdline[200]; + char **argv; + BOOL ret; + + si.cb = sizeof(si); + winetest_get_mainargs(&argv); + sprintf(cmdline, "\"%s\" %s %s", argv[0], argv[1], arg); + ret = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); + ok(ret, "CreateProcess failed: %u\n", GetLastError()); + CloseHandle(pi.hThread); + return pi.hProcess; +} + +DEFINE_GUID(CLSID_test1,0xdeadf00d,0x0001,0x44c7,0x85,0x0f,0x2a,0x0f,0x46,0x5c,0x0c,0x6c); + +static HRESULT WINAPI test1_QueryInterface(ITest1 *iface, REFIID iid, void **out) +{ + if (winetest_debug > 1) trace("%s\n", wine_dbgstr_guid(iid)); + if (IsEqualGUID(iid, &IID_IUnknown) || IsEqualGUID(iid, &IID_ITest1)) + { + *out = iface; + return S_OK; + } + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI test1_AddRef(ITest1 *iface) +{ + return 2; +} + +static ULONG WINAPI test1_Release(ITest1 *iface) +{ + return 1; +} + +static HRESULT WINAPI test1_GetClassID(ITest1 *iface, CLSID *clsid) +{ + *clsid = CLSID_test1; + return S_OK; +} + +static int WINAPI test1_square(ITest1 *iface, int x) +{ + return x * x; +} + +static const ITest1Vtbl test1_vtbl = +{ + test1_QueryInterface, + test1_AddRef, + test1_Release, + test1_GetClassID, + test1_square, +}; + +static HRESULT WINAPI test_cf_QueryInterface(IClassFactory *iface, REFIID iid, void **out) +{ + if (IsEqualGUID(iid, &IID_IUnknown) || IsEqualGUID(iid, &IID_IClassFactory)) + { + *out = iface; + return S_OK; + } + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI test_cf_AddRef(IClassFactory *iface) +{ + return 2; +} + +static ULONG WINAPI test_cf_Release(IClassFactory *iface) +{ + return 1; +} + +static HRESULT WINAPI test_cf_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID iid, void **out) +{ + ITest1 *obj = heap_alloc(sizeof(*obj)); + + obj->lpVtbl = &test1_vtbl; + + return ITest1_QueryInterface(obj, iid, out); +} + +static HRESULT WINAPI test_cf_LockServer(IClassFactory *iface, BOOL lock) +{ + return S_OK; +} + +static const IClassFactoryVtbl test_cf_vtbl = +{ + test_cf_QueryInterface, + test_cf_AddRef, + test_cf_Release, + test_cf_CreateInstance, + test_cf_LockServer, +}; + +static IClassFactory test_cf = { &test_cf_vtbl }; + +extern CStdPSFactoryBuffer gPFactory; +extern const ProxyFileInfo * aProxyFileList; + +static void local_server_proc(void) +{ + DWORD obj_cookie, ps_cookie, index; + HANDLE stop_event, ready_event; + IPSFactoryBuffer *ps; + HRESULT hr; + + stop_event = OpenEventA(EVENT_ALL_ACCESS, FALSE, "wine_cstub_test_server_stop"); + ready_event = OpenEventA(EVENT_ALL_ACCESS, FALSE, "wine_cstub_test_server_ready"); + + CoInitialize(NULL); + + hr = CoRegisterClassObject(&CLSID_test1, (IUnknown *)&test_cf, + CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &obj_cookie); + ok(hr == S_OK, "got %#x\n", hr); + + hr = NdrDllGetClassObject(&CLSID_test_ps, &IID_IPSFactoryBuffer, (void **)&ps, + &aProxyFileList, &CLSID_test_ps, &gPFactory); + ok(hr == S_OK, "got %#x\n", hr); + + hr = CoRegisterClassObject(&CLSID_test_ps, (IUnknown *)ps, + CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &ps_cookie); + ok(hr == S_OK, "got %#x\n", hr); + + hr = CoRegisterPSClsid(&IID_ITest1, &CLSID_test_ps); + ok(hr == S_OK, "got %#x\n", hr); + + SetEvent(ready_event); + + hr = CoWaitForMultipleHandles(0, 1000, 1, &stop_event, &index); + ok(hr == S_OK, "got %#x\n", hr); + ok(!index, "got %u\n", index); + + hr = CoRevokeClassObject(ps_cookie); + ok(hr == S_OK, "got %#x\n", hr); + + hr = CoRevokeClassObject(obj_cookie); + ok(hr == S_OK, "got %#x\n", hr); + + CoUninitialize(); + ExitProcess(0); +} + +static void test_delegated_methods(void) +{ + HANDLE process, stop_event, ready_event; + IPSFactoryBuffer *ps; + ITest1 *test_obj; + DWORD ps_cookie; + CLSID clsid; + HRESULT hr; + int ret; + + stop_event = CreateEventA(NULL, TRUE, FALSE, "wine_cstub_test_server_stop"); + ready_event = CreateEventA(NULL, TRUE, FALSE, "wine_cstub_test_server_ready"); + + process = create_process("server"); + ok(!WaitForSingleObject(ready_event, 1000), "wait failed\n"); + + hr = NdrDllGetClassObject(&CLSID_test_ps, &IID_IPSFactoryBuffer, (void **)&ps, + &aProxyFileList, &CLSID_test_ps, &gPFactory); + ok(hr == S_OK, "got %#x\n", hr); + + hr = CoRegisterClassObject(&CLSID_test_ps, (IUnknown *)ps, + CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &ps_cookie); + ok(hr == S_OK, "got %#x\n", hr); + + hr = CoRegisterPSClsid(&IID_ITest1, &CLSID_test_ps); + ok(hr == S_OK, "got %#x\n", hr); + + hr = CoCreateInstance(&CLSID_test1, NULL, CLSCTX_LOCAL_SERVER, &IID_ITest1, (void **)&test_obj); + ok(hr == S_OK, "got %#x\n", hr); + + ret = ITest1_square(test_obj, 3); + ok(ret == 9, "got %d\n", ret); + + hr = ITest1_GetClassID(test_obj, &clsid); +todo_wine { + ok(hr == S_OK, "got %#x\n", hr); + ok(IsEqualGUID(&clsid, &CLSID_test1), "got %s\n", wine_dbgstr_guid(&clsid)); +} + + ITest1_Release(test_obj); + + SetEvent(stop_event); + ok(!WaitForSingleObject(process, 1000), "wait failed\n"); + + hr = CoRevokeClassObject(ps_cookie); + ok(hr == S_OK, "got %#x\n", hr); +} + START_TEST( cstub ) { IPSFactoryBuffer *ppsf; + int argc; + char **argv; + + argc = winetest_get_mainargs( &argv ); + if (argc > 2 && !strcmp(argv[2], "server")) + { + local_server_proc(); + return; + } OleInitialize(NULL); @@ -1209,6 +1441,7 @@ START_TEST( cstub ) test_Release(ppsf); test_delegating_Invoke(ppsf); test_NdrDllRegisterProxy(); + test_delegated_methods(); OleUninitialize(); } diff --git a/dlls/rpcrt4/tests/cstub.idl b/dlls/rpcrt4/tests/cstub.idl new file mode 100644 index 00000000000..461bd87b308 --- /dev/null +++ b/dlls/rpcrt4/tests/cstub.idl @@ -0,0 +1,37 @@ +/* + * IDL to test COM object proxy/stub functions + * + * Copyright 2018 Zebediah Figura + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#pragma makedep proxy + +import "oleidl.idl"; + +[ + uuid(deadbeef-0001-44c7-850f-2a0f465c0c6c), + object +] +interface ITest1 : IPersist +{ + int square(int x); +} + +[ + uuid(deadbeef-ffff-44c7-850f-2a0f465c0c6c) +] +coclass test_ps { interface IPSFactoryBuffer; }