[PATCH v2 1/1] hnetcfg/tests: Add firewall tests

Fabian Maurer wine at gitlab.winehq.org
Wed May 11 17:01:50 CDT 2022


From: Fabian Maurer <dark.shadow4 at web.de>

Signed-off-by: Fabian Maurer <dark.shadow4 at web.de>
---
 dlls/hnetcfg/tests/Makefile.in |   2 +-
 dlls/hnetcfg/tests/policy.c    | 578 +++++++++++++++++++++++++++++++++
 2 files changed, 579 insertions(+), 1 deletion(-)

diff --git a/dlls/hnetcfg/tests/Makefile.in b/dlls/hnetcfg/tests/Makefile.in
index 922370ae5e3..cb03cb8b9a0 100644
--- a/dlls/hnetcfg/tests/Makefile.in
+++ b/dlls/hnetcfg/tests/Makefile.in
@@ -1,5 +1,5 @@
 TESTDLL   = hnetcfg.dll
-IMPORTS   = ole32 uuid oleaut32 advapi32 mpr
+IMPORTS   = ole32 uuid oleaut32 advapi32 mpr iphlpapi
 
 C_SRCS = \
 	policy.c
diff --git a/dlls/hnetcfg/tests/policy.c b/dlls/hnetcfg/tests/policy.c
index 4a50bf6d23b..e3eda8a7c2b 100644
--- a/dlls/hnetcfg/tests/policy.c
+++ b/dlls/hnetcfg/tests/policy.c
@@ -23,8 +23,11 @@
 #include "oleauto.h"
 #include "olectl.h"
 #include "dispex.h"
+#include "winsock2.h"
+#include "iphlpapi.h"
 
 #include "wine/test.h"
+#include "wine/heap.h"
 
 #include "netfw.h"
 #include "natupnp.h"
@@ -35,6 +38,578 @@ static ULONG get_refcount(IUnknown *unk)
     return IUnknown_Release(unk);
 }
 
+typedef struct
+{
+    const WCHAR *application_name;
+    const WCHAR *description;
+    const WCHAR *grouping;
+    const WCHAR *interface_types;
+    const WCHAR *local_addresses;
+    const WCHAR *local_ports;
+    const WCHAR *name;
+    const WCHAR *remote_addresses;
+    const WCHAR *remote_ports;
+    const WCHAR *service_name;
+    const WCHAR *interface_name;
+    NET_FW_ACTION action;
+    LONG protocol;
+    VARIANT_BOOL enabled;
+    VARIANT_BOOL edge_traversal;
+    LONG profiles;
+    NET_FW_RULE_DIRECTION direction;
+} rule_test;
+
+#define compare_rule(rule, rule_expected) \
+    compare_rule_(rule, rule_expected, __FILE__, __LINE__)
+
+static void compare_rule_(rule_test *rule, rule_test *rule_expected, const char *file, int line)
+{
+    BOOL success;
+
+    success = !lstrcmpW(rule->application_name, rule_expected->application_name);
+    ok_(file, line)(success, "application_name: Expected %s, got %s\n", wine_dbgstr_w(rule_expected->application_name), wine_dbgstr_w(rule->application_name));
+
+    success = !lstrcmpW(rule->description, rule_expected->description);
+    ok_(file, line)(success, "description: Expected %s, got %s\n", wine_dbgstr_w(rule_expected->description), wine_dbgstr_w(rule->description));
+
+    success = !lstrcmpW(rule->grouping, rule_expected->grouping);
+    ok_(file, line)(success, "grouping: Expected %s, got %s\n", wine_dbgstr_w(rule_expected->grouping), wine_dbgstr_w(rule->grouping));
+
+    success = !lstrcmpW(rule->interface_types, rule_expected->interface_types);
+    ok_(file, line)(success, "interface_types: Expected %s, got %s\n", wine_dbgstr_w(rule_expected->interface_types), wine_dbgstr_w(rule->interface_types));
+
+    success = !lstrcmpW(rule->local_addresses, rule_expected->local_addresses);
+    ok_(file, line)(success, "local_addresses: Expected %s, got %s\n", wine_dbgstr_w(rule_expected->local_addresses), wine_dbgstr_w(rule->local_addresses));
+
+    success = !lstrcmpW(rule->local_ports, rule_expected->local_ports);
+    ok_(file, line)(success, "local_ports: Expected %s, got %s\n", wine_dbgstr_w(rule_expected->local_ports), wine_dbgstr_w(rule->local_ports));
+
+    success = !lstrcmpW(rule->name, rule_expected->name);
+    ok_(file, line)(success, "name: Expected %s, got %s\n", wine_dbgstr_w(rule_expected->name), wine_dbgstr_w(rule->name));
+
+    success = !lstrcmpW(rule->remote_addresses, rule_expected->remote_addresses);
+    ok_(file, line)(success, "remote_addresses: Expected %s, got %s\n", wine_dbgstr_w(rule_expected->remote_addresses), wine_dbgstr_w(rule->remote_addresses));
+
+    success = !lstrcmpW(rule->remote_ports, rule_expected->remote_ports);
+    ok_(file, line)(success, "remote_ports: Expected %s, got %s\n", wine_dbgstr_w(rule_expected->remote_ports), wine_dbgstr_w(rule->remote_ports));
+
+    success = !lstrcmpW(rule->service_name, rule_expected->service_name);
+    ok_(file, line)(success, "service_name: Expected %s, got %s\n", wine_dbgstr_w(rule_expected->service_name), wine_dbgstr_w(rule->service_name));
+
+    success = !lstrcmpW(rule->interface_name, rule_expected->interface_name);
+    ok_(file, line)(success, "interface_name: Expected %s, got %s\n", wine_dbgstr_w(rule_expected->interface_name), wine_dbgstr_w(rule->interface_name));
+
+
+    ok_(file, line)(rule->action == rule_expected->action, "action: Expected %d, got %d\n", rule_expected->action, rule->action);
+    ok_(file, line)(rule->protocol == rule_expected->protocol, "protocol: Expected %ld, got %ld\n", rule_expected->protocol, rule->protocol);
+    ok_(file, line)(rule->enabled == rule_expected->enabled, "enabled: Expected %d, got %d\n", rule_expected->enabled, rule->enabled);
+    ok_(file, line)(rule->edge_traversal == rule_expected->edge_traversal, "edge_traversal: Expected %d, got %d\n", rule_expected->edge_traversal, rule->edge_traversal);
+    ok_(file, line)(rule->profiles == rule_expected->profiles, "profiles: Expected %ld, got %ld\n", rule_expected->profiles, rule->profiles);
+    ok_(file, line)(rule->direction == rule_expected->direction, "direction: Expected %d, got %d\n", rule_expected->direction, rule->direction);
+}
+
+static void append_rule_entry(const WCHAR** entry, const WCHAR* append, WCHAR *rule_buffer, DWORD *next_buffer_pos, DWORD rule_buffer_len)
+{
+    if(*entry == NULL)
+        *entry = append;
+    else
+    {
+        DWORD entry_len = lstrlenW(*entry);
+        DWORD len = entry_len + lstrlenW(append) + 2; /* Account for comma and null terminator */
+        WCHAR buffer[1024] = {0};
+        if (*next_buffer_pos + len >= rule_buffer_len || len >= ARRAY_SIZE(buffer))
+        {
+            ok(0, "Buffer too small!\n");
+            return;
+        }
+        lstrcatW(buffer, *entry);
+        lstrcatW(buffer, L",");
+        lstrcatW(buffer, append);
+        if (*entry + entry_len + 1 == rule_buffer + *next_buffer_pos) /* Already at end of buffer */
+        {
+            /* Just extend */
+            memcpy((WCHAR*)*entry, buffer, len * sizeof(WCHAR));
+            *next_buffer_pos += lstrlenW(append) + 1;
+        }
+        else
+        {
+            memcpy(rule_buffer + *next_buffer_pos, buffer, len * sizeof(WCHAR));
+            *entry = rule_buffer + *next_buffer_pos;
+            *next_buffer_pos += len;
+        }
+    }
+}
+
+static void parse_rule_entry_from_registry(rule_test *rule, const WCHAR *left, const WCHAR *right, WCHAR *rule_buffer, DWORD *next_buffer_pos, DWORD rule_buffer_len)
+{
+    const WCHAR* ignore[] = {
+        L"ICMP4", L"ICMP6", L"Defer", L"LUAuth", L"LUOwn", L"TTK", L"TTK2_22", L"TTK2_27", L"TTK2_28", L"RA42", L"RA62",
+        L"LPort2_20", L"AppPkgId", L"Platform", L"Platform2",
+    };
+    if (!lstrcmpW(left, L"Name"))
+        rule->name = right;
+    else if (!lstrcmpW(left, L"App"))
+        rule->application_name = right;
+    else if (!lstrcmpW(left, L"EmbedCtxt"))
+        rule->grouping = right;
+    else if (!lstrcmpW(left, L"Active"))
+    {
+        if (!lstrcmpW(right, L"TRUE"))
+            rule->enabled = VARIANT_TRUE;
+        else if (!lstrcmpW(right, L"FALSE"))
+            rule->enabled = VARIANT_FALSE;
+        else
+            ok(0, "Invalid Action value: %s\n", wine_dbgstr_w(right));
+    }
+    else if (!lstrcmpW(left, L"LPort"))
+        append_rule_entry(&rule->local_ports, right, rule_buffer, next_buffer_pos, rule_buffer_len);
+    else if (!lstrcmpW(left, L"RPort"))
+        append_rule_entry(&rule->remote_ports, right, rule_buffer, next_buffer_pos, rule_buffer_len);
+    else if (!lstrcmpW(left, L"Svc"))
+        rule->service_name = right;
+    else if (!lstrcmpW(left, L"Protocol"))
+        rule->protocol = wcstol(right, 0, 10);
+    else if (!lstrcmpW(left, L"Edge"))
+    {
+        if (!lstrcmpW(right, L"TRUE"))
+            rule->edge_traversal = VARIANT_TRUE;
+        else if (!lstrcmpW(right, L"FALSE"))
+            rule->edge_traversal = VARIANT_FALSE;
+        else
+            ok(0, "Invalid Edge value: %s\n", wine_dbgstr_w(right));
+    }
+    else if (!lstrcmpW(left, L"Action"))
+    {
+        if (!lstrcmpW(right, L"Allow"))
+            rule->action = NET_FW_ACTION_ALLOW;
+        else if (!lstrcmpW(right, L"Block"))
+            rule->action = NET_FW_ACTION_BLOCK;
+        else
+            ok(0, "Invalid Action value: %s\n", wine_dbgstr_w(right));
+    }
+    else if (!lstrcmpW(left, L"Dir"))
+    {
+        if (!lstrcmpW(right, L"In"))
+           rule->direction = NET_FW_RULE_DIR_IN;
+        else if (!lstrcmpW(right, L"Out"))
+            rule->direction = NET_FW_RULE_DIR_OUT;
+        else
+           ok(0, "Invalid Direction value: %s\n", wine_dbgstr_w(right));
+    }
+    else if (!lstrcmpW(left, L"Profile"))
+    {
+        if (!lstrcmpW(right, L"Private"))
+            rule->profiles |= NET_FW_PROFILE2_PRIVATE;
+        else if (!lstrcmpW(right, L"Public"))
+            rule->profiles |= NET_FW_PROFILE2_PUBLIC;
+        else if (!lstrcmpW(right, L"Domain"))
+            rule->profiles |= NET_FW_PROFILE2_DOMAIN;
+        else
+            ok(0, "Invalid Profile value: %s\n", wine_dbgstr_w(right));
+    }
+    else if (!lstrcmpW(left, L"Desc"))
+        rule->description = right;
+    else if (!lstrcmpW(left, L"RA4"))
+        rule->remote_addresses = right;
+    else if (!lstrcmpW(left, L"RA6"))
+        rule->remote_addresses = right;
+    else if (!lstrcmpW(left, L"LA4"))
+        rule->local_addresses = right;
+    else if (!lstrcmpW(left, L"LA6"))
+        rule->local_addresses = right;
+    else if (!lstrcmpW(left, L"IF"))
+    {
+        IP_ADAPTER_ADDRESSES *adapters = NULL;
+        ULONG len = 0;
+        BOOL found = FALSE;
+        HRESULT hr;
+        char buffer[100];
+
+        hr = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, NULL, &len);
+        ok(hr == ERROR_NO_DATA || hr == ERROR_BUFFER_OVERFLOW, "GetAdaptersAddresses returned %08lx\n", hr);
+        if(hr == ERROR_NO_DATA)
+            return;
+
+        adapters = heap_alloc(len);
+        hr = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, adapters, &len);
+        ok(hr == ERROR_SUCCESS, "GetAdaptersAddresses returned %08lx\n", hr);
+
+        WideCharToMultiByte(CP_ACP, 0, right, -1, buffer, sizeof(buffer), NULL, NULL);
+
+        while (adapters)
+        {
+            if (!lstrcmpA(adapters->AdapterName, buffer))
+            {
+                rule->interface_name = adapters->FriendlyName;
+                found = TRUE;
+            }
+            adapters = adapters->Next;
+        }
+
+        ok (found, "Can't find interface: %s\n", wine_dbgstr_w(right));
+    }
+    else if (!lstrcmpW(left, L"LPort2_10"))
+        append_rule_entry(&rule->local_ports, right, rule_buffer, next_buffer_pos, rule_buffer_len);
+    else if (!lstrcmpW(left, L"RPort2_10"))
+        append_rule_entry(&rule->remote_ports, right, rule_buffer, next_buffer_pos, rule_buffer_len);
+    else if (!lstrcmpW(left, L"IFType"))
+        rule->interface_types = right;
+    else
+    {
+        for (int i = 0; i < ARRAY_SIZE(ignore); i++)
+        {
+            if (!lstrcmpW(left, ignore[i]))
+                return;
+        }
+        ok(0, "Unhandled entry %s = %s\n", wine_dbgstr_w(left), wine_dbgstr_w(right));
+    }
+}
+
+static void parse_rule_from_registry(rule_test *rule, WCHAR *rule_buffer, DWORD next_buffer_pos, DWORD rule_buffer_len)
+{
+    /* Skip version */
+    WCHAR *rule_text = wcschr(rule_buffer, '|') + 1;
+    do
+    {
+        int len_entry = wcschr(rule_text, '|') - rule_text;
+
+        /* Parse left/right */
+        int len_left = wcschr(rule_text, '=') - rule_text;
+        rule_text[len_left] = 0;
+        rule_text[len_entry] = 0;
+        parse_rule_entry_from_registry(rule, rule_text, rule_text + len_left + 1, rule_buffer, &next_buffer_pos, rule_buffer_len);
+
+        rule_text += len_entry + 1;
+    } while (*rule_text);
+}
+
+static BOOL read_rule_from_registry(rule_test *rule, const WCHAR *target_name, WCHAR *rule_buffer, DWORD rule_buffer_len)
+{
+    HKEY key;
+    int i = 0;
+    WCHAR name[200];
+    DWORD type = REG_SZ;
+    DWORD data_len = rule_buffer_len;
+    DWORD name_len = sizeof(name);
+    static const char *path = "SYSTEM\\CurrentControlSet\\Services\\SharedAccess\\Parameters\\FirewallPolicy\\FirewallRules";
+    LSTATUS status = RegCreateKeyExA(HKEY_LOCAL_MACHINE, path, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &key, NULL);
+    ok(status == 0, "RegCreateKeyExA failed: %ld\n", status);
+
+    memset(rule, 0, sizeof(rule_test));
+
+    if (status)
+        return FALSE;
+
+    while (RegEnumValueW(key, i, name, &name_len, NULL, &type, (BYTE*)rule_buffer, &data_len) == ERROR_SUCCESS)
+    {
+        rule_buffer[data_len] = 0;
+
+        memset(rule, 0, sizeof(rule_test));
+        parse_rule_from_registry(rule, rule_buffer, data_len + 1, rule_buffer_len);
+        if (!lstrcmpW(rule->name, target_name))
+        {
+            RegCloseKey(key);
+            return TRUE;
+        }
+        name_len = sizeof(name);
+        data_len = rule_buffer_len;
+        i++;
+    }
+    RegCloseKey(key);
+    return FALSE;
+}
+
+static void fill_rule(INetFwRule *rule, rule_test *rule_info)
+{
+    HRESULT hr;
+    BSTR application_name = SysAllocString(rule_info->application_name);
+    BSTR description      = SysAllocString(rule_info->description);
+    BSTR grouping         = SysAllocString(rule_info->grouping);
+    BSTR interface_types  = SysAllocString(rule_info->interface_types);
+    BSTR local_addresses  = SysAllocString(rule_info->local_addresses);
+    BSTR local_ports      = SysAllocString(rule_info->local_ports);
+    BSTR name             = SysAllocString(rule_info->name);
+    BSTR remote_addresses = SysAllocString(rule_info->remote_addresses);
+    BSTR remote_ports     = SysAllocString(rule_info->remote_ports);
+    BSTR service_name     = SysAllocString(rule_info->service_name);
+
+    hr = INetFwRule_put_Name(rule, name);
+    ok(hr == S_OK, "Got %08lx\n", hr);
+    hr = INetFwRule_put_Grouping(rule, grouping);
+    ok(hr == S_OK, "Got %08lx\n", hr);
+
+    hr = INetFwRule_put_Protocol(rule, rule_info->protocol);
+    ok(hr == S_OK, "Got %08lx\n", hr);
+    hr = INetFwRule_put_Action(rule, rule_info->action);
+    ok(hr == S_OK, "Got %08lx\n", hr);
+    hr = INetFwRule_put_ApplicationName(rule, application_name);
+    ok(hr == S_OK, "Got %08lx\n", hr);
+    hr = INetFwRule_put_Description(rule, description);
+    ok(hr == S_OK, "Got %08lx\n", hr);
+    hr = INetFwRule_put_Direction(rule, NET_FW_RULE_DIR_IN);
+    ok(hr == S_OK, "Got %08lx\n", hr);
+    hr = INetFwRule_put_EdgeTraversal(rule, rule_info->edge_traversal);
+    ok(hr == S_OK, "Got %08lx\n", hr);
+    hr = INetFwRule_put_Enabled(rule, rule_info->enabled);
+    ok(hr == S_OK, "Got %08lx\n", hr);
+    hr = INetFwRule_put_InterfaceTypes(rule, interface_types);
+    ok(hr == S_OK, "Got %08lx\n", hr);
+    hr = INetFwRule_put_LocalAddresses(rule, local_addresses);
+    ok(hr == S_OK, "Got %08lx\n", hr);
+    hr = INetFwRule_put_LocalPorts(rule, local_ports);
+    ok(hr == S_OK, "Got %08lx\n", hr);
+    hr = INetFwRule_put_Profiles(rule, rule_info->profiles);
+    ok(hr == S_OK, "Got %08lx\n", hr);
+    hr = INetFwRule_put_RemoteAddresses(rule, remote_addresses);
+    ok(hr == S_OK, "Got %08lx\n", hr);
+    hr = INetFwRule_put_RemotePorts(rule, remote_ports);
+    ok(hr == S_OK, "Got %08lx\n", hr);
+    hr = INetFwRule_put_ServiceName(rule, service_name);
+
+    if (rule_info->interface_name)
+    {
+        VARIANT interfaces;
+        SAFEARRAY *interface_list;
+        LONG interface_index = 0;
+        VARIANT variant_interface_name;
+        BSTR interface_name = SysAllocString(rule_info->interface_name);
+
+        variant_interface_name.n1.n2.vt = VT_BSTR;
+        variant_interface_name.n1.n2.n3.bstrVal = interface_name;
+        interface_list = SafeArrayCreateVector(VT_VARIANT, 0, 1);
+        ok(interface_list != NULL, "SafeArrayCreateVector failed\n");
+        hr = SafeArrayPutElement(interface_list, &interface_index, &variant_interface_name);
+        ok(hr == S_OK, "Got %08lx\n", hr);
+
+        interfaces.n1.n2.vt = VT_ARRAY | VT_VARIANT;
+        interfaces.n1.n2.n3.parray = interface_list;
+
+        hr = INetFwRule_put_Interfaces(rule, interfaces);
+        ok(hr == S_OK, "Got %08lx\n", hr);
+
+        hr = SafeArrayDestroy(interface_list);
+        ok(hr == S_OK, "Got %08lx\n", hr);
+
+        SysFreeString(interface_name);
+    }
+
+    SysFreeString(application_name);
+    SysFreeString(description);
+    SysFreeString(grouping);
+    SysFreeString(interface_types);
+    SysFreeString(local_addresses);
+    SysFreeString(local_ports);
+    SysFreeString(name);
+    SysFreeString(remote_addresses);
+    SysFreeString(remote_ports);
+    SysFreeString(service_name);
+}
+
+#define verify_rule(rule, rule_info) verify_rule_(rule, rule_info, __LINE__)
+static void verify_rule_(INetFwRule *rule, rule_test *rule_info, int line)
+{
+    HRESULT hr;
+    BSTR application_name;
+    BSTR description;
+    BSTR grouping;
+    BSTR interface_types;
+    BSTR local_addresses;
+    BSTR local_ports;
+    BSTR name;
+    BSTR remote_addresses;
+    BSTR remote_ports;
+    BSTR service_name;
+    NET_FW_ACTION action;
+    NET_FW_RULE_DIRECTION direction;
+    VARIANT_BOOL edge_traversal;
+    VARIANT_BOOL enabled;
+    LONG profiles;
+    LONG protocol;
+    VARIANT interfaces;
+
+    hr = INetFwRule_get_Action(rule, &action);
+    ok_(__FILE__, line)(hr == S_OK, "action: Got %08lx\n", hr);
+    hr = INetFwRule_get_ApplicationName(rule, &application_name);
+    ok_(__FILE__, line)(hr == S_OK, "application_name: Got %08lx\n", hr);
+    hr = INetFwRule_get_Description(rule, &description);
+    ok_(__FILE__, line)(hr == S_OK, "description: Got %08lx\n", hr);
+    hr = INetFwRule_get_Direction(rule, &direction);
+    ok_(__FILE__, line)(hr == S_OK, "direction: Got %08lx\n", hr);
+    hr = INetFwRule_get_EdgeTraversal(rule, &edge_traversal);
+    ok_(__FILE__, line)(hr == S_OK, "edge_traversal: Got %08lx\n", hr);
+    hr = INetFwRule_get_Enabled(rule, &enabled);
+    ok_(__FILE__, line)(hr == S_OK, "enabled: Got %08lx\n", hr);
+    hr = INetFwRule_get_Grouping(rule, &grouping);
+    ok_(__FILE__, line)(hr == S_OK, "grouping: Got %08lx\n", hr);
+    hr = INetFwRule_get_Interfaces(rule, &interfaces);
+    ok_(__FILE__, line)(hr == S_OK, "interfaces: Got %08lx\n", hr);
+    hr = INetFwRule_get_InterfaceTypes(rule, &interface_types);
+    ok_(__FILE__, line)(hr == S_OK, "interface_types: Got %08lx\n", hr);
+    hr = INetFwRule_get_LocalAddresses(rule, &local_addresses);
+    ok_(__FILE__, line)(hr == S_OK, "local_addresses: Got %08lx\n", hr);
+    hr = INetFwRule_get_LocalPorts(rule, &local_ports);
+    ok_(__FILE__, line)(hr == S_OK, "local_ports: Got %08lx\n", hr);
+    hr = INetFwRule_get_Name(rule, &name);
+    ok_(__FILE__, line)(hr == S_OK, "name: Got %08lx\n", hr);
+    hr = INetFwRule_get_Profiles(rule, &profiles);
+    profiles = profiles & 0x7; /* Only lower 3 bits are relevant for this bitmask, so only check those */
+    ok_(__FILE__, line)(hr == S_OK, "profiles: Got %08lx\n", hr);
+    hr = INetFwRule_get_Protocol(rule, &protocol);
+    ok_(__FILE__, line)(hr == S_OK, "protocol: Got %08lx\n", hr);
+    hr = INetFwRule_get_RemoteAddresses(rule, &remote_addresses);
+    ok_(__FILE__, line)(hr == S_OK, "remote_addresses: Got %08lx\n", hr);
+    hr = INetFwRule_get_RemotePorts(rule, &remote_ports);
+    ok_(__FILE__, line)(hr == S_OK, "remote_ports: Got %08lx\n", hr);
+    hr = INetFwRule_get_ServiceName(rule, &service_name);
+    ok_(__FILE__, line)(hr == S_OK, "service_name: Got %08lx\n", hr);
+
+    ok_(__FILE__, line)(rule_info->action == action, "action: Expected %dl, got %dl\n", rule_info->action, action);
+    ok_(__FILE__, line)(rule_info->direction == direction, "direction: Expected %d, got %d\n", rule_info->direction, direction);
+    ok_(__FILE__, line)(rule_info->profiles == profiles, "profiles: Expected %08lx, got %08lx\n", rule_info->profiles, profiles);
+    ok_(__FILE__, line)(rule_info->protocol == protocol, "protocol: Expected %ld, got %ld\n", rule_info->protocol, protocol);
+    ok_(__FILE__, line)(rule_info->edge_traversal == edge_traversal, "edge_traversal: Expected %d, got %d\n", rule_info->edge_traversal, edge_traversal);
+    ok_(__FILE__, line)(rule_info->enabled == enabled, "enabled: Expected %d, got %d\n", rule_info->enabled, enabled);
+
+    ok_(__FILE__, line)(lstrcmpW(rule_info->application_name, application_name) == 0, "application_name: Expected %s, got %s\n", wine_dbgstr_w(rule_info->application_name), wine_dbgstr_w(application_name));
+    ok_(__FILE__, line)(lstrcmpW(rule_info->description, description) == 0, "description: Expected %s, got %s\n", wine_dbgstr_w(rule_info->description), wine_dbgstr_w(description));
+    ok_(__FILE__, line)(lstrcmpW(rule_info->grouping, grouping) == 0, "grouping: Expected %s, got %s\n", wine_dbgstr_w(rule_info->grouping), wine_dbgstr_w(grouping));
+    ok_(__FILE__, line)(lstrcmpW(rule_info->interface_types, interface_types) == 0, "interface_types: Expected %s, got %s\n", wine_dbgstr_w(rule_info->interface_types), wine_dbgstr_w(interface_types));
+    ok_(__FILE__, line)(lstrcmpW(rule_info->local_addresses, local_addresses) == 0, "local_addresses: Expected %s, got %s\n", wine_dbgstr_w(rule_info->local_addresses), wine_dbgstr_w(local_addresses));
+    ok_(__FILE__, line)(lstrcmpW(rule_info->local_ports, local_ports) == 0, "local_ports: Expected %s, got %s\n", wine_dbgstr_w(rule_info->local_ports), wine_dbgstr_w(local_ports));
+    ok_(__FILE__, line)(lstrcmpW(rule_info->name, name) == 0, "name: Expected %s, got %s\n", wine_dbgstr_w(rule_info->name), wine_dbgstr_w(name));
+    ok_(__FILE__, line)(lstrcmpW(rule_info->remote_addresses, remote_addresses) == 0, "remote_addresses: Expected %s, got %s\n", wine_dbgstr_w(rule_info->remote_addresses), wine_dbgstr_w(remote_addresses));
+    ok_(__FILE__, line)(lstrcmpW(rule_info->remote_ports, remote_ports) == 0, "remote_ports: Expected %s, got %s\n", wine_dbgstr_w(rule_info->remote_ports), wine_dbgstr_w(remote_ports));
+    ok_(__FILE__, line)(lstrcmpW(rule_info->service_name, service_name) == 0, "service_name: Expected %s, got %s\n", wine_dbgstr_w(rule_info->service_name), wine_dbgstr_w(service_name));
+
+    SysFreeString(application_name);
+    SysFreeString(description);
+    SysFreeString(grouping);
+    SysFreeString(interface_types);
+    SysFreeString(local_addresses);
+    SysFreeString(local_ports);
+    SysFreeString(name);
+    SysFreeString(remote_addresses);
+    SysFreeString(remote_ports);
+    SysFreeString(service_name);
+}
+
+static void test_INetFwRules(INetFwRules *rules)
+{
+    rule_test rule_reg;
+    INetFwRule *rule_get;
+    WCHAR rule_buffer[1024];
+    BOOL success;
+
+    static const WCHAR *str_application_name    = L"test-application";
+    static const WCHAR *str_description         = L"test-rule-description";
+    static const WCHAR *str_grouping            = L"test-grouping";
+    static const WCHAR *str_name_empty          = L"wine-test-rule-empty";
+    static const WCHAR *str_name_full           = L"wine-test-rule-full";
+    static const WCHAR *str_service_name        = L"test-service";
+    static const WCHAR *str_interface_types_lan = L"Lan";
+    static const WCHAR *str_interface_types_all = L"All";
+    static const WCHAR *str_address             = L"127.0.0.0/255.255.255.0";
+    static const WCHAR *str_address_all         = L"*";
+    static const WCHAR *str_ports               = L"80,443";
+    BSTR rule_name_empty = SysAllocString(str_name_empty);
+    BSTR rule_name_full = SysAllocString(str_name_full);
+    HRESULT hr;
+    INetFwRule *rule;
+    rule_test rule_info = {0};
+    IP_ADAPTER_ADDRESSES *adapters = NULL;
+    ULONG len = 0;
+
+    /* Test default values for empty rule */
+    hr = CoCreateInstance(&CLSID_NetFwRule, NULL, CLSCTX_INPROC_SERVER, &IID_INetFwRule, (void**)&rule);
+    todo_wine
+    ok (hr == S_OK, "Got %08lx\n", hr);
+
+    if(!rule)
+        goto cleanup;
+
+    hr = INetFwRule_put_Name(rule, rule_name_empty);
+    ok(hr == S_OK, "Got %08lx\n", hr);
+
+    hr = INetFwRules_Add(rules, rule);
+    ok (hr == 0, "INetFwRules_Add failed: %08lx\n", hr);
+
+    rule_info.action           = NET_FW_ACTION_ALLOW;
+    rule_info.direction        = NET_FW_RULE_DIR_IN;
+    rule_info.profiles         = NET_FW_PROFILE2_PRIVATE | NET_FW_PROFILE2_PUBLIC | NET_FW_PROFILE2_DOMAIN;
+    rule_info.protocol         = 256; /* Unknown */
+    rule_info.interface_types  = str_interface_types_all;
+    rule_info.local_addresses  = str_address_all;
+    rule_info.name             = str_name_empty;
+    rule_info.remote_addresses = str_address_all;
+
+    verify_rule(rule, &rule_info);
+
+    /* Test filled rule */
+    hr = CoCreateInstance(&CLSID_NetFwRule, NULL, CLSCTX_INPROC_SERVER, &IID_INetFwRule, (void**)&rule);
+    ok(hr == S_OK, "Got %08lx\n", hr);
+
+    if(!rule)
+        goto cleanup;
+
+    hr = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, NULL, &len);
+    ok(hr == ERROR_NO_DATA || hr == ERROR_BUFFER_OVERFLOW, "GetAdaptersAddresses returned %08lx\n", hr);
+    if(hr == ERROR_NO_DATA)
+    {
+        rule_info.interface_name = NULL;
+        skip("No adapters found, can't create rule for specific interface\n");
+    }
+    else
+    {
+        adapters = heap_alloc(len);
+        hr = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, adapters, &len);
+        ok(hr == ERROR_SUCCESS, "GetAdaptersAddresses returned %08lx\n", hr);
+
+        rule_info.interface_name = adapters->FriendlyName;
+    }
+
+    rule_info.application_name = str_application_name;
+    rule_info.description      = str_description;
+    rule_info.grouping         = str_grouping;
+    rule_info.interface_types  = str_interface_types_lan;
+    rule_info.local_addresses  = str_address;
+    rule_info.local_ports      = str_ports;
+    rule_info.name             = str_name_full;
+    rule_info.remote_addresses = str_address;
+    rule_info.remote_ports     = str_ports;
+    rule_info.service_name     = str_service_name;
+    rule_info.protocol         = 6; /* TCP */
+    rule_info.action           = NET_FW_ACTION_ALLOW;
+    rule_info.enabled          = VARIANT_TRUE;
+    rule_info.edge_traversal   = VARIANT_TRUE;
+    rule_info.profiles         = NET_FW_PROFILE2_PRIVATE | NET_FW_PROFILE2_PUBLIC | NET_FW_PROFILE2_DOMAIN;
+    rule_info.direction        = NET_FW_RULE_DIR_IN;
+
+    fill_rule(rule, &rule_info);
+    verify_rule(rule, &rule_info);
+
+    hr = INetFwRules_Add(rules, rule);
+    ok (hr == 0, "INetFwRules_Add failed: %08lx\n", hr);
+
+    success = read_rule_from_registry(&rule_reg, str_name_full, rule_buffer, ARRAY_SIZE(rule_buffer));
+    ok(success, "Failed to get rule %s\n", wine_dbgstr_w(str_name_full));
+    if (success)
+        compare_rule(&rule_reg, &rule_info);
+
+    hr = INetFwRules_Item(rules, rule_name_full, &rule_get);
+    ok (hr == S_OK, "Got %08lx\n", hr);
+    if (hr == S_OK)
+        verify_rule(rule_get, &rule_info);
+
+    hr = INetFwRules_Remove(rules, rule_name_full);
+    ok (hr == 0, "INetFwRules_Remove failed: %08lx\n", hr);
+
+cleanup:
+    SysFreeString(rule_name_empty);
+    SysFreeString(rule_name_full);
+    if (adapters)
+        heap_free(adapters);
+}
+
 static void test_policy2_rules(INetFwPolicy2 *policy2)
 {
     HRESULT hr;
@@ -69,6 +644,8 @@ static void test_policy2_rules(INetFwPolicy2 *policy2)
     hr = INetFwRules_get__NewEnum(rules, NULL);
     ok(hr == E_POINTER, "got %08lx\n", hr);
 
+    test_INetFwRules(rules);
+
     INetFwRules_Release(rules);
     INetFwRules_Release(rules2);
 }
@@ -328,6 +905,7 @@ static void test_IUPnPNAT(void)
     IUPnPNAT_Release(nat);
 }
 
+
 START_TEST(policy)
 {
     INetFwMgr *manager;
-- 
GitLab

https://gitlab.winehq.org/wine/wine/-/merge_requests/59



More information about the wine-devel mailing list