1 /* 2 * PROJECT: ReactOS api tests 3 * LICENSE: GPL - See COPYING in the top level directory 4 * PURPOSE: Test for WSHIoctl: 5 * - SIO_GET_INTERFACE_LIST 6 * PROGRAMMERS: Andreas Maier 7 */ 8 9 #include "ws2_32.h" 10 11 #include <iphlpapi.h> 12 13 void traceaddr(char* txt, sockaddr_gen a) 14 { 15 trace(" %s.AddressIn.sin_family %x\n", txt, a.AddressIn.sin_family); 16 trace(" %s.AddressIn.sin_port %x\n", txt, a.AddressIn.sin_port); 17 trace(" %s.AddressIn.sin_addr.s_addr %lx\n", txt, a.AddressIn.sin_addr.s_addr); 18 } 19 20 BOOL Test_WSAIoctl_InitTest( 21 OUT PMIB_IPADDRTABLE* ppTable) 22 { 23 PMIB_IPADDRROW pRow; 24 DWORD ret, i1; 25 ULONG TableSize; 26 PMIB_IPADDRTABLE pTable; 27 28 TableSize = 0; 29 *ppTable = NULL; 30 ret = GetIpAddrTable(NULL, &TableSize, FALSE); 31 if (ret != ERROR_INSUFFICIENT_BUFFER) 32 { 33 skip("GetIpAddrTable failed with %ld. Abort Testing.\n", ret); 34 return FALSE; 35 } 36 37 /* get sorted ip-address table. Sort order is the ip-address. */ 38 pTable = (PMIB_IPADDRTABLE)malloc(TableSize); 39 *ppTable = pTable; 40 ret = GetIpAddrTable(pTable, &TableSize, TRUE); 41 if (ret != NO_ERROR) 42 { 43 skip("GetIpAddrTable failed with %ld. Abort Testing.\n", ret); 44 return FALSE; 45 } 46 47 if (winetest_debug >= 2) 48 { 49 trace("Result of GetIpAddrTable:\n"); 50 trace("Count: %ld\n", pTable->dwNumEntries); 51 pRow = pTable->table; 52 for (i1 = 0; i1 < pTable->dwNumEntries; i1++) 53 { 54 trace("** Entry %ld **\n", i1); 55 trace(" dwAddr %lx\n", pRow->dwAddr); 56 trace(" dwIndex %lx\n", pRow->dwIndex); 57 trace(" dwMask %lx\n", pRow->dwMask); 58 trace(" dwBCastAddr %lx\n", pRow->dwBCastAddr); 59 trace(" dwReasmSize %lx\n", pRow->dwReasmSize); 60 trace(" wType %x\n", pRow->wType); 61 pRow++; 62 } 63 trace("END\n"); 64 } 65 66 return TRUE; 67 } 68 69 void Test_WSAIoctl_GetInterfaceList() 70 { 71 WSADATA wdata; 72 INT iResult; 73 SOCKET sck; 74 ULONG buflen, BytesReturned, BCastAddr; 75 ULONG infoCount, i1, j1, iiFlagsExpected; 76 BYTE* buf = NULL; 77 LPINTERFACE_INFO ifInfo; 78 PMIB_IPADDRTABLE pTable = NULL; 79 PMIB_IPADDRROW pRow; 80 81 /* Get PMIB_IPADDRTABE - these results we should get from wshtcpip.dll too. */ 82 /* pTable is allocated by Test_WSAIoctl_InitTest! */ 83 if (!Test_WSAIoctl_InitTest(&pTable)) 84 goto cleanup; 85 86 /* Start up Winsock */ 87 iResult = WSAStartup(MAKEWORD(2, 2), &wdata); 88 ok(iResult == 0, "WSAStartup failed. iResult = %d\n", iResult); 89 90 /* Create the socket */ 91 sck = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_IP, 0, 0, 0); 92 ok(sck != INVALID_SOCKET, "WSASocket failed. sck = %d\n", (INT)sck); 93 if (sck == INVALID_SOCKET) 94 { 95 skip("Failed to create socket!\n"); 96 goto cleanup; 97 } 98 99 /* Do the Ioctl (buffer to small) */ 100 buflen = sizeof(INTERFACE_INFO)-1; 101 buf = (BYTE*)HeapAlloc(GetProcessHeap(), 0, buflen); 102 if (buf == NULL) 103 { 104 skip("Failed to allocate memory!\n"); 105 goto cleanup; 106 } 107 BytesReturned = 0; 108 iResult = WSAIoctl(sck, SIO_GET_INTERFACE_LIST, 0, 0, 109 buf, buflen, &BytesReturned, 0, 0); 110 ok(iResult == -1, "WSAIoctl/SIO_GET_INTERFACE_LIST did not fail! iResult = %d.\n", iResult); 111 ok_hex(WSAGetLastError(), WSAEFAULT); 112 ok(BytesReturned == 0, "WSAIoctl/SIO_GET_INTERFACE_LIST: BytesReturned should be 0, not %ld.\n", BytesReturned); 113 HeapFree(GetProcessHeap(), 0, buf); 114 buf = NULL; 115 116 /* Do the Ioctl 117 In most cases no loop is done. 118 Only if WSAIoctl fails with WSAEFAULT (buffer to small) we need to retry with a 119 larger buffer */ 120 i1 = 0; 121 while (TRUE) 122 { 123 if (buf != NULL) 124 { 125 HeapFree(GetProcessHeap(), 0, buf); 126 buf = NULL; 127 } 128 129 buflen = sizeof(INTERFACE_INFO) * (i1+1) * 32; 130 buf = (BYTE*)HeapAlloc(GetProcessHeap(), 0, buflen); 131 if (buf == NULL) 132 { 133 skip("Failed to allocate memory!\n"); 134 goto cleanup; 135 } 136 BytesReturned = 0; 137 iResult = WSAIoctl(sck, SIO_GET_INTERFACE_LIST, 0, 0, 138 buf, buflen, &BytesReturned, 0, 0); 139 /* we have what we want ... leave loop */ 140 if (iResult == NO_ERROR) 141 break; 142 /* only retry if buffer was to small */ 143 /* to avoid infinite loop we maximum retry count is 4 */ 144 if ((i1 >= 4) || (WSAGetLastError() != WSAEFAULT)) 145 { 146 ok_hex(iResult, NO_ERROR); 147 skip("WSAIoctl / SIO_GET_INTERFACE_LIST\n"); 148 goto cleanup; 149 } 150 /* buffer to small -> retry */ 151 i1++; 152 } 153 154 ok_dec(BytesReturned % sizeof(INTERFACE_INFO), 0); 155 156 /* Calculate how many INTERFACE_INFO we got */ 157 infoCount = BytesReturned / sizeof(INTERFACE_INFO); 158 ok(infoCount == pTable->dwNumEntries, 159 "Wrong count of entries! Got %ld, expected %ld.\n", pTable->dwNumEntries, infoCount); 160 161 if (winetest_debug >= 2) 162 { 163 trace("WSAIoctl\n"); 164 trace(" BytesReturned %ld - InfoCount %ld\n ", BytesReturned, infoCount); 165 ifInfo = (LPINTERFACE_INFO)buf; 166 for (i1 = 0; i1 < infoCount; i1++) 167 { 168 trace("entry-index %ld\n", i1); 169 trace(" iiFlags %ld\n", ifInfo->iiFlags); 170 traceaddr("ifInfo^.iiAddress", ifInfo->iiAddress); 171 traceaddr("ifInfo^.iiBroadcastAddress", ifInfo->iiBroadcastAddress); 172 traceaddr("ifInfo^.iiNetmask", ifInfo->iiNetmask); 173 ifInfo++; 174 } 175 } 176 177 /* compare entries */ 178 ifInfo = (LPINTERFACE_INFO)buf; 179 for (i1 = 0; i1 < infoCount; i1++) 180 { 181 if (winetest_debug >= 2) 182 trace("Entry %ld\n", i1); 183 for (j1 = 0; j1 < pTable->dwNumEntries; j1++) 184 { 185 if (ifInfo[i1].iiAddress.AddressIn.sin_addr.s_addr == pTable->table[j1].dwAddr) 186 { 187 pRow = &pTable->table[j1]; 188 break; 189 } 190 } 191 if (j1 == pTable->dwNumEntries) 192 { 193 skip("Skipping interface\n"); 194 continue; 195 } 196 197 /* iiFlags 198 * Don't know if this value is fix for SIO_GET_INTERFACE_LIST! */ 199 iiFlagsExpected = IFF_BROADCAST | IFF_MULTICAST; 200 if ((pRow->wType & MIB_IPADDR_DISCONNECTED) == 0) 201 iiFlagsExpected |= IFF_UP; 202 if (pRow->dwAddr == ntohl(INADDR_LOOPBACK)) 203 { 204 iiFlagsExpected |= IFF_LOOPBACK; 205 /* on Windows 7 loopback has broadcast flag cleared */ 206 //iiFlagsExpected &= ~IFF_BROADCAST; 207 } 208 209 ok_hex(ifInfo[i1].iiFlags, iiFlagsExpected); 210 ok_hex(ifInfo[i1].iiAddress.AddressIn.sin_addr.s_addr, pRow->dwAddr); 211 // dwBCastAddr is not the "real" Broadcast-Address. 212 BCastAddr = (pRow->dwBCastAddr == 1 && (iiFlagsExpected & IFF_BROADCAST) != 0) ? 0xFFFFFFFF : 0x0; 213 ok_hex(ifInfo[i1].iiBroadcastAddress.AddressIn.sin_addr.s_addr, BCastAddr); 214 ok_hex(ifInfo[i1].iiNetmask.AddressIn.sin_addr.s_addr, pRow->dwMask); 215 } 216 217 cleanup: 218 if (sck != 0) 219 closesocket(sck); 220 if (pTable != NULL) 221 free(pTable); 222 if (buf != NULL) 223 HeapFree(GetProcessHeap(), 0, buf); 224 WSACleanup(); 225 } 226 227 START_TEST(WSAIoctl) 228 { 229 Test_WSAIoctl_GetInterfaceList(); 230 } 231