hnetcfg: Implement static_ports__NewEnum().

Signed-off-by: Paul Gofman <pgofman@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Paul Gofman 2022-02-02 11:32:57 +03:00 committed by Alexandre Julliard
parent 7ed9fb0a68
commit de05efdea2
2 changed files with 184 additions and 8 deletions

View File

@ -735,6 +735,22 @@ static BOOL find_port_mapping( LONG port, BSTR protocol, struct port_mapping *re
return found;
}
static unsigned int get_port_mapping_range( unsigned int index, unsigned int count, struct port_mapping *ret )
{
unsigned int i;
AcquireSRWLockExclusive( &upnp_gateway_connection_lock );
for (i = 0; i < count && index + i < upnp_gateway_connection.mapping_count; ++i)
if (!copy_port_mapping( &ret[i], &upnp_gateway_connection.mappings[index + i] ))
{
ERR( "No memory.\n" );
break;
}
ReleaseSRWLockExclusive( &upnp_gateway_connection_lock );
return i;
}
static unsigned int get_port_mapping_count(void)
{
unsigned int ret;
@ -1048,6 +1064,164 @@ static HRESULT static_port_mapping_create( const struct port_mapping *mapping_da
return S_OK;
}
struct port_mapping_enum
{
IEnumVARIANT IEnumVARIANT_iface;
LONG refs;
unsigned int index;
};
static inline struct port_mapping_enum *impl_from_IEnumVARIANT( IEnumVARIANT *iface )
{
return CONTAINING_RECORD(iface, struct port_mapping_enum, IEnumVARIANT_iface);
}
static ULONG WINAPI port_mapping_enum_AddRef(
IEnumVARIANT *iface )
{
struct port_mapping_enum *mapping_enum = impl_from_IEnumVARIANT( iface );
return InterlockedIncrement( &mapping_enum->refs );
}
static ULONG WINAPI port_mapping_enum_Release(
IEnumVARIANT *iface )
{
struct port_mapping_enum *mapping_enum = impl_from_IEnumVARIANT( iface );
LONG refs = InterlockedDecrement( &mapping_enum->refs );
if (!refs)
{
TRACE("destroying %p\n", mapping_enum);
free( mapping_enum );
release_gateway_connection();
}
return refs;
}
static HRESULT WINAPI port_mapping_enum_QueryInterface(
IEnumVARIANT *iface,
REFIID riid,
void **ppvObject )
{
struct port_mapping_enum *mapping_enum = impl_from_IEnumVARIANT( iface );
TRACE("%p %s %p\n", mapping_enum, debugstr_guid( riid ), ppvObject );
if ( IsEqualGUID( riid, &IID_IEnumVARIANT ) ||
IsEqualGUID( riid, &IID_IUnknown ) )
{
*ppvObject = iface;
}
else
{
FIXME("interface %s not implemented\n", debugstr_guid(riid));
return E_NOINTERFACE;
}
IEnumVARIANT_AddRef( iface );
return S_OK;
}
static HRESULT WINAPI port_mapping_enum_Next( IEnumVARIANT *iface, ULONG celt, VARIANT *var, ULONG *fetched )
{
struct port_mapping_enum *mapping_enum = impl_from_IEnumVARIANT( iface );
struct port_mapping *data;
IStaticPortMapping *pm;
unsigned int i, count;
HRESULT ret;
TRACE( "iface %p, celt %u, var %p, fetched %p.\n", iface, celt, var, fetched );
if (fetched) *fetched = 0;
if (!celt) return S_OK;
if (!var) return E_POINTER;
if (!(data = calloc( 1, celt * sizeof(*data) ))) return E_OUTOFMEMORY;
count = get_port_mapping_range( mapping_enum->index, celt, data );
TRACE( "count %u.\n", count );
for (i = 0; i < count; ++i)
{
if (FAILED(static_port_mapping_create( &data[i], &pm ))) break;
V_VT(&var[i]) = VT_DISPATCH;
V_DISPATCH(&var[i]) = (IDispatch *)pm;
}
mapping_enum->index += i;
if (fetched) *fetched = i;
ret = (i < celt) ? S_FALSE : S_OK;
for ( ; i < count; ++i)
{
free_port_mapping( &data[i] );
VariantInit( &var[i] );
}
for ( ; i < celt; ++i)
VariantInit( &var[i] );
free( data );
return ret;
}
static HRESULT WINAPI port_mapping_enum_Skip( IEnumVARIANT *iface, ULONG celt )
{
struct port_mapping_enum *mapping_enum = impl_from_IEnumVARIANT( iface );
unsigned int count = get_port_mapping_count();
TRACE( "iface %p, celt %u.\n", iface, celt );
mapping_enum->index += celt;
return mapping_enum->index <= count ? S_OK : S_FALSE;
}
static HRESULT WINAPI port_mapping_enum_Reset( IEnumVARIANT *iface )
{
struct port_mapping_enum *mapping_enum = impl_from_IEnumVARIANT( iface );
TRACE( "iface %p.\n", iface );
mapping_enum->index = 0;
return S_OK;
}
static HRESULT create_port_mapping_enum( IUnknown **ret );
static HRESULT WINAPI port_mapping_enum_Clone( IEnumVARIANT *iface, IEnumVARIANT **ret )
{
struct port_mapping_enum *mapping_enum = impl_from_IEnumVARIANT( iface );
HRESULT hr;
TRACE( "iface %p, ret %p.\n", iface, ret );
if (!ret) return E_POINTER;
*ret = NULL;
if (FAILED(hr = create_port_mapping_enum( (IUnknown **)ret ))) return hr;
impl_from_IEnumVARIANT( *ret )->index = mapping_enum->index;
return S_OK;
}
static const IEnumVARIANTVtbl port_mapping_enum_vtbl =
{
port_mapping_enum_QueryInterface,
port_mapping_enum_AddRef,
port_mapping_enum_Release,
port_mapping_enum_Next,
port_mapping_enum_Skip,
port_mapping_enum_Reset,
port_mapping_enum_Clone,
};
static HRESULT create_port_mapping_enum( IUnknown **ret )
{
struct port_mapping_enum *mapping_enum;
if (!(mapping_enum = calloc( 1, sizeof(*mapping_enum) ))) return E_OUTOFMEMORY;
grab_gateway_connection();
mapping_enum->refs = 1;
mapping_enum->IEnumVARIANT_iface.lpVtbl = &port_mapping_enum_vtbl;
mapping_enum->index = 0;
*ret = (IUnknown *)&mapping_enum->IEnumVARIANT_iface;
return S_OK;
}
struct static_port_mapping_collection
{
IStaticPortMappingCollection IStaticPortMappingCollection_iface;
@ -1183,11 +1357,12 @@ static HRESULT WINAPI static_ports__NewEnum(
IStaticPortMappingCollection *iface,
IUnknown **ret )
{
FIXME( "iface %p, ret %p stub.\n", iface, ret );
TRACE( "iface %p, ret %p.\n", iface, ret );
if (ret) *ret = NULL;
if (!ret) return E_POINTER;
return E_NOTIMPL;
*ret = NULL;
return create_port_mapping_enum( ret );
}
static HRESULT WINAPI static_ports_get_Item(

View File

@ -184,8 +184,7 @@ static void test_static_port_mapping_collection( IStaticPortMappingCollection *p
refcount = get_refcount((IUnknown *)ports);
hr = IStaticPortMappingCollection_get__NewEnum(ports, &unk);
todo_wine ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
if (FAILED(hr)) return;
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
hr = IUnknown_QueryInterface(unk, &IID_IEnumVARIANT, (void **)&enum_ports);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
@ -213,14 +212,14 @@ static void test_static_port_mapping_collection( IStaticPortMappingCollection *p
hr = IStaticPortMappingCollection_Add(ports, 12345, (BSTR)L"udp", 12345, (BSTR)L"1.2.3.4",
VARIANT_TRUE, (BSTR)L"wine_test", &pm);
ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
todo_wine ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
hr = IStaticPortMappingCollection_Add(ports, 12345, (BSTR)L"UDP", 12345, (BSTR)L"1.2.3.4",
VARIANT_TRUE, (BSTR)L"wine_test", &pm);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
todo_wine ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
hr = IStaticPortMappingCollection_get_Count(ports, &count2);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
ok(count2 == expected_count, "Got unexpected count2 %u, expected %u.\n", count2, expected_count);
todo_wine ok(count2 == expected_count, "Got unexpected count2 %u, expected %u.\n", count2, expected_count);
hr = IStaticPortMappingCollection_get_Item(ports, 12345, NULL, &pm);
ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
@ -280,6 +279,8 @@ static void test_static_port_mapping_collection( IStaticPortMappingCollection *p
hr = IStaticPortMappingCollection_Remove(ports, 12345, (BSTR)L"UDP");
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
hr = IStaticPortMappingCollection_Remove(ports, 12345, (BSTR)L"UDP");
todo_wine ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
IEnumVARIANT_Release(enum_ports);
}