#include <config.h>
#include "iphlpapi_private.h"
+#include <strsafe.h>
WINE_DEFAULT_DEBUG_CHANNEL(iphlpapi);
BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
- WSADATA wsaData;
-
switch (fdwReason) {
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls( hinstDLL );
interfaceMapInit();
- WSAStartup(MAKEWORD(2, 2), &wsaData);
break;
case DLL_PROCESS_DETACH:
- WSACleanup();
interfaceMapFree();
break;
}
else {
DWORD dwSize = 0;
+ *ppIfTable = NULL;
ret = GetIfTable(*ppIfTable, &dwSize, bOrder);
if (ret == ERROR_INSUFFICIENT_BUFFER) {
*ppIfTable = (PMIB_IFTABLE)HeapAlloc(heap, flags, dwSize);
ret = GetIfTable(*ppIfTable, &dwSize, bOrder);
+ if (ret != NO_ERROR) {
+ HeapFree(heap, flags, *ppIfTable);
+ *ppIfTable = NULL;
+ }
}
}
TRACE("returning %ld\n", ret);
else {
DWORD dwSize = 0;
+ *ppIpAddrTable = NULL;
ret = GetIpAddrTable(*ppIpAddrTable, &dwSize, bOrder);
if (ret == ERROR_INSUFFICIENT_BUFFER) {
*ppIpAddrTable = (PMIB_IPADDRTABLE)HeapAlloc(heap, flags, dwSize);
ret = GetIpAddrTable(*ppIpAddrTable, &dwSize, bOrder);
+ if (ret != NO_ERROR) {
+ HeapFree(heap, flags, *ppIpAddrTable);
+ *ppIpAddrTable = NULL;
+ }
}
}
TRACE("returning %ld\n", ret);
else {
DWORD dwSize = 0;
+ *ppIpForwardTable = NULL;
ret = GetIpForwardTable(*ppIpForwardTable, &dwSize, bOrder);
if (ret == ERROR_INSUFFICIENT_BUFFER) {
*ppIpForwardTable = (PMIB_IPFORWARDTABLE)HeapAlloc(heap, flags, dwSize);
ret = GetIpForwardTable(*ppIpForwardTable, &dwSize, bOrder);
+ if (ret != NO_ERROR) {
+ HeapFree(heap, flags, *ppIpForwardTable);
+ *ppIpForwardTable = NULL;
+ }
}
}
TRACE("returning %ld\n", ret);
else {
DWORD dwSize = 0;
+ *ppIpNetTable = NULL;
ret = GetIpNetTable(*ppIpNetTable, &dwSize, bOrder);
if (ret == ERROR_INSUFFICIENT_BUFFER) {
*ppIpNetTable = (PMIB_IPNETTABLE)HeapAlloc(heap, flags, dwSize);
ret = GetIpNetTable(*ppIpNetTable, &dwSize, bOrder);
+ if (ret != NO_ERROR) {
+ HeapFree(heap, flags, *ppIpNetTable);
+ *ppIpNetTable = NULL;
+ }
}
}
TRACE("returning %ld\n", ret);
else {
DWORD dwSize = 0;
+ *ppTcpTable = NULL;
ret = GetTcpTable(*ppTcpTable, &dwSize, bOrder);
if (ret == ERROR_INSUFFICIENT_BUFFER) {
*ppTcpTable = (PMIB_TCPTABLE)HeapAlloc(heap, flags, dwSize);
ret = GetTcpTable(*ppTcpTable, &dwSize, bOrder);
+ if (ret != NO_ERROR) {
+ HeapFree(heap, flags, *ppTcpTable);
+ *ppTcpTable = NULL;
+ }
}
}
TRACE("returning %ld\n", ret);
else {
DWORD dwSize = 0;
+ *ppUdpTable = NULL;
ret = GetUdpTable(*ppUdpTable, &dwSize, bOrder);
if (ret == ERROR_INSUFFICIENT_BUFFER) {
*ppUdpTable = (PMIB_UDPTABLE)HeapAlloc(heap, flags, dwSize);
ret = GetUdpTable(*ppUdpTable, &dwSize, bOrder);
+ if (ret != NO_ERROR) {
+ HeapFree(heap, flags, *ppUdpTable);
+ *ppUdpTable = NULL;
+ }
}
}
TRACE("returning %ld\n", ret);
AllocateAndGetIpForwardTableFromStack(&table, FALSE, GetProcessHeap(), 0);
if (table) {
- DWORD ndx, matchedBits, matchedNdx = 0;
+ DWORD ndx, minMaskSize, matchedNdx = 0;
- for (ndx = 0, matchedBits = 0; ndx < table->dwNumEntries; ndx++) {
+ for (ndx = 0, minMaskSize = 255; ndx < table->dwNumEntries; ndx++) {
if ((dwDestAddr & table->table[ndx].dwForwardMask) ==
(table->table[ndx].dwForwardDest & table->table[ndx].dwForwardMask)) {
- DWORD numShifts, mask;
+ DWORD hostMaskSize;
- for (numShifts = 0, mask = table->table[ndx].dwForwardMask;
- mask && !(mask & 1); mask >>= 1, numShifts++)
- ;
- if (numShifts > matchedBits) {
- matchedBits = numShifts;
+ if (!_BitScanForward(&hostMaskSize, ntohl(table->table[ndx].dwForwardMask)))
+ {
+ hostMaskSize = 32;
+ }
+ if (hostMaskSize < minMaskSize) {
+ minMaskSize = hostMaskSize;
matchedNdx = ndx;
}
}
return ret;
}
+static int TcpTableSorter(const void *a, const void *b);
+
/******************************************************************
* GetExtendedTcpTable (IPHLPAPI.@)
*
DWORD WINAPI GetExtendedTcpTable(PVOID pTcpTable, PDWORD pdwSize, BOOL bOrder, ULONG ulAf, TCP_TABLE_CLASS TableClass, ULONG Reserved)
{
+ DWORD i, count;
DWORD ret = NO_ERROR;
- if (TableClass == TCP_TABLE_OWNER_PID_ALL) {
- if (*pdwSize == 0) {
- *pdwSize = sizeof(MIB_TCPTABLE_OWNER_PID);
- return ERROR_INSUFFICIENT_BUFFER;
- } else {
- ZeroMemory(pTcpTable, sizeof(MIB_TCPTABLE_OWNER_PID));
- return NO_ERROR;
+ if (!pdwSize)
+ {
+ return ERROR_INVALID_PARAMETER;
}
- }
+ if (ulAf != AF_INET)
+ {
+ UNIMPLEMENTED;
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ switch (TableClass)
+ {
+ case TCP_TABLE_BASIC_ALL:
+ ret = GetTcpTable(pTcpTable, pdwSize, bOrder);
+ break;
+
+ case TCP_TABLE_BASIC_CONNECTIONS:
+ {
+ PMIB_TCPTABLE pOurTcpTable = getTcpTable();
+ PMIB_TCPTABLE pTheirTcpTable = pTcpTable;
+
+ if (pOurTcpTable)
+ {
+ for (i = 0, count = 0; i < pOurTcpTable->dwNumEntries; ++i)
+ {
+ if (pOurTcpTable->table[i].State != MIB_TCP_STATE_LISTEN)
+ {
+ ++count;
+ }
+ }
+
+ if (sizeof(MIB_TCPTABLE) + count * sizeof(MIB_TCPROW) > *pdwSize || !pTheirTcpTable)
+ {
+ *pdwSize = sizeof(MIB_TCPTABLE) + count * sizeof(MIB_TCPROW);
+ ret = ERROR_INSUFFICIENT_BUFFER;
+ }
+ else
+ {
+ pTheirTcpTable->dwNumEntries = count;
+
+ for (i = 0, count = 0; i < pOurTcpTable->dwNumEntries; ++i)
+ {
+ if (pOurTcpTable->table[i].State != MIB_TCP_STATE_LISTEN)
+ {
+ memcpy(&pTheirTcpTable->table[count], &pOurTcpTable->table[i], sizeof(MIB_TCPROW));
+ ++count;
+ }
+ }
+ ASSERT(count == pTheirTcpTable->dwNumEntries);
+
+ if (bOrder)
+ qsort(pTheirTcpTable->table, pTheirTcpTable->dwNumEntries,
+ sizeof(MIB_TCPROW), TcpTableSorter);
+ }
+
+ free(pOurTcpTable);
+ }
+ }
+ break;
+
+ case TCP_TABLE_BASIC_LISTENER:
+ {
+ PMIB_TCPTABLE pOurTcpTable = getTcpTable();
+ PMIB_TCPTABLE pTheirTcpTable = pTcpTable;
+
+ if (pOurTcpTable)
+ {
+ for (i = 0, count = 0; i < pOurTcpTable->dwNumEntries; ++i)
+ {
+ if (pOurTcpTable->table[i].State == MIB_TCP_STATE_LISTEN)
+ {
+ ++count;
+ }
+ }
+
+ if (sizeof(MIB_TCPTABLE) + count * sizeof(MIB_TCPROW) > *pdwSize || !pTheirTcpTable)
+ {
+ *pdwSize = sizeof(MIB_TCPTABLE) + count * sizeof(MIB_TCPROW);
+ ret = ERROR_INSUFFICIENT_BUFFER;
+ }
+ else
+ {
+ pTheirTcpTable->dwNumEntries = count;
+
+ for (i = 0, count = 0; i < pOurTcpTable->dwNumEntries; ++i)
+ {
+ if (pOurTcpTable->table[i].State == MIB_TCP_STATE_LISTEN)
+ {
+ memcpy(&pTheirTcpTable->table[count], &pOurTcpTable->table[i], sizeof(MIB_TCPROW));
+ ++count;
+ }
+ }
+ ASSERT(count == pTheirTcpTable->dwNumEntries);
+
+ if (bOrder)
+ qsort(pTheirTcpTable->table, pTheirTcpTable->dwNumEntries,
+ sizeof(MIB_TCPROW), TcpTableSorter);
+ }
+
+ free(pOurTcpTable);
+ }
+ }
+ break;
+
+ case TCP_TABLE_OWNER_PID_ALL:
+ {
+ PMIB_TCPTABLE_OWNER_PID pOurTcpTable = getOwnerTcpTable();
+ PMIB_TCPTABLE_OWNER_PID pTheirTcpTable = pTcpTable;
+
+ if (pOurTcpTable)
+ {
+ if (sizeof(DWORD) + pOurTcpTable->dwNumEntries * sizeof(MIB_TCPROW_OWNER_PID) > *pdwSize || !pTheirTcpTable)
+ {
+ *pdwSize = sizeof(DWORD) + pOurTcpTable->dwNumEntries * sizeof(MIB_TCPROW_OWNER_PID);
+ ret = ERROR_INSUFFICIENT_BUFFER;
+ }
+ else
+ {
+ memcpy(pTheirTcpTable, pOurTcpTable, sizeof(DWORD) + pOurTcpTable->dwNumEntries * sizeof(MIB_TCPROW_OWNER_PID));
+
+ /* Don't sort on PID, so use basic helper */
+ if (bOrder)
+ qsort(pTheirTcpTable->table, pTheirTcpTable->dwNumEntries,
+ sizeof(MIB_TCPROW_OWNER_PID), TcpTableSorter);
+ }
+
+ free(pOurTcpTable);
+ }
+ }
+ break;
+
+ case TCP_TABLE_OWNER_PID_CONNECTIONS:
+ {
+ PMIB_TCPTABLE_OWNER_PID pOurTcpTable = getOwnerTcpTable();
+ PMIB_TCPTABLE_OWNER_PID 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_PID) > *pdwSize || !pTheirTcpTable)
+ {
+ *pdwSize = sizeof(DWORD) + count * sizeof(MIB_TCPROW_OWNER_PID);
+ 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_PID));
+ ++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_PID), TcpTableSorter);
+ }
+
+ free(pOurTcpTable);
+ }
+ }
+ break;
+
+ case TCP_TABLE_OWNER_PID_LISTENER:
+ {
+ PMIB_TCPTABLE_OWNER_PID pOurTcpTable = getOwnerTcpTable();
+ PMIB_TCPTABLE_OWNER_PID 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_PID) > *pdwSize || !pTheirTcpTable)
+ {
+ *pdwSize = sizeof(DWORD) + count * sizeof(MIB_TCPROW_OWNER_PID);
+ 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_PID));
+ ++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_PID), TcpTableSorter);
+ }
+
+ free(pOurTcpTable);
+ }
+ }
+ break;
+
+ default:
+ UNIMPLEMENTED;
+ ret = ERROR_INVALID_PARAMETER;
+ break;
+ }
- UNIMPLEMENTED;
return ret;
}
*/
DWORD WINAPI GetNetworkParams(PFIXED_INFO pFixedInfo, PULONG pOutBufLen)
{
- DWORD ret, size;
+ DWORD ret, size, type;
LONG regReturn;
HKEY hKey;
PIPHLP_RES_INFO resInfo;
}
memset(pFixedInfo, 0, size);
- size = sizeof(pFixedInfo->HostName);
- GetComputerNameExA(ComputerNameDnsHostname, pFixedInfo->HostName, &size);
- size = sizeof(pFixedInfo->DomainName);
- GetComputerNameExA(ComputerNameDnsDomain, pFixedInfo->DomainName, &size);
+ /* Check for DhcpHostname and DhcpDomain first */
+ regReturn = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
+ "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
+ 0,
+ KEY_READ,
+ &hKey);
+ if (regReturn == ERROR_SUCCESS) {
+ /* Windows doesn't honor DHCP option 12 even if RFC requires it if it is returned by DHCP server! */
+#if 0
+ type = REG_SZ;
+ size = sizeof(pFixedInfo->HostName);
+ regReturn = RegQueryValueExA(hKey,
+ "DhcpHostname",
+ NULL,
+ &type,
+ (LPBYTE)pFixedInfo->HostName,
+ &size);
+ if (regReturn == ERROR_FILE_NOT_FOUND || (regReturn == ERROR_SUCCESS && size < 1))
+ {
+#endif
+ type = REG_SZ;
+ size = sizeof(pFixedInfo->HostName);
+ regReturn = RegQueryValueExA(hKey,
+ "Hostname",
+ NULL,
+ &type,
+ (LPBYTE)pFixedInfo->HostName,
+ &size);
+#if 0
+ }
+#endif
+
+ type = REG_SZ;
+ size = sizeof(pFixedInfo->DomainName);
+ regReturn = RegQueryValueExA(hKey,
+ "DhcpDomain",
+ NULL,
+ &type,
+ (LPBYTE)pFixedInfo->DomainName,
+ &size);
+ if (regReturn == ERROR_FILE_NOT_FOUND || (regReturn == ERROR_SUCCESS && size < 1))
+ {
+ type = REG_SZ;
+ size = sizeof(pFixedInfo->DomainName);
+ regReturn = RegQueryValueExA(hKey,
+ "Domain",
+ NULL,
+ &type,
+ (LPBYTE)pFixedInfo->DomainName,
+ &size);
+ }
+ RegCloseKey(hKey);
+ }
TRACE("GetComputerNameExA: %s\n", pFixedInfo->DomainName);
{
DWORD Status, Version = 0;
- if (!AdapterInfo || !AdapterInfo->Name)
+ if (!AdapterInfo)
return ERROR_INVALID_PARAMETER;
/* Maybe we should do this in DllMain */
{
DWORD Status, Version = 0;
- if (!AdapterInfo || !AdapterInfo->Name)
+ if (!AdapterInfo)
return ERROR_INVALID_PARAMETER;
/* Maybe we should do this in DllMain */
return 0L;
}
+DWORD GetInterfaceNameInternal(_In_ const GUID * pInterfaceGUID,
+ _Out_writes_bytes_to_(*pOutBufLen, *pOutBufLen) PWCHAR pInterfaceName,
+ _Inout_ PULONG pOutBufLen)
+{
+ UNICODE_STRING GuidString;
+ DWORD result, type;
+ WCHAR szKeyName[2*MAX_PATH];
+ HRESULT hr;
+ HKEY hKey;
+
+ if (pInterfaceGUID == NULL || pOutBufLen == NULL)
+ return ERROR_INVALID_PARAMETER;
+
+ result = RtlStringFromGUID(pInterfaceGUID, &GuidString);
+
+ if (!NT_SUCCESS(result))
+ {
+ // failed to convert guid to string
+ return RtlNtStatusToDosError(result);
+ }
+
+ hr = StringCbPrintfW(szKeyName, sizeof(szKeyName), L"SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s\\Connection", GuidString.Buffer);
+ RtlFreeUnicodeString(&GuidString);
+
+ if (FAILED(hr))
+ {
+ // key name is too long
+ return ERROR_BUFFER_OVERFLOW;
+ }
+
+ result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_READ, &hKey);
+
+ if (result != ERROR_SUCCESS)
+ {
+ // failed to find adapter entry
+ return ERROR_NOT_FOUND;
+ }
+
+ result = RegQueryValueExW(hKey, L"Name", NULL, &type, (PVOID)pInterfaceName, pOutBufLen);
+
+ RegCloseKey(hKey);
+
+ if (result == ERROR_MORE_DATA)
+ {
+ *pOutBufLen = MAX_INTERFACE_NAME_LEN * 2;
+ return ERROR_INSUFFICIENT_BUFFER;
+ }
+
+ if (result != ERROR_SUCCESS || type != REG_SZ)
+ {
+ // failed to read adapter name
+ return ERROR_NO_DATA;
+ }
+ return ERROR_SUCCESS;
+}
+
+/*
+ * @implemented
+ */
DWORD WINAPI
-NhGetInterfaceNameFromDeviceGuid(DWORD dwUnknown1,
- DWORD dwUnknown2,
- DWORD dwUnknown3,
+NhGetInterfaceNameFromDeviceGuid(_In_ const GUID * pInterfaceGUID,
+ _Out_writes_bytes_to_(*pOutBufLen, *pOutBufLen) PWCHAR pInterfaceName,
+ _Inout_ PULONG pOutBufLen,
DWORD dwUnknown4,
DWORD dwUnknown5)
{
- FIXME("NhGetInterfaceNameFromDeviceGuid() stub\n");
- return 0L;
+ SetLastError(ERROR_SUCCESS);
+
+ if (pInterfaceName == NULL)
+ return ERROR_INVALID_PARAMETER;
+
+ return GetInterfaceNameInternal(pInterfaceGUID, pInterfaceName, pOutBufLen);
+}
+
+/*
+ * @implemented
+ */
+DWORD WINAPI
+NhGetInterfaceNameFromGuid(_In_ const GUID * pInterfaceGUID,
+ _Out_writes_bytes_to_(*pOutBufLen, *pOutBufLen) PWCHAR pInterfaceName,
+ _Inout_ PULONG pOutBufLen,
+ DWORD dwUnknown4,
+ DWORD dwUnknown5)
+{
+ DWORD result;
+
+ result = GetInterfaceNameInternal(pInterfaceGUID, pInterfaceName, pOutBufLen);
+
+ if (result == ERROR_NOT_FOUND)
+ SetLastError(ERROR_PATH_NOT_FOUND);
+
+ return result;
}