msi/tests: Delete the temp .msi file in all failure cases.
[wine.git] / dlls / nsiproxy.sys / ndis.c
blob372272dd1151d7b0a29fe735500c770b322dfc6d
1 /*
2 * nsiproxy.sys ndis module
4 * Copyright 2003, 2006, 2011 Juan Lang
5 * Copyright 2021 Huw Davies
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #if 0
22 #pragma makedep unix
23 #endif
25 #include "config.h"
27 #include <stdarg.h>
28 #include <sys/types.h>
29 #include <sys/socket.h>
30 #include <sys/ioctl.h>
31 #include <unistd.h>
33 #ifdef HAVE_NET_IF_H
34 #include <net/if.h>
35 #endif
37 #ifdef HAVE_NET_IF_ARP_H
38 #include <net/if_arp.h>
39 #endif
41 #ifdef HAVE_NETINET_IN_H
42 #include <netinet/in.h>
43 #endif
45 #ifdef HAVE_NETINET_IF_ETHER_H
46 #include <netinet/if_ether.h>
47 #endif
49 #ifdef HAVE_NET_ROUTE_H
50 #include <net/route.h>
51 #endif
53 #ifdef HAVE_SYS_SYSCTL_H
54 #include <sys/sysctl.h>
55 #endif
57 #ifdef HAVE_NET_IF_DL_H
58 #include <net/if_dl.h>
59 #endif
61 #ifdef HAVE_NET_IF_TYPES_H
62 #include <net/if_types.h>
63 #endif
65 #ifdef HAVE_LINUX_WIRELESS_H
66 #include <linux/wireless.h>
67 #endif
69 #include <pthread.h>
71 #include "ntstatus.h"
72 #define WIN32_NO_STATUS
73 #include "windef.h"
74 #include "winbase.h"
75 #include "winternl.h"
76 #include "winioctl.h"
77 #define USE_WS_PREFIX
78 #include "winsock2.h"
79 #include "ws2ipdef.h"
80 #include "nldef.h"
81 #include "ifdef.h"
82 #include "netiodef.h"
83 #include "ddk/wdm.h"
84 #include "wine/nsi.h"
85 #include "wine/list.h"
86 #include "wine/debug.h"
87 #include "wine/unixlib.h"
89 #include "unix_private.h"
91 WINE_DEFAULT_DEBUG_CHANNEL(nsi);
93 struct if_entry
95 struct list entry;
96 GUID if_guid;
97 NET_LUID if_luid;
98 WCHAR *if_name;
99 char if_unix_name[IFNAMSIZ];
100 IF_PHYSICAL_ADDRESS if_phys_addr;
101 UINT if_index;
102 UINT if_type;
105 static struct list if_list = LIST_INIT( if_list );
106 static pthread_mutex_t if_list_lock = PTHREAD_MUTEX_INITIALIZER;
108 static struct if_entry *find_entry_from_index( UINT index )
110 struct if_entry *entry;
112 LIST_FOR_EACH_ENTRY( entry, &if_list, struct if_entry, entry )
113 if (entry->if_index == index) return entry;
115 return NULL;
118 static struct if_entry *find_entry_from_luid( const NET_LUID *luid )
120 struct if_entry *entry;
122 LIST_FOR_EACH_ENTRY( entry, &if_list, struct if_entry, entry )
123 if (entry->if_luid.Value == luid->Value) return entry;
125 return NULL;
128 #if defined (SIOCGIFHWADDR) && defined (HAVE_STRUCT_IFREQ_IFR_HWADDR)
129 static NTSTATUS if_get_physical( const char *name, UINT *type, IF_PHYSICAL_ADDRESS *phys_addr )
131 int fd, size, i;
132 struct ifreq ifr;
133 NTSTATUS ret = STATUS_SUCCESS;
134 static const struct type_lookup
136 unsigned short ifi_type;
137 IFTYPE mib_type;
138 UINT addr_len;
139 } types[] =
141 { ARPHRD_LOOPBACK, MIB_IF_TYPE_LOOPBACK, 0 },
142 { ARPHRD_ETHER, MIB_IF_TYPE_ETHERNET, ETH_ALEN },
143 { ARPHRD_FDDI, MIB_IF_TYPE_FDDI, ETH_ALEN },
144 { ARPHRD_IEEE802, MIB_IF_TYPE_TOKENRING, ETH_ALEN },
145 { ARPHRD_IEEE802_TR, MIB_IF_TYPE_TOKENRING, ETH_ALEN },
146 { ARPHRD_SLIP, MIB_IF_TYPE_SLIP, 0 },
147 { ARPHRD_PPP, MIB_IF_TYPE_PPP, 0 }
150 *type = MIB_IF_TYPE_OTHER;
151 memset( phys_addr, 0, sizeof(*phys_addr) );
153 size = strlen( name ) + 1;
154 if (size > sizeof(ifr.ifr_name)) return STATUS_NAME_TOO_LONG;
155 memset( &ifr, 0, sizeof(ifr) );
156 memcpy( ifr.ifr_name, name, size );
158 fd = socket( PF_INET, SOCK_DGRAM, 0 );
159 if (fd == -1) return STATUS_TOO_MANY_OPENED_FILES;
161 if (ioctl( fd, SIOCGIFHWADDR, &ifr ))
163 ret = STATUS_DEVICE_DATA_ERROR;
164 goto err;
167 for (i = 0; i < ARRAY_SIZE(types); i++)
168 if (ifr.ifr_hwaddr.sa_family == types[i].ifi_type)
170 *type = types[i].mib_type;
171 phys_addr->Length = types[i].addr_len;
172 memcpy( phys_addr->Address, ifr.ifr_hwaddr.sa_data, phys_addr->Length );
173 break;
176 if (*type == MIB_IF_TYPE_OTHER && !ioctl( fd, SIOCGIFFLAGS, &ifr ) && ifr.ifr_flags & IFF_POINTOPOINT)
177 *type = MIB_IF_TYPE_PPP;
179 #ifdef HAVE_LINUX_WIRELESS_H
180 if (*type == MIB_IF_TYPE_ETHERNET)
182 struct iwreq pwrq;
184 memset( &pwrq, 0, sizeof(pwrq) );
185 memcpy( pwrq.ifr_name, name, size );
186 if (ioctl( fd, SIOCGIWNAME, &pwrq ) != -1)
188 TRACE( "iface %s, wireless protocol %s.\n", debugstr_a(name), debugstr_a(pwrq.u.name) );
189 *type = IF_TYPE_IEEE80211;
192 #endif
194 err:
195 close( fd );
196 return ret;
199 #elif defined (HAVE_SYS_SYSCTL_H) && defined (HAVE_NET_IF_DL_H)
201 static NTSTATUS if_get_physical( const char *name, UINT *type, IF_PHYSICAL_ADDRESS *phys_addr )
203 struct if_msghdr *ifm;
204 struct sockaddr_dl *sdl;
205 u_char *p, *buf;
206 size_t mib_len;
207 int mib[] = { CTL_NET, AF_ROUTE, 0, AF_LINK, NET_RT_IFLIST, 0 }, i;
208 static const struct type_lookup
210 u_char sdl_type;
211 IFTYPE mib_type;
212 } types[] =
214 { IFT_ETHER, MIB_IF_TYPE_ETHERNET },
215 { IFT_FDDI, MIB_IF_TYPE_FDDI },
216 { IFT_ISO88024, MIB_IF_TYPE_TOKENRING },
217 { IFT_ISO88025, MIB_IF_TYPE_TOKENRING },
218 { IFT_PPP, MIB_IF_TYPE_PPP },
219 { IFT_SLIP, MIB_IF_TYPE_SLIP },
220 { IFT_LOOP, MIB_IF_TYPE_LOOPBACK }
223 *type = MIB_IF_TYPE_OTHER;
224 memset( phys_addr, 0, sizeof(*phys_addr) );
226 if (sysctl( mib, 6, NULL, &mib_len, NULL, 0 ) < 0) return STATUS_TOO_MANY_OPENED_FILES;
228 buf = malloc( mib_len );
229 if (!buf) return STATUS_NO_MEMORY;
231 if (sysctl( mib, 6, buf, &mib_len, NULL, 0 ) < 0)
233 free( buf );
234 return STATUS_TOO_MANY_OPENED_FILES;
237 for (p = buf; p < buf + mib_len; p += ifm->ifm_msglen)
239 ifm = (struct if_msghdr *)p;
240 sdl = (struct sockaddr_dl *)(ifm + 1);
242 if (ifm->ifm_type != RTM_IFINFO || (ifm->ifm_addrs & RTA_IFP) == 0) continue;
244 if (sdl->sdl_family != AF_LINK || sdl->sdl_nlen == 0 ||
245 memcmp( sdl->sdl_data, name, max( sdl->sdl_nlen, strlen( name ) ) ))
246 continue;
248 for (i = 0; i < ARRAY_SIZE(types); i++)
249 if (sdl->sdl_type == types[i].sdl_type)
251 *type = types[i].mib_type;
252 break;
255 phys_addr->Length = sdl->sdl_alen;
256 if (phys_addr->Length > sizeof(phys_addr->Address)) phys_addr->Length = 0;
257 memcpy( phys_addr->Address, LLADDR(sdl), phys_addr->Length );
258 break;
261 free( buf );
262 return STATUS_SUCCESS;
264 #endif
266 static WCHAR *strdupAtoW( const char *str )
268 WCHAR *ret = NULL;
269 SIZE_T len;
271 if (!str) return ret;
272 len = strlen( str ) + 1;
273 ret = malloc( len * sizeof(WCHAR) );
274 if (ret) ntdll_umbstowcs( str, len, ret, len );
275 return ret;
278 static struct if_entry *add_entry( UINT index, char *name )
280 struct if_entry *entry;
281 int name_len = strlen( name );
283 if (name_len >= sizeof(entry->if_unix_name)) return NULL;
284 entry = malloc( sizeof(*entry) );
285 if (!entry) return NULL;
287 entry->if_index = index;
288 memcpy( entry->if_unix_name, name, name_len + 1 );
289 entry->if_name = strdupAtoW( name );
290 if (!entry->if_name)
292 free( entry );
293 return NULL;
296 if_get_physical( name, &entry->if_type, &entry->if_phys_addr );
298 entry->if_luid.Info.Reserved = 0;
299 entry->if_luid.Info.NetLuidIndex = index;
300 entry->if_luid.Info.IfType = entry->if_type;
302 memset( &entry->if_guid, 0, sizeof(entry->if_guid) );
303 entry->if_guid.Data1 = index;
304 memcpy( entry->if_guid.Data4 + 2, "NetDev", 6 );
306 list_add_tail( &if_list, &entry->entry );
307 return entry;
310 static unsigned int update_if_table( void )
312 struct if_nameindex *indices = if_nameindex(), *entry;
313 unsigned int append_count = 0;
315 for (entry = indices; entry->if_index; entry++)
317 if (!find_entry_from_index( entry->if_index ) && add_entry( entry->if_index, entry->if_name ))
318 ++append_count;
321 if_freenameindex( indices );
322 return append_count;
325 static void if_counted_string_init( IF_COUNTED_STRING *str, const WCHAR *value )
327 str->Length = value ? min( lstrlenW( value ), ARRAY_SIZE(str->String) - 1 ) * sizeof(WCHAR) : 0;
328 if (str->Length) memcpy( str->String, value, str->Length );
329 memset( (char *)str->String + str->Length, 0, sizeof(str->String) - str->Length );
332 static void ifinfo_fill_dynamic( struct if_entry *entry, struct nsi_ndis_ifinfo_dynamic *data )
334 int fd, name_len = strlen( entry->if_unix_name );
335 struct ifreq req;
337 memset( data, 0, sizeof(*data) );
339 if (name_len >= sizeof(req.ifr_name)) return;
340 memcpy( req.ifr_name, entry->if_unix_name, name_len + 1 );
342 fd = socket( PF_INET, SOCK_DGRAM, 0 );
343 if (fd == -1) return;
345 if (!ioctl( fd, SIOCGIFFLAGS, &req ))
347 if (req.ifr_flags & IFF_UP) data->oper_status = IfOperStatusUp;
348 #ifdef IFF_DORMANT
349 else if (req.ifr_flags & IFF_DORMANT) data->oper_status = IfOperStatusDormant;
350 #endif
351 else data->oper_status = IfOperStatusDown;
352 } else data->oper_status = IfOperStatusUnknown;
354 data->flags.unk = 0;
355 data->flags.not_media_conn = 0;
356 data->flags.unk2 = 0;
357 #ifdef __linux__
359 char filename[64];
360 FILE *fp;
362 sprintf( filename, "/sys/class/net/%s/carrier", entry->if_unix_name );
363 if (!(fp = fopen( filename, "r" ))) data->media_conn_state = MediaConnectStateUnknown;
364 else
366 if (fgetc( fp ) == '1') data->media_conn_state = MediaConnectStateConnected;
367 else data->media_conn_state = MediaConnectStateDisconnected;
368 fclose( fp );
371 #else
372 data->media_conn_state = MediaConnectStateConnected;
373 #endif
374 data->unk = 0;
376 if (!ioctl( fd, SIOCGIFMTU, &req )) data->mtu = req.ifr_mtu;
377 else data->mtu = 0;
379 close( fd );
381 #ifdef __linux__
383 FILE *fp;
385 if ((fp = fopen( "/proc/net/dev", "r" )))
387 char buf[512], *ptr;
389 while ((ptr = fgets( buf, sizeof(buf), fp )))
391 while (*ptr && isspace( *ptr )) ptr++;
392 if (!ascii_strncasecmp( ptr, entry->if_unix_name, name_len ) && ptr[name_len] == ':')
394 unsigned long long values[9];
395 ptr += name_len + 1;
396 sscanf( ptr, "%llu %llu %llu %llu %*u %*u %*u %llu %llu %llu %llu %llu",
397 values, values + 1, values + 2, values + 3, values + 4,
398 values + 5, values + 6, values + 7, values + 8 );
399 data->in_octets = values[0];
400 data->in_ucast_pkts = values[1];
401 data->in_errors = values[2];
402 data->in_discards = values[3];
403 data->in_mcast_pkts = values[4];
404 data->out_octets = values[5];
405 data->out_ucast_pkts = values[6];
406 data->out_errors = values[7];
407 data->out_discards = values[8];
408 break;
411 fclose( fp );
414 #elif defined(HAVE_SYS_SYSCTL_H) && defined(NET_RT_IFLIST)
416 int mib[] = { CTL_NET, PF_ROUTE, 0, AF_INET, NET_RT_IFLIST, entry->if_index };
417 size_t needed;
418 char *buf = NULL, *end;
419 struct if_msghdr *ifm;
420 struct if_data ifdata;
422 if (sysctl( mib, ARRAY_SIZE(mib), NULL, &needed, NULL, 0 ) == -1) goto done;
423 buf = malloc( needed );
424 if (!buf) goto done;
425 if (sysctl( mib, ARRAY_SIZE(mib), buf, &needed, NULL, 0 ) == -1) goto done;
426 for (end = buf + needed; buf < end; buf += ifm->ifm_msglen)
428 ifm = (struct if_msghdr *) buf;
429 if (ifm->ifm_type == RTM_IFINFO)
431 ifdata = ifm->ifm_data;
432 data->xmit_speed = data->rcv_speed = ifdata.ifi_baudrate;
433 data->in_octets = ifdata.ifi_ibytes;
434 data->in_errors = ifdata.ifi_ierrors;
435 data->in_discards = ifdata.ifi_iqdrops;
436 data->in_ucast_pkts = ifdata.ifi_ipackets;
437 data->in_mcast_pkts = ifdata.ifi_imcasts;
438 data->out_octets = ifdata.ifi_obytes;
439 data->out_ucast_pkts = ifdata.ifi_opackets;
440 data->out_mcast_pkts = ifdata.ifi_omcasts;
441 data->out_errors = ifdata.ifi_oerrors;
442 break;
445 done:
446 free( buf );
448 #endif
451 static void ifinfo_fill_entry( struct if_entry *entry, NET_LUID *key, struct nsi_ndis_ifinfo_rw *rw,
452 struct nsi_ndis_ifinfo_dynamic *dyn, struct nsi_ndis_ifinfo_static *stat )
454 if (key) memcpy( key, &entry->if_luid, sizeof(entry->if_luid) );
456 if (rw)
458 memset( &rw->network_guid, 0, sizeof(entry->if_guid) );
459 rw->admin_status = MIB_IF_ADMIN_STATUS_UP;
460 if_counted_string_init( &rw->alias, entry->if_name );
461 memcpy( &rw->phys_addr, &entry->if_phys_addr, sizeof(entry->if_phys_addr) );
462 rw->pad = 0;
463 if_counted_string_init( &rw->name2, NULL );
464 rw->unk = 0;
467 if (dyn) ifinfo_fill_dynamic( entry, dyn );
469 if (stat)
471 stat->if_index = entry->if_index;
472 if_counted_string_init( &stat->descr, entry->if_name ); /* get a more descriptive name */
473 stat->type = entry->if_type;
474 stat->access_type = (entry->if_type == MIB_IF_TYPE_LOOPBACK) ? NET_IF_ACCESS_LOOPBACK : NET_IF_ACCESS_BROADCAST;
475 stat->unk = 0;
476 stat->conn_type = NET_IF_CONNECTION_DEDICATED;
477 memcpy( &stat->if_guid, &entry->if_guid, sizeof(entry->if_guid) );
478 stat->conn_present = entry->if_type != MIB_IF_TYPE_LOOPBACK;
479 memcpy( &stat->perm_phys_addr, &entry->if_phys_addr, sizeof(entry->if_phys_addr) );
480 stat->flags.hw = entry->if_type != MIB_IF_TYPE_LOOPBACK;
481 stat->flags.filter = 0;
482 stat->flags.unk = 0;
483 stat->media_type = 0;
484 stat->phys_medium_type = 0;
488 static NTSTATUS ifinfo_enumerate_all( void *key_data, UINT key_size, void *rw_data, UINT rw_size,
489 void *dynamic_data, UINT dynamic_size,
490 void *static_data, UINT static_size, UINT_PTR *count )
492 struct if_entry *entry;
493 UINT num = 0;
494 NTSTATUS status = STATUS_SUCCESS;
495 BOOL want_data = key_size || rw_size || dynamic_size || static_size;
497 TRACE( "%p %d %p %d %p %d %p %d %p\n", key_data, key_size, rw_data, rw_size,
498 dynamic_data, dynamic_size, static_data, static_size, count );
500 pthread_mutex_lock( &if_list_lock );
502 update_if_table();
504 LIST_FOR_EACH_ENTRY( entry, &if_list, struct if_entry, entry )
506 if (num < *count)
508 ifinfo_fill_entry( entry, key_data, rw_data, dynamic_data, static_data );
509 key_data = (BYTE *)key_data + key_size;
510 rw_data = (BYTE *)rw_data + rw_size;
511 dynamic_data = (BYTE *)dynamic_data + dynamic_size;
512 static_data = (BYTE *)static_data + static_size;
514 num++;
517 pthread_mutex_unlock( &if_list_lock );
519 if (!want_data || num <= *count) *count = num;
520 else status = STATUS_BUFFER_OVERFLOW;
522 return status;
525 static NTSTATUS ifinfo_get_all_parameters( const void *key, UINT key_size, void *rw_data, UINT rw_size,
526 void *dynamic_data, UINT dynamic_size,
527 void *static_data, UINT static_size )
529 struct if_entry *entry;
530 NTSTATUS status = STATUS_OBJECT_NAME_NOT_FOUND;
532 TRACE( "%p %d %p %d %p %d %p %d\n", key, key_size, rw_data, rw_size,
533 dynamic_data, dynamic_size, static_data, static_size );
535 pthread_mutex_lock( &if_list_lock );
537 if (!(entry = find_entry_from_luid( (const NET_LUID *)key )))
539 update_if_table();
540 entry = find_entry_from_luid( (const NET_LUID *)key );
542 if (entry)
544 ifinfo_fill_entry( entry, NULL, rw_data, dynamic_data, static_data );
545 status = STATUS_SUCCESS;
548 pthread_mutex_unlock( &if_list_lock );
550 return status;
553 static NTSTATUS ifinfo_get_rw_parameter( struct if_entry *entry, void *data, UINT data_size, UINT data_offset )
555 switch (data_offset)
557 case FIELD_OFFSET( struct nsi_ndis_ifinfo_rw, alias ):
559 IF_COUNTED_STRING *str = (IF_COUNTED_STRING *)data;
560 if (data_size != sizeof(*str)) return STATUS_INVALID_PARAMETER;
561 if_counted_string_init( str, entry->if_name );
562 return STATUS_SUCCESS;
564 default:
565 FIXME( "Offset %#x not handled\n", data_offset );
568 return STATUS_INVALID_PARAMETER;
571 static NTSTATUS ifinfo_get_static_parameter( struct if_entry *entry, void *data, UINT data_size, UINT data_offset )
573 switch (data_offset)
575 case FIELD_OFFSET( struct nsi_ndis_ifinfo_static, if_index ):
576 if (data_size != sizeof(UINT)) return STATUS_INVALID_PARAMETER;
577 *(UINT *)data = entry->if_index;
578 return STATUS_SUCCESS;
580 case FIELD_OFFSET( struct nsi_ndis_ifinfo_static, if_guid ):
581 if (data_size != sizeof(GUID)) return STATUS_INVALID_PARAMETER;
582 *(GUID *)data = entry->if_guid;
583 return STATUS_SUCCESS;
585 default:
586 FIXME( "Offset %#x not handled\n", data_offset );
588 return STATUS_INVALID_PARAMETER;
591 static NTSTATUS ifinfo_get_parameter( const void *key, UINT key_size, UINT param_type,
592 void *data, UINT data_size, UINT data_offset )
594 struct if_entry *entry;
595 NTSTATUS status = STATUS_OBJECT_NAME_NOT_FOUND;
597 TRACE( "%p %d %d %p %d %d\n", key, key_size, param_type, data, data_size, data_offset );
599 pthread_mutex_lock( &if_list_lock );
601 if (!(entry = find_entry_from_luid( (const NET_LUID *)key )))
603 update_if_table();
604 entry = find_entry_from_luid( (const NET_LUID *)key );
606 if (entry)
608 switch (param_type)
610 case NSI_PARAM_TYPE_RW:
611 status = ifinfo_get_rw_parameter( entry, data, data_size, data_offset );
612 break;
613 case NSI_PARAM_TYPE_STATIC:
614 status = ifinfo_get_static_parameter( entry, data, data_size, data_offset );
615 break;
619 pthread_mutex_unlock( &if_list_lock );
621 return status;
624 static NTSTATUS index_luid_get_parameter( const void *key, UINT key_size, UINT param_type,
625 void *data, UINT data_size, UINT data_offset )
627 struct if_entry *entry;
628 NTSTATUS status = STATUS_OBJECT_NAME_NOT_FOUND;
630 TRACE( "%p %d %d %p %d %d\n", key, key_size, param_type, data, data_size, data_offset );
632 if (param_type != NSI_PARAM_TYPE_STATIC || data_size != sizeof(NET_LUID) || data_offset != 0)
633 return STATUS_INVALID_PARAMETER;
635 pthread_mutex_lock( &if_list_lock );
637 if (!(entry = find_entry_from_index( *(UINT *)key )))
639 update_if_table();
640 entry = find_entry_from_index( *(UINT *)key );
642 if (entry)
644 *(NET_LUID *)data = entry->if_luid;
645 status = STATUS_SUCCESS;
647 pthread_mutex_unlock( &if_list_lock );
648 return status;
651 BOOL convert_unix_name_to_luid( const char *unix_name, NET_LUID *luid )
653 struct if_entry *entry;
654 BOOL ret = FALSE;
655 int updated = 0;
657 pthread_mutex_lock( &if_list_lock );
661 LIST_FOR_EACH_ENTRY( entry, &if_list, struct if_entry, entry )
663 if (!strcmp( entry->if_unix_name, unix_name ))
665 *luid = entry->if_luid;
666 ret = TRUE;
667 goto done;
670 } while (!updated++ && update_if_table());
672 done:
673 pthread_mutex_unlock( &if_list_lock );
675 return ret;
678 BOOL convert_luid_to_unix_name( const NET_LUID *luid, const char **unix_name )
680 struct if_entry *entry;
681 BOOL ret = FALSE;
682 int updated = 0;
684 pthread_mutex_lock( &if_list_lock );
688 LIST_FOR_EACH_ENTRY( entry, &if_list, struct if_entry, entry )
690 if (entry->if_luid.Value == luid->Value)
692 *unix_name = entry->if_unix_name;
693 ret = TRUE;
694 goto done;
697 } while (!updated++ && update_if_table());
699 done:
700 pthread_mutex_unlock( &if_list_lock );
702 return ret;
705 static const struct module_table tables[] =
708 NSI_NDIS_IFINFO_TABLE,
710 sizeof(NET_LUID), sizeof(struct nsi_ndis_ifinfo_rw),
711 sizeof(struct nsi_ndis_ifinfo_dynamic), sizeof(struct nsi_ndis_ifinfo_static)
713 ifinfo_enumerate_all,
714 ifinfo_get_all_parameters,
715 ifinfo_get_parameter
718 NSI_NDIS_INDEX_LUID_TABLE,
720 sizeof(UINT), 0,
721 0, sizeof(NET_LUID)
723 NULL,
724 NULL,
725 index_luid_get_parameter
727 { ~0u }
730 const struct module ndis_module =
732 &NPI_MS_NDIS_MODULEID,
733 tables