diff --git a/dlls/netcfgx/netcfg.c b/dlls/netcfgx/netcfg.c index 8653d292d6b..43db0ef8de0 100644 --- a/dlls/netcfgx/netcfg.c +++ b/dlls/netcfgx/netcfg.c @@ -30,6 +30,8 @@ WINE_DEFAULT_DEBUG_CHANNEL( netcfgx ); typedef struct NetConfiguration { INetCfg INetCfg_iface; + INetCfgLock INetCfgLock_iface; + LONG ref; } NetConfiguration; @@ -38,14 +40,24 @@ static inline NetConfiguration *impl_from_INetCfg(INetCfg *iface) return CONTAINING_RECORD(iface, NetConfiguration, INetCfg_iface); } +static inline NetConfiguration *impl_from_INetCfgLock(INetCfgLock *iface) +{ + return CONTAINING_RECORD(iface, NetConfiguration, INetCfgLock_iface); +} + static HRESULT WINAPI netcfg_QueryInterface(INetCfg *iface, REFIID riid, void **ppvObject) { - TRACE("%p %s %p\n", iface, debugstr_guid(riid), ppvObject); + NetConfiguration *This = impl_from_INetCfg(iface); + TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject); if (IsEqualGUID(riid, &IID_INetCfg) || IsEqualGUID(riid, &IID_IUnknown)) { - *ppvObject = iface; + *ppvObject = &This->INetCfg_iface; + } + else if(IsEqualGUID(riid, &IID_INetCfgLock)) + { + *ppvObject = &This->INetCfgLock_iface; } else { @@ -53,7 +65,7 @@ static HRESULT WINAPI netcfg_QueryInterface(INetCfg *iface, REFIID riid, void ** return E_NOINTERFACE; } - INetCfg_AddRef( iface ); + IUnknown_AddRef((IUnknown*)*ppvObject); return S_OK; } @@ -153,6 +165,62 @@ static const struct INetCfgVtbl NetCfgVtbl = netcfg_QueryNetCfgClass }; + +static HRESULT WINAPI netcfglock_QueryInterface(INetCfgLock *iface, REFIID riid,void **ppvObject) +{ + NetConfiguration *This = impl_from_INetCfgLock(iface); + + return netcfg_QueryInterface(&This->INetCfg_iface, riid, ppvObject); +} + +static ULONG WINAPI netcfglock_AddRef(INetCfgLock *iface) +{ + NetConfiguration *This = impl_from_INetCfgLock(iface); + + return netcfg_AddRef(&This->INetCfg_iface); +} + +static ULONG WINAPI netcfglock_Release(INetCfgLock *iface) +{ + NetConfiguration *This = impl_from_INetCfgLock(iface); + return netcfg_Release(&This->INetCfg_iface); +} + +static HRESULT WINAPI netcfglock_AcquireWriteLock(INetCfgLock *iface, DWORD cmsTimeout, + LPCWSTR pszwClientDescription, LPWSTR *ppszwClientDescription) +{ + NetConfiguration *This = impl_from_INetCfgLock(iface); + FIXME("%p %d %s %p\n", This, cmsTimeout, debugstr_w(pszwClientDescription), ppszwClientDescription); + + return S_OK; +} + +static HRESULT WINAPI netcfglock_ReleaseWriteLock(INetCfgLock *iface) +{ + NetConfiguration *This = impl_from_INetCfgLock(iface); + FIXME("%p\n", This); + + return S_OK; +} + +static HRESULT WINAPI netcfglock_IsWriteLocked(INetCfgLock *iface, LPWSTR *ppszwClientDescription) +{ + NetConfiguration *This = impl_from_INetCfgLock(iface); + FIXME("%p %p\n", This, ppszwClientDescription); + + return E_NOTIMPL; +} + +static const struct INetCfgLockVtbl NetCfgLockVtbl = +{ + netcfglock_QueryInterface, + netcfglock_AddRef, + netcfglock_Release, + netcfglock_AcquireWriteLock, + netcfglock_ReleaseWriteLock, + netcfglock_IsWriteLocked +}; + HRESULT INetCfg_CreateInstance(IUnknown **ppUnk) { NetConfiguration *This; @@ -162,6 +230,7 @@ HRESULT INetCfg_CreateInstance(IUnknown **ppUnk) return E_OUTOFMEMORY; This->INetCfg_iface.lpVtbl = &NetCfgVtbl; + This->INetCfgLock_iface.lpVtbl = &NetCfgLockVtbl; This->ref = 1; *ppUnk = (IUnknown*)This; diff --git a/dlls/netcfgx/tests/netcfgx.c b/dlls/netcfgx/tests/netcfgx.c index 6427f856e02..2a9f0eb4b3f 100644 --- a/dlls/netcfgx/tests/netcfgx.c +++ b/dlls/netcfgx/tests/netcfgx.c @@ -26,17 +26,38 @@ void create_configuration(void) { static const WCHAR tcpipW[] = {'M','S','_','T','C','P','I','P',0}; + static const WCHAR myclient[] = {'M','Y',' ','C','L','I','E','N','T',0}; HRESULT hr; INetCfg *config = NULL; + INetCfgLock *netlock = NULL; INetCfgComponent *component = NULL; + LPWSTR client = NULL; hr = CoCreateInstance( &CLSID_CNetCfg, NULL, CLSCTX_ALL, &IID_INetCfg, (LPVOID*)&config); ok(hr == S_OK, "Failed to create object\n"); if(SUCCEEDED(hr)) { + hr = INetCfg_QueryInterface(config, &IID_INetCfgLock, (LPVOID*)&netlock); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = INetCfgLock_AcquireWriteLock(netlock, 5000, myclient, &client); + ok(hr == S_OK || + hr == E_ACCESSDENIED /* Not run as admin */, "got 0x%08x\n", hr); + if(hr == S_OK) + { + trace("Lock value: %s\n", wine_dbgstr_w(client)); + CoTaskMemFree(client); + } + else if(hr == E_ACCESSDENIED) + trace("Not run with Admin permissions\n"); + hr = INetCfg_Initialize(config, NULL); ok(hr == S_OK, "got 0x%08x\n", hr); + /* AcquireWriteLock needs to be run before Initialize */ + hr = INetCfgLock_AcquireWriteLock(netlock, 5000, myclient, &client); + todo_wine ok(hr == NETCFG_E_ALREADY_INITIALIZED || hr == E_ACCESSDENIED, "got 0x%08x\n", hr); + hr = INetCfg_FindComponent(config, tcpipW, &component); todo_wine ok(hr == S_OK, "got 0x%08x\n", hr); if(hr == S_OK) @@ -44,9 +65,15 @@ void create_configuration(void) INetCfgComponent_Release(component); } + hr = INetCfg_Apply(config); + todo_wine ok(hr == S_OK || hr == NETCFG_E_NO_WRITE_LOCK, "got 0x%08x\n", hr); + hr = INetCfg_Uninitialize(config); ok(hr == S_OK, "got 0x%08x\n", hr); + hr = INetCfgLock_ReleaseWriteLock(netlock); + ok(hr == S_OK, "got 0x%08x\n", hr); + INetCfg_Release(config); } }