--- /dev/null
+/*
+ * PROJECT: ReactOS API Tests
+ * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE: Tests for network interface name resolving functions
+ * COPYRIGHT: Copyright 2017 Stanislav Motylkov
+ */
+
+#include <apitest.h>
+
+#define WIN32_NO_STATUS
+#include <iphlpapi.h>
+#include <ndk/rtlfuncs.h>
+#include <initguid.h>
+
+DEFINE_GUID(MY_TEST_GUID, 0x8D1AB70F, 0xADF0, 0x49FC, 0x9D, 0x07, 0x4E, 0x89, 0x29, 0x2D, 0xC5, 0x2B);
+static DWORD (WINAPI * pNhGetInterfaceNameFromGuid)(PVOID, PVOID, PULONG, DWORD, DWORD);
+static DWORD (WINAPI * pNhGetInterfaceNameFromDeviceGuid)(PVOID, PVOID, PULONG, DWORD, DWORD);
+
+/*
+ * Tests for NhGetInterfaceNameFromGuid
+ */
+static
+VOID
+test_NhGetInterfaceNameFromGuid(GUID AdapterGUID, DWORD par1, DWORD par2)
+{
+ DWORD ApiReturn, Error;
+ ULONG ulOutBufLen;
+ WCHAR Name[MAX_INTERFACE_NAME_LEN + 4];
+ GUID UniqueGUID = MY_TEST_GUID;
+
+ // Test NULL GUID
+ SetLastError(0xbeeffeed);
+ Error = 0xbeeffeed;
+ ZeroMemory(&Name, sizeof(Name));
+ ApiReturn = ERROR_SUCCESS;
+ ulOutBufLen = sizeof(Name);
+ StartSeh()
+ ApiReturn = pNhGetInterfaceNameFromGuid(NULL, &Name, &ulOutBufLen, par1, par2);
+ Error = GetLastError();
+ EndSeh(STATUS_SUCCESS);
+
+ ok(ApiReturn == ERROR_INVALID_PARAMETER,
+ "ApiReturn returned %ld, expected ERROR_INVALID_PARAMETER\n",
+ ApiReturn);
+ ok(Error == 0xbeeffeed,
+ "GetLastError() returned %ld, expected 0xbeeffeed\n",
+ Error);
+ ok(ulOutBufLen == sizeof(Name),
+ "ulOutBufLen is %ld, expected = sizeof(Name)\n",
+ ulOutBufLen);
+ ok_wstr(L"", Name);
+
+ // Test correct GUID, but NULL name
+ SetLastError(0xbeeffeed);
+ ZeroMemory(&Name, sizeof(Name));
+ ApiReturn = pNhGetInterfaceNameFromGuid(&AdapterGUID, NULL, &ulOutBufLen, par1, par2);
+ Error = GetLastError();
+
+ ok(ApiReturn == ERROR_SUCCESS,
+ "ApiReturn returned %ld, expected ERROR_SUCCESS\n",
+ ApiReturn);
+ ok(Error == 0xbeeffeed,
+ "GetLastError() returned %ld, expected 0xbeeffeed\n",
+ Error);
+ ok(ulOutBufLen > 0,
+ "ulOutBufLen is %ld, expected > 0\n",
+ ulOutBufLen);
+ ok_wstr(L"", Name);
+
+ // NhGetInterfaceNameFromGuid will throw exception if pOutBufLen is NULL
+ SetLastError(0xbeeffeed);
+ Error = 0xbeeffeed;
+ ZeroMemory(&Name, sizeof(Name));
+ ApiReturn = ERROR_SUCCESS;
+ StartSeh()
+ ApiReturn = pNhGetInterfaceNameFromGuid(&AdapterGUID, &Name, NULL, par1, par2);
+ Error = GetLastError();
+ EndSeh(STATUS_SUCCESS);
+
+ ok(ApiReturn == ERROR_INVALID_PARAMETER,
+ "ApiReturn returned %ld, expected ERROR_INVALID_PARAMETER\n",
+ ApiReturn);
+ ok(Error == 0xbeeffeed,
+ "GetLastError() returned %ld, expected 0xbeeffeed\n",
+ Error);
+ ok(ulOutBufLen > 0,
+ "ulOutBufLen is %ld, expected > 0\n",
+ ulOutBufLen);
+ ok_wstr(L"", Name);
+
+ // Test correct values
+ SetLastError(0xbeeffeed);
+ ZeroMemory(&Name, sizeof(Name));
+ ulOutBufLen = sizeof(Name);
+ ApiReturn = pNhGetInterfaceNameFromGuid(&AdapterGUID, &Name, &ulOutBufLen, par1, par2);
+ Error = GetLastError();
+
+ ok(ApiReturn == ERROR_SUCCESS,
+ "ApiReturn returned %ld, expected ERROR_SUCCESS\n",
+ ApiReturn);
+ ok(Error == 0xbeeffeed,
+ "GetLastError() returned %ld, expected 0xbeeffeed\n",
+ Error);
+ ok(ulOutBufLen > 0,
+ "ulOutBufLen is %ld, expected > 0\n",
+ ulOutBufLen);
+ Error = wcslen(Name);
+ ok(Error > 0,
+ "wcslen(Name) is %ld, expected > 0\n",
+ Error);
+ if (Error > 0)
+ trace("Adapter name: \"%S\"\n", Name);
+
+ // Test correct values, but with new unique GUID
+ SetLastError(0xbeeffeed);
+ ZeroMemory(&Name, sizeof(Name));
+ ulOutBufLen = sizeof(Name);
+ ApiReturn = pNhGetInterfaceNameFromGuid((PVOID)&UniqueGUID, &Name, &ulOutBufLen, par1, par2);
+ Error = GetLastError();
+
+ ok(ApiReturn == ERROR_NOT_FOUND,
+ "ApiReturn returned %ld, expected ERROR_NOT_FOUND\n",
+ ApiReturn);
+ ok(Error == ERROR_PATH_NOT_FOUND,
+ "GetLastError() returned %ld, expected ERROR_PATH_NOT_FOUND\n",
+ Error);
+ ok(ulOutBufLen == sizeof(Name),
+ "ulOutBufLen is %ld, expected = sizeof(Name)\n",
+ ulOutBufLen);
+ ok_wstr(L"", Name);
+
+ // Test correct values, but with small length
+ SetLastError(0xbeeffeed);
+ ZeroMemory(&Name, sizeof(Name));
+ ulOutBufLen = 0;
+ ApiReturn = pNhGetInterfaceNameFromGuid(&AdapterGUID, &Name, &ulOutBufLen, par1, par2);
+ Error = GetLastError();
+
+ ok(ApiReturn == ERROR_INSUFFICIENT_BUFFER,
+ "ApiReturn returned %ld, expected ERROR_INSUFFICIENT_BUFFER\n",
+ ApiReturn);
+ ok(Error == 0xbeeffeed,
+ "GetLastError() returned %ld, expected 0xbeeffeed\n",
+ Error);
+ ok(ulOutBufLen == MAX_INTERFACE_NAME_LEN * 2,
+ "ulOutBufLen is %ld, expected = MAX_INTERFACE_NAME_LEN * 2\n",
+ ulOutBufLen);
+ ok_wstr(L"", Name);
+}
+
+/*
+ * Tests for NhGetInterfaceNameFromDeviceGuid
+ */
+static
+VOID
+test_NhGetInterfaceNameFromDeviceGuid(GUID AdapterGUID, DWORD par1, DWORD par2)
+{
+ DWORD ApiReturn, Error;
+ ULONG ulOutBufLen;
+ WCHAR Name[MAX_INTERFACE_NAME_LEN];
+ GUID UniqueGUID = MY_TEST_GUID;
+
+ // Test NULL GUID
+ // Windows XP: NhGetInterfaceNameFromDeviceGuid throws exception here
+ SetLastError(0xbeeffeed);
+ Error = 0xbeeffeed;
+ ZeroMemory(&Name, sizeof(Name));
+ ApiReturn = ERROR_SUCCESS;
+ ulOutBufLen = sizeof(Name);
+ StartSeh()
+ ApiReturn = pNhGetInterfaceNameFromDeviceGuid(NULL, &Name, &ulOutBufLen, par1, par2);
+ Error = GetLastError();
+ EndSeh(STATUS_SUCCESS);
+
+ ok(ApiReturn == ERROR_INVALID_PARAMETER,
+ "ApiReturn returned %ld, expected ERROR_INVALID_PARAMETER\n",
+ ApiReturn);
+ ok(Error == ERROR_SUCCESS,
+ "GetLastError() returned %ld, expected ERROR_SUCCESS\n",
+ Error);
+ ok(ulOutBufLen == sizeof(Name),
+ "ulOutBufLen is %ld, expected = sizeof(Name)\n",
+ ulOutBufLen);
+ ok_wstr(L"", Name);
+
+ // Test correct GUID, but NULL name
+ SetLastError(0xbeeffeed);
+ Error = 0xbeeffeed;
+ ZeroMemory(&Name, sizeof(Name));
+ ApiReturn = ERROR_SUCCESS;
+ StartSeh()
+ ApiReturn = pNhGetInterfaceNameFromDeviceGuid(&AdapterGUID, NULL, &ulOutBufLen, par1, par2);
+ Error = GetLastError();
+ EndSeh(STATUS_SUCCESS);
+
+ ok(ApiReturn == ERROR_INVALID_PARAMETER,
+ "ApiReturn returned %ld, expected ERROR_INVALID_PARAMETER\n",
+ ApiReturn);
+ ok(Error == ERROR_SUCCESS,
+ "GetLastError() returned %ld, expected ERROR_SUCCESS\n",
+ Error);
+ ok(ulOutBufLen > 0,
+ "ulOutBufLen is %ld, expected > 0\n",
+ ulOutBufLen);
+ ok_wstr(L"", Name);
+
+ // NhGetInterfaceNameFromDeviceGuid will throw exception if pOutBufLen is NULL
+ SetLastError(0xbeeffeed);
+ Error = 0xbeeffeed;
+ ZeroMemory(&Name, sizeof(Name));
+ ApiReturn = ERROR_SUCCESS;
+ StartSeh()
+ ApiReturn = pNhGetInterfaceNameFromDeviceGuid(&AdapterGUID, &Name, NULL, par1, par2);
+ Error = GetLastError();
+ EndSeh(STATUS_SUCCESS);
+
+ ok(ApiReturn == ERROR_INVALID_PARAMETER,
+ "ApiReturn returned %ld, expected ERROR_INVALID_PARAMETER\n",
+ ApiReturn);
+ ok(Error == ERROR_SUCCESS,
+ "GetLastError() returned %ld, expected ERROR_SUCCESS\n",
+ Error);
+ ok(ulOutBufLen > 0,
+ "ulOutBufLen is %ld, expected > 0\n",
+ ulOutBufLen);
+ ok_wstr(L"", Name);
+
+ // Test correct values
+ SetLastError(0xbeeffeed);
+ ZeroMemory(&Name, sizeof(Name));
+ ulOutBufLen = sizeof(Name);
+ ApiReturn = pNhGetInterfaceNameFromDeviceGuid(&AdapterGUID, &Name, &ulOutBufLen, par1, par2);
+ Error = GetLastError();
+
+ ok(ApiReturn == ERROR_SUCCESS,
+ "ApiReturn returned %ld, expected ERROR_SUCCESS\n",
+ ApiReturn);
+ ok(Error == ERROR_SUCCESS,
+ "GetLastError() returned %ld, expected ERROR_SUCCESS\n",
+ Error);
+ ok(ulOutBufLen > 0,
+ "ulOutBufLen is %ld, expected > 0\n",
+ ulOutBufLen);
+ Error = wcslen(Name);
+ ok(Error > 0,
+ "wcslen(Name) is %ld, expected > 0\n",
+ Error);
+ if (Error > 0)
+ trace("Adapter name: \"%S\"\n", Name);
+
+ // Test correct values, but with new unique GUID
+ SetLastError(0xbeeffeed);
+ ZeroMemory(&Name, sizeof(Name));
+ ulOutBufLen = sizeof(Name);
+ ApiReturn = pNhGetInterfaceNameFromDeviceGuid((PVOID)&UniqueGUID, &Name, &ulOutBufLen, par1, par2);
+ Error = GetLastError();
+
+ ok(ApiReturn == ERROR_NOT_FOUND,
+ "ApiReturn returned %ld, expected ERROR_NOT_FOUND\n",
+ ApiReturn);
+ ok(Error == ERROR_SUCCESS,
+ "GetLastError() returned %ld, expected ERROR_SUCCESS\n",
+ Error);
+ ok(ulOutBufLen == sizeof(Name),
+ "ulOutBufLen is %ld, expected = sizeof(Name)\n",
+ ulOutBufLen);
+ ok_wstr(L"", Name);
+
+ // Test correct values, but with small length
+ SetLastError(0xbeeffeed);
+ ZeroMemory(&Name, sizeof(Name));
+ ulOutBufLen = 0;
+ ApiReturn = pNhGetInterfaceNameFromDeviceGuid(&AdapterGUID, &Name, &ulOutBufLen, par1, par2);
+ Error = GetLastError();
+
+ ok(ApiReturn == ERROR_INSUFFICIENT_BUFFER,
+ "ApiReturn returned %ld, expected ERROR_INSUFFICIENT_BUFFER\n",
+ ApiReturn);
+ ok(Error == ERROR_SUCCESS,
+ "GetLastError() returned %ld, expected ERROR_SUCCESS\n",
+ Error);
+ ok(ulOutBufLen == MAX_INTERFACE_NAME_LEN * 2,
+ "ulOutBufLen is %ld, expected = MAX_INTERFACE_NAME_LEN * 2\n",
+ ulOutBufLen);
+ ok_wstr(L"", Name);
+}
+
+static
+VOID
+test_GetInterfaceName(VOID)
+{
+ PIP_INTERFACE_INFO pInfo = NULL;
+ ULONG ulOutBufLen = 0;
+ DWORD ApiReturn;
+ WCHAR Name[MAX_ADAPTER_NAME];
+ UNICODE_STRING GuidString;
+ GUID AdapterGUID;
+ HINSTANCE hIpHlpApi;
+
+ ApiReturn = GetInterfaceInfo(pInfo, &ulOutBufLen);
+ ok(ApiReturn == ERROR_INSUFFICIENT_BUFFER,
+ "GetInterfaceInfo(pInfo, &ulOutBufLen) returned %ld, expected ERROR_INSUFFICIENT_BUFFER\n",
+ ApiReturn);
+ if (ApiReturn != ERROR_INSUFFICIENT_BUFFER)
+ {
+ skip("Can't determine size of IP_INTERFACE_INFO. Can't proceed\n");
+ return;
+ }
+
+ pInfo = (IP_INTERFACE_INFO *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ulOutBufLen);
+ if (pInfo == NULL)
+ {
+ skip("pInfo is NULL. Can't proceed\n");
+ return;
+ }
+
+ ApiReturn = GetInterfaceInfo(pInfo, &ulOutBufLen);
+ ok(ApiReturn == NO_ERROR,
+ "GetInterfaceInfo(pInfo, &ulOutBufLen) returned %ld, expected NO_ERROR\n",
+ ApiReturn);
+ if (ApiReturn != NO_ERROR || ulOutBufLen == 0)
+ {
+ skip("GetInterfaceInfo failed with error %ld. Can't proceed\n", ApiReturn);
+ return;
+ }
+
+ if (pInfo->NumAdapters > 0)
+ CopyMemory(&Name, &pInfo->Adapter[0].Name, sizeof(Name));
+
+ if (pInfo->NumAdapters == 0)
+ {
+ HeapFree(GetProcessHeap(), 0, pInfo);
+ skip("pInfo->NumAdapters = 0. Can't proceed\n");
+ return;
+ }
+ trace("pInfo->NumAdapters: %lu\n", pInfo->NumAdapters);
+
+ HeapFree(GetProcessHeap(), 0, pInfo);
+
+ ApiReturn = wcsncmp(Name, L"\\DEVICE\\TCPIP_", 14);
+ ok(ApiReturn == 0,
+ "wcsncmp(Name, L\"\\DEVICE\\TCPIP_\", 14) returned %ld, expected 0\n",
+ ApiReturn);
+ if (ApiReturn != 0)
+ {
+ if (wcslen(Name) == 0)
+ {
+ skip("pInfo->Adapter[0].Name is empty. Can't proceed\n");
+ return;
+ }
+ else
+ {
+ // workaround for ReactOS
+ trace("pInfo->Adapter[0].Name = \"%ls\" is incorrect.\n", Name);
+ RtlInitUnicodeString(&GuidString, &Name[0]);
+ }
+ }
+ else
+ {
+ RtlInitUnicodeString(&GuidString, &Name[14]);
+ }
+
+ ApiReturn = RtlGUIDFromString(&GuidString, &AdapterGUID);
+ RtlFreeUnicodeString(&GuidString);
+ if (ApiReturn != 0)
+ {
+ skip("RtlGUIDFromString failed. Can't proceed\n");
+ return;
+ }
+
+ hIpHlpApi = GetModuleHandleW(L"iphlpapi.dll");
+ if (!hIpHlpApi)
+ {
+ skip("Failed to load iphlpapi.dll. Can't proceed\n");
+ return;
+ }
+
+ pNhGetInterfaceNameFromGuid = (void *)GetProcAddress(hIpHlpApi, "NhGetInterfaceNameFromGuid");
+
+ if (!pNhGetInterfaceNameFromGuid)
+ skip("NhGetInterfaceNameFromGuid not found. Can't proceed\n");
+ else
+ test_NhGetInterfaceNameFromGuid(AdapterGUID, 0, 0);
+
+ pNhGetInterfaceNameFromDeviceGuid = (void *)GetProcAddress(hIpHlpApi, "NhGetInterfaceNameFromDeviceGuid");
+
+ if (!pNhGetInterfaceNameFromDeviceGuid)
+ skip("NhGetInterfaceNameFromDeviceGuid not found. Can't proceed\n");
+ else
+ test_NhGetInterfaceNameFromDeviceGuid(AdapterGUID, 1, 0);
+}
+
+START_TEST(GetInterfaceName)
+{
+ test_GetInterfaceName();
+}