From 6cf1de4492b05544e902af37b7076daff4ae6367 Mon Sep 17 00:00:00 2001 From: Hans Leidekker Date: Wed, 22 Jul 2015 14:26:59 +0200 Subject: [PATCH] iphlpapi: Implement a couple of interface identifier conversion functions. --- dlls/iphlpapi/iphlpapi.spec | 14 +-- dlls/iphlpapi/iphlpapi_main.c | 171 ++++++++++++++++++++++++++++- dlls/iphlpapi/tests/iphlpapi.c | 195 +++++++++++++++++++++++++++++++++ include/Makefile.in | 1 + include/netioapi.h | 32 ++++++ 5 files changed, 404 insertions(+), 9 deletions(-) create mode 100644 include/netioapi.h diff --git a/dlls/iphlpapi/iphlpapi.spec b/dlls/iphlpapi/iphlpapi.spec index d7a52b7e4c5..aa7c7f081a4 100644 --- a/dlls/iphlpapi/iphlpapi.spec +++ b/dlls/iphlpapi/iphlpapi.spec @@ -12,15 +12,15 @@ #@ stub ConvertGuidToStringA #@ stub ConvertGuidToStringW #@ stub ConvertInterfaceAliasToLuid -#@ stub ConvertInterfaceGuidToLuid -#@ stub ConvertInterfaceIndexToLuid +@ stdcall ConvertInterfaceGuidToLuid( ptr ptr ) +@ stdcall ConvertInterfaceIndexToLuid( long ptr ) #@ stub ConvertInterfaceLuidToAlias @ stdcall ConvertInterfaceLuidToGuid( ptr ptr ) -#@ stub ConvertInterfaceLuidToIndex -#@ stub ConvertInterfaceLuidToNameA -#@ stub ConvertInterfaceLuidToNameW -#@ stub ConvertInterfaceNameToLuidA -#@ stub ConvertInterfaceNameToLuidW +@ stdcall ConvertInterfaceLuidToIndex( ptr ptr ) +@ stdcall ConvertInterfaceLuidToNameA( ptr ptr long ) +@ stdcall ConvertInterfaceLuidToNameW( ptr ptr long ) +@ stdcall ConvertInterfaceNameToLuidA( str ptr ) +@ stdcall ConvertInterfaceNameToLuidW( wstr ptr ) #@ stub ConvertInterfacePhysicalAddressToLuid #@ stub ConvertIpv4MaskToLength #@ stub ConvertLengthToIpv4Mask diff --git a/dlls/iphlpapi/iphlpapi_main.c b/dlls/iphlpapi/iphlpapi_main.c index 26474489ae2..b6e2a07ee65 100644 --- a/dlls/iphlpapi/iphlpapi_main.c +++ b/dlls/iphlpapi/iphlpapi_main.c @@ -51,8 +51,10 @@ #include "ipstats.h" #include "ipifcons.h" #include "fltdefs.h" +#include "netioapi.h" #include "wine/debug.h" +#include "wine/unicode.h" WINE_DEFAULT_DEBUG_CHANNEL(iphlpapi); @@ -2744,11 +2746,176 @@ ULONG WINAPI GetTcp6Table2(PMIB_TCP6TABLE2 table, PULONG size, BOOL order) return ERROR_NOT_SUPPORTED; } +/****************************************************************** + * ConvertInterfaceGuidToLuid (IPHLPAPI.@) + */ +DWORD WINAPI ConvertInterfaceGuidToLuid(const GUID *guid, NET_LUID *luid) +{ + DWORD ret; + MIB_IFROW row; + + TRACE("(%s %p)\n", debugstr_guid(guid), luid); + + if (!guid || !luid) return ERROR_INVALID_PARAMETER; + + row.dwIndex = guid->Data1; + if ((ret = GetIfEntry( &row ))) return ret; + + luid->Info.Reserved = 0; + luid->Info.NetLuidIndex = guid->Data1; + luid->Info.IfType = row.dwType; + return NO_ERROR; +} + +/****************************************************************** + * ConvertInterfaceIndexToLuid (IPHLPAPI.@) + */ +DWORD WINAPI ConvertInterfaceIndexToLuid(NET_IFINDEX index, NET_LUID *luid) +{ + MIB_IFROW row; + + TRACE("(%u %p)\n", index, luid); + + if (!luid) return ERROR_INVALID_PARAMETER; + memset( luid, 0, sizeof(*luid) ); + + row.dwIndex = index; + if (GetIfEntry( &row )) return ERROR_FILE_NOT_FOUND; + + luid->Info.Reserved = 0; + luid->Info.NetLuidIndex = index; + luid->Info.IfType = row.dwType; + return NO_ERROR; +} + /****************************************************************** * ConvertInterfaceLuidToGuid (IPHLPAPI.@) */ DWORD WINAPI ConvertInterfaceLuidToGuid(const NET_LUID *luid, GUID *guid) { - FIXME("(%p %p) stub\n", luid, guid); - return ERROR_CALL_NOT_IMPLEMENTED; + DWORD ret; + MIB_IFROW row; + + TRACE("(%p %p)\n", luid, guid); + + if (!luid || !guid) return ERROR_INVALID_PARAMETER; + + row.dwIndex = luid->Info.NetLuidIndex; + if ((ret = GetIfEntry( &row ))) return ret; + + guid->Data1 = luid->Info.NetLuidIndex; + return NO_ERROR; +} + +/****************************************************************** + * ConvertInterfaceLuidToIndex (IPHLPAPI.@) + */ +DWORD WINAPI ConvertInterfaceLuidToIndex(const NET_LUID *luid, NET_IFINDEX *index) +{ + DWORD ret; + MIB_IFROW row; + + TRACE("(%p %p)\n", luid, index); + + if (!luid || !index) return ERROR_INVALID_PARAMETER; + + row.dwIndex = luid->Info.NetLuidIndex; + if ((ret = GetIfEntry( &row ))) return ret; + + *index = luid->Info.NetLuidIndex; + return NO_ERROR; +} + +/****************************************************************** + * ConvertInterfaceLuidToNameA (IPHLPAPI.@) + */ +DWORD WINAPI ConvertInterfaceLuidToNameA(const NET_LUID *luid, char *name, SIZE_T len) +{ + DWORD ret; + MIB_IFROW row; + + TRACE("(%p %p %u)\n", luid, name, (DWORD)len); + + if (!luid) return ERROR_INVALID_PARAMETER; + + row.dwIndex = luid->Info.NetLuidIndex; + if ((ret = GetIfEntry( &row ))) return ret; + + if (!name || len < WideCharToMultiByte( CP_UNIXCP, 0, row.wszName, -1, NULL, 0, NULL, NULL )) + return ERROR_NOT_ENOUGH_MEMORY; + + WideCharToMultiByte( CP_UNIXCP, 0, row.wszName, -1, name, len, NULL, NULL ); + return NO_ERROR; +} + +/****************************************************************** + * ConvertInterfaceLuidToNameW (IPHLPAPI.@) + */ +DWORD WINAPI ConvertInterfaceLuidToNameW(const NET_LUID *luid, WCHAR *name, SIZE_T len) +{ + DWORD ret; + MIB_IFROW row; + + TRACE("(%p %p %u)\n", luid, name, (DWORD)len); + + if (!luid || !name) return ERROR_INVALID_PARAMETER; + + row.dwIndex = luid->Info.NetLuidIndex; + if ((ret = GetIfEntry( &row ))) return ret; + + if (len < strlenW( row.wszName ) + 1) return ERROR_NOT_ENOUGH_MEMORY; + strcpyW( name, row.wszName ); + return NO_ERROR; +} + +/****************************************************************** + * ConvertInterfaceNameToLuidA (IPHLPAPI.@) + */ +DWORD WINAPI ConvertInterfaceNameToLuidA(const char *name, NET_LUID *luid) +{ + DWORD ret; + IF_INDEX index; + MIB_IFROW row; + + TRACE("(%s %p)\n", debugstr_a(name), luid); + + if ((ret = getInterfaceIndexByName( name, &index ))) return ERROR_INVALID_NAME; + if (!luid) return ERROR_INVALID_PARAMETER; + + row.dwIndex = index; + if ((ret = GetIfEntry( &row ))) return ret; + + luid->Info.Reserved = 0; + luid->Info.NetLuidIndex = index; + luid->Info.IfType = row.dwType; + return NO_ERROR; +} + +/****************************************************************** + * ConvertInterfaceNameToLuidW (IPHLPAPI.@) + */ +DWORD WINAPI ConvertInterfaceNameToLuidW(const WCHAR *name, NET_LUID *luid) +{ + DWORD ret; + IF_INDEX index; + MIB_IFROW row; + char nameA[IF_MAX_STRING_SIZE + 1]; + + TRACE("(%s %p)\n", debugstr_w(name), luid); + + if (!luid) return ERROR_INVALID_PARAMETER; + memset( luid, 0, sizeof(*luid) ); + + if (!WideCharToMultiByte( CP_UNIXCP, 0, name, -1, nameA, sizeof(nameA), NULL, NULL )) + return ERROR_INVALID_NAME; + + if ((ret = getInterfaceIndexByName( nameA, &index ))) return ret; + + row.dwIndex = index; + if ((ret = GetIfEntry( &row ))) return ret; + + luid->Info.Reserved = 0; + luid->Info.NetLuidIndex = index; + luid->Info.IfType = row.dwType; + return NO_ERROR; } diff --git a/dlls/iphlpapi/tests/iphlpapi.c b/dlls/iphlpapi/tests/iphlpapi.c index 3594b3b36b2..30e75b76932 100644 --- a/dlls/iphlpapi/tests/iphlpapi.c +++ b/dlls/iphlpapi/tests/iphlpapi.c @@ -81,6 +81,14 @@ static DWORD (WINAPI *pIcmpSendEcho)(HANDLE,IPAddr,LPVOID,WORD,PIP_OPTION_INFORM static DWORD (WINAPI *pCreateSortedAddressPairs)(const PSOCKADDR_IN6,ULONG,const PSOCKADDR_IN6,ULONG,ULONG, PSOCKADDR_IN6_PAIR*,ULONG*); static void (WINAPI *pFreeMibTable)(void*); +static DWORD (WINAPI *pConvertInterfaceGuidToLuid)(const GUID*,NET_LUID*); +static DWORD (WINAPI *pConvertInterfaceIndexToLuid)(NET_IFINDEX,NET_LUID*); +static DWORD (WINAPI *pConvertInterfaceLuidToGuid)(const NET_LUID*,GUID*); +static DWORD (WINAPI *pConvertInterfaceLuidToIndex)(const NET_LUID*,NET_IFINDEX*); +static DWORD (WINAPI *pConvertInterfaceLuidToNameW)(const NET_LUID*,WCHAR*,SIZE_T); +static DWORD (WINAPI *pConvertInterfaceLuidToNameA)(const NET_LUID*,char*,SIZE_T); +static DWORD (WINAPI *pConvertInterfaceNameToLuidA)(const char*,NET_LUID*); +static DWORD (WINAPI *pConvertInterfaceNameToLuidW)(const WCHAR*,NET_LUID*); static void loadIPHlpApi(void) { @@ -117,6 +125,14 @@ static void loadIPHlpApi(void) pIcmpSendEcho = (void *)GetProcAddress(hLibrary, "IcmpSendEcho"); pCreateSortedAddressPairs = (void *)GetProcAddress(hLibrary, "CreateSortedAddressPairs"); pFreeMibTable = (void *)GetProcAddress(hLibrary, "FreeMibTable"); + pConvertInterfaceGuidToLuid = (void *)GetProcAddress(hLibrary, "ConvertInterfaceGuidToLuid"); + pConvertInterfaceIndexToLuid = (void *)GetProcAddress(hLibrary, "ConvertInterfaceIndexToLuid"); + pConvertInterfaceLuidToGuid = (void *)GetProcAddress(hLibrary, "ConvertInterfaceLuidToGuid"); + pConvertInterfaceLuidToIndex = (void *)GetProcAddress(hLibrary, "ConvertInterfaceLuidToIndex"); + pConvertInterfaceLuidToNameA = (void *)GetProcAddress(hLibrary, "ConvertInterfaceLuidToNameA"); + pConvertInterfaceLuidToNameW = (void *)GetProcAddress(hLibrary, "ConvertInterfaceLuidToNameW"); + pConvertInterfaceNameToLuidA = (void *)GetProcAddress(hLibrary, "ConvertInterfaceNameToLuidA"); + pConvertInterfaceNameToLuidW = (void *)GetProcAddress(hLibrary, "ConvertInterfaceNameToLuidW"); } } @@ -1627,6 +1643,184 @@ static void test_CreateSortedAddressPairs(void) pFreeMibTable( pair ); } +static void test_interface_identifier_conversion(void) +{ + DWORD ret, size; + NET_LUID luid; + GUID guid; + IP_ADAPTER_ADDRESSES *buf, *aa; + SIZE_T len; + WCHAR nameW[IF_MAX_STRING_SIZE + 1]; + char nameA[IF_MAX_STRING_SIZE + 1]; + NET_IFINDEX index; + + if (!pConvertInterfaceIndexToLuid) + { + win_skip( "ConvertInterfaceIndexToLuid not available\n" ); + return; + } + + size = 0; + ret = pGetAdaptersAddresses( AF_UNSPEC, 0, NULL, NULL, &size ); + if (ret != ERROR_BUFFER_OVERFLOW) return; + + buf = HeapAlloc( GetProcessHeap(), 0, size ); + pGetAdaptersAddresses( AF_UNSPEC, 0, NULL, buf, &size ); + for (aa = buf; aa; aa = aa->Next) { if (aa->IfType == IF_TYPE_ETHERNET_CSMACD) break; } + if (aa->IfType != IF_TYPE_ETHERNET_CSMACD) + { + skip( "no suitable interface found\n" ); + return; + } + + /* ConvertInterfaceIndexToLuid */ + ret = pConvertInterfaceIndexToLuid( 0, NULL ); + ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret ); + + memset( &luid, 0xff, sizeof(luid) ); + ret = pConvertInterfaceIndexToLuid( 0, &luid ); + ok( ret == ERROR_FILE_NOT_FOUND, "got %u\n", ret ); + ok( !luid.Info.Reserved, "got %x\n", luid.Info.Reserved ); + ok( !luid.Info.NetLuidIndex, "got %u\n", luid.Info.NetLuidIndex ); + ok( !luid.Info.IfType, "got %u\n", luid.Info.IfType ); + + memset( &luid, 0, sizeof(luid) ); + ret = pConvertInterfaceIndexToLuid( aa->IfIndex, &luid ); + ok( !ret, "got %u\n", ret ); + ok( !luid.Info.Reserved, "got %x\n", luid.Info.Reserved ); + ok( luid.Info.NetLuidIndex, "got %u\n", luid.Info.NetLuidIndex ); + ok( luid.Info.IfType == IF_TYPE_ETHERNET_CSMACD, "got %u\n", luid.Info.IfType ); + + /* ConvertInterfaceLuidToIndex */ + ret = pConvertInterfaceLuidToIndex( NULL, NULL ); + ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret ); + + ret = pConvertInterfaceLuidToIndex( NULL, &index ); + ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret ); + + ret = pConvertInterfaceLuidToIndex( &luid, NULL ); + ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret ); + + ret = pConvertInterfaceLuidToIndex( &luid, &index ); + ok( !ret, "got %u\n", ret ); + + /* ConvertInterfaceLuidToGuid */ + ret = pConvertInterfaceLuidToGuid( NULL, NULL ); + ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret ); + + memset( &guid, 0xff, sizeof(guid) ); + ret = pConvertInterfaceLuidToGuid( NULL, &guid ); + ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret ); + ok( guid.Data1 == 0xffffffff, "got %x\n", guid.Data1 ); + + ret = pConvertInterfaceLuidToGuid( &luid, NULL ); + ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret ); + + memset( &guid, 0, sizeof(guid) ); + ret = pConvertInterfaceLuidToGuid( &luid, &guid ); + ok( !ret, "got %u\n", ret ); + ok( guid.Data1, "got %x\n", guid.Data1 ); + + /* ConvertInterfaceGuidToLuid */ + ret = pConvertInterfaceGuidToLuid( NULL, NULL ); + ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret ); + + luid.Info.NetLuidIndex = 1; + ret = pConvertInterfaceGuidToLuid( NULL, &luid ); + ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret ); + ok( luid.Info.NetLuidIndex == 1, "got %u\n", luid.Info.NetLuidIndex ); + + ret = pConvertInterfaceGuidToLuid( &guid, NULL ); + ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret ); + + memset( &luid, 0, sizeof(luid) ); + ret = pConvertInterfaceGuidToLuid( &guid, &luid ); + ok( !ret, "got %u\n", ret ); + ok( luid.Info.NetLuidIndex, "got %u\n", luid.Info.NetLuidIndex ); + + /* ConvertInterfaceLuidToNameW */ + ret = pConvertInterfaceLuidToNameW( NULL, NULL, 0 ); + ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret ); + + ret = pConvertInterfaceLuidToNameW( &luid, NULL, 0 ); + ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret ); + + ret = pConvertInterfaceLuidToNameW( NULL, nameW, 0 ); + ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret ); + + ret = pConvertInterfaceLuidToNameW( &luid, nameW, 0 ); + ok( ret == ERROR_NOT_ENOUGH_MEMORY, "got %u\n", ret ); + + nameW[0] = 0; + len = sizeof(nameW)/sizeof(nameW[0]); + ret = pConvertInterfaceLuidToNameW( &luid, nameW, len ); + ok( !ret, "got %u\n", ret ); + ok( nameW[0], "name not set\n" ); + + /* ConvertInterfaceLuidToNameA */ + ret = pConvertInterfaceLuidToNameA( NULL, NULL, 0 ); + ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret ); + + ret = pConvertInterfaceLuidToNameA( &luid, NULL, 0 ); + ok( ret == ERROR_NOT_ENOUGH_MEMORY, "got %u\n", ret ); + + ret = pConvertInterfaceLuidToNameA( NULL, nameA, 0 ); + ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret ); + + ret = pConvertInterfaceLuidToNameA( &luid, nameA, 0 ); + ok( ret == ERROR_NOT_ENOUGH_MEMORY, "got %u\n", ret ); + + nameA[0] = 0; + len = sizeof(nameA)/sizeof(nameA[0]); + ret = pConvertInterfaceLuidToNameA( &luid, nameA, len ); + ok( !ret, "got %u\n", ret ); + ok( nameA[0], "name not set\n" ); + + /* ConvertInterfaceNameToLuidW */ + ret = pConvertInterfaceNameToLuidW( NULL, NULL ); + ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret ); + + memset( &luid, 0xff, sizeof(luid) ); + ret = pConvertInterfaceNameToLuidW( NULL, &luid ); + ok( ret == ERROR_INVALID_NAME, "got %u\n", ret ); + ok( !luid.Info.Reserved, "got %x\n", luid.Info.Reserved ); + ok( !luid.Info.NetLuidIndex, "got %u\n", luid.Info.NetLuidIndex ); + ok( !luid.Info.IfType, "got %u\n", luid.Info.IfType ); + + ret = pConvertInterfaceNameToLuidW( nameW, NULL ); + ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret ); + + memset( &luid, 0xff, sizeof(luid) ); + ret = pConvertInterfaceNameToLuidW( nameW, &luid ); + ok( !ret, "got %u\n", ret ); + ok( !luid.Info.Reserved, "got %x\n", luid.Info.Reserved ); + ok( luid.Info.NetLuidIndex, "got %u\n", luid.Info.NetLuidIndex ); + ok( luid.Info.IfType == IF_TYPE_ETHERNET_CSMACD, "got %u\n", luid.Info.IfType ); + + /* ConvertInterfaceNameToLuidA */ + ret = pConvertInterfaceNameToLuidA( NULL, NULL ); + ok( ret == ERROR_INVALID_NAME, "got %u\n", ret ); + + memset( &luid, 0xff, sizeof(luid) ); + ret = pConvertInterfaceNameToLuidA( NULL, &luid ); + ok( ret == ERROR_INVALID_NAME, "got %u\n", ret ); + ok( luid.Info.Reserved, "got %x\n", luid.Info.Reserved ); + ok( luid.Info.NetLuidIndex, "got %u\n", luid.Info.NetLuidIndex ); + ok( luid.Info.IfType, "got %u\n", luid.Info.IfType ); + + ret = pConvertInterfaceNameToLuidA( nameA, NULL ); + ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret ); + + memset( &luid, 0xff, sizeof(luid) ); + ret = pConvertInterfaceNameToLuidA( nameA, &luid ); + ok( !ret, "got %u\n", ret ); + ok( !luid.Info.Reserved, "got %x\n", luid.Info.Reserved ); + ok( luid.Info.NetLuidIndex, "got %u\n", luid.Info.NetLuidIndex ); + ok( luid.Info.IfType == IF_TYPE_ETHERNET_CSMACD, "got %u\n", luid.Info.IfType ); + + HeapFree( GetProcessHeap(), 0, buf ); +} + START_TEST(iphlpapi) { @@ -1647,6 +1841,7 @@ START_TEST(iphlpapi) test_GetExtendedTcpTable(); test_GetExtendedUdpTable(); test_CreateSortedAddressPairs(); + test_interface_identifier_conversion(); freeIPHlpApi(); } } diff --git a/include/Makefile.in b/include/Makefile.in index 882e78a211b..3b8d8d103b9 100644 --- a/include/Makefile.in +++ b/include/Makefile.in @@ -475,6 +475,7 @@ SRCDIR_INCLUDES = \ msxmldid.h \ nb30.h \ ndrtypes.h \ + netioapi.h \ nldef.h \ npapi.h \ nspapi.h \ diff --git a/include/netioapi.h b/include/netioapi.h new file mode 100644 index 00000000000..3f533f88926 --- /dev/null +++ b/include/netioapi.h @@ -0,0 +1,32 @@ +/* + * Copyright 2015 Hans Leidekker for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __WINE_NETIOAPI_H +#define __WINE_NETIOAPI_H + +DWORD WINAPI ConvertInterfaceGuidToLuid(const GUID*,NET_LUID*); +DWORD WINAPI ConvertInterfaceIndexToLuid(NET_IFINDEX,NET_LUID*); +DWORD WINAPI ConvertInterfaceLuidToGuid(const NET_LUID*,GUID*); +DWORD WINAPI ConvertInterfaceLuidToIndex(const NET_LUID*,NET_IFINDEX*); +DWORD WINAPI ConvertInterfaceLuidToNameA(const NET_LUID*,char*,SIZE_T); +DWORD WINAPI ConvertInterfaceLuidToNameW(const NET_LUID*,WCHAR*,SIZE_T); +DWORD WINAPI ConvertInterfaceNameToLuidA(const char*,NET_LUID*); +DWORD WINAPI ConvertInterfaceNameToLuidW(const WCHAR*,NET_LUID*); +void WINAPI FreeMibTable(void*); + +#endif /* __WINE_NETIOAPI_H */