[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