Use iphlpapi to enumerate LAN adapters.
Add names to NetBIOS transports, and eliminates loopback adapters from
enumerated LAN adapters.
diff --git a/dlls/netapi32/Makefile.in b/dlls/netapi32/Makefile.in
index 31c8304..67663f7 100644
--- a/dlls/netapi32/Makefile.in
+++ b/dlls/netapi32/Makefile.in
@@ -4,7 +4,7 @@
SRCDIR = @srcdir@
VPATH = @srcdir@
MODULE = netapi32.dll
-IMPORTS = advapi32 kernel32
+IMPORTS = iphlpapi advapi32 kernel32
LDDLLFLAGS = @LDDLLFLAGS@
SYMBOLFILE = $(MODULE).tmp.o
diff --git a/dlls/netapi32/netapi32.c b/dlls/netapi32/netapi32.c
index 73cea52..8d1f192 100644
--- a/dlls/netapi32/netapi32.c
+++ b/dlls/netapi32/netapi32.c
@@ -20,6 +20,7 @@
#include <string.h>
#include <stdio.h>
+#include <stdlib.h>
#include <fcntl.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
@@ -33,183 +34,73 @@
#include "winerror.h"
#include "nb30.h"
#include "lmcons.h"
-
-#ifdef HAVE_SYS_FILE_H
-# include <sys/file.h>
-#endif
-#ifdef HAVE_SYS_IOCTL_H
-# include <sys/ioctl.h>
-#endif
-#ifdef HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif
-#ifdef HAVE_SYS_SOCKIO_H
-# include <sys/sockio.h>
-#endif
-#ifdef HAVE_NET_IF_H
-# include <net/if.h>
-#endif
-#ifdef HAVE_NETINET_IN_H
-# include <netinet/in.h>
-#endif
-
-#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
-# ifndef max
-# define max(a,b) ((a) > (b) ? (a) : (b))
-# endif
-# define ifreq_size(i) max(sizeof(struct ifreq),\
-sizeof((i).ifr_name)+(i).ifr_addr.sa_len)
-# else
-# define ifreq_size(i) sizeof(struct ifreq)
-# endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
+#include "iphlpapi.h"
WINE_DEFAULT_DEBUG_CHANNEL(netbios);
HMODULE NETAPI32_hModule = 0;
-struct NetBiosAdapter
-{
- int valid;
- unsigned char address[6];
-};
-
-static struct NetBiosAdapter NETBIOS_Adapter[MAX_LANA];
-
-# ifdef SIOCGIFHWADDR
-int get_hw_address(int sd, struct ifreq *ifr, unsigned char *address)
-{
- if (ioctl(sd, SIOCGIFHWADDR, ifr) < 0)
- return -1;
- memcpy(address, (unsigned char *)&ifr->ifr_hwaddr.sa_data, 6);
- return 0;
-}
-# else
-# ifdef SIOCGENADDR
-int get_hw_address(int sd, struct ifreq *ifr, unsigned char *address)
-{
- if (ioctl(sd, SIOCGENADDR, ifr) < 0)
- return -1;
- memcpy(address, (unsigned char *) ifr->ifr_enaddr, 6);
- return 0;
-}
-# else
-int get_hw_address(int sd, struct ifreq *ifr, unsigned char *address)
-{
- return -1;
-}
-# endif /* SIOCGENADDR */
-# endif /* SIOCGIFHWADDR */
-
-int enum_hw(void)
-{
- int ret = 0;
-#ifdef HAVE_NET_IF_H
- int sd;
- struct ifreq ifr, *ifrp;
- struct ifconf ifc;
- unsigned char buf[1024];
- int i, ofs;
- /* BSD 4.4 defines the size of an ifreq to be
- * max(sizeof(ifreq), sizeof(ifreq.ifr_name)+ifreq.ifr_addr.sa_len
- * However, under earlier systems, sa_len isn't present, so
- * the size is just sizeof(struct ifreq)
- */
-
- sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
- if (sd < 0)
- return NRC_OPENERROR;
-
- memset(buf, 0, sizeof(buf));
- ifc.ifc_len = sizeof(buf);
- ifc.ifc_buf = buf;
- /* get the ifconf interface */
- if (ioctl (sd, SIOCGIFCONF, (char *)&ifc) < 0)
- {
- close(sd);
- return NRC_OPENERROR;
- }
-
- /* loop through the interfaces, looking for a valid one */
- /* n = ifc.ifc_len; */
- ofs = 0;
- for (i = 0; i < ifc.ifc_len; i++)
- {
- unsigned char *a = NETBIOS_Adapter[i].address;
-
- ifrp = (struct ifreq *)((char *)ifc.ifc_buf+ofs);
- strncpy(ifr.ifr_name, ifrp->ifr_name, IFNAMSIZ);
-
- /* try to get the address for this interface */
- if(get_hw_address(sd, &ifr, a)==0)
- {
- /* make sure it's not blank */
- /* if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5])
- continue; */
-
- TRACE("Found valid adapter %d at %02x:%02x:%02x:%02x:%02x:%02x\n", i,
- a[0],a[1],a[2],a[3],a[4],a[5]);
-
- NETBIOS_Adapter[i].valid = TRUE;
-
- ret++;
- }
- ofs += ifreq_size(ifr);
- }
- close(sd);
- TRACE("found %d adapters\n",ret);
-#endif /* HAVE_NET_IF_H */
- return ret;
-}
-
-void wprint_mac(WCHAR* buffer, int index)
-{
- int i;
- unsigned char val;
- for (i = 0; i<6; i++)
- {
- val = NETBIOS_Adapter[index].address[i];
- if ((val >>4) >9)
- buffer[2*i] = (WCHAR)((val >>4) + 'A' - 10);
- else
- buffer[2*i] = (WCHAR)((val >>4) + '0');
- if ((val & 0xf ) >9)
- buffer[2*i+1] = (WCHAR)((val & 0xf) + 'A' - 10);
- else
- buffer[2*i+1] = (WCHAR)((val & 0xf) + '0');
- }
- buffer[12]=(WCHAR)0;
-
-}
static UCHAR NETBIOS_Enum(PNCB ncb)
{
int i;
LANA_ENUM *lanas = (PLANA_ENUM) ncb->ncb_buffer;
-
+ DWORD apiReturn, size = 0;
+ PMIB_IFTABLE table;
+ UCHAR ret;
+
TRACE("NCBENUM\n");
-
- lanas->length = 0;
- for (i = 0; i < enum_hw(); i++)
- {
- lanas->lana[lanas->length] = i;
- lanas->length++;
- }
- return NRC_GOODRET;
+
+ apiReturn = GetIfTable(NULL, &size, FALSE);
+ if (apiReturn != NO_ERROR)
+ {
+ table = (PMIB_IFTABLE)malloc(size);
+ if (table)
+ {
+ apiReturn = GetIfTable(table, &size, FALSE);
+ if (apiReturn == NO_ERROR)
+ {
+ lanas->length = 0;
+ for (i = 0; i < table->dwNumEntries && lanas->length < MAX_LANA;
+ i++)
+ {
+ if (table->table[i].dwType != MIB_IF_TYPE_LOOPBACK)
+ {
+ lanas->lana[lanas->length] = table->table[i].dwIndex;
+ lanas->length++;
+ }
+ }
+ ret = NRC_GOODRET;
+ }
+ else
+ ret = NRC_SYSTEM;
+ free(table);
+ }
+ else
+ ret = NRC_NORESOURCES;
+ }
+ else
+ ret = NRC_SYSTEM;
+ return ret;
}
static UCHAR NETBIOS_Astat(PNCB ncb)
{
- struct NetBiosAdapter *nad = &NETBIOS_Adapter[ncb->ncb_lana_num];
PADAPTER_STATUS astat = (PADAPTER_STATUS) ncb->ncb_buffer;
-
+ MIB_IFROW row;
+
TRACE("NCBASTAT (Adapter %d)\n", ncb->ncb_lana_num);
-
- if(!nad->valid)
- return NRC_INVADDRESS;
-
+
memset(astat, 0, sizeof astat);
- memcpy(astat->adapter_address, nad->address, sizeof astat->adapter_address);
-
+
+ row.dwIndex = ncb->ncb_lana_num;
+ if (GetIfEntry(&row) != NO_ERROR)
+ return NRC_INVADDRESS;
+ /* doubt anyone cares, but why not.. */
+ if (row.dwType == MIB_IF_TYPE_TOKENRING)
+ astat->adapter_type = 0xff;
+ else
+ astat->adapter_type = 0xfe; /* for Ethernet */
return NRC_GOODRET;
}
@@ -241,9 +132,16 @@
{
case NCBRESET:
FIXME("NCBRESET adapter %d\n",pncb->ncb_lana_num);
- if( (pncb->ncb_lana_num < MAX_LANA ) &&
- NETBIOS_Adapter[pncb->ncb_lana_num].valid)
- ret = NRC_GOODRET;
+ if(pncb->ncb_lana_num < MAX_LANA )
+ {
+ MIB_IFROW row;
+
+ row.dwIndex = pncb->ncb_lana_num;
+ if (GetIfEntry(&row) != NO_ERROR)
+ ret = NRC_GOODRET;
+ else
+ ret = NRC_ILLCMD; /* NetBIOS emulator not found */
+ }
else
ret = NRC_ILLCMD; /* NetBIOS emulator not found */
break;
diff --git a/dlls/netapi32/wksta.c b/dlls/netapi32/wksta.c
index 8908f8a..32adb7c 100644
--- a/dlls/netapi32/wksta.c
+++ b/dlls/netapi32/wksta.c
@@ -18,12 +18,14 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <stdlib.h>
#include "winbase.h"
#include "nb30.h"
#include "lmcons.h"
#include "lmapibuf.h"
#include "lmerr.h"
#include "lmwksta.h"
+#include "iphlpapi.h"
#include "winerror.h"
#include "winternl.h"
#include "ntsecapi.h"
@@ -59,8 +61,53 @@
}
}
-int enum_hw(void);
-void wprint_mac(WCHAR* buffer, int index);
+static void wprint_mac(WCHAR* buffer, PIP_ADAPTER_INFO adapter)
+{
+ if (adapter != NULL)
+ {
+ int i;
+ unsigned char val;
+
+ for (i = 0; i<max(adapter->AddressLength, 6); i++)
+ {
+ val = adapter->Address[i];
+ if ((val >>4) >9)
+ buffer[2*i] = (WCHAR)((val >>4) + 'A' - 10);
+ else
+ buffer[2*i] = (WCHAR)((val >>4) + '0');
+ if ((val & 0xf ) >9)
+ buffer[2*i+1] = (WCHAR)((val & 0xf) + 'A' - 10);
+ else
+ buffer[2*i+1] = (WCHAR)((val & 0xf) + '0');
+ }
+ buffer[12]=(WCHAR)0;
+ }
+ else
+ buffer[0] = 0;
+}
+
+#define TRANSPORT_NAME_HEADER "\\Device\\NetBT_Tcpip_"
+#define TRANSPORT_NAME_LEN \
+ (sizeof(TRANSPORT_NAME_HEADER) + MAX_ADAPTER_NAME_LENGTH)
+
+static void wprint_name(WCHAR *buffer, int len, PIP_ADAPTER_INFO adapter)
+{
+ WCHAR *ptr;
+ const char *name;
+
+ if (!buffer)
+ return;
+ if (!adapter)
+ return;
+
+ for (ptr = buffer, name = TRANSPORT_NAME_HEADER; *name && ptr < buffer + len;
+ ptr++, name++)
+ *ptr = *name;
+ for (name = adapter->AdapterName; name && *name && ptr < buffer + len;
+ ptr++, name++)
+ *ptr = *name;
+ *ptr = '\0';
+}
NET_API_STATUS WINAPI
NetWkstaTransportEnum(LPCWSTR ServerName, DWORD level, LPBYTE* pbuf,
@@ -84,49 +131,73 @@
switch (level)
{
- case 0: /* transport info */
- {
- PWKSTA_TRANSPORT_INFO_0 ti;
- int i,size_needed,n_adapt = enum_hw();
-
- if (n_adapt == 0)
+ case 0: /* transport info */
+ {
+ PWKSTA_TRANSPORT_INFO_0 ti;
+ int i,size_needed,n_adapt;
+ DWORD apiReturn, adaptInfoSize = 0;
+ PIP_ADAPTER_INFO info, ptr;
+
+ apiReturn = GetAdaptersInfo(NULL, &adaptInfoSize);
+ if (apiReturn == ERROR_NO_DATA)
return ERROR_NETWORK_UNREACHABLE;
if (!read_entries)
return STATUS_ACCESS_VIOLATION;
if (!total_entries || !pbuf)
return RPC_X_NULL_REF_POINTER;
-
- size_needed = n_adapt * (sizeof(WKSTA_TRANSPORT_INFO_0)
- * 13 * sizeof (WCHAR));
- if (prefmaxlen == MAX_PREFERRED_LENGTH)
- NetApiBufferAllocate( size_needed, (LPVOID *) pbuf);
- else
- {
- if (size_needed > prefmaxlen)
- return ERROR_MORE_DATA;
- NetApiBufferAllocate(prefmaxlen,
- (LPVOID *) pbuf);
- }
- for (i = 0; i <n_adapt; i++)
- {
- ti = (PWKSTA_TRANSPORT_INFO_0)
- ((PBYTE) *pbuf + i * sizeof(WKSTA_TRANSPORT_INFO_0));
- ti->wkti0_quality_of_service=0;
- ti->wkti0_number_of_vcs=0;
- ti->wkti0_transport_name=NULL;
- ti->wkti0_transport_address= (LPWSTR)
- ((PBYTE )*pbuf + n_adapt* sizeof(WKSTA_TRANSPORT_INFO_0)
- + i * 13 * sizeof (WCHAR));
- ti->wkti0_wan_ish=TRUE; /*TCPIP/NETBIOS Protocoll*/
- wprint_mac(ti->wkti0_transport_address,i);
- TRACE("%d of %d:ti at %p transport_address at %p %s\n",i,n_adapt,
- ti, ti->wkti0_transport_address, debugstr_w(ti->wkti0_transport_address));
- }
+
+ info = (PIP_ADAPTER_INFO)malloc(adaptInfoSize);
+ apiReturn = GetAdaptersInfo(info, &adaptInfoSize);
+ if (apiReturn != NO_ERROR)
+ {
+ free(info);
+ return apiReturn;
+ }
+
+ for (n_adapt = 0, ptr = info; ptr; ptr = ptr->Next)
+ n_adapt++;
+ size_needed = n_adapt * (sizeof(WKSTA_TRANSPORT_INFO_0)
+ + n_adapt * TRANSPORT_NAME_LEN * sizeof (WCHAR)
+ + n_adapt * 13 * sizeof (WCHAR));
+ if (prefmaxlen == MAX_PREFERRED_LENGTH)
+ NetApiBufferAllocate( size_needed, (LPVOID *) pbuf);
+ else
+ {
+ if (size_needed > prefmaxlen)
+ {
+ free(info);
+ return ERROR_MORE_DATA;
+ }
+ NetApiBufferAllocate(prefmaxlen,
+ (LPVOID *) pbuf);
+ }
+ for (i = 0, ptr = info; ptr; ptr = ptr->Next, i++)
+ {
+ ti = (PWKSTA_TRANSPORT_INFO_0)
+ ((PBYTE) *pbuf + i * sizeof(WKSTA_TRANSPORT_INFO_0));
+ ti->wkti0_quality_of_service=0;
+ ti->wkti0_number_of_vcs=0;
+ ti->wkti0_transport_name= (LPWSTR)
+ ((PBYTE )*pbuf +
+ n_adapt * sizeof(WKSTA_TRANSPORT_INFO_0)
+ + i * TRANSPORT_NAME_LEN * sizeof (WCHAR));
+ wprint_name(ti->wkti0_transport_name,TRANSPORT_NAME_LEN, ptr);
+ ti->wkti0_transport_address= (LPWSTR)
+ ((PBYTE )*pbuf +
+ n_adapt * sizeof(WKSTA_TRANSPORT_INFO_0) +
+ n_adapt * TRANSPORT_NAME_LEN * sizeof (WCHAR)
+ + i * 13 * sizeof (WCHAR));
+ ti->wkti0_wan_ish=TRUE; /*TCPIP/NETBIOS Protocoll*/
+ wprint_mac(ti->wkti0_transport_address, ptr);
+ TRACE("%d of %d:ti at %p transport_address at %p %s\n",i,n_adapt,
+ ti, ti->wkti0_transport_address, debugstr_w(ti->wkti0_transport_address));
+ }
*read_entries = n_adapt;
*total_entries = n_adapt;
- if(hresume) *hresume= 0;
- break;
- }
+ free(info);
+ if(hresume) *hresume= 0;
+ break;
+ }
default:
ERR("Invalid level %ld is specified\n", level);
return ERROR_INVALID_LEVEL;
diff --git a/include/nb30.h b/include/nb30.h
index b04a11b..a9d7beb 100644
--- a/include/nb30.h
+++ b/include/nb30.h
@@ -100,9 +100,11 @@
#define NRC_ILLCMD 0x03
#define NRC_CMDTMO 0x05
#define NRC_INCOMP 0x06
+#define NRC_NORESOURCES 0x38
#define NRC_INVADDRESS 0x39
#define NRC_PENDING 0xff
#define NRC_OPENERROR 0x3f
+#define NRC_SYSTEM 0x40
#ifdef __cplusplus
}