[WS2_32_APITESTS] Add tests for SIO_GET_INTERFACE_LIST. Brought to you by Andreas...
authorPeter Hater <7element@mail.bg>
Fri, 21 Oct 2016 16:47:38 +0000 (16:47 +0000)
committerPeter Hater <7element@mail.bg>
Fri, 21 Oct 2016 16:47:38 +0000 (16:47 +0000)
Minor modifications by me on comparison and expected flags.
ROSTESTS-246

svn path=/trunk/; revision=73011

rostests/apitests/ws2_32/CMakeLists.txt
rostests/apitests/ws2_32/WSAIoctl.c [new file with mode: 0644]
rostests/apitests/ws2_32/testlist.c

index e87ad03..7294ef5 100644 (file)
@@ -9,6 +9,7 @@ list(APPEND SOURCE
     nostartup.c
     recv.c
     send.c
+    WSAIoctl.c
     WSARecv.c
     WSAStartup.c
     testlist.c)
@@ -16,5 +17,5 @@ list(APPEND SOURCE
 add_executable(ws2_32_apitest ${SOURCE})
 target_link_libraries(ws2_32_apitest wine ${PSEH_LIB})
 set_module_type(ws2_32_apitest win32cui)
-add_importlibs(ws2_32_apitest ws2_32 msvcrt kernel32 ntdll)
+add_importlibs(ws2_32_apitest ws2_32 msvcrt iphlpapi kernel32 ntdll)
 add_cd_file(TARGET ws2_32_apitest DESTINATION reactos/bin FOR all)
diff --git a/rostests/apitests/ws2_32/WSAIoctl.c b/rostests/apitests/ws2_32/WSAIoctl.c
new file mode 100644 (file)
index 0000000..2e1f722
--- /dev/null
@@ -0,0 +1,232 @@
+/*
+ * PROJECT:         ReactOS api tests
+ * LICENSE:         GPL - See COPYING in the top level directory
+ * PURPOSE:         Test for WSHIoctl:
+ *                  - SIO_GET_INTERFACE_LIST 
+ * PROGRAMMERS:     Andreas Maier
+ */
+
+#include <apitest.h>
+
+#include <stdio.h>
+#include "ws2tcpip.h"
+#include "iphlpapi.h"
+
+void traceaddr(char* txt, sockaddr_gen a)
+{
+    trace("  %s.AddressIn.sin_family %x\n", txt, a.AddressIn.sin_family);
+    trace("  %s.AddressIn.sin_port %x\n", txt, a.AddressIn.sin_port);
+    trace("  %s.AddressIn.sin_addr.s_addr %lx\n", txt, a.AddressIn.sin_addr.s_addr);
+}
+
+BOOL Test_WSAIoctl_InitTest(
+    OUT PMIB_IPADDRTABLE* ppTable)
+{
+    PMIB_IPADDRROW pRow;
+    DWORD ret, i1;
+    ULONG TableSize;
+    PMIB_IPADDRTABLE pTable;
+
+    TableSize = 0;
+    *ppTable = NULL;
+    ret = GetIpAddrTable(NULL, &TableSize, FALSE);
+    if (ret != ERROR_INSUFFICIENT_BUFFER)
+    {
+        skip("GetIpAddrTable failed with %ld. Abort Testing.\n", ret);
+        return FALSE;
+    }
+
+    /* get sorted ip-address table. Sort order is the ip-address. */
+    pTable = (PMIB_IPADDRTABLE)malloc(TableSize);
+    *ppTable = pTable;
+    ret = GetIpAddrTable(pTable, &TableSize, TRUE);
+    if (ret != NO_ERROR) 
+    {
+        skip("GetIpAddrTable failed with %ld. Abort Testing.\n", ret);
+        return FALSE;
+    }
+
+    if (winetest_debug >= 2)
+    {
+        trace("Result of GetIpAddrTable:\n");
+        trace("Count: %ld\n", pTable->dwNumEntries);
+        pRow = pTable->table;
+        for (i1 = 0; i1 < pTable->dwNumEntries; i1++)
+        {
+            trace("** Entry %ld **\n", i1);
+            trace("  dwAddr %lx\n", pRow->dwAddr);
+            trace("  dwIndex %lx\n", pRow->dwIndex);
+            trace("  dwMask %lx\n", pRow->dwMask);
+            trace("  dwBCastAddr %lx\n", pRow->dwBCastAddr);
+            trace("  dwReasmSize %lx\n", pRow->dwReasmSize);
+            trace("  wType %x\n", pRow->wType);
+            pRow++;
+        }
+        trace("END\n");
+    }
+
+    return TRUE;
+}
+
+void Test_WSAIoctl_GetInterfaceList()
+{
+    WSADATA wdata;
+    INT iResult;
+    SOCKET sck;
+    ULONG buflen, BytesReturned, BCastAddr;
+    ULONG infoCount, i1, j1, iiFlagsExpected;
+    BYTE* buf = NULL;
+    LPINTERFACE_INFO ifInfo;
+    PMIB_IPADDRTABLE pTable = NULL;
+    PMIB_IPADDRROW pRow;
+
+    /* Get PMIB_IPADDRTABE - these results we should get from wshtcpip.dll too. */ 
+    /* pTable is allocated by Test_WSAIoctl_InitTest! */
+    if (!Test_WSAIoctl_InitTest(&pTable))
+        goto cleanup;
+
+    /* Start up Winsock */
+    iResult = WSAStartup(MAKEWORD(2, 2), &wdata);
+    ok(iResult == 0, "WSAStartup failed. iResult = %d\n", iResult);
+
+    /* Create the socket */
+    sck = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_IP, 0, 0, 0);
+    ok(sck != INVALID_SOCKET, "WSASocket failed. sck = %d\n", (INT)sck);
+    if (sck == INVALID_SOCKET)
+    {
+        skip("Failed to create socket!\n");
+        goto cleanup;
+    }
+
+    /* Do the Ioctl (buffer to small) */
+    buflen = sizeof(INTERFACE_INFO)-1;
+    buf = (BYTE*)HeapAlloc(GetProcessHeap(), 0, buflen);
+    if (buf == NULL)
+    {
+        skip("Failed to allocate memory!\n");
+        goto cleanup;
+    }
+    BytesReturned = 0;
+    iResult = WSAIoctl(sck, SIO_GET_INTERFACE_LIST, 0, 0,
+                       buf, buflen, &BytesReturned, 0, 0);
+    ok(iResult == -1, "WSAIoctl/SIO_GET_INTERFACE_LIST did not fail! iResult = %d.\n", iResult);
+    ok_hex(WSAGetLastError(), WSAEFAULT);
+    ok(BytesReturned == 0, "WSAIoctl/SIO_GET_INTERFACE_LIST: BytesReturned should be 0, not %ld.\n", BytesReturned);
+    HeapFree(GetProcessHeap(), 0, buf);
+    buf = NULL;
+
+    /* Do the Ioctl 
+       In most cases no loop is done. 
+       Only if WSAIoctl fails with WSAEFAULT (buffer to small) we need to retry with a 
+       larger buffer */
+    i1 = 0;
+    while (TRUE) 
+    {
+        if (buf != NULL)
+        {
+            HeapFree(GetProcessHeap(), 0, buf);
+            buf = NULL;
+        }
+
+        buflen = sizeof(INTERFACE_INFO) * (i1+1) * 32;
+        buf = (BYTE*)HeapAlloc(GetProcessHeap(), 0, buflen);
+        if (buf == NULL)
+        {
+            skip("Failed to allocate memory!\n");
+            goto cleanup;
+        }
+        BytesReturned = 0;
+        iResult = WSAIoctl(sck, SIO_GET_INTERFACE_LIST, 0, 0,
+                           buf, buflen, &BytesReturned, 0, 0);
+        /* we have what we want ... leave loop */
+        if (iResult == NO_ERROR)
+            break;
+        /* only retry if buffer was to small */
+        /* to avoid infinite loop we maximum retry count is 4 */
+        if ((i1 >= 4) || (WSAGetLastError() != WSAEFAULT))
+        {
+            ok_hex(iResult, NO_ERROR);
+            skip("WSAIoctl / SIO_GET_INTERFACE_LIST\n");
+            goto cleanup;
+        }
+        /* buffer to small -> retry */
+        i1++;
+    }
+
+    ok_dec(BytesReturned % sizeof(INTERFACE_INFO), 0);
+
+    /* Calculate how many INTERFACE_INFO we got */
+    infoCount = BytesReturned / sizeof(INTERFACE_INFO);
+    ok(infoCount == pTable->dwNumEntries, 
+       "Wrong count of entries! Got %ld, expected %ld.\n", pTable->dwNumEntries, infoCount);    
+
+    if (winetest_debug >= 2)
+    {
+        trace("WSAIoctl\n");
+        trace("  BytesReturned %ld - InfoCount %ld\n ", BytesReturned, infoCount);
+        ifInfo = (LPINTERFACE_INFO)buf;
+        for (i1 = 0; i1 < infoCount; i1++)
+        {
+            trace("entry-index %ld\n", i1);
+            trace("  iiFlags %ld\n", ifInfo->iiFlags);
+            traceaddr("ifInfo^.iiAddress", ifInfo->iiAddress);
+            traceaddr("ifInfo^.iiBroadcastAddress", ifInfo->iiBroadcastAddress);
+            traceaddr("ifInfo^.iiNetmask", ifInfo->iiNetmask);
+            ifInfo++;
+        }
+    }
+
+    /* compare entries */
+    ifInfo = (LPINTERFACE_INFO)buf;
+    for (i1 = 0; i1 < infoCount; i1++)
+    {
+        if (winetest_debug >= 2)
+            trace("Entry %ld\n", i1);
+        for (j1 = 0; j1 < pTable->dwNumEntries; j1++)
+        {
+            if (ifInfo[i1].iiAddress.AddressIn.sin_addr.s_addr == pTable->table[j1].dwAddr)
+            {
+                pRow = &pTable->table[j1];
+                break;
+            }
+        }
+        if (j1 == pTable->dwNumEntries)
+        {
+            skip("Skipping interface\n");
+            continue;
+        }
+
+        /* iiFlags
+         * Don't know if this value is fix for SIO_GET_INTERFACE_LIST! */ 
+        iiFlagsExpected = IFF_BROADCAST | IFF_MULTICAST;
+        if ((pRow->wType & MIB_IPADDR_DISCONNECTED) == 0)
+            iiFlagsExpected |= IFF_UP;
+        if (pRow->dwAddr == ntohl(INADDR_LOOPBACK))
+        {
+            iiFlagsExpected |= IFF_LOOPBACK;
+            /* on Windows 7 loopback has broadcast flag cleared */
+            //iiFlagsExpected &= ~IFF_BROADCAST;
+        }
+        
+        ok_hex(ifInfo[i1].iiFlags, iiFlagsExpected);
+        ok_hex(ifInfo[i1].iiAddress.AddressIn.sin_addr.s_addr, pRow->dwAddr);
+        // dwBCastAddr is not the "real" Broadcast-Address. 
+        BCastAddr = (pRow->dwBCastAddr == 1 && (iiFlagsExpected & IFF_BROADCAST) != 0) ? 0xFFFFFFFF : 0x0;
+        ok_hex(ifInfo[i1].iiBroadcastAddress.AddressIn.sin_addr.s_addr, BCastAddr);
+        ok_hex(ifInfo[i1].iiNetmask.AddressIn.sin_addr.s_addr, pRow->dwMask);
+    }
+
+cleanup:
+    if (sck != 0)
+        closesocket(sck);
+    if (pTable != NULL)
+       free(pTable);
+    if (buf != NULL)
+       HeapFree(GetProcessHeap(), 0, buf);
+    WSACleanup();
+}
+
+START_TEST(WSAIoctl)
+{
+    Test_WSAIoctl_GetInterfaceList();
+}
index c038513..fcaa364 100644 (file)
@@ -11,6 +11,7 @@ extern void func_ioctlsocket(void);
 extern void func_nostartup(void);
 extern void func_recv(void);
 extern void func_send(void);
+extern void func_WSAIoctl(void);
 extern void func_WSARecv(void);
 extern void func_WSAStartup(void);
 
@@ -24,6 +25,7 @@ const struct test winetest_testlist[] =
     { "nostartup", func_nostartup },
     { "recv", func_recv },
     { "send", func_send },
+    { "WSAIoctl", func_WSAIoctl },
     { "WSARecv", func_WSARecv },
     { "WSAStartup", func_WSAStartup },
     { 0, 0 }