Signed-off-by: Isabella Bosia ibosia@codeweavers.com --- dlls/iphlpapi/tests/Makefile.in | 6 +- dlls/iphlpapi/tests/ndis.c | 157 ++++++++++++++++++++++++++++++++ 2 files changed, 161 insertions(+), 2 deletions(-) create mode 100644 dlls/iphlpapi/tests/ndis.c
diff --git a/dlls/iphlpapi/tests/Makefile.in b/dlls/iphlpapi/tests/Makefile.in index d813101354..2357f033bf 100644 --- a/dlls/iphlpapi/tests/Makefile.in +++ b/dlls/iphlpapi/tests/Makefile.in @@ -1,5 +1,7 @@ TESTDLL = iphlpapi.dll -IMPORTS = iphlpapi +IMPORTS = iphlpapi advapi32 ole32 +
C_SRCS = \ - iphlpapi.c + iphlpapi.c \ + ndis.c diff --git a/dlls/iphlpapi/tests/ndis.c b/dlls/iphlpapi/tests/ndis.c new file mode 100644 index 0000000000..bdefdd6594 --- /dev/null +++ b/dlls/iphlpapi/tests/ndis.c @@ -0,0 +1,157 @@ +/* + * Unit tests for ndis ioctls + * + * Copyright (c) 2020 Isabella Bosia + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <windows.h> +#include <winioctl.h> +#include <ntddndis.h> +#include <winsock2.h> +#include <ws2ipdef.h> +#include <iphlpapi.h> +#include <netioapi.h> +#include <shlwapi.h> +#include <stdio.h> +#include <string.h> +#include "wine/test.h" + +static void test_device(const char *service_name, const MIB_IF_ROW2 *row) +{ + DWORD size; + int ret; + NDIS_MEDIUM medium; + UCHAR addr[IF_MAX_PHYS_ADDRESS_LENGTH]; + char target_path[48]; + char file_name[43]; + HANDLE netdev; + int oid; + BOOL device_needs_removing = FALSE; + DWORD err; + + ret = QueryDosDeviceA( service_name, target_path, sizeof(target_path) ); + err = GetLastError(); + ok( ret || err == ERROR_FILE_NOT_FOUND, "Couldn't query the device and can't handle this error\n" ); + + if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND) + { + device_needs_removing = TRUE; + snprintf( target_path, sizeof(target_path), "\Device\%s", service_name ); + ok( DefineDosDeviceA( DDD_RAW_TARGET_PATH, service_name, target_path ) != 0, "DDD failed to create\n" ); + } + + snprintf( file_name, sizeof(file_name), "\\.\%s", service_name ); + netdev = CreateFileA( file_name, 0, 1, NULL, 3, 0, NULL ); + if (netdev != INVALID_HANDLE_VALUE) + { + oid = OID_GEN_MEDIA_SUPPORTED; + ret = DeviceIoControl( netdev, IOCTL_NDIS_QUERY_GLOBAL_STATS, + &oid, sizeof(oid), &medium, sizeof(medium), &size, NULL ); + ok( ret && medium == row->MediaType, "OID_GEN_MEDIA_SUPPORTED failed\n" ); + + oid = OID_GEN_MEDIA_IN_USE; + ret = DeviceIoControl( netdev, IOCTL_NDIS_QUERY_GLOBAL_STATS, + &oid, sizeof(oid), &medium, sizeof(medium), &size, NULL ); + ok( ret && medium == row->MediaType, "OID_GEN_MEDIA_IN_USE failed\n" ); + + oid = OID_802_3_PERMANENT_ADDRESS; + ret = DeviceIoControl( netdev, IOCTL_NDIS_QUERY_GLOBAL_STATS, + &oid, sizeof(oid), addr, sizeof(addr), &size, NULL ); + ok( ret, "OID_802_3_PERMANENT_ADDRESS failed\n" ); + ok( row->PhysicalAddressLength == size && !memcmp( row->PermanentPhysicalAddress, addr, size ), + "Wrong permanent address\n" ); + + oid = OID_802_3_CURRENT_ADDRESS; + ret = DeviceIoControl( netdev, IOCTL_NDIS_QUERY_GLOBAL_STATS, + &oid, sizeof(oid), addr, sizeof(addr), &size, NULL ); + ok( ret, "OID_802_3_CURRENT_ADDRESS failed\n" ); + ok( row->PhysicalAddressLength == size && !memcmp( row->PhysicalAddress, addr, size ), + "Wrong current address\n" ); + } + else + skip( "Could not open device\n" ); + + if (device_needs_removing) + ok( DefineDosDeviceA( DDD_REMOVE_DEFINITION | DDD_RAW_TARGET_PATH | DDD_EXACT_MATCH_ON_REMOVE, + service_name, target_path ) != 0, "DDD failed to remove\n" ); +} + +void test_ndis_ioctl(void) +{ + HKEY nics, sub_key; + LSTATUS ret; + char card[16]; + BYTE data[100]; + WCHAR description[100]; + DWORD size, type, i = 0; + + ret = RegOpenKeyExA( HKEY_LOCAL_MACHINE, + "Software\Microsoft\Windows NT\CurrentVersion\NetworkCards", 0, KEY_READ, &nics ); + ok( ret == ERROR_SUCCESS, "NetworkCards key missing\n" ); + + while (1) + { + MIB_IF_ROW2 row = { 0 }; + char service_name[39] = { 0 }; + WCHAR guidstrW[39]; + GUID guid; + + + size = sizeof(card); + ret = RegEnumKeyExA( nics, i, card, &size, NULL, NULL, NULL, NULL ); + if (ret != ERROR_SUCCESS) + break; + i++; + + ret = RegOpenKeyExA( nics, card, 0, KEY_READ, &sub_key ); + ok( ret == ERROR_SUCCESS, "Could not open network card subkey\n" ); + + size = sizeof(data); + ret = RegQueryValueExA( sub_key, "ServiceName", NULL, &type, data, &size ); + ok( ret == ERROR_SUCCESS && type == REG_SZ, "Wrong ServiceName\n" ); + + memcpy( service_name, data, size ); + MultiByteToWideChar( CP_ACP, 0, (char *)data, -1, guidstrW, ARRAY_SIZE(guidstrW) ); + CLSIDFromString( guidstrW, (LPCLSID)&guid ); + ConvertInterfaceGuidToLuid( &guid, &row.InterfaceLuid ); + + ret = GetIfEntry2(&row); + ok( ret == NO_ERROR, "GetIfEntry2 failed\n" ); + + ok( IsEqualGUID( &guid, &row.InterfaceGuid ), "Wrong ServiceName\n" ); + + size = sizeof(data); + ret = RegQueryValueExA( sub_key, "Description", NULL, &type, data, &size ); + MultiByteToWideChar( CP_ACP, 0, (char *)data, -1, description, ARRAY_SIZE(description) ); + ok( ret == ERROR_SUCCESS && type == REG_SZ, "Wrong Description\n" ); + + trace( "testing device <%s>\n", wine_dbgstr_w(description) ); + test_device( service_name, &row ); + + RegCloseKey( sub_key ); + } + + if (i == 0) + skip( "Network card subkeys missing\n" ); + + RegCloseKey( nics ); +} + +START_TEST(ndis) +{ + test_ndis_ioctl(); +}