[PATCH 3/7] hnetcfg: Implement static_ports_get_Item().

Paul Gofman pgofman at codeweavers.com
Wed Feb 2 02:32:55 CST 2022


Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
---
 dlls/hnetcfg/apps.c            |   1 +
 dlls/hnetcfg/hnetcfg_private.h |   1 +
 dlls/hnetcfg/port.c            | 358 ++++++++++++++++++++++++++++++++-
 3 files changed, 357 insertions(+), 3 deletions(-)

diff --git a/dlls/hnetcfg/apps.c b/dlls/hnetcfg/apps.c
index f351e2482e8..9f0b30cd28a 100644
--- a/dlls/hnetcfg/apps.c
+++ b/dlls/hnetcfg/apps.c
@@ -116,6 +116,7 @@ static REFIID tid_id[] =
     &IID_INetFwProfile,
     &IID_IUPnPNAT,
     &IID_IStaticPortMappingCollection,
+    &IID_IStaticPortMapping,
 };
 
 HRESULT get_typeinfo( enum type_id tid, ITypeInfo **ret )
diff --git a/dlls/hnetcfg/hnetcfg_private.h b/dlls/hnetcfg/hnetcfg_private.h
index 91fef756464..9e6c4ec9618 100644
--- a/dlls/hnetcfg/hnetcfg_private.h
+++ b/dlls/hnetcfg/hnetcfg_private.h
@@ -29,6 +29,7 @@ enum type_id
     INetFwRules_tid,
     IUPnPNAT_tid,
     IStaticPortMappingCollection_tid,
+    IStaticPortMapping_tid,
     last_tid
 };
 
diff --git a/dlls/hnetcfg/port.c b/dlls/hnetcfg/port.c
index 070ba1ef7ab..c04aaefe56a 100644
--- a/dlls/hnetcfg/port.c
+++ b/dlls/hnetcfg/port.c
@@ -92,6 +92,28 @@ static void free_mappings(void)
     upnp_gateway_connection.mapping_count = 0;
 }
 
+static BOOL copy_port_mapping( struct port_mapping *dst, const struct port_mapping *src )
+{
+    memset( dst, 0, sizeof(*dst) );
+
+#define COPY_BSTR_CHECK(name) if (src->name && !(dst->name = SysAllocString( src->name ))) \
+    { \
+        free_port_mapping( dst ); \
+        return FALSE; \
+    }
+
+    COPY_BSTR_CHECK( external_ip );
+    COPY_BSTR_CHECK( protocol );
+    COPY_BSTR_CHECK( client );
+    COPY_BSTR_CHECK( descr );
+#undef COPY_BSTR_CHECK
+
+    dst->external = src->external;
+    dst->internal = src->internal;
+    dst->enabled = src->enabled;
+    return TRUE;
+}
+
 static BOOL parse_search_response( char *response, WCHAR *locationW, unsigned int location_size )
 {
     char *saveptr = NULL, *tok, *tok2;
@@ -695,6 +717,327 @@ static void release_gateway_connection(void)
     ReleaseSRWLockExclusive( &upnp_gateway_connection_lock );
 }
 
+static BOOL find_port_mapping( LONG port, BSTR protocol, struct port_mapping *ret )
+{
+    unsigned int i;
+    BOOL found;
+
+    AcquireSRWLockExclusive( &upnp_gateway_connection_lock );
+    for (i = 0; i < upnp_gateway_connection.mapping_count; ++i)
+    {
+        if (upnp_gateway_connection.mappings[i].external == port
+            && !wcscmp( upnp_gateway_connection.mappings[i].protocol, protocol ))
+            break;
+    }
+    found = i < upnp_gateway_connection.mapping_count;
+    if (found) copy_port_mapping( ret, &upnp_gateway_connection.mappings[i] );
+    ReleaseSRWLockExclusive( &upnp_gateway_connection_lock );
+    return found;
+}
+
+static BOOL is_valid_protocol( BSTR protocol )
+{
+    if (!protocol) return FALSE;
+    return !wcscmp( protocol, L"UDP" ) || !wcscmp( protocol, L"TCP" );
+}
+
+struct static_port_mapping
+{
+    IStaticPortMapping IStaticPortMapping_iface;
+    LONG refs;
+    struct port_mapping data;
+};
+
+static inline struct static_port_mapping *impl_from_IStaticPortMapping( IStaticPortMapping *iface )
+{
+    return CONTAINING_RECORD(iface, struct static_port_mapping, IStaticPortMapping_iface);
+}
+
+static ULONG WINAPI static_port_mapping_AddRef(
+    IStaticPortMapping *iface )
+{
+    struct static_port_mapping *mapping = impl_from_IStaticPortMapping( iface );
+    return InterlockedIncrement( &mapping->refs );
+}
+
+static ULONG WINAPI static_port_mapping_Release(
+    IStaticPortMapping *iface )
+{
+    struct static_port_mapping *mapping = impl_from_IStaticPortMapping( iface );
+    LONG refs = InterlockedDecrement( &mapping->refs );
+    if (!refs)
+    {
+        TRACE("destroying %p\n", mapping);
+        free_port_mapping( &mapping->data );
+        free( mapping );
+    }
+    return refs;
+}
+
+static HRESULT WINAPI static_port_mapping_QueryInterface(
+    IStaticPortMapping *iface,
+    REFIID riid,
+    void **ppvObject )
+{
+    struct static_port_mapping *mapping = impl_from_IStaticPortMapping( iface );
+
+    TRACE("%p %s %p\n", mapping, debugstr_guid( riid ), ppvObject );
+
+    if ( IsEqualGUID( riid, &IID_IStaticPortMapping ) ||
+         IsEqualGUID( riid, &IID_IDispatch ) ||
+         IsEqualGUID( riid, &IID_IUnknown ) )
+    {
+        *ppvObject = iface;
+    }
+    else
+    {
+        FIXME("interface %s not implemented\n", debugstr_guid(riid));
+        return E_NOINTERFACE;
+    }
+    IStaticPortMapping_AddRef( iface );
+    return S_OK;
+}
+
+static HRESULT WINAPI static_port_mapping_GetTypeInfoCount(
+    IStaticPortMapping *iface,
+    UINT *pctinfo )
+{
+    struct static_port_mapping *mapping = impl_from_IStaticPortMapping( iface );
+
+    TRACE("%p %p\n", mapping, pctinfo);
+    *pctinfo = 1;
+    return S_OK;
+}
+
+static HRESULT WINAPI static_port_mapping_GetTypeInfo(
+    IStaticPortMapping *iface,
+    UINT iTInfo,
+    LCID lcid,
+    ITypeInfo **ppTInfo )
+{
+    struct static_port_mapping *mapping = impl_from_IStaticPortMapping( iface );
+
+    TRACE("%p %u %u %p\n", mapping, iTInfo, lcid, ppTInfo);
+    return get_typeinfo( IStaticPortMapping_tid, ppTInfo );
+}
+
+static HRESULT WINAPI static_port_mapping_GetIDsOfNames(
+    IStaticPortMapping *iface,
+    REFIID riid,
+    LPOLESTR *rgszNames,
+    UINT cNames,
+    LCID lcid,
+    DISPID *rgDispId )
+{
+    struct static_port_mapping *mapping = impl_from_IStaticPortMapping( iface );
+    ITypeInfo *typeinfo;
+    HRESULT hr;
+
+    TRACE("%p %s %p %u %u %p\n", mapping, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
+
+    hr = get_typeinfo( IStaticPortMapping_tid, &typeinfo );
+    if (SUCCEEDED(hr))
+    {
+        hr = ITypeInfo_GetIDsOfNames( typeinfo, rgszNames, cNames, rgDispId );
+        ITypeInfo_Release( typeinfo );
+    }
+    return hr;
+}
+
+static HRESULT WINAPI static_port_mapping_Invoke(
+    IStaticPortMapping *iface,
+    DISPID dispIdMember,
+    REFIID riid,
+    LCID lcid,
+    WORD wFlags,
+    DISPPARAMS *pDispParams,
+    VARIANT *pVarResult,
+    EXCEPINFO *pExcepInfo,
+    UINT *puArgErr )
+{
+    struct static_port_mapping *mapping = impl_from_IStaticPortMapping( iface );
+    ITypeInfo *typeinfo;
+    HRESULT hr;
+
+    TRACE("%p %d %s %d %d %p %p %p %p\n", mapping, dispIdMember, debugstr_guid(riid),
+          lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
+
+    hr = get_typeinfo( IStaticPortMapping_tid, &typeinfo );
+    if (SUCCEEDED(hr))
+    {
+        hr = ITypeInfo_Invoke( typeinfo, &mapping->IStaticPortMapping_iface, dispIdMember,
+                               wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr );
+        ITypeInfo_Release( typeinfo );
+    }
+    return hr;
+}
+
+static HRESULT WINAPI static_port_mapping_get_ExternalIPAddress(
+    IStaticPortMapping *iface,
+    BSTR *value )
+{
+    struct static_port_mapping *mapping = impl_from_IStaticPortMapping( iface );
+
+    TRACE( "iface %p, value %p.\n", iface, value );
+
+    if (!value) return E_POINTER;
+    *value = SysAllocString( mapping->data.external_ip );
+    if (mapping->data.external_ip && !*value) return E_OUTOFMEMORY;
+    return S_OK;
+}
+
+static HRESULT WINAPI static_port_mapping_get_ExternalPort(
+    IStaticPortMapping *iface,
+    LONG *value )
+{
+    struct static_port_mapping *mapping = impl_from_IStaticPortMapping( iface );
+
+    TRACE( "iface %p, value %p.\n", iface, value );
+
+    if (!value) return E_POINTER;
+    *value = mapping->data.external;
+    return S_OK;
+}
+
+static HRESULT WINAPI static_port_mapping_get_InternalPort(
+    IStaticPortMapping *iface,
+    LONG *value )
+{
+    struct static_port_mapping *mapping = impl_from_IStaticPortMapping( iface );
+
+    TRACE( "iface %p, value %p.\n", iface, value );
+
+    if (!value) return E_POINTER;
+    *value = mapping->data.internal;
+    return S_OK;
+}
+
+static HRESULT WINAPI static_port_mapping_get_Protocol(
+    IStaticPortMapping *iface,
+    BSTR *value )
+{
+    struct static_port_mapping *mapping = impl_from_IStaticPortMapping( iface );
+
+    TRACE( "iface %p, value %p.\n", iface, value );
+
+    if (!value) return E_POINTER;
+    *value = SysAllocString( mapping->data.protocol );
+    if (mapping->data.protocol && !*value) return E_OUTOFMEMORY;
+    return S_OK;
+}
+
+static HRESULT WINAPI static_port_mapping_get_InternalClient(
+    IStaticPortMapping *iface,
+    BSTR *value )
+{
+    struct static_port_mapping *mapping = impl_from_IStaticPortMapping( iface );
+
+    TRACE( "iface %p, value %p.\n", iface, value );
+
+    if (!value) return E_POINTER;
+    *value = SysAllocString( mapping->data.client );
+    if (mapping->data.client && !*value) return E_OUTOFMEMORY;
+    return S_OK;
+}
+
+static HRESULT WINAPI static_port_mapping_get_Enabled(
+    IStaticPortMapping *iface,
+    VARIANT_BOOL *value )
+{
+    struct static_port_mapping *mapping = impl_from_IStaticPortMapping( iface );
+
+    TRACE( "iface %p, value %p.\n", iface, value );
+
+    if (!value) return E_POINTER;
+    *value = mapping->data.enabled;
+    return S_OK;
+}
+
+static HRESULT WINAPI static_port_mapping_get_Description(
+    IStaticPortMapping *iface,
+    BSTR *value )
+{
+    struct static_port_mapping *mapping = impl_from_IStaticPortMapping( iface );
+
+    TRACE( "iface %p, value %p.\n", iface, value );
+
+    if (!value) return E_POINTER;
+    *value = SysAllocString( mapping->data.descr );
+    if (mapping->data.descr && !*value) return E_OUTOFMEMORY;
+    return S_OK;
+}
+
+static HRESULT WINAPI static_port_mapping_EditInternalClient(
+    IStaticPortMapping *iface,
+    BSTR value )
+{
+    FIXME( "iface %p, value %s stub.\n", iface, debugstr_w(value) );
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI static_port_mapping_Enable(
+    IStaticPortMapping *iface,
+    VARIANT_BOOL value )
+{
+    FIXME( "iface %p, value %d stub.\n", iface, value );
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI static_port_mapping_EditDescription(
+    IStaticPortMapping *iface,
+    BSTR value )
+{
+    FIXME( "iface %p, value %s stub.\n", iface, debugstr_w(value) );
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI static_port_mapping_EditInternalPort(
+    IStaticPortMapping *iface,
+    LONG value )
+{
+    FIXME( "iface %p, value %d stub.\n", iface, value );
+
+    return E_NOTIMPL;
+}
+
+static const IStaticPortMappingVtbl static_port_mapping_vtbl =
+{
+    static_port_mapping_QueryInterface,
+    static_port_mapping_AddRef,
+    static_port_mapping_Release,
+    static_port_mapping_GetTypeInfoCount,
+    static_port_mapping_GetTypeInfo,
+    static_port_mapping_GetIDsOfNames,
+    static_port_mapping_Invoke,
+    static_port_mapping_get_ExternalIPAddress,
+    static_port_mapping_get_ExternalPort,
+    static_port_mapping_get_InternalPort,
+    static_port_mapping_get_Protocol,
+    static_port_mapping_get_InternalClient,
+    static_port_mapping_get_Enabled,
+    static_port_mapping_get_Description,
+    static_port_mapping_EditInternalClient,
+    static_port_mapping_Enable,
+    static_port_mapping_EditDescription,
+    static_port_mapping_EditInternalPort,
+};
+
+static HRESULT static_port_mapping_create( const struct port_mapping *mapping_data, IStaticPortMapping **ret )
+{
+    struct static_port_mapping *mapping;
+
+    if (!(mapping = calloc( 1, sizeof(*mapping) ))) return E_OUTOFMEMORY;
+
+    mapping->refs = 1;
+    mapping->IStaticPortMapping_iface.lpVtbl = &static_port_mapping_vtbl;
+    mapping->data = *mapping_data;
+    *ret = &mapping->IStaticPortMapping_iface;
+    return S_OK;
+}
+
 struct static_port_mapping_collection
 {
     IStaticPortMappingCollection IStaticPortMappingCollection_iface;
@@ -843,10 +1186,19 @@ static HRESULT WINAPI static_ports_get_Item(
     BSTR protocol,
     IStaticPortMapping **mapping )
 {
-    FIXME( "iface %p, port %d, protocol %s stub.\n", iface, port, debugstr_w(protocol) );
+    struct port_mapping mapping_data;
+    HRESULT ret;
 
-    if (mapping) *mapping = NULL;
-    return E_NOTIMPL;
+    TRACE( "iface %p, port %d, protocol %s.\n", iface, port, debugstr_w(protocol) );
+
+    if (!mapping) return E_POINTER;
+    *mapping = NULL;
+    if (!is_valid_protocol( protocol )) return E_INVALIDARG;
+    if (port < 0 || port > 65535) return E_INVALIDARG;
+
+    if (!find_port_mapping( port, protocol, &mapping_data )) return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
+    if (FAILED(ret = static_port_mapping_create( &mapping_data, mapping ))) free_port_mapping( &mapping_data );
+    return ret;
 }
 
 static HRESULT WINAPI static_ports_get_Count(
-- 
2.34.1




More information about the wine-devel mailing list