diff --git a/configure b/configure index d405d6741a4..f2be330d459 100755 --- a/configure +++ b/configure @@ -19248,6 +19248,7 @@ wine_fn_config_makefile dlls/commdlg.dll16 enable_win16 wine_fn_config_makefile dlls/compobj.dll16 enable_win16 wine_fn_config_makefile dlls/compstui enable_compstui wine_fn_config_makefile dlls/comsvcs enable_comsvcs +wine_fn_config_makefile dlls/comsvcs/tests enable_tests wine_fn_config_makefile dlls/concrt140 enable_concrt140 wine_fn_config_makefile dlls/connect enable_connect wine_fn_config_makefile dlls/credui enable_credui diff --git a/configure.ac b/configure.ac index cd1bf44ab44..328b5724056 100644 --- a/configure.ac +++ b/configure.ac @@ -3111,6 +3111,7 @@ WINE_CONFIG_MAKEFILE(dlls/commdlg.dll16,enable_win16) WINE_CONFIG_MAKEFILE(dlls/compobj.dll16,enable_win16) WINE_CONFIG_MAKEFILE(dlls/compstui) WINE_CONFIG_MAKEFILE(dlls/comsvcs) +WINE_CONFIG_MAKEFILE(dlls/comsvcs/tests) WINE_CONFIG_MAKEFILE(dlls/concrt140) WINE_CONFIG_MAKEFILE(dlls/connect) WINE_CONFIG_MAKEFILE(dlls/credui) diff --git a/dlls/comsvcs/tests/Makefile.in b/dlls/comsvcs/tests/Makefile.in new file mode 100644 index 00000000000..9a7047ebaf7 --- /dev/null +++ b/dlls/comsvcs/tests/Makefile.in @@ -0,0 +1,5 @@ +TESTDLL = comsvcs.dll +IMPORTS = uuid oleaut32 ole32 + +C_SRCS = \ + dispenser.c diff --git a/dlls/comsvcs/tests/dispenser.c b/dlls/comsvcs/tests/dispenser.c new file mode 100644 index 00000000000..187800ec6a0 --- /dev/null +++ b/dlls/comsvcs/tests/dispenser.c @@ -0,0 +1,256 @@ +/* + * Copyright 2018 Alistair Leslie-Hughes + * + * 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 + */ + +#define COBJMACROS + +#include + +#include "windef.h" +#include "winbase.h" +#include "ole2.h" +#include "comsvcs.h" + +#include "wine/test.h" + +#define DEFINE_EXPECT(func) \ + static BOOL expect_ ## func = FALSE, called_ ## func = FALSE + +#define SET_EXPECT(func) \ + expect_ ## func = TRUE + +#define CHECK_CALLED(func) \ + do { \ + ok(called_ ## func, "expected " #func "\n"); \ + expect_ ## func = called_ ## func = FALSE; \ + }while(0) + +#define CHECK_EXPECT2(func) \ + do { \ + trace(#func "\n"); \ + ok(expect_ ##func, "unexpected call " #func "\n"); \ + called_ ## func = TRUE; \ + }while(0) + +#define CHECK_CALLED_BROKEN(func) \ + do { \ + ok(called_ ## func || broken(!called_ ## func), "expected " #func "\n"); \ + expect_ ## func = called_ ## func = FALSE; \ + }while(0) + +DEFINE_EXPECT(driver_CreateResource); +DEFINE_EXPECT(driver_DestroyResource); +DEFINE_EXPECT(driver_ResetResource); +DEFINE_EXPECT(driver_Release); + +HRESULT driver_DestroyResource_ret = S_OK; + +static HRESULT WINAPI driver_QueryInterface(IDispenserDriver *iface, REFIID riid, void **object) +{ + if (IsEqualGUID(riid, &IID_IUnknown) || + IsEqualGUID(riid, &IID_IDispenserDriver)) + { + *object = iface; + + return S_OK; + } + + ok(0, "Unknown iterface %s\n", wine_dbgstr_guid(riid)); + return E_NOINTERFACE; +} + +static ULONG WINAPI driver_AddRef(IDispenserDriver *iface) +{ + trace("AddRef\n"); + return 2; +} + +static ULONG WINAPI driver_Release(IDispenserDriver *iface) +{ + CHECK_EXPECT2(driver_Release); + return 1; +} + +static HRESULT WINAPI driver_CreateResource(IDispenserDriver *iface, const RESTYPID restypid, RESID *resid, TIMEINSECS *destroy) +{ + CHECK_EXPECT2(driver_CreateResource); + + *resid = 10; + return S_OK; +} + +static HRESULT WINAPI driver_RateResource(IDispenserDriver *iface, const RESTYPID restypid, const RESID resid, + const BOOL requires, RESOURCERATING *rating) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI driver_EnlistResource(IDispenserDriver *iface, const RESID resid, const TRANSID transid) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI driver_ResetResource(IDispenserDriver *iface, const RESID resid) +{ + CHECK_EXPECT2(driver_ResetResource); + ok((int)resid == 10, "RESID %d\n", (int)resid); + return S_OK; +} + +static HRESULT WINAPI driver_DestroyResource(IDispenserDriver *iface, const RESID resid) +{ + todo_wine CHECK_EXPECT2(driver_DestroyResource); + return driver_DestroyResource_ret; +} + +static HRESULT WINAPI driver_DestroyResourceS(IDispenserDriver *iface, const SRESID resid) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + + +static const struct IDispenserDriverVtbl driver_vtbl = +{ + driver_QueryInterface, + driver_AddRef, + driver_Release, + driver_CreateResource, + driver_RateResource, + driver_EnlistResource, + driver_ResetResource, + driver_DestroyResource, + driver_DestroyResourceS +}; + +static IDispenserDriver DispenserDriver = { &driver_vtbl }; + +static void create_dispenser(void) +{ + static const WCHAR pool0[] = {'S','C','.','P','o','o','l',' ','0',' ','0',0}; + static const WCHAR pool1[] = {'S','C','.','P','o','o','l',' ','1',' ','1',0}; + static const WCHAR data[] = {'d','a','t','a','1',0}; + HRESULT hr; + IDispenserManager *dispenser = NULL; + IHolder *holder1 = NULL, *holder2 = NULL, *holder3 = NULL; + RESID resid; + BSTR str; + + hr = CoCreateInstance( &CLSID_DispenserManager, NULL, CLSCTX_ALL, &IID_IDispenserManager, (void**)&dispenser); + ok(hr == S_OK, "Failed to create object 0x%08x\n", hr); + if(FAILED(hr)) + { + win_skip("DispenserManager not available\n"); + return; + } + + hr = IDispenserManager_RegisterDispenser(dispenser, &DispenserDriver, pool0, &holder1); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IDispenserManager_RegisterDispenser(dispenser, &DispenserDriver, pool0, &holder2); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(holder1 != holder2, "same holder object returned\n"); + + hr = IDispenserManager_RegisterDispenser(dispenser, &DispenserDriver, pool1, &holder3); + ok(hr == S_OK, "got 0x%08x\n", hr); + + if(holder1) + { + SET_EXPECT(driver_CreateResource); + SET_EXPECT(driver_Release); + + str = SysAllocString(data); + hr = IHolder_AllocResource(holder1, (RESTYPID)str, &resid); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(resid == 10, "got %d\n", (int)resid); + SysFreeString(str); + + CHECK_CALLED(driver_CreateResource); + todo_wine CHECK_CALLED_BROKEN(driver_Release); + + SET_EXPECT(driver_ResetResource); + hr = IHolder_FreeResource(holder1, resid); + ok(hr == S_OK, "got 0x%08x\n", hr); + todo_wine CHECK_CALLED(driver_ResetResource); + + SET_EXPECT(driver_DestroyResource); + SET_EXPECT(driver_Release); + hr = IHolder_Close(holder1); + ok(hr == S_OK, "got 0x%08x\n", hr); + CHECK_CALLED(driver_Release); + CHECK_CALLED(driver_DestroyResource); + + IHolder_Release(holder1); + } + if(holder2) + { + SET_EXPECT(driver_CreateResource); + SET_EXPECT(driver_Release); + + str = SysAllocString(data); + hr = IHolder_AllocResource(holder2, (RESTYPID)str, &resid); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(resid == 10, "got %d\n", (int)resid); + SysFreeString(str); + + CHECK_CALLED(driver_CreateResource); + todo_wine CHECK_CALLED_BROKEN(driver_Release); + + SET_EXPECT(driver_ResetResource); + hr = IHolder_FreeResource(holder2, resid); + ok(hr == S_OK, "got 0x%08x\n", hr); + todo_wine CHECK_CALLED(driver_ResetResource); + + /* DestroyResource return doesn't directly affect the Holder Close return value */ + driver_DestroyResource_ret = E_FAIL; + SET_EXPECT(driver_DestroyResource); + SET_EXPECT(driver_Release); + hr = IHolder_Close(holder2); + ok(hr == S_OK, "got 0x%08x\n", hr); + CHECK_CALLED(driver_Release); + CHECK_CALLED(driver_DestroyResource); + driver_DestroyResource_ret = S_OK; + IHolder_Release(holder2); + } + if(holder3) + { + SET_EXPECT(driver_Release); + hr = IHolder_Close(holder3); + ok(hr == S_OK, "got 0x%08x\n", hr); + CHECK_CALLED(driver_Release); + IHolder_Release(holder3); + } + + IDispenserManager_Release(dispenser); +} + + +START_TEST(dispenser) +{ + HRESULT hr; + + hr = CoInitialize(0); + ok( hr == S_OK, "failed to init com\n"); + if (hr != S_OK) + return; + + create_dispenser(); + + CoUninitialize(); +}