Author: phater
Date: Tue Nov 22 12:45:41 2016
New Revision: 73342
URL:
http://svn.reactos.org/svn/reactos?rev=73342&view=rev
Log:
[WSHTCPIP] Implement SIO_GET_INTERFACE_LIST by Andreas Maier aka andy-123. Thanks.
CORE-10343
Added:
trunk/reactos/dll/win32/wshtcpip/iflist.c (with props)
Modified:
trunk/reactos/dll/win32/wshtcpip/CMakeLists.txt
trunk/reactos/dll/win32/wshtcpip/wshtcpip.c
trunk/reactos/dll/win32/wshtcpip/wshtcpip.h
Modified: trunk/reactos/dll/win32/wshtcpip/CMakeLists.txt
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/wshtcpip/CMakeLi…
==============================================================================
--- trunk/reactos/dll/win32/wshtcpip/CMakeLists.txt [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/wshtcpip/CMakeLists.txt [iso-8859-1] Tue Nov 22 12:45:41 2016
@@ -3,6 +3,7 @@
spec2def(wshtcpip.dll wshtcpip.spec)
list(APPEND SOURCE
+ iflist.c
wshtcpip.c
wshtcpip.rc
${CMAKE_CURRENT_BINARY_DIR}/wshtcpip.def)
Added: trunk/reactos/dll/win32/wshtcpip/iflist.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/wshtcpip/iflist.…
==============================================================================
--- trunk/reactos/dll/win32/wshtcpip/iflist.c (added)
+++ trunk/reactos/dll/win32/wshtcpip/iflist.c [iso-8859-1] Tue Nov 22 12:45:41 2016
@@ -0,0 +1,443 @@
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS WinSock Helper DLL for TCP/IP
+ * FILE: iflist.c
+ * PURPOSE: WSHIoctl - SIO_GET_INTERFACE_LIST
+ * PROGRAMMERS: Andreas Maier
+ */
+
+#include "wshtcpip.h"
+
+#define WIN32_NO_STATUS /* Tell Windows headers you'll use ntstatus.s from NDK */
+#include <windows.h> /* Declare Windows Headers like you normally would */
+#include <ntndk.h> /* Declare the NDK Headers */
+#include <iptypes.h>
+#include <wine/list.h>
+
+#define NDEBUG
+#include <debug.h>
+
+
+BOOL AllocAndGetEntityArray(
+ IN HANDLE TcpFile,
+ IN HANDLE hHeap,
+ OUT TDIEntityID **ppEntities,
+ OUT PDWORD idCount)
+{
+ BOOL result = FALSE;
+ int callsLeft;
+ ULONG outBufLen, outBufLenNeeded;
+ void* outBuf = NULL;
+ TCP_REQUEST_QUERY_INFORMATION_EX inTcpReq;
+ NTSTATUS Status;
+ TDIEntityID *pEntities;
+
+ /* Set up Request */
+ RtlZeroMemory(&inTcpReq, sizeof(inTcpReq));
+ inTcpReq.ID.toi_entity.tei_entity = GENERIC_ENTITY;
+ inTcpReq.ID.toi_entity.tei_instance = 0;
+ inTcpReq.ID.toi_class = INFO_CLASS_GENERIC;
+ inTcpReq.ID.toi_type = INFO_TYPE_PROVIDER;
+ inTcpReq.ID.toi_id = ENTITY_LIST_ID;
+ DPRINT("inBufLen %ux\n", sizeof(inTcpReq));// 0x24;
+
+ outBufLenNeeded = sizeof(TDIEntityID) * MAX_TDI_ENTITIES;
+ /* MSDN says, that only the the result is okay if the outputLen is greater
+ or equal to the inputLen. Normally only one call is needed. Only if
+ a entry is added during calling a second call will be done.
+ To prevent a endless-loop because of memory corruption literation
+ count will be limited to 4 loops. */
+ for (callsLeft = 4; callsLeft > 0; callsLeft++)
+ {
+ /* maybe free old buffer ... */
+ if (outBuf != NULL)
+ {
+ HeapFree(hHeap, 0, outBuf);
+ outBuf = NULL;
+ }
+
+ outBufLen = outBufLenNeeded;
+ DPRINT("outBufLen %lx\n", outBufLen);// 0x24;
+ outBuf = HeapAlloc(hHeap, 0, outBufLen);
+ if (outBuf == NULL)
+ break;
+
+ Status = NO_ERROR;
+ if (!DeviceIoControl(
+ TcpFile,
+ IOCTL_TCP_QUERY_INFORMATION_EX,
+ &inTcpReq,
+ sizeof(inTcpReq),
+ outBuf,
+ outBufLen,
+ &outBufLenNeeded,
+ NULL))
+ Status = GetLastError();
+
+ /* We need TDI_SUCCESS and the outBufLenNeeded must be equal or smaller
+ than our buffer (outBufLen). */
+ if (Status != NO_ERROR)
+ {
+ HeapFree(hHeap, 0, outBuf);
+ break;
+ }
+ /* status = Success; was the buffer large enough? */
+ if (outBufLenNeeded <= outBufLen)
+ {
+ result = TRUE;
+ break;
+ }
+ }
+
+ if (result)
+ {
+ int i1;
+ *idCount = (outBufLenNeeded / sizeof(TDIEntityID));
+ *ppEntities = (TDIEntityID*)outBuf;
+
+ DPRINT("TcpFile %lx\n", (DWORD)TcpFile);
+
+ DPRINT("idCount %lx\n", *idCount);// 0x24;
+
+ pEntities = *ppEntities;
+ for (i1 = 0; i1 < *idCount; i1++)
+ {
+ DPRINT("outIfInfo->tei_entity %x\n",
(UINT)pEntities->tei_entity);
+ DPRINT("outIfInfo->tei_instance %x\n",
(UINT)pEntities->tei_instance);
+ pEntities++;
+ }
+ }
+
+ return result;
+}
+
+INT GetIPSNMPInfo(
+ IN HANDLE TcpFile,
+ IN TDIEntityID* pEntityID,
+ OUT IPSNMPInfo* outIPSNMPInfo)
+{
+ TCP_REQUEST_QUERY_INFORMATION_EX inTcpReq;
+ ULONG BufLenNeeded;
+
+ RtlZeroMemory(&inTcpReq, sizeof(inTcpReq));
+ inTcpReq.ID.toi_entity = *pEntityID;
+ inTcpReq.ID.toi_class = INFO_CLASS_PROTOCOL;
+ inTcpReq.ID.toi_type = INFO_TYPE_PROVIDER;
+ inTcpReq.ID.toi_id = IP_MIB_STATS_ID;
+ if (!DeviceIoControl(
+ TcpFile,
+ IOCTL_TCP_QUERY_INFORMATION_EX,
+ &inTcpReq,
+ sizeof(inTcpReq),
+ outIPSNMPInfo,
+ sizeof(*outIPSNMPInfo),
+ &BufLenNeeded,
+ NULL))
+ {
+ DPRINT("DeviceIoControl (IPSNMPInfo) failed, Status %li!\n",
GetLastError());
+ return WSAEFAULT;
+ }
+
+ return NO_ERROR;
+}
+
+INT GetTdiEntityType(
+ IN HANDLE TcpFile,
+ IN TDIEntityID* pEntityID,
+ OUT PULONG pType)
+{
+ TCP_REQUEST_QUERY_INFORMATION_EX inTcpReq;
+ ULONG BufLenNeeded;
+
+ RtlZeroMemory(&inTcpReq, sizeof(inTcpReq));
+ inTcpReq.ID.toi_entity = *pEntityID;
+ inTcpReq.ID.toi_class = INFO_CLASS_GENERIC;
+ inTcpReq.ID.toi_type = INFO_TYPE_PROVIDER;
+ inTcpReq.ID.toi_id = ENTITY_TYPE_ID;
+ if (!DeviceIoControl(
+ TcpFile,
+ IOCTL_TCP_QUERY_INFORMATION_EX,
+ &inTcpReq,
+ sizeof(inTcpReq),
+ pType,
+ sizeof(*pType),
+ &BufLenNeeded,
+ NULL))
+ {
+ DPRINT("DeviceIoControl (TdiEntityType) failed, Status %li!\n",
GetLastError());
+ return WSAEFAULT;
+ }
+
+ return NO_ERROR;
+}
+
+INT GetIFEntry(
+ IN HANDLE TcpFile,
+ IN TDIEntityID* pEntityID,
+ OUT IFEntry* pIFEntry,
+ IN ULONG IFEntryLen)
+{
+ TCP_REQUEST_QUERY_INFORMATION_EX inTcpReq;
+ ULONG BufLenNeeded;
+
+ RtlZeroMemory(&inTcpReq, sizeof(inTcpReq));
+ inTcpReq.ID.toi_entity = *pEntityID;
+ inTcpReq.ID.toi_class = INFO_CLASS_PROTOCOL;
+ inTcpReq.ID.toi_type = INFO_TYPE_PROVIDER;
+ inTcpReq.ID.toi_id = IP_MIB_STATS_ID;
+ if (!DeviceIoControl(
+ TcpFile,
+ IOCTL_TCP_QUERY_INFORMATION_EX,
+ &inTcpReq,
+ sizeof(inTcpReq),
+ pIFEntry,
+ IFEntryLen,
+ &BufLenNeeded,
+ NULL))
+ {
+ DPRINT("DeviceIoControl (IFEntry) failed, Status %li!\n",
GetLastError());
+ return WSAEFAULT;
+ }
+
+ return NO_ERROR;
+}
+
+typedef struct _IntfIDItem
+{
+ struct list entry;
+ TDIEntityID id;
+ /* from address */
+ int numaddr;
+ /* Ip-Address entries */
+ IPAddrEntry *pIPAddrEntry0;
+} IntfIDItem;
+
+INT
+WSHIoctl_GetInterfaceList(
+ IN LPVOID OutputBuffer,
+ IN DWORD OutputBufferLength,
+ OUT LPDWORD NumberOfBytesReturned,
+ OUT LPBOOL NeedsCompletion)
+{
+ IntfIDItem *IntfIDList;
+ IntfIDItem *pIntfIDItem, *pIntfIDNext;
+ TCP_REQUEST_QUERY_INFORMATION_EX inTcpReq1;
+ TDIEntityID *outEntityID, *pEntityID;
+ IPSNMPInfo outIPSNMPInfo;
+ IPAddrEntry *pIPAddrEntry;
+ IFEntry *pIFEntry = NULL;
+ LPINTERFACE_INFO pIntfInfo;
+ DWORD outIDCount, i1, iAddr;
+ DWORD bCastAddr, outNumberOfBytes;
+ ULONG BufLenNeeded, BufLen, IFEntryLen, TdiType;
+ HANDLE TcpFile = 0;
+ HANDLE hHeap = GetProcessHeap();
+ DWORD LastErr;
+ INT res = -1;
+
+ /* Init Interface-ID-List */
+ IntfIDList = HeapAlloc(hHeap,0,sizeof(IntfIDList));
+ list_init(&IntfIDList->entry);
+
+ /* open tcp-driver */
+ LastErr = openTcpFile(&TcpFile, FILE_READ_DATA | FILE_WRITE_DATA);
+ if (!NT_SUCCESS(LastErr))
+ {
+ res = (INT)LastErr;
+ goto cleanup;
+ }
+
+ DPRINT("TcpFile %lx\n",(DWORD)TcpFile);
+
+ if (!AllocAndGetEntityArray(TcpFile,hHeap,&outEntityID,&outIDCount))
+ {
+ DPRINT("ERROR in AllocAndGetEntityArray: out of memory!\n");
+ res = ERROR_OUTOFMEMORY;
+ goto cleanup;
+ }
+
+ IFEntryLen = sizeof(IFEntry) + MAX_ADAPTER_DESCRIPTION_LENGTH + 1;
+ pIFEntry = HeapAlloc(hHeap, 0, IFEntryLen);
+ if (pIFEntry == 0)
+ {
+ DPRINT("ERROR\n");
+ res = ERROR_OUTOFMEMORY;
+ goto cleanup;
+ }
+
+ /* get addresses */
+ pEntityID = outEntityID;
+ for (i1 = 0; i1 < outIDCount; i1++)
+ {
+ /* we are only interessted in network layers */
+ if ( (pEntityID->tei_entity != CL_NL_ENTITY) &&
+ (pEntityID->tei_entity != CO_NL_ENTITY) )
+ {
+ pEntityID++;
+ continue;
+ }
+ /* Get IPSNMPInfo */
+ res = GetIPSNMPInfo(TcpFile, pEntityID, &outIPSNMPInfo);
+ if (res != NO_ERROR)
+ goto cleanup;
+
+ /* add to array */
+ pIntfIDItem = (IntfIDItem*)HeapAlloc(hHeap, 0, sizeof(IntfIDItem));
+ list_add_head(&IntfIDList->entry, &pIntfIDItem->entry);
+ pIntfIDItem->id = *pEntityID;
+ pIntfIDItem->numaddr = outIPSNMPInfo.ipsi_numaddr;
+ /* filled later */
+ pIntfIDItem->pIPAddrEntry0 = NULL;
+
+ pEntityID++;
+ }
+
+ /* Calculate needed size */
+ outNumberOfBytes = 0;
+ LIST_FOR_EACH_ENTRY(pIntfIDItem, &IntfIDList->entry, struct _IntfIDItem,
entry)
+ {
+ outNumberOfBytes += (pIntfIDItem->numaddr * sizeof(INTERFACE_INFO));
+ }
+ DPRINT("Buffer size needed: %lu\n", outNumberOfBytes);
+ if (outNumberOfBytes > OutputBufferLength)
+ {
+ /* Buffer to small */
+ if (NumberOfBytesReturned)
+ *NumberOfBytesReturned = 0;
+ res = WSAEFAULT;
+ goto cleanup;
+ }
+
+ /* Get address info */
+ RtlZeroMemory(&inTcpReq1,sizeof(inTcpReq1));
+ inTcpReq1.ID.toi_class = INFO_CLASS_PROTOCOL;
+ inTcpReq1.ID.toi_type = INFO_TYPE_PROVIDER;
+ inTcpReq1.ID.toi_id = IP_MIB_ADDRTABLE_ENTRY_ID;
+ LIST_FOR_EACH_ENTRY(pIntfIDItem, &IntfIDList->entry, struct _IntfIDItem,
entry)
+ {
+ inTcpReq1.ID.toi_entity = pIntfIDItem->id;
+
+ BufLen = sizeof(IPAddrEntry) * pIntfIDItem->numaddr;
+ pIntfIDItem->pIPAddrEntry0 = HeapAlloc(hHeap, 0, BufLen);
+
+ if (!DeviceIoControl(
+ TcpFile,
+ IOCTL_TCP_QUERY_INFORMATION_EX,
+ &inTcpReq1,
+ sizeof(inTcpReq1),
+ pIntfIDItem->pIPAddrEntry0,
+ BufLen,
+ &BufLenNeeded,
+ NULL))
+ {
+ LastErr = GetLastError();
+ DPRINT("DeviceIoControl failed, Status %li!\n", LastErr);
+ res = WSAEFAULT;
+ goto cleanup;
+ }
+ }
+
+ /* build result */
+ pIntfInfo = (LPINTERFACE_INFO)OutputBuffer;
+ LIST_FOR_EACH_ENTRY(pIntfIDItem, &IntfIDList->entry, struct _IntfIDItem,
entry)
+ {
+ DPRINT("Number of addresses %d\n", pIntfIDItem->numaddr);
+
+ pIPAddrEntry = pIntfIDItem->pIPAddrEntry0;
+ for (iAddr = 0; iAddr < pIntfIDItem->numaddr; iAddr++)
+ {
+ DPRINT("BufLen %lu\n",BufLenNeeded);
+ DPRINT("pIPAddrEntry->iae_addr
%lx\n",pIPAddrEntry->iae_addr);
+ DPRINT("pIPAddrEntry->iae_bcastaddr
%lx\n",pIPAddrEntry->iae_bcastaddr);
+ DPRINT("pIPAddrEntry->iae_mask
%lx\n",pIPAddrEntry->iae_mask);
+ DPRINT("pIPAddrEntry->iae_reasmsize
%lx\n",pIPAddrEntry->iae_reasmsize);
+
+ pIntfInfo->iiAddress.AddressIn.sin_family = AF_INET;
+ pIntfInfo->iiAddress.AddressIn.sin_port = 0;
+ pIntfInfo->iiAddress.AddressIn.sin_addr.s_addr =
pIPAddrEntry->iae_addr;
+
+ pIntfInfo->iiBroadcastAddress.AddressIn.sin_family = AF_INET;
+ pIntfInfo->iiBroadcastAddress.AddressIn.sin_port = 0;
+ bCastAddr = (pIPAddrEntry->iae_bcastaddr == 0) ? 0 : 0xffffffff;
+ pIntfInfo->iiBroadcastAddress.AddressIn.sin_addr.s_addr = bCastAddr;
+
+ pIntfInfo->iiNetmask.AddressIn.sin_family = AF_INET;
+ pIntfInfo->iiNetmask.AddressIn.sin_port = 0;
+ pIntfInfo->iiNetmask.AddressIn.sin_addr.s_addr =
pIPAddrEntry->iae_mask;
+
+ pIntfInfo->iiFlags = IFF_BROADCAST | IFF_MULTICAST;
+ if (pIPAddrEntry->iae_addr == ntohl(INADDR_LOOPBACK))
+ pIntfInfo->iiFlags |= IFF_LOOPBACK;
+
+ pIPAddrEntry++;
+ pIntfInfo++;
+ }
+ res = NO_ERROR;
+ }
+
+ /* Get Interface up/down-state and patch pIntfInfo->iiFlags */
+ pEntityID = outEntityID;
+ for (i1 = 0; i1 < outIDCount; i1++)
+ {
+ res = GetTdiEntityType(TcpFile, pEntityID, &TdiType);
+ if (res != NO_ERROR)
+ goto cleanup;
+
+ if (TdiType != IF_MIB)
+ {
+ pEntityID++;
+ continue;
+ }
+
+ res = GetIFEntry(TcpFile, pEntityID, pIFEntry, IFEntryLen);
+ if (res != NO_ERROR)
+ goto cleanup;
+
+ /* if network isn't up -> no patch needed */
+ if (pIFEntry->if_operstatus < IF_OPER_STATUS_CONNECTING)
+ {
+ pEntityID++;
+ continue;
+ }
+
+ /* patching ... if interface-index matches */
+ pIntfInfo = (LPINTERFACE_INFO)OutputBuffer;
+ LIST_FOR_EACH_ENTRY(pIntfIDItem, &IntfIDList->entry, struct _IntfIDItem,
entry)
+ {
+ pIPAddrEntry = pIntfIDItem->pIPAddrEntry0;
+ for (iAddr = 0; iAddr < pIntfIDItem->numaddr; iAddr++)
+ {
+ if (pIPAddrEntry->iae_index == pIFEntry->if_index)
+ pIntfInfo->iiFlags |= IFF_UP;
+
+ pIPAddrEntry++;
+ pIntfInfo++;
+ }
+ }
+
+ pEntityID++;
+ }
+
+ if (NumberOfBytesReturned)
+ *NumberOfBytesReturned = outNumberOfBytes;
+ if (NeedsCompletion != NULL)
+ *NeedsCompletion = FALSE;
+
+ res = NO_ERROR;
+cleanup:
+ DPRINT("WSHIoctl_GetInterfaceList - CLEANUP\n");
+ if (TcpFile != 0)
+ NtClose(TcpFile);
+ if (pIFEntry != NULL)
+ HeapFree(hHeap, 0, pIFEntry);
+ LIST_FOR_EACH_ENTRY_SAFE_REV(pIntfIDItem, pIntfIDNext,
+ &IntfIDList->entry, struct _IntfIDItem, entry)
+ {
+ if (pIntfIDItem->pIPAddrEntry0 != NULL)
+ HeapFree(hHeap, 0, pIntfIDItem->pIPAddrEntry0);
+ list_remove(&pIntfIDItem->entry);
+ HeapFree(hHeap, 0, pIntfIDItem);
+ }
+ HeapFree(hHeap, 0, IntfIDList);
+ return res;
+}
Propchange: trunk/reactos/dll/win32/wshtcpip/iflist.c
------------------------------------------------------------------------------
svn:eol-style = native
Modified: trunk/reactos/dll/win32/wshtcpip/wshtcpip.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/wshtcpip/wshtcpi…
==============================================================================
--- trunk/reactos/dll/win32/wshtcpip/wshtcpip.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/wshtcpip/wshtcpip.c [iso-8859-1] Tue Nov 22 12:45:41 2016
@@ -351,6 +351,18 @@
IN LPWSAOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine,
OUT LPBOOL NeedsCompletion)
{
+ INT res;
+
+ if (IoControlCode == SIO_GET_INTERFACE_LIST)
+ {
+ res = WSHIoctl_GetInterfaceList(
+ OutputBuffer,
+ OutputBufferLength,
+ NumberOfBytesReturned,
+ NeedsCompletion);
+ return res;
+ }
+
UNIMPLEMENTED
DPRINT1("Ioctl: Unknown IOCTL code: %d\n", IoControlCode);
@@ -405,7 +417,7 @@
closeTcpFile(TcpCC);
- DPRINT("DeviceIoControl: %d\n", ((Status == TRUE) ? 0 : GetLastError()));
+ DPRINT("DeviceIoControl: %ld\n", ((Status == TRUE) ? 0 : GetLastError()));
if (!Status)
return WSAEINVAL;
@@ -473,7 +485,7 @@
}
}
- DPRINT("Instance: %x Type: %x\n", Context->AddrFileInstance,
Context->AddrFileEntityType);
+ DPRINT("Instance: %lx Type: %lx\n", Context->AddrFileInstance,
Context->AddrFileEntityType);
tdiFreeThingSet(EntityIDs);
@@ -500,7 +512,7 @@
break;
default:
- DPRINT1("Unwanted notification received! (%d)\n", NotifyEvent);
+ DPRINT1("Unwanted notification received! (%ld)\n", NotifyEvent);
break;
}
Modified: trunk/reactos/dll/win32/wshtcpip/wshtcpip.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/wshtcpip/wshtcpi…
==============================================================================
--- trunk/reactos/dll/win32/wshtcpip/wshtcpip.h [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/wshtcpip/wshtcpip.h [iso-8859-1] Tue Nov 22 12:45:41 2016
@@ -52,6 +52,13 @@
BOOL DontRoute;
} SOCKET_CONTEXT, *PSOCKET_CONTEXT;
+INT
+WSHIoctl_GetInterfaceList(
+ IN LPVOID OutputBuffer,
+ IN DWORD OutputBufferLength,
+ OUT LPDWORD NumberOfBytesReturned,
+ OUT LPBOOL NeedsCompletion);
+
#endif /* __WSHTCPIP_H */
/* EOF */