* iphlpapi dll implementation
*
* Copyright (C) 2003 Juan Lang
+ * 2018 Pierre Schweitzer
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
#include <config.h>
#include "iphlpapi_private.h"
#include <strsafe.h>
+#include <psapi.h>
WINE_DEFAULT_DEBUG_CHANNEL(iphlpapi);
}
+/******************************************************************
+ * AllocateAndGetTcpExTableFromStack (IPHLPAPI.@)
+ *
+ *
+ * PARAMS
+ *
+ * ppTcpTable [Out]
+ * bOrder [In] -- passed to GetExtendedTcpTable to order the table
+ * heap [In] -- heap from which the table is allocated
+ * flags [In] -- flags to HeapAlloc
+ * family [In] -- passed to GetExtendedTcpTable to select INET family
+ *
+ * RETURNS
+ *
+ * DWORD
+ *
+ */
+DWORD WINAPI AllocateAndGetTcpExTableFromStack(PVOID *ppTcpTable,
+ BOOL bOrder, HANDLE heap, DWORD flags, DWORD family)
+{
+ DWORD ret;
+
+ TRACE("ppTcpTable %p, bOrder %ld, heap 0x%08lx, flags 0x%08lx, family 0x%08lx\n",
+ ppTcpTable, (DWORD)bOrder, (DWORD)heap, flags, family);
+ if (!ppTcpTable)
+ ret = ERROR_INVALID_PARAMETER;
+ else {
+ DWORD dwSize = 0;
+
+ *ppTcpTable = NULL;
+ ret = GetExtendedTcpTable(*ppTcpTable, &dwSize, bOrder, family, TCP_TABLE_OWNER_PID_ALL, 0);
+ if (ret == ERROR_INSUFFICIENT_BUFFER) {
+ *ppTcpTable = (PMIB_TCPTABLE_OWNER_PID)HeapAlloc(heap, flags, dwSize);
+ ret = GetExtendedTcpTable(*ppTcpTable, &dwSize, bOrder, family, TCP_TABLE_OWNER_PID_ALL, 0);
+ if (ret != NO_ERROR) {
+ HeapFree(heap, flags, *ppTcpTable);
+ *ppTcpTable = NULL;
+ }
+ }
+ }
+ TRACE("returning %ld\n", ret);
+ return ret;
+}
+
+
+/******************************************************************
+ * AllocateAndGetTcpExTable2FromStack (IPHLPAPI.@)
+ *
+ *
+ * PARAMS
+ *
+ * ppTcpTable [Out]
+ * bOrder [In] -- passed to GetExtendedTcpTable to order the table
+ * heap [In] -- heap from which the table is allocated
+ * flags [In] -- flags to HeapAlloc
+ * family [In] -- passed to GetExtendedTcpTable to select INET family
+ * class [In] -- passed to GetExtendedTcpTable to select information
+ *
+ * RETURNS
+ *
+ * DWORD
+ *
+ */
+DWORD WINAPI AllocateAndGetTcpExTable2FromStack(PVOID *ppTcpTable,
+ BOOL bOrder, HANDLE heap, DWORD flags, DWORD family, TCP_TABLE_CLASS class)
+{
+ DWORD ret;
+
+ TRACE("ppTcpTable %p, bOrder %ld, heap 0x%08lx, flags 0x%08lx, family %ld, class %ld\n",
+ ppTcpTable, (DWORD)bOrder, (DWORD)heap, flags, family, class);
+ if (!ppTcpTable)
+ ret = ERROR_INVALID_PARAMETER;
+ else {
+ DWORD dwSize = 0;
+
+ *ppTcpTable = NULL;
+ ret = GetExtendedTcpTable(*ppTcpTable, &dwSize, bOrder, family, class, 0);
+ if (ret == ERROR_INSUFFICIENT_BUFFER) {
+ *ppTcpTable = HeapAlloc(heap, flags, dwSize);
+ ret = GetExtendedTcpTable(*ppTcpTable, &dwSize, bOrder, family, class, 0);
+ if (ret != NO_ERROR) {
+ HeapFree(heap, flags, *ppTcpTable);
+ *ppTcpTable = NULL;
+ }
+ }
+ }
+ TRACE("returning %ld\n", ret);
+ return ret;
+}
+
+
/******************************************************************
* AllocateAndGetUdpTableFromStack (IPHLPAPI.@)
*
}
+/******************************************************************
+ * AllocateAndGetUdpExTableFromStack (IPHLPAPI.@)
+ *
+ *
+ * PARAMS
+ *
+ * ppUdpTable [Out]
+ * bOrder [In] -- passed to GetExtendedUdpTable to order the table
+ * heap [In] -- heap from which the table is allocated
+ * flags [In] -- flags to HeapAlloc
+ * family [In] -- passed to GetExtendedUdpTable to select INET family
+ *
+ * RETURNS
+ *
+ * DWORD
+ *
+ */
+DWORD WINAPI AllocateAndGetUdpExTableFromStack(PVOID *ppUdpTable,
+ BOOL bOrder, HANDLE heap, DWORD flags, DWORD family)
+{
+ DWORD ret;
+
+ TRACE("ppUdpTable %p, bOrder %ld, heap 0x%08lx, flags 0x%08lx, family 0x%08lx\n",
+ ppUdpTable, (DWORD)bOrder, (DWORD)heap, flags, family);
+ if (!ppUdpTable)
+ ret = ERROR_INVALID_PARAMETER;
+ else {
+ DWORD dwSize = 0;
+
+ *ppUdpTable = NULL;
+ ret = GetExtendedUdpTable(*ppUdpTable, &dwSize, bOrder, family, UDP_TABLE_OWNER_PID, 0);
+ if (ret == ERROR_INSUFFICIENT_BUFFER) {
+ *ppUdpTable = (PMIB_UDPTABLE_OWNER_PID)HeapAlloc(heap, flags, dwSize);
+ ret = GetExtendedUdpTable(*ppUdpTable, &dwSize, bOrder, family, UDP_TABLE_OWNER_PID, 0);
+ if (ret != NO_ERROR) {
+ HeapFree(heap, flags, *ppUdpTable);
+ *ppUdpTable = NULL;
+ }
+ }
+ }
+ TRACE("returning %ld\n", ret);
+ return ret;
+}
+
+
+/******************************************************************
+ * AllocateAndGetUdpExTable2FromStack (IPHLPAPI.@)
+ *
+ *
+ * PARAMS
+ *
+ * ppUdpTable [Out]
+ * bOrder [In] -- passed to GetExtendedUdpTable to order the table
+ * heap [In] -- heap from which the table is allocated
+ * flags [In] -- flags to HeapAlloc
+ * family [In] -- passed to GetExtendedUdpTable to select INET family
+ * class [In] -- passed to GetExtendedUdpTable to select information
+ *
+ * RETURNS
+ *
+ * DWORD
+ *
+ */
+DWORD WINAPI AllocateAndGetUdpExTable2FromStack(PVOID *ppUdpTable,
+ BOOL bOrder, HANDLE heap, DWORD flags, DWORD family, UDP_TABLE_CLASS class)
+{
+ DWORD ret;
+
+ TRACE("ppUdpTable %p, bOrder %ld, heap 0x%08lx, flags 0x%08lx, family %ld, class %ld\n",
+ ppUdpTable, (DWORD)bOrder, (DWORD)heap, flags, family, class);
+ if (!ppUdpTable)
+ ret = ERROR_INVALID_PARAMETER;
+ else {
+ DWORD dwSize = 0;
+
+ *ppUdpTable = NULL;
+ ret = GetExtendedUdpTable(*ppUdpTable, &dwSize, bOrder, family, class, 0);
+ if (ret == ERROR_INSUFFICIENT_BUFFER) {
+ *ppUdpTable = HeapAlloc(heap, flags, dwSize);
+ ret = GetExtendedUdpTable(*ppUdpTable, &dwSize, bOrder, family, class, 0);
+ if (ret != NO_ERROR) {
+ HeapFree(heap, flags, *ppUdpTable);
+ *ppUdpTable = NULL;
+ }
+ }
+ }
+ TRACE("returning %ld\n", ret);
+ return ret;
+}
+
+
/******************************************************************
* CreateIpForwardEntry (IPHLPAPI.@)
*
}
break;
+ case TCP_TABLE_OWNER_MODULE_ALL:
+ {
+ PMIB_TCPTABLE_OWNER_MODULE pOurTcpTable = getOwnerModTcpTable();
+ PMIB_TCPTABLE_OWNER_MODULE pTheirTcpTable = pTcpTable;
+
+ if (pOurTcpTable)
+ {
+ if (sizeof(DWORD) + pOurTcpTable->dwNumEntries * sizeof(MIB_TCPROW_OWNER_MODULE) > *pdwSize || !pTheirTcpTable)
+ {
+ *pdwSize = sizeof(DWORD) + pOurTcpTable->dwNumEntries * sizeof(MIB_TCPROW_OWNER_MODULE);
+ ret = ERROR_INSUFFICIENT_BUFFER;
+ }
+ else
+ {
+ memcpy(pTheirTcpTable, pOurTcpTable, sizeof(DWORD) + pOurTcpTable->dwNumEntries * sizeof(MIB_TCPROW_OWNER_MODULE));
+
+ /* Don't sort on PID, so use basic helper */
+ if (bOrder)
+ qsort(pTheirTcpTable->table, pTheirTcpTable->dwNumEntries,
+ sizeof(MIB_TCPROW_OWNER_MODULE), TcpTableSorter);
+ }
+
+ free(pOurTcpTable);
+ }
+ }
+ break;
+
+ case TCP_TABLE_OWNER_MODULE_CONNECTIONS:
+ {
+ PMIB_TCPTABLE_OWNER_MODULE pOurTcpTable = getOwnerModTcpTable();
+ PMIB_TCPTABLE_OWNER_MODULE pTheirTcpTable = pTcpTable;
+
+ if (pOurTcpTable)
+ {
+ for (i = 0, count = 0; i < pOurTcpTable->dwNumEntries; ++i)
+ {
+ if (pOurTcpTable->table[i].dwState != MIB_TCP_STATE_LISTEN)
+ {
+ ++count;
+ }
+ }
+
+ if (sizeof(DWORD) + count * sizeof(MIB_TCPROW_OWNER_MODULE) > *pdwSize || !pTheirTcpTable)
+ {
+ *pdwSize = sizeof(DWORD) + count * sizeof(MIB_TCPROW_OWNER_MODULE);
+ ret = ERROR_INSUFFICIENT_BUFFER;
+ }
+ else
+ {
+ pTheirTcpTable->dwNumEntries = count;
+
+ for (i = 0, count = 0; i < pOurTcpTable->dwNumEntries; ++i)
+ {
+ if (pOurTcpTable->table[i].dwState != MIB_TCP_STATE_LISTEN)
+ {
+ memcpy(&pTheirTcpTable->table[count], &pOurTcpTable->table[i], sizeof(MIB_TCPROW_OWNER_MODULE));
+ ++count;
+ }
+ }
+ ASSERT(count == pTheirTcpTable->dwNumEntries);
+
+ /* Don't sort on PID, so use basic helper */
+ if (bOrder)
+ qsort(pTheirTcpTable->table, pTheirTcpTable->dwNumEntries,
+ sizeof(MIB_TCPROW_OWNER_MODULE), TcpTableSorter);
+ }
+
+ free(pOurTcpTable);
+ }
+ }
+ break;
+
+ case TCP_TABLE_OWNER_MODULE_LISTENER:
+ {
+ PMIB_TCPTABLE_OWNER_MODULE pOurTcpTable = getOwnerModTcpTable();
+ PMIB_TCPTABLE_OWNER_MODULE pTheirTcpTable = pTcpTable;
+
+ if (pOurTcpTable)
+ {
+ for (i = 0, count = 0; i < pOurTcpTable->dwNumEntries; ++i)
+ {
+ if (pOurTcpTable->table[i].dwState == MIB_TCP_STATE_LISTEN)
+ {
+ ++count;
+ }
+ }
+
+ if (sizeof(DWORD) + count * sizeof(MIB_TCPROW_OWNER_MODULE) > *pdwSize || !pTheirTcpTable)
+ {
+ *pdwSize = sizeof(DWORD) + count * sizeof(MIB_TCPROW_OWNER_MODULE);
+ ret = ERROR_INSUFFICIENT_BUFFER;
+ }
+ else
+ {
+ pTheirTcpTable->dwNumEntries = count;
+
+ for (i = 0, count = 0; i < pOurTcpTable->dwNumEntries; ++i)
+ {
+ if (pOurTcpTable->table[i].dwState == MIB_TCP_STATE_LISTEN)
+ {
+ memcpy(&pTheirTcpTable->table[count], &pOurTcpTable->table[i], sizeof(MIB_TCPROW_OWNER_MODULE));
+ ++count;
+ }
+ }
+ ASSERT(count == pTheirTcpTable->dwNumEntries);
+
+ /* Don't sort on PID, so use basic helper */
+ if (bOrder)
+ qsort(pTheirTcpTable->table, pTheirTcpTable->dwNumEntries,
+ sizeof(MIB_TCPROW_OWNER_MODULE), TcpTableSorter);
+ }
+
+ free(pOurTcpTable);
+ }
+ }
+ break;
+
default:
- UNIMPLEMENTED;
ret = ERROR_INVALID_PARAMETER;
break;
}
}
break;
+ case UDP_TABLE_OWNER_MODULE:
+ {
+ PMIB_UDPTABLE_OWNER_MODULE pOurUdpTable = getOwnerModUdpTable();
+ PMIB_UDPTABLE_OWNER_MODULE pTheirUdpTable = pUdpTable;
+
+ if (pOurUdpTable)
+ {
+ if (sizeof(DWORD) + pOurUdpTable->dwNumEntries * sizeof(MIB_UDPROW_OWNER_MODULE) > *pdwSize || !pTheirUdpTable)
+ {
+ *pdwSize = sizeof(DWORD) + pOurUdpTable->dwNumEntries * sizeof(MIB_UDPROW_OWNER_MODULE);
+ ret = ERROR_INSUFFICIENT_BUFFER;
+ }
+ else
+ {
+ memcpy(pTheirUdpTable, pOurUdpTable, sizeof(DWORD) + pOurUdpTable->dwNumEntries * sizeof(MIB_UDPROW_OWNER_MODULE));
+
+ if (bOrder)
+ qsort(pTheirUdpTable->table, pTheirUdpTable->dwNumEntries,
+ sizeof(MIB_UDPROW_OWNER_MODULE), UdpTableSorter);
+ }
+
+ free(pOurUdpTable);
+ }
+ }
+ break;
+
default:
- UNIMPLEMENTED;
ret = ERROR_INVALID_PARAMETER;
break;
}
*/
DWORD WINAPI GetOwnerModuleFromTcpEntry( PMIB_TCPROW_OWNER_MODULE pTcpEntry, TCPIP_OWNER_MODULE_INFO_CLASS Class, PVOID Buffer, PDWORD pdwSize)
{
- DWORD ret = NO_ERROR;
- UNIMPLEMENTED;
- return ret;
+ HANDLE Process;
+ DWORD FileLen, PathLen;
+ WCHAR File[MAX_PATH], Path[MAX_PATH];
+ PTCPIP_OWNER_MODULE_BASIC_INFO BasicInfo;
+
+ if (pTcpEntry->dwOwningPid == 0)
+ {
+ return ERROR_NOT_FOUND;
+ }
+
+ Process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pTcpEntry->dwOwningPid);
+ if (Process == NULL)
+ {
+ return GetLastError();
+ }
+
+ FileLen = GetModuleBaseNameW(Process, NULL, File, MAX_PATH);
+ if (FileLen != 0)
+ {
+ PathLen = GetModuleFileNameExW(Process, NULL, Path, MAX_PATH);
+ if (PathLen == 0)
+ {
+ CloseHandle(Process);
+ return GetLastError();
+ }
+
+ /* Add NULL char */
+ ++FileLen;
+ ++PathLen;
+ PathLen *= sizeof(WCHAR);
+ FileLen *= sizeof(WCHAR);
+ }
+ else if (GetLastError() == ERROR_PARTIAL_COPY)
+ {
+ wcscpy(File, L"System");
+ wcscpy(Path, L"System");
+
+ PathLen = sizeof(L"System");
+ FileLen = sizeof(L"System");
+ }
+
+ CloseHandle(Process);
+
+ if (*pdwSize < sizeof(TCPIP_OWNER_MODULE_BASIC_INFO) + PathLen + FileLen)
+ {
+ *pdwSize = sizeof(TCPIP_OWNER_MODULE_BASIC_INFO) + PathLen + FileLen;
+ return ERROR_INSUFFICIENT_BUFFER;
+ }
+
+ BasicInfo = Buffer;
+ BasicInfo->pModuleName = (PVOID)((ULONG_PTR)BasicInfo + sizeof(TCPIP_OWNER_MODULE_BASIC_INFO));
+ BasicInfo->pModulePath = (PVOID)((ULONG_PTR)BasicInfo->pModuleName + FileLen);
+ wcscpy(BasicInfo->pModuleName, File);
+ wcscpy(BasicInfo->pModulePath, Path);
+ *pdwSize = sizeof(TCPIP_OWNER_MODULE_BASIC_INFO) + PathLen + FileLen;
+
+ return NO_ERROR;
}
static void CreateNameServerListEnumNamesFunc( PWCHAR Interface, PWCHAR Server, PVOID Data)