Paul Gofman : hnetcfg: Implement static_ports__NewEnum().

Alexandre Julliard julliard at winehq.org
Wed Feb 2 16:38:02 CST 2022


Module: wine
Branch: master
Commit: de05efdea217d25c296ecd9fb698075cc91528e5
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=de05efdea217d25c296ecd9fb698075cc91528e5

Author: Paul Gofman <pgofman at codeweavers.com>
Date:   Wed Feb  2 11:32:57 2022 +0300

hnetcfg: Implement static_ports__NewEnum().

Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/hnetcfg/port.c         | 181 +++++++++++++++++++++++++++++++++++++++++++-
 dlls/hnetcfg/tests/policy.c |  11 +--
 2 files changed, 184 insertions(+), 8 deletions(-)

diff --git a/dlls/hnetcfg/port.c b/dlls/hnetcfg/port.c
index 34e054527d9..8c80b02babc 100644
--- a/dlls/hnetcfg/port.c
+++ b/dlls/hnetcfg/port.c
@@ -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(
diff --git a/dlls/hnetcfg/tests/policy.c b/dlls/hnetcfg/tests/policy.c
index 19b6e3f6f2e..ffe3442dcd0 100644
--- a/dlls/hnetcfg/tests/policy.c
+++ b/dlls/hnetcfg/tests/policy.c
@@ -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);
 }




More information about the wine-cvs mailing list