Wine-Devel
Threads by month
- ----- 2026 -----
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- 22 participants
- 84527 discussions
[PATCH 3/5] iphlpapi: Implement AllocateAndGetUdpTableFromStack() on top of nsi.
by Huw Davies Aug. 18, 2021
by Huw Davies Aug. 18, 2021
Aug. 18, 2021
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/iphlpapi/iphlpapi_main.c | 21 ++
dlls/iphlpapi/ipstats.c | 524 ----------------------------------
2 files changed, 21 insertions(+), 524 deletions(-)
diff --git a/dlls/iphlpapi/iphlpapi_main.c b/dlls/iphlpapi/iphlpapi_main.c
index bcda2b81b6e..82c63b0dfce 100644
--- a/dlls/iphlpapi/iphlpapi_main.c
+++ b/dlls/iphlpapi/iphlpapi_main.c
@@ -3491,6 +3491,27 @@ DWORD WINAPI GetExtendedUdpTable( void *table, DWORD *size, BOOL sort, ULONG fam
return err;
}
+DWORD WINAPI AllocateAndGetUdpTableFromStack( MIB_UDPTABLE **table, BOOL sort, HANDLE heap, DWORD flags )
+{
+ DWORD err, size = 0x100, attempt;
+
+ TRACE("table %p, sort %d, heap %p, flags 0x%08x\n", table, sort, heap, flags );
+
+ if (!table) return ERROR_INVALID_PARAMETER;
+
+ for (attempt = 0; attempt < 5; attempt++)
+ {
+ *table = HeapAlloc( heap, flags, size );
+ if (!*table) return ERROR_NOT_ENOUGH_MEMORY;
+ err = GetExtendedUdpTable( *table, &size, sort, WS_AF_INET, UDP_TABLE_BASIC, 0 );
+ if (!err) break;
+ HeapFree( heap, flags, *table );
+ *table = NULL;
+ if (err != ERROR_INSUFFICIENT_BUFFER) break;
+ }
+ return err;
+}
+
static void unicast_row_fill( MIB_UNICASTIPADDRESS_ROW *row, USHORT fam, void *key, struct nsi_ip_unicast_rw *rw,
struct nsi_ip_unicast_dynamic *dyn, struct nsi_ip_unicast_static *stat )
{
diff --git a/dlls/iphlpapi/ipstats.c b/dlls/iphlpapi/ipstats.c
index 65bf65fec7b..1a71396e388 100644
--- a/dlls/iphlpapi/ipstats.c
+++ b/dlls/iphlpapi/ipstats.c
@@ -200,81 +200,6 @@ static DWORD kstat_get_ui32( kstat_t *ksp, const char *name )
}
#endif
-#if defined(HAVE_SYS_TIHDR_H) && defined(T_OPTMGMT_ACK)
-static int open_streams_mib( const char *proto )
-{
- int fd;
- struct strbuf buf;
- struct request
- {
- struct T_optmgmt_req req_header;
- struct opthdr opt_header;
- } request;
-
- if ((fd = open( "/dev/arp", O_RDWR )) == -1)
- {
- WARN( "could not open /dev/arp: %s\n", strerror(errno) );
- return -1;
- }
- if (proto) ioctl( fd, I_PUSH, proto );
-
- request.req_header.PRIM_type = T_SVR4_OPTMGMT_REQ;
- request.req_header.OPT_length = sizeof(request.opt_header);
- request.req_header.OPT_offset = FIELD_OFFSET( struct request, opt_header );
- request.req_header.MGMT_flags = T_CURRENT;
- request.opt_header.level = MIB2_IP;
- request.opt_header.name = 0;
- request.opt_header.len = 0;
-
- buf.len = sizeof(request);
- buf.buf = (caddr_t)&request;
- if (putmsg( fd, &buf, NULL, 0 ) == -1)
- {
- WARN( "putmsg: %s\n", strerror(errno) );
- close( fd );
- fd = -1;
- }
- return fd;
-}
-
-static void *read_mib_entry( int fd, int level, int name, int *len )
-{
- struct strbuf buf;
- void *data;
- int ret, flags = 0;
-
- struct reply
- {
- struct T_optmgmt_ack ack_header;
- struct opthdr opt_header;
- } reply;
-
- for (;;)
- {
- buf.maxlen = sizeof(reply);
- buf.buf = (caddr_t)&reply;
- if ((ret = getmsg( fd, &buf, NULL, &flags )) < 0) return NULL;
- if (!(ret & MOREDATA)) return NULL;
- if (reply.ack_header.PRIM_type != T_OPTMGMT_ACK) return NULL;
- if (buf.len < sizeof(reply.ack_header)) return NULL;
- if (reply.ack_header.OPT_length < sizeof(reply.opt_header)) return NULL;
-
- if (!(data = HeapAlloc( GetProcessHeap(), 0, reply.opt_header.len ))) return NULL;
- buf.maxlen = reply.opt_header.len;
- buf.buf = (caddr_t)data;
- flags = 0;
- if (getmsg( fd, NULL, &buf, &flags ) >= 0 &&
- reply.opt_header.level == level &&
- reply.opt_header.name == name)
- {
- *len = buf.len;
- return data;
- }
- HeapFree( GetProcessHeap(), 0, data );
- }
-}
-#endif /* HAVE_SYS_TIHDR_H && T_OPTMGMT_ACK */
-
/******************************************************************
* GetUdpStatistics (IPHLPAPI.@)
*
@@ -443,452 +368,3 @@ DWORD WINAPI GetUdpStatistics(PMIB_UDPSTATS stats)
{
return GetUdpStatisticsEx(stats, WS_AF_INET);
}
-
-static void *append_table_row( HANDLE heap, DWORD flags, void *table, DWORD *table_size, DWORD *table_capacity,
- const void *row, DWORD row_size )
-{
- DWORD *num_entries = table; /* this must be the first field */
- if (*num_entries == *table_capacity)
- {
- void *new_table;
- *table_size += *table_capacity * row_size;
- if (!(new_table = HeapReAlloc( heap, flags, table, *table_size )))
- {
- HeapFree( heap, 0, table );
- return NULL;
- }
- num_entries = table = new_table;
- *table_capacity *= 2;
- }
- memcpy( (char *)table + *table_size - (*table_capacity - *num_entries) * row_size, row, row_size );
- (*num_entries)++;
- return table;
-}
-
-struct pid_map
-{
- unsigned int pid;
- unsigned int unix_pid;
-};
-
-static struct pid_map *get_pid_map( unsigned int *num_entries )
-{
- struct pid_map *map;
- unsigned int i = 0, buffer_len = 4096, process_count, pos = 0;
- NTSTATUS ret;
- char *buffer = NULL, *new_buffer;
-
- if (!(buffer = HeapAlloc( GetProcessHeap(), 0, buffer_len ))) return NULL;
-
- for (;;)
- {
- SERVER_START_REQ( list_processes )
- {
- wine_server_set_reply( req, buffer, buffer_len );
- ret = wine_server_call( req );
- buffer_len = reply->info_size;
- process_count = reply->process_count;
- }
- SERVER_END_REQ;
-
- if (ret != STATUS_INFO_LENGTH_MISMATCH) break;
-
- if (!(new_buffer = HeapReAlloc( GetProcessHeap(), 0, buffer, buffer_len )))
- {
- HeapFree( GetProcessHeap(), 0, buffer );
- return NULL;
- }
- buffer = new_buffer;
- }
-
- if (!(map = HeapAlloc( GetProcessHeap(), 0, process_count * sizeof(*map) )))
- {
- HeapFree( GetProcessHeap(), 0, buffer );
- return NULL;
- }
-
- for (i = 0; i < process_count; ++i)
- {
- const struct process_info *process;
-
- pos = (pos + 7) & ~7;
- process = (const struct process_info *)(buffer + pos);
-
- map[i].pid = process->pid;
- map[i].unix_pid = process->unix_pid;
-
- pos += sizeof(struct process_info) + process->name_len;
- pos = (pos + 7) & ~7;
- pos += process->thread_count * sizeof(struct thread_info);
- }
-
- HeapFree( GetProcessHeap(), 0, buffer );
- *num_entries = process_count;
- return map;
-}
-
-static unsigned int find_owning_pid( struct pid_map *map, unsigned int num_entries, UINT_PTR inode )
-{
-#ifdef __linux__
- unsigned int i, len_socket;
- char socket[32];
-
- sprintf( socket, "socket:[%lu]", inode );
- len_socket = strlen( socket );
- for (i = 0; i < num_entries; i++)
- {
- char dir[32];
- struct dirent *dirent;
- DIR *dirfd;
-
- sprintf( dir, "/proc/%u/fd", map[i].unix_pid );
- if ((dirfd = opendir( dir )))
- {
- while ((dirent = readdir( dirfd )))
- {
- char link[sizeof(dirent->d_name) + 32], name[32];
- int len;
-
- sprintf( link, "/proc/%u/fd/%s", map[i].unix_pid, dirent->d_name );
- if ((len = readlink( link, name, sizeof(name) - 1 )) > 0) name[len] = 0;
- if (len == len_socket && !strcmp( socket, name ))
- {
- closedir( dirfd );
- return map[i].pid;
- }
- }
- closedir( dirfd );
- }
- }
- return 0;
-#elif defined(HAVE_LIBPROCSTAT)
- struct procstat *pstat;
- struct kinfo_proc *proc;
- struct filestat_list *fds;
- struct filestat *fd;
- struct sockstat sock;
- unsigned int i, proc_count;
-
- pstat = procstat_open_sysctl();
- if (!pstat) return 0;
-
- for (i = 0; i < num_entries; i++)
- {
- proc = procstat_getprocs( pstat, KERN_PROC_PID, map[i].unix_pid, &proc_count );
- if (!proc || proc_count < 1) continue;
-
- fds = procstat_getfiles( pstat, proc, 0 );
- if (!fds)
- {
- procstat_freeprocs( pstat, proc );
- continue;
- }
-
- STAILQ_FOREACH( fd, fds, next )
- {
- char errbuf[_POSIX2_LINE_MAX];
-
- if (fd->fs_type != PS_FST_TYPE_SOCKET) continue;
-
- procstat_get_socket_info( pstat, fd, &sock, errbuf );
-
- if (sock.so_pcb == inode)
- {
- procstat_freefiles( pstat, fds );
- procstat_freeprocs( pstat, proc );
- procstat_close( pstat );
- return map[i].pid;
- }
- }
-
- procstat_freefiles( pstat, fds );
- procstat_freeprocs( pstat, proc );
- }
-
- procstat_close( pstat );
- return 0;
-#elif defined(HAVE_PROC_PIDINFO)
- struct proc_fdinfo *fds;
- struct socket_fdinfo sock;
- unsigned int i, j, n;
-
- for (i = 0; i < num_entries; i++)
- {
- int fd_len = proc_pidinfo( map[i].unix_pid, PROC_PIDLISTFDS, 0, NULL, 0 );
- if (fd_len <= 0) continue;
-
- fds = HeapAlloc( GetProcessHeap(), 0, fd_len );
- if (!fds) continue;
-
- proc_pidinfo( map[i].unix_pid, PROC_PIDLISTFDS, 0, fds, fd_len );
- n = fd_len / sizeof(struct proc_fdinfo);
- for (j = 0; j < n; j++)
- {
- if (fds[j].proc_fdtype != PROX_FDTYPE_SOCKET) continue;
-
- proc_pidfdinfo( map[i].unix_pid, fds[j].proc_fd, PROC_PIDFDSOCKETINFO, &sock, sizeof(sock) );
- if (sock.psi.soi_pcb == inode)
- {
- HeapFree( GetProcessHeap(), 0, fds );
- return map[i].pid;
- }
- }
-
- HeapFree( GetProcessHeap(), 0, fds );
- }
- return 0;
-#else
- FIXME( "not implemented\n" );
- return 0;
-#endif
-}
-
-static DWORD get_udp_table_sizes( UDP_TABLE_CLASS class, DWORD row_count, DWORD *row_size )
-{
- DWORD table_size;
-
- switch (class)
- {
- case UDP_TABLE_BASIC:
- {
- table_size = FIELD_OFFSET(MIB_UDPTABLE, table[row_count]);
- if (row_size) *row_size = sizeof(MIB_UDPROW);
- break;
- }
- case UDP_TABLE_OWNER_PID:
- {
- table_size = FIELD_OFFSET(MIB_UDPTABLE_OWNER_PID, table[row_count]);
- if (row_size) *row_size = sizeof(MIB_UDPROW_OWNER_PID);
- break;
- }
- case UDP_TABLE_OWNER_MODULE:
- {
- table_size = FIELD_OFFSET(MIB_UDPTABLE_OWNER_MODULE, table[row_count]);
- if (row_size) *row_size = sizeof(MIB_UDPROW_OWNER_MODULE);
- break;
- }
- default:
- ERR("unhandled class %u\n", class);
- return 0;
- }
- return table_size;
-}
-
-static int compare_udp_rows(const void *a, const void *b)
-{
- const MIB_UDPROW *rowA = a;
- const MIB_UDPROW *rowB = b;
- int ret;
-
- if ((ret = rowA->dwLocalAddr - rowB->dwLocalAddr) != 0) return ret;
- return rowA->dwLocalPort - rowB->dwLocalPort;
-}
-
-DWORD build_udp_table( UDP_TABLE_CLASS class, void **tablep, BOOL order, HANDLE heap, DWORD flags,
- DWORD *size )
-{
- MIB_UDPTABLE *table;
- MIB_UDPROW_OWNER_MODULE row;
- DWORD ret = NO_ERROR, count = 16, table_size, row_size;
-
- if (!(table_size = get_udp_table_sizes( class, count, &row_size )))
- return ERROR_INVALID_PARAMETER;
-
- if (!(table = HeapAlloc( heap, flags, table_size )))
- return ERROR_OUTOFMEMORY;
-
- table->dwNumEntries = 0;
- memset( &row, 0, sizeof(row) );
-
-#ifdef __linux__
- {
- FILE *fp;
-
- if ((fp = fopen( "/proc/net/udp", "r" )))
- {
- char buf[512], *ptr;
- struct pid_map *map = NULL;
- unsigned int num_entries = 0;
- int inode;
-
- if (class >= UDP_TABLE_OWNER_PID) map = get_pid_map( &num_entries );
-
- /* skip header line */
- ptr = fgets( buf, sizeof(buf), fp );
- while ((ptr = fgets( buf, sizeof(buf), fp )))
- {
- if (sscanf( ptr, "%*u: %x:%x %*s %*s %*s %*s %*s %*s %*s %d",
- &row.dwLocalAddr, &row.dwLocalPort, &inode ) != 3)
- continue;
- row.dwLocalPort = htons( row.dwLocalPort );
-
- if (class >= UDP_TABLE_OWNER_PID)
- row.dwOwningPid = find_owning_pid( map, num_entries, inode );
- if (class >= UDP_TABLE_OWNER_MODULE)
- {
- row.liCreateTimestamp.QuadPart = 0; /* FIXME */
- row.dwFlags = 0;
- memset( &row.OwningModuleInfo, 0, sizeof(row.OwningModuleInfo) );
- }
- if (!(table = append_table_row( heap, flags, table, &table_size, &count, &row, row_size )))
- break;
- }
- HeapFree( GetProcessHeap(), 0, map );
- fclose( fp );
- }
- else ret = ERROR_NOT_SUPPORTED;
- }
-#elif defined(HAVE_SYS_TIHDR_H) && defined(T_OPTMGMT_ACK)
- {
- void *data;
- int fd, len;
- mib2_udpEntry_t *entry;
-
- if ((fd = open_streams_mib( "udp" )) != -1)
- {
- if ((data = read_mib_entry( fd, MIB2_UDP, MIB2_UDP_ENTRY, &len )))
- {
- for (entry = data; (char *)(entry + 1) <= (char *)data + len; entry++)
- {
- row.dwLocalAddr = entry->udpLocalAddress;
- row.dwLocalPort = htons( entry->udpLocalPort );
- if (!(table = append_table_row( heap, flags, table, &table_size, &count, &row, row_size )))
- break;
- }
- HeapFree( GetProcessHeap(), 0, data );
- }
- close( fd );
- }
- else ret = ERROR_NOT_SUPPORTED;
- }
-#elif defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_STRUCT_XINPGEN)
- {
- size_t Len = 0;
- char *Buf = NULL;
- struct xinpgen *pXIG, *pOrigXIG;
- struct pid_map *pMap = NULL;
- unsigned NumEntries;
-
- if (sysctlbyname ("net.inet.udp.pcblist", NULL, &Len, NULL, 0) < 0)
- {
- ERR ("Failure to read net.inet.udp.pcblist via sysctlbyname!\n");
- ret = ERROR_NOT_SUPPORTED;
- goto done;
- }
-
- Buf = HeapAlloc (GetProcessHeap (), 0, Len);
- if (!Buf)
- {
- ret = ERROR_OUTOFMEMORY;
- goto done;
- }
-
- if (sysctlbyname ("net.inet.udp.pcblist", Buf, &Len, NULL, 0) < 0)
- {
- ERR ("Failure to read net.inet.udp.pcblist via sysctlbyname!\n");
- ret = ERROR_NOT_SUPPORTED;
- goto done;
- }
-
- if (class >= UDP_TABLE_OWNER_PID)
- pMap = get_pid_map( &NumEntries );
-
- /* Might be nothing here; first entry is just a header it seems */
- if (Len <= sizeof (struct xinpgen)) goto done;
-
- pOrigXIG = (struct xinpgen *)Buf;
- pXIG = pOrigXIG;
-
- for (pXIG = (struct xinpgen *)((char *)pXIG + pXIG->xig_len);
- pXIG->xig_len > sizeof (struct xinpgen);
- pXIG = (struct xinpgen *)((char *)pXIG + pXIG->xig_len))
- {
-#if __FreeBSD_version >= 1200026
- struct xinpcb *pINData = (struct xinpcb *)pXIG;
- struct xsocket *pSockData = &pINData->xi_socket;
-#else
- struct inpcb *pINData = &((struct xinpcb *)pXIG)->xi_inp;
- struct xsocket *pSockData = &((struct xinpcb *)pXIG)->xi_socket;
-#endif
-
- /* Ignore sockets for other protocols */
- if (pSockData->xso_protocol != IPPROTO_UDP)
- continue;
-
- /* Ignore PCBs that were freed while generating the data */
- if (pINData->inp_gencnt > pOrigXIG->xig_gen)
- continue;
-
- /* we're only interested in IPv4 addresses */
- if (!(pINData->inp_vflag & INP_IPV4) ||
- (pINData->inp_vflag & INP_IPV6))
- continue;
-
- /* If all 0's, skip it */
- if (!pINData->inp_laddr.s_addr &&
- !pINData->inp_lport)
- continue;
-
- /* Fill in structure details */
- row.dwLocalAddr = pINData->inp_laddr.s_addr;
- row.dwLocalPort = pINData->inp_lport;
- if (class >= UDP_TABLE_OWNER_PID)
- row.dwOwningPid = find_owning_pid( pMap, NumEntries, (UINT_PTR)pSockData->so_pcb );
- if (class >= UDP_TABLE_OWNER_MODULE)
- {
- row.liCreateTimestamp.QuadPart = 0; /* FIXME */
- row.dwFlags = 0;
- row.SpecificPortBind = !(pINData->inp_flags & INP_ANONPORT);
- memset( &row.OwningModuleInfo, 0, sizeof(row.OwningModuleInfo) );
- }
- if (!(table = append_table_row( heap, flags, table, &table_size, &count, &row, row_size )))
- break;
- }
-
- done:
- HeapFree( GetProcessHeap(), 0, pMap );
- HeapFree (GetProcessHeap (), 0, Buf);
- }
-#else
- FIXME( "not implemented\n" );
- ret = ERROR_NOT_SUPPORTED;
-#endif
-
- if (!table) return ERROR_OUTOFMEMORY;
- if (!ret)
- {
- if (order && table->dwNumEntries)
- qsort( table->table, table->dwNumEntries, row_size, compare_udp_rows );
- *tablep = table;
- }
- else HeapFree( heap, flags, table );
- if (size) *size = get_udp_table_sizes( class, count, NULL );
- TRACE( "returning ret %u table %p\n", ret, table );
- return ret;
-}
-
-/******************************************************************
- * AllocateAndGetUdpTableFromStack (IPHLPAPI.@)
- *
- * Get the UDP listener table.
- * Like GetUdpTable(), but allocate the returned table from heap.
- *
- * PARAMS
- * ppUdpTable [Out] pointer into which the MIB_UDPTABLE is
- * allocated and returned.
- * bOrder [In] whether to sort the table
- * heap [In] heap from which the table is allocated
- * flags [In] flags to HeapAlloc
- *
- * RETURNS
- * ERROR_INVALID_PARAMETER if ppUdpTable is NULL, whatever GetUdpTable()
- * returns otherwise.
- */
-DWORD WINAPI AllocateAndGetUdpTableFromStack(PMIB_UDPTABLE *ppUdpTable, BOOL bOrder,
- HANDLE heap, DWORD flags)
-{
- TRACE("table %p, bOrder %d, heap %p, flags 0x%08x\n", ppUdpTable, bOrder, heap, flags);
-
- if (!ppUdpTable) return ERROR_INVALID_PARAMETER;
- return build_udp_table( UDP_TABLE_BASIC, (void **)ppUdpTable, bOrder, heap, flags, NULL );
-}
--
2.23.0
1
0
Aug. 18, 2021
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/iphlpapi/iphlpapi_main.c | 225 +++++++++++++++++-----
dlls/iphlpapi/ipstats.c | 350 ----------------------------------
dlls/iphlpapi/ipstats.h | 33 ----
3 files changed, 175 insertions(+), 433 deletions(-)
delete mode 100644 dlls/iphlpapi/ipstats.h
diff --git a/dlls/iphlpapi/iphlpapi_main.c b/dlls/iphlpapi/iphlpapi_main.c
index e78689d8f11..bcda2b81b6e 100644
--- a/dlls/iphlpapi/iphlpapi_main.c
+++ b/dlls/iphlpapi/iphlpapi_main.c
@@ -43,7 +43,6 @@
#include "windns.h"
#include "iphlpapi.h"
#include "ifenum.h"
-#include "ipstats.h"
#include "ipifcons.h"
#include "fltdefs.h"
#include "ifdef.h"
@@ -3289,81 +3288,207 @@ DWORD WINAPI AllocateAndGetTcpExTableFromStack( void **table, BOOL sort, HANDLE
* Get a table of active UDP connections.
*
* PARAMS
- * pUdpTable [Out] buffer for UDP connections table
- * pdwSize [In/Out] length of output buffer
- * bOrder [In] whether to order the table
- *
- * RETURNS
- * Success: NO_ERROR
- * Failure: error code from winerror.h
+ * table [Out] buffer for UDP connections table
+ * size [In/Out] length of output buffer
+ * sort [In] whether to order the table
*
- * NOTES
- * If pdwSize is less than required, the function will return
- * ERROR_INSUFFICIENT_BUFFER, and *pdwSize will be set to the
- * required byte size.
- * If bOrder is true, the returned table will be sorted, first by
- * local address, then by local port number.
*/
-DWORD WINAPI GetUdpTable(PMIB_UDPTABLE pUdpTable, PDWORD pdwSize, BOOL bOrder)
+DWORD WINAPI GetUdpTable( MIB_UDPTABLE *table, DWORD *size, BOOL sort )
{
- return GetExtendedUdpTable(pUdpTable, pdwSize, bOrder, WS_AF_INET, UDP_TABLE_BASIC, 0);
+ return GetExtendedUdpTable( table, size, sort, WS_AF_INET, UDP_TABLE_BASIC, 0 );
}
/******************************************************************
* GetUdp6Table (IPHLPAPI.@)
*/
-DWORD WINAPI GetUdp6Table(PMIB_UDP6TABLE pUdpTable, PDWORD pdwSize, BOOL bOrder)
+DWORD WINAPI GetUdp6Table( MIB_UDP6TABLE *table, DWORD *size, BOOL sort )
{
- return GetExtendedUdpTable(pUdpTable, pdwSize, bOrder, WS_AF_INET6, UDP_TABLE_BASIC, 0);
+ return GetExtendedUdpTable( table, size, sort, WS_AF_INET6, UDP_TABLE_BASIC, 0 );
}
-/******************************************************************
- * GetExtendedUdpTable (IPHLPAPI.@)
- */
-DWORD WINAPI GetExtendedUdpTable(PVOID pUdpTable, PDWORD pdwSize, BOOL bOrder,
- ULONG ulAf, UDP_TABLE_CLASS TableClass, ULONG Reserved)
+static DWORD udp_table_size( ULONG family, ULONG table_class, DWORD row_count, DWORD *row_size )
{
- DWORD ret, size;
- void *table;
+ switch (table_class)
+ {
+ case UDP_TABLE_BASIC:
+ *row_size = (family == WS_AF_INET) ? sizeof(MIB_UDPROW) : sizeof(MIB_UDP6ROW);
+ return (family == WS_AF_INET) ? FIELD_OFFSET(MIB_UDPTABLE, table[row_count]) :
+ FIELD_OFFSET(MIB_UDP6TABLE, table[row_count]);
- TRACE("pUdpTable %p, pdwSize %p, bOrder %d, ulAf %u, TableClass %u, Reserved %u\n",
- pUdpTable, pdwSize, bOrder, ulAf, TableClass, Reserved);
+ case UDP_TABLE_OWNER_PID:
+ *row_size = (family == WS_AF_INET) ? sizeof(MIB_UDPROW_OWNER_PID) : sizeof(MIB_UDP6ROW_OWNER_PID);
+ return (family == WS_AF_INET) ? FIELD_OFFSET(MIB_UDPTABLE_OWNER_PID, table[row_count]) :
+ FIELD_OFFSET(MIB_UDP6TABLE_OWNER_PID, table[row_count]);
- if (!pdwSize) return ERROR_INVALID_PARAMETER;
+ case UDP_TABLE_OWNER_MODULE:
+ *row_size = (family == WS_AF_INET) ? sizeof(MIB_UDPROW_OWNER_MODULE) : sizeof(MIB_UDP6ROW_OWNER_MODULE);
+ return (family == WS_AF_INET) ? FIELD_OFFSET(MIB_UDPTABLE_OWNER_MODULE, table[row_count]) :
+ FIELD_OFFSET(MIB_UDP6TABLE_OWNER_MODULE, table[row_count]);
- if (TableClass == UDP_TABLE_OWNER_MODULE)
- FIXME("UDP_TABLE_OWNER_MODULE not fully supported\n");
+ default:
+ ERR( "unhandled class %u\n", table_class );
+ return 0;
+ }
+}
- switch (ulAf)
+static void udp_row_fill( void *table, DWORD num, ULONG family, ULONG table_class,
+ struct nsi_udp_endpoint_key *key,
+ struct nsi_udp_endpoint_static *stat )
+{
+ if (family == WS_AF_INET)
{
- case WS_AF_INET:
- ret = build_udp_table(TableClass, &table, bOrder, GetProcessHeap(), 0, &size);
- break;
-
- case WS_AF_INET6:
- ret = build_udp6_table(TableClass, &table, bOrder, GetProcessHeap(), 0, &size);
- break;
-
+ switch (table_class)
+ {
+ case UDP_TABLE_BASIC:
+ {
+ MIB_UDPROW *row = ((MIB_UDPTABLE *)table)->table + num;
+ row->dwLocalAddr = key->local.Ipv4.sin_addr.WS_s_addr;
+ row->dwLocalPort = key->local.Ipv4.sin_port;
+ return;
+ }
+ case UDP_TABLE_OWNER_PID:
+ {
+ MIB_UDPROW_OWNER_PID *row = ((MIB_UDPTABLE_OWNER_PID *)table)->table + num;
+ row->dwLocalAddr = key->local.Ipv4.sin_addr.WS_s_addr;
+ row->dwLocalPort = key->local.Ipv4.sin_port;
+ row->dwOwningPid = stat->pid;
+ return;
+ }
+ case UDP_TABLE_OWNER_MODULE:
+ {
+ MIB_UDPROW_OWNER_MODULE *row = ((MIB_UDPTABLE_OWNER_MODULE *)table)->table + num;
+ row->dwLocalAddr = key->local.Ipv4.sin_addr.WS_s_addr;
+ row->dwLocalPort = key->local.Ipv4.sin_port;
+ row->dwOwningPid = stat->pid;
+ row->liCreateTimestamp.QuadPart = stat->create_time;
+ row->dwFlags = stat->flags;
+ row->OwningModuleInfo[0] = stat->mod_info;
+ memset( row->OwningModuleInfo + 1, 0, sizeof(row->OwningModuleInfo) - sizeof(row->OwningModuleInfo[0]) );
+ return;
+ }
default:
- FIXME("ulAf = %u not supported\n", ulAf);
- ret = ERROR_NOT_SUPPORTED;
+ ERR( "Unknown class %d\n", table_class );
+ return;
+ }
}
+ else
+ {
+ switch (table_class)
+ {
+ case UDP_TABLE_BASIC:
+ {
+ MIB_UDP6ROW *row = ((MIB_UDP6TABLE *)table)->table + num;
+ memcpy( &row->dwLocalAddr, &key->local.Ipv6.sin6_addr, sizeof(row->dwLocalAddr) );
+ row->dwLocalScopeId = key->local.Ipv6.sin6_scope_id;
+ row->dwLocalPort = key->local.Ipv6.sin6_port;
+ return;
+ }
+ case UDP_TABLE_OWNER_PID:
+ {
+ MIB_UDP6ROW_OWNER_PID *row = ((MIB_UDP6TABLE_OWNER_PID *)table)->table + num;
+ memcpy( &row->ucLocalAddr, &key->local.Ipv6.sin6_addr, sizeof(row->ucLocalAddr) );
+ row->dwLocalScopeId = key->local.Ipv6.sin6_scope_id;
+ row->dwLocalPort = key->local.Ipv6.sin6_port;
+ row->dwOwningPid = stat->pid;
+ return;
+ }
+ case UDP_TABLE_OWNER_MODULE:
+ {
+ MIB_UDP6ROW_OWNER_MODULE *row = ((MIB_UDP6TABLE_OWNER_MODULE *)table)->table + num;
+ memcpy( &row->ucLocalAddr, &key->local.Ipv6.sin6_addr, sizeof(row->ucLocalAddr) );
+ row->dwLocalScopeId = key->local.Ipv6.sin6_scope_id;
+ row->dwLocalPort = key->local.Ipv6.sin6_port;
+ row->dwOwningPid = stat->pid;
+ row->liCreateTimestamp.QuadPart = stat->create_time;
+ row->dwFlags = stat->flags;
+ row->OwningModuleInfo[0] = stat->mod_info;
+ memset( row->OwningModuleInfo + 1, 0, sizeof(row->OwningModuleInfo) - sizeof(row->OwningModuleInfo[0]) );
+ return;
+ }
+ default:
+ ERR( "Unknown class %d\n", table_class );
+ return;
+ }
+ }
+ ERR( "Unknown family %d\n", family );
+ return;
+}
- if (ret)
- return ret;
+static int udp_row_cmp( const void *a, const void *b )
+{
+ const MIB_UDPROW *rowA = a;
+ const MIB_UDPROW *rowB = b;
+ int ret;
+
+ if ((ret = RtlUlongByteSwap( rowA->dwLocalAddr ) - RtlUlongByteSwap( rowB->dwLocalAddr )) != 0) return ret;
+ return RtlUshortByteSwap( rowA->dwLocalPort ) - RtlUshortByteSwap( rowB->dwLocalPort );
+}
+
+static int udp6_row_cmp( const void *a, const void *b )
+{
+ const MIB_UDP6ROW *rowA = a;
+ const MIB_UDP6ROW *rowB = b;
+ int ret;
+
+ if ((ret = memcmp( &rowA->dwLocalAddr, &rowB->dwLocalAddr, sizeof(rowA->dwLocalAddr) )) != 0) return ret;
+ if ((ret = rowA->dwLocalScopeId - rowB->dwLocalScopeId) != 0) return ret;
+ return RtlUshortByteSwap( rowA->dwLocalPort ) - RtlUshortByteSwap( rowB->dwLocalPort );
+}
+
+/******************************************************************
+ * GetExtendedUdpTable (IPHLPAPI.@)
+ */
+DWORD WINAPI GetExtendedUdpTable( void *table, DWORD *size, BOOL sort, ULONG family,
+ UDP_TABLE_CLASS table_class, ULONG reserved )
+{
+ DWORD err, count, needed, i, num = 0, row_size = 0;
+ struct nsi_udp_endpoint_key *key;
+ struct nsi_udp_endpoint_static *stat;
+
+ TRACE( "table %p, size %p, sort %d, family %u, table_class %u, reserved %u\n",
+ table, size, sort, family, table_class, reserved );
+
+ if (!size || !ip_module_id( family )) return ERROR_INVALID_PARAMETER;
+
+ err = NsiAllocateAndGetTable( 1, &NPI_MS_UDP_MODULEID, NSI_UDP_ENDPOINT_TABLE, (void **)&key, sizeof(*key),
+ NULL, 0, NULL, 0, (void **)&stat, sizeof(*stat), &count, 0 );
+ if (err) return err;
+
+ for (i = 0; i < count; i++)
+ if (key[i].local.si_family == family)
+ num++;
- if (!pUdpTable || *pdwSize < size)
+ needed = udp_table_size( family, table_class, num, &row_size );
+ if (!table || *size < needed)
{
- *pdwSize = size;
- ret = ERROR_INSUFFICIENT_BUFFER;
+ *size = needed;
+ err = ERROR_INSUFFICIENT_BUFFER;
}
else
{
- *pdwSize = size;
- memcpy(pUdpTable, table, size);
+ *size = needed;
+ *(DWORD *)table = num;
+ num = 0;
+ for (i = 0; i < count; i++)
+ {
+ if (key[i].local.si_family != family) continue;
+ udp_row_fill( table, num++, family, table_class, key + i, stat + i );
+ }
+ }
+
+ if (!err && sort)
+ {
+ int (*fn)(const void *, const void *);
+ DWORD offset = udp_table_size( family, table_class, 0, &row_size );
+
+ if (family == WS_AF_INET) fn = udp_row_cmp;
+ else fn = udp6_row_cmp;
+
+ qsort( (BYTE *)table + offset, num, row_size, fn );
}
- HeapFree(GetProcessHeap(), 0, table);
- return ret;
+
+ NsiFreeTable( key, NULL, NULL, stat );
+ return err;
}
static void unicast_row_fill( MIB_UNICASTIPADDRESS_ROW *row, USHORT fam, void *key, struct nsi_ip_unicast_rw *rw,
diff --git a/dlls/iphlpapi/ipstats.c b/dlls/iphlpapi/ipstats.c
index 326db56f5bc..65bf65fec7b 100644
--- a/dlls/iphlpapi/ipstats.c
+++ b/dlls/iphlpapi/ipstats.c
@@ -158,7 +158,6 @@
#include "winsock2.h"
#include "ws2ipdef.h"
#include "ifenum.h"
-#include "ipstats.h"
#include "iphlpapi.h"
#include "wine/debug.h"
@@ -868,355 +867,6 @@ DWORD build_udp_table( UDP_TABLE_CLASS class, void **tablep, BOOL order, HANDLE
return ret;
}
-static DWORD get_udp6_table_sizes( UDP_TABLE_CLASS class, DWORD row_count, DWORD *row_size )
-{
- DWORD table_size;
-
- switch (class)
- {
- case UDP_TABLE_BASIC:
- {
- table_size = FIELD_OFFSET(MIB_UDP6TABLE, table[row_count]);
- if (row_size) *row_size = sizeof(MIB_UDP6ROW);
- break;
- }
- case UDP_TABLE_OWNER_PID:
- {
- table_size = FIELD_OFFSET(MIB_UDP6TABLE_OWNER_PID, table[row_count]);
- if (row_size) *row_size = sizeof(MIB_UDP6ROW_OWNER_PID);
- break;
- }
- case UDP_TABLE_OWNER_MODULE:
- {
- table_size = FIELD_OFFSET(MIB_UDP6TABLE_OWNER_MODULE, table[row_count]);
- if (row_size) *row_size = sizeof(MIB_UDP6ROW_OWNER_MODULE);
- break;
- }
- default:
- ERR("unhandled class %u\n", class);
- return 0;
- }
- return table_size;
-}
-
-static int compare_udp6_rows(const void *a, const void *b)
-{
- const MIB_UDP6ROW *rowA = a;
- const MIB_UDP6ROW *rowB = b;
- int ret;
-
- if ((ret = memcmp(&rowA->dwLocalAddr, &rowB->dwLocalAddr, sizeof(rowA->dwLocalAddr))) != 0) return ret;
- if ((ret = rowA->dwLocalScopeId - rowB->dwLocalScopeId) != 0) return ret;
- return rowA->dwLocalPort - rowB->dwLocalPort;
-}
-
-#if defined(__linux__) || (defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_STRUCT_XINPGEN))
-struct ipv6_addr_scope
-{
- IN6_ADDR addr;
- DWORD scope;
-};
-
-static struct ipv6_addr_scope *get_ipv6_addr_scope_table(unsigned int *size)
-{
- struct ipv6_addr_scope *table = NULL;
- unsigned int table_size = 0;
-#ifdef __linux__
- char buf[512], *ptr;
- FILE *fp;
-#elif defined(HAVE_GETIFADDRS)
- struct ifaddrs *addrs, *cur;
-#endif
-
- if (!(table = HeapAlloc( GetProcessHeap(), 0, sizeof(table[0]) )))
- return NULL;
-
-#ifdef __linux__
- if (!(fp = fopen( "/proc/net/if_inet6", "r" )))
- goto failed;
-
- while ((ptr = fgets( buf, sizeof(buf), fp )))
- {
- WORD a[8];
- DWORD scope;
- struct ipv6_addr_scope *new_table;
- struct ipv6_addr_scope *entry;
- unsigned int i;
-
- if (sscanf( ptr, "%4hx%4hx%4hx%4hx%4hx%4hx%4hx%4hx %*s %*s %x",
- &a[0], &a[1], &a[2], &a[3], &a[4], &a[5], &a[6], &a[7], &scope ) != 9)
- continue;
-
- table_size++;
- if (!(new_table = HeapReAlloc( GetProcessHeap(), 0, table, table_size * sizeof(table[0]) )))
- {
- fclose(fp);
- goto failed;
- }
-
- table = new_table;
- entry = &table[table_size - 1];
-
- i = 0;
- while (i < 8)
- {
- entry->addr.u.Word[i] = htons(a[i]);
- i++;
- }
-
- entry->scope = htons(scope);
- }
-
- fclose(fp);
-#elif defined(HAVE_GETIFADDRS)
- if (getifaddrs(&addrs) == -1)
- goto failed;
-
- for (cur = addrs; cur; cur = cur->ifa_next)
- {
- struct sockaddr_in6 *sin6;
- struct ipv6_addr_scope *new_table;
- struct ipv6_addr_scope *entry;
-
- if (cur->ifa_addr->sa_family != AF_INET6)
- continue;
-
- sin6 = (struct sockaddr_in6 *)cur->ifa_addr;
-
- table_size++;
- if (!(new_table = HeapReAlloc( GetProcessHeap(), 0, table, table_size * sizeof(table[0]) )))
- {
- freeifaddrs(addrs);
- goto failed;
- }
-
- table = new_table;
- entry = &table[table_size - 1];
-
- memcpy(&entry->addr, &sin6->sin6_addr, sizeof(entry->addr));
- entry->scope = sin6->sin6_scope_id;
- }
-
- freeifaddrs(addrs);
-#else
- FIXME( "not implemented\n" );
- goto failed;
-#endif
-
- *size = table_size;
- return table;
-
-failed:
- HeapFree( GetProcessHeap(), 0, table );
- return NULL;
-}
-
-static DWORD find_ipv6_addr_scope(const IN6_ADDR *addr, const struct ipv6_addr_scope *table, unsigned int size)
-{
- const BYTE multicast_scope_mask = 0x0F;
- const BYTE multicast_scope_shift = 0;
- unsigned int i = 0;
-
- if (WS_IN6_IS_ADDR_UNSPECIFIED(addr))
- return 0;
-
- if (WS_IN6_IS_ADDR_MULTICAST(addr))
- return htons((addr->u.Byte[1] & multicast_scope_mask) >> multicast_scope_shift);
-
- if (!table)
- return -1;
-
- while (i < size)
- {
- if (memcmp(&table[i].addr, addr, sizeof(table[i].addr)) == 0)
- return table[i].scope;
- i++;
- }
-
- return -1;
-}
-#endif
-
-DWORD build_udp6_table( UDP_TABLE_CLASS class, void **tablep, BOOL order, HANDLE heap, DWORD flags,
- DWORD *size )
-{
- MIB_UDP6TABLE *table;
- MIB_UDP6ROW_OWNER_MODULE row;
- DWORD ret = NO_ERROR, count = 16, table_size, row_size;
-
- if (!(table_size = get_udp6_table_sizes( class, count, &row_size )))
- return ERROR_INVALID_PARAMETER;
-
- if (!(table = HeapAlloc( heap, flags, table_size )))
- return ERROR_OUTOFMEMORY;
-
- table->dwNumEntries = 0;
- memset( &row, 0, sizeof(row) );
-
-#ifdef __linux__
- {
- FILE *fp;
-
- if ((fp = fopen( "/proc/net/udp6", "r" )))
- {
- char buf[512], *ptr;
- struct pid_map *map = NULL;
- unsigned int num_entries = 0;
- struct ipv6_addr_scope *addr_scopes;
- unsigned int addr_scopes_size = 0;
- int inode;
-
- addr_scopes = get_ipv6_addr_scope_table(&addr_scopes_size);
-
- if (class >= UDP_TABLE_OWNER_PID) map = get_pid_map( &num_entries );
-
- /* skip header line */
- ptr = fgets( buf, sizeof(buf), fp );
- while ((ptr = fgets( buf, sizeof(buf), fp )))
- {
- DWORD *local_addr = (DWORD *)&row.ucLocalAddr;
-
- if (sscanf( ptr, "%*u: %8x%8x%8x%8x:%x %*s %*s %*s %*s %*s %*s %*s %d",
- &local_addr[0], &local_addr[1], &local_addr[2], &local_addr[3],
- &row.dwLocalPort, &inode ) != 6)
- continue;
- row.dwLocalScopeId = find_ipv6_addr_scope((const IN6_ADDR *)&row.ucLocalAddr, addr_scopes, addr_scopes_size);
- row.dwLocalPort = htons( row.dwLocalPort );
-
- if (class >= UDP_TABLE_OWNER_PID)
- row.dwOwningPid = find_owning_pid( map, num_entries, inode );
- if (class >= UDP_TABLE_OWNER_MODULE)
- {
- row.liCreateTimestamp.QuadPart = 0; /* FIXME */
- row.dwFlags = 0;
- memset( &row.OwningModuleInfo, 0, sizeof(row.OwningModuleInfo) );
- }
- if (!(table = append_table_row( heap, flags, table, &table_size, &count, &row, row_size )))
- break;
- }
- HeapFree( GetProcessHeap(), 0, map );
- HeapFree( GetProcessHeap(), 0, addr_scopes );
- fclose( fp );
- }
- else ret = ERROR_NOT_SUPPORTED;
- }
-#elif defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_STRUCT_XINPGEN)
- {
- static const char zero[sizeof(IN6_ADDR)] = {0};
-
- size_t len = 0;
- char *buf = NULL;
- struct xinpgen *xig, *orig_xig;
- struct pid_map *map = NULL;
- unsigned num_entries;
- struct ipv6_addr_scope *addr_scopes = NULL;
- unsigned int addr_scopes_size = 0;
-
- if (sysctlbyname( "net.inet.udp.pcblist", NULL, &len, NULL, 0 ) < 0)
- {
- ERR( "Failure to read net.inet.udp.pcblist via sysctlbyname!\n" );
- ret = ERROR_NOT_SUPPORTED;
- goto done;
- }
-
- buf = HeapAlloc( GetProcessHeap(), 0, len );
- if (!buf)
- {
- ret = ERROR_OUTOFMEMORY;
- goto done;
- }
-
- if (sysctlbyname( "net.inet.udp.pcblist", buf, &len, NULL, 0 ) < 0)
- {
- ERR ("Failure to read net.inet.udp.pcblist via sysctlbyname!\n");
- ret = ERROR_NOT_SUPPORTED;
- goto done;
- }
-
- addr_scopes = get_ipv6_addr_scope_table( &addr_scopes_size );
- if (!addr_scopes)
- {
- ret = ERROR_OUTOFMEMORY;
- goto done;
- }
-
- if (class >= UDP_TABLE_OWNER_PID) map = get_pid_map( &num_entries );
-
- /* Might be nothing here; first entry is just a header it seems */
- if (len <= sizeof (struct xinpgen)) goto done;
-
- orig_xig = (struct xinpgen *)buf;
- xig = orig_xig;
-
- for (xig = (struct xinpgen *)((char *)xig + xig->xig_len);
- xig->xig_len > sizeof (struct xinpgen);
- xig = (struct xinpgen *)((char *)xig + xig->xig_len))
- {
-#if __FreeBSD_version >= 1200026
- struct xinpcb *in = (struct xinpcb *)xig;
- struct xsocket *sock = &in->xi_socket;
-#else
- struct inpcb *in = &((struct xinpcb *)xig)->xi_inp;
- struct xsocket *sock = &((struct xinpcb *)xig)->xi_socket;
-#endif
-
- /* Ignore sockets for other protocols */
- if (sock->xso_protocol != IPPROTO_UDP)
- continue;
-
- /* Ignore PCBs that were freed while generating the data */
- if (in->inp_gencnt > orig_xig->xig_gen)
- continue;
-
- /* we're only interested in IPv6 addresses */
- if (!(in->inp_vflag & INP_IPV6) ||
- (in->inp_vflag & INP_IPV4))
- continue;
-
- /* If all 0's, skip it */
- if (!memcmp( &in->in6p_laddr.s6_addr, zero, sizeof(zero) ) && !in->inp_lport)
- continue;
-
- /* Fill in structure details */
- memcpy(row.ucLocalAddr, &in->in6p_laddr.s6_addr, sizeof(row.ucLocalAddr));
- row.dwLocalPort = in->inp_lport;
- row.dwLocalScopeId = find_ipv6_addr_scope((const IN6_ADDR *)&row.ucLocalAddr, addr_scopes, addr_scopes_size);
- if (class >= UDP_TABLE_OWNER_PID)
- row.dwOwningPid = find_owning_pid( map, num_entries, (UINT_PTR)sock->so_pcb );
- if (class >= UDP_TABLE_OWNER_MODULE)
- {
- row.liCreateTimestamp.QuadPart = 0; /* FIXME */
- row.dwFlags = 0;
- row.SpecificPortBind = !(in->inp_flags & INP_ANONPORT);
- memset( &row.OwningModuleInfo, 0, sizeof(row.OwningModuleInfo) );
- }
- if (!(table = append_table_row( heap, flags, table, &table_size, &count, &row, row_size )))
- break;
- }
-
- done:
- HeapFree( GetProcessHeap(), 0, map );
- HeapFree( GetProcessHeap(), 0, buf );
- HeapFree( GetProcessHeap(), 0, addr_scopes );
- }
-#else
- FIXME( "not implemented\n" );
- ret = ERROR_NOT_SUPPORTED;
-#endif
-
- if (!table) return ERROR_OUTOFMEMORY;
- if (!ret)
- {
- if (order && table->dwNumEntries)
- qsort( table->table, table->dwNumEntries, row_size, compare_udp6_rows );
- *tablep = table;
- }
- else HeapFree( heap, flags, table );
- if (size) *size = get_udp6_table_sizes( class, count, NULL );
- TRACE( "returning ret %u table %p\n", ret, table );
- return ret;
-}
-
/******************************************************************
* AllocateAndGetUdpTableFromStack (IPHLPAPI.@)
*
diff --git a/dlls/iphlpapi/ipstats.h b/dlls/iphlpapi/ipstats.h
deleted file mode 100644
index 60398609207..00000000000
--- a/dlls/iphlpapi/ipstats.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/* ipstats.h
- * Copyright (C) 2003,2006 Juan Lang
- *
- * 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
- *
- * This module implements functions that get network-related statistics.
- * It's meant to hide some platform-specificisms.
- */
-#ifndef WINE_IPSTATS_H_
-#define WINE_IPSTATS_H_
-
-#include <stdarg.h>
-
-#include "windef.h"
-#include "winbase.h"
-#include "iprtrmib.h"
-
-DWORD build_udp_table(UDP_TABLE_CLASS, void **, BOOL, HANDLE, DWORD, DWORD *) DECLSPEC_HIDDEN;
-DWORD build_udp6_table(UDP_TABLE_CLASS, void **, BOOL, HANDLE, DWORD, DWORD *) DECLSPEC_HIDDEN;
-
-#endif /* ndef WINE_IPSTATS_H_ */
--
2.23.0
1
0
Aug. 18, 2021
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/nsi/tests/nsi.c | 65 ++++++
dlls/nsiproxy.sys/Makefile.in | 3 +-
dlls/nsiproxy.sys/nsi.c | 1 +
dlls/nsiproxy.sys/nsiproxy_private.h | 19 ++
dlls/nsiproxy.sys/tcp.c | 20 +-
dlls/nsiproxy.sys/udp.c | 291 +++++++++++++++++++++++++++
include/wine/nsi.h | 18 ++
7 files changed, 400 insertions(+), 17 deletions(-)
create mode 100644 dlls/nsiproxy.sys/udp.c
diff --git a/dlls/nsi/tests/nsi.c b/dlls/nsi/tests/nsi.c
index b5352e2b121..ce09bbf8a22 100644
--- a/dlls/nsi/tests/nsi.c
+++ b/dlls/nsi/tests/nsi.c
@@ -938,6 +938,68 @@ static void test_tcp_tables( int family, int table_type )
winetest_pop_context();
}
+static void test_udp_tables( int family )
+{
+ DWORD i, err, count, size;
+ struct nsi_udp_endpoint_key *keys;
+ struct nsi_udp_endpoint_static *stat;
+ MIB_UDPTABLE_OWNER_MODULE *table;
+ MIB_UDP6TABLE_OWNER_MODULE *table6;
+ MIB_UDPROW_OWNER_MODULE *row;
+ MIB_UDP6ROW_OWNER_MODULE *row6;
+
+ winetest_push_context( "%s", family == AF_INET ? "AF_INET" : "AF_INET6" );
+
+ err = NsiAllocateAndGetTable( 1, &NPI_MS_UDP_MODULEID, NSI_UDP_ENDPOINT_TABLE, (void **)&keys, sizeof(*keys),
+ NULL, 0, NULL, 0, (void **)&stat, sizeof(*stat), &count, 0 );
+ ok( !err, "got %x\n", err );
+
+ size = 0;
+ err = GetExtendedUdpTable( NULL, &size, 0, family, UDP_TABLE_OWNER_MODULE, 0 );
+ size *= 2;
+ table = malloc( size );
+ table6 = (MIB_UDP6TABLE_OWNER_MODULE *)table;
+ err = GetExtendedUdpTable( table, &size, 0, family, UDP_TABLE_OWNER_MODULE, 0 );
+ ok( !err, "got %d\n", err );
+
+ row = table->table;
+ row6 = table6->table;
+
+ for (i = 0; i < count; i++)
+ {
+ if (keys[i].local.si_family != family) continue;
+
+ if (family == AF_INET)
+ {
+ ok( unstable( row->dwLocalAddr == keys[i].local.Ipv4.sin_addr.s_addr ), "%08x vs %08x\n",
+ row->dwLocalAddr, keys[i].local.Ipv4.sin_addr.s_addr );
+ ok( unstable( row->dwLocalPort == keys[i].local.Ipv4.sin_port ), "%d vs %d\n",
+ row->dwLocalPort, keys[i].local.Ipv4.sin_port );
+ ok( unstable( row->dwOwningPid == stat[i].pid ), "%x vs %x\n", row->dwOwningPid, stat[i].pid );
+ ok( unstable( row->liCreateTimestamp.QuadPart == stat[i].create_time ), "mismatch\n" );
+ ok( unstable( row->dwFlags == stat[i].flags ), "%x vs %x\n", row->dwFlags, stat[i].flags );
+ ok( unstable( row->OwningModuleInfo[0] == stat[i].mod_info ), "mismatch\n");
+ row++;
+ }
+ else if (family == AF_INET6)
+ {
+ ok( unstable( !memcmp( row6->ucLocalAddr, keys[i].local.Ipv6.sin6_addr.s6_addr, sizeof(IN6_ADDR) ) ),
+ "mismatch\n" );
+ ok( unstable( row6->dwLocalScopeId == keys[i].local.Ipv6.sin6_scope_id ), "%x vs %x\n",
+ row6->dwLocalScopeId, keys[i].local.Ipv6.sin6_scope_id );
+ ok( unstable( row6->dwLocalPort == keys[i].local.Ipv6.sin6_port ), "%d vs %d\n",
+ row6->dwLocalPort, keys[i].local.Ipv6.sin6_port );
+ ok( unstable( row6->dwOwningPid == stat[i].pid ), "%x vs %x\n", row6->dwOwningPid, stat[i].pid );
+ ok( unstable( row6->liCreateTimestamp.QuadPart == stat[i].create_time ), "mismatch\n" );
+ ok( unstable( row6->dwFlags == stat[i].flags ), "%x vs %x\n", row6->dwFlags, stat[i].flags );
+ ok( unstable( row6->OwningModuleInfo[0] == stat[i].mod_info ), "mismatch\n");
+ row6++;
+ }
+ }
+ free( table );
+ NsiFreeTable( keys, NULL, NULL, stat );
+ winetest_pop_context();
+}
START_TEST( nsi )
{
@@ -967,4 +1029,7 @@ START_TEST( nsi )
test_tcp_tables( AF_INET6, TCP_TABLE_OWNER_MODULE_ALL );
test_tcp_tables( AF_INET6, TCP_TABLE_OWNER_MODULE_CONNECTIONS );
test_tcp_tables( AF_INET6, TCP_TABLE_OWNER_MODULE_LISTENER );
+
+ test_udp_tables( AF_INET );
+ test_udp_tables( AF_INET6 );
}
diff --git a/dlls/nsiproxy.sys/Makefile.in b/dlls/nsiproxy.sys/Makefile.in
index 3f8965236ba..cee4b72c33f 100644
--- a/dlls/nsiproxy.sys/Makefile.in
+++ b/dlls/nsiproxy.sys/Makefile.in
@@ -7,4 +7,5 @@ C_SRCS = \
ip.c \
ndis.c \
nsi.c \
- tcp.c
+ tcp.c \
+ udp.c
diff --git a/dlls/nsiproxy.sys/nsi.c b/dlls/nsiproxy.sys/nsi.c
index ef57c65ce4d..e29446abb50 100644
--- a/dlls/nsiproxy.sys/nsi.c
+++ b/dlls/nsiproxy.sys/nsi.c
@@ -41,6 +41,7 @@ static const struct module *modules[] =
&ipv4_module,
&ipv6_module,
&tcp_module,
+ &udp_module,
};
static const struct module_table *get_module_table( const NPI_MODULEID *id, DWORD table )
diff --git a/dlls/nsiproxy.sys/nsiproxy_private.h b/dlls/nsiproxy.sys/nsiproxy_private.h
index 17e0189b378..7dd8748e3f7 100644
--- a/dlls/nsiproxy.sys/nsiproxy_private.h
+++ b/dlls/nsiproxy.sys/nsiproxy_private.h
@@ -92,6 +92,24 @@ static inline BOOL convert_index_to_luid( DWORD index, NET_LUID *luid )
return !nsi_get_parameter_ex( ¶ms );
}
+struct ipv6_addr_scope
+{
+ IN6_ADDR addr;
+ DWORD scope;
+};
+
+struct ipv6_addr_scope *get_ipv6_addr_scope_table( unsigned int *size ) DECLSPEC_HIDDEN;
+DWORD find_ipv6_addr_scope( const IN6_ADDR *addr, const struct ipv6_addr_scope *table, unsigned int size ) DECLSPEC_HIDDEN;
+
+struct pid_map
+{
+ unsigned int pid;
+ unsigned int unix_pid;
+};
+
+struct pid_map *get_pid_map( unsigned int *num_entries ) DECLSPEC_HIDDEN;
+unsigned int find_owning_pid( struct pid_map *map, unsigned int num_entries, UINT_PTR inode ) DECLSPEC_HIDDEN;
+
struct module_table
{
DWORD table;
@@ -116,3 +134,4 @@ extern const struct module ndis_module DECLSPEC_HIDDEN;
extern const struct module ipv4_module DECLSPEC_HIDDEN;
extern const struct module ipv6_module DECLSPEC_HIDDEN;
extern const struct module tcp_module DECLSPEC_HIDDEN;
+extern const struct module udp_module DECLSPEC_HIDDEN;
diff --git a/dlls/nsiproxy.sys/tcp.c b/dlls/nsiproxy.sys/tcp.c
index 27f85ee3104..3d0f3a67dd7 100644
--- a/dlls/nsiproxy.sys/tcp.c
+++ b/dlls/nsiproxy.sys/tcp.c
@@ -230,13 +230,7 @@ static inline MIB_TCP_STATE tcp_state_to_mib_state( int state )
}
}
-struct ipv6_addr_scope
-{
- IN6_ADDR addr;
- DWORD scope;
-};
-
-static struct ipv6_addr_scope *get_ipv6_addr_scope_table( unsigned int *size )
+struct ipv6_addr_scope *get_ipv6_addr_scope_table( unsigned int *size )
{
struct ipv6_addr_scope *table = NULL;
unsigned int table_size = 0, num = 0;
@@ -323,7 +317,7 @@ failed:
return NULL;
}
-static DWORD find_ipv6_addr_scope( const IN6_ADDR *addr, const struct ipv6_addr_scope *table, unsigned int size )
+DWORD find_ipv6_addr_scope( const IN6_ADDR *addr, const struct ipv6_addr_scope *table, unsigned int size )
{
const BYTE multicast_scope_mask = 0x0F;
const BYTE multicast_scope_shift = 0;
@@ -343,13 +337,7 @@ static DWORD find_ipv6_addr_scope( const IN6_ADDR *addr, const struct ipv6_addr_
return -1;
}
-struct pid_map
-{
- unsigned int pid;
- unsigned int unix_pid;
-};
-
-static struct pid_map *get_pid_map( unsigned int *num_entries )
+struct pid_map *get_pid_map( unsigned int *num_entries )
{
struct pid_map *map;
unsigned int i = 0, buffer_len = 4096, process_count, pos = 0;
@@ -405,7 +393,7 @@ static struct pid_map *get_pid_map( unsigned int *num_entries )
return map;
}
-static unsigned int find_owning_pid( struct pid_map *map, unsigned int num_entries, UINT_PTR inode )
+unsigned int find_owning_pid( struct pid_map *map, unsigned int num_entries, UINT_PTR inode )
{
#ifdef __linux__
unsigned int i, len_socket;
diff --git a/dlls/nsiproxy.sys/udp.c b/dlls/nsiproxy.sys/udp.c
new file mode 100644
index 00000000000..454aefe95aa
--- /dev/null
+++ b/dlls/nsiproxy.sys/udp.c
@@ -0,0 +1,291 @@
+/*
+ * nsiproxy.sys udp module
+ *
+ * Copyright 2003, 2006, 2011 Juan Lang
+ * Copyright 2021 Huw Davies
+ *
+ * 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
+ */
+#include "config.h"
+#include <stdarg.h>
+
+#ifdef HAVE_SYS_SYSCTL_H
+#include <sys/sysctl.h>
+#endif
+
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+#ifdef HAVE_SYS_SOCKETVAR_H
+#include <sys/socketvar.h>
+#endif
+
+#ifdef HAVE_NETINET_IP_H
+#include <netinet/ip.h>
+#endif
+
+#ifdef HAVE_NETINET_IP_VAR_H
+#include <netinet/ip_var.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_PCB_H
+#include <netinet/in_pcb.h>
+#endif
+
+#ifdef HAVE_NETINET_UDP_H
+#include <netinet/udp.h>
+#endif
+
+#ifdef HAVE_NETINET_UDP_VAR_H
+#include <netinet/udp_var.h>
+#endif
+
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
+#include "windef.h"
+#include "winbase.h"
+#include "winternl.h"
+#define USE_WS_PREFIX
+#include "winsock2.h"
+#include "ifdef.h"
+#include "netiodef.h"
+#include "ws2ipdef.h"
+#include "udpmib.h"
+#include "wine/heap.h"
+#include "wine/nsi.h"
+#include "wine/debug.h"
+#include "wine/server.h"
+
+#include "nsiproxy_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(nsi);
+
+static NTSTATUS udp_endpoint_enumerate_all( void *key_data, DWORD key_size, void *rw_data, DWORD rw_size,
+ void *dynamic_data, DWORD dynamic_size,
+ void *static_data, DWORD static_size, DWORD_PTR *count )
+{
+ DWORD num = 0;
+ NTSTATUS status = STATUS_SUCCESS;
+ BOOL want_data = key_size || rw_size || dynamic_size || static_size;
+ struct nsi_udp_endpoint_key key, *key_out = key_data;
+ struct nsi_udp_endpoint_static stat, *stat_out = static_data;
+ struct ipv6_addr_scope *addr_scopes = NULL;
+ unsigned int addr_scopes_size = 0, pid_map_size = 0;
+ struct pid_map *pid_map = NULL;
+
+ TRACE( "%p %d %p %d %p %d %p %d %p\n", key_data, key_size, rw_data, rw_size,
+ dynamic_data, dynamic_size, static_data, static_size, count );
+
+#ifdef __linux__
+ {
+ FILE *fp;
+ char buf[512], *ptr;
+ int inode;
+
+ if (!(fp = fopen( "/proc/net/udp", "r" ))) return ERROR_NOT_SUPPORTED;
+
+ memset( &key, 0, sizeof(key) );
+ memset( &stat, 0, sizeof(stat) );
+ pid_map = get_pid_map( &pid_map_size );
+
+ /* skip header line */
+ ptr = fgets( buf, sizeof(buf), fp );
+ while ((ptr = fgets( buf, sizeof(buf), fp )))
+ {
+ if (sscanf( ptr, "%*u: %x:%hx %*s %*s %*s %*s %*s %*s %*s %d",
+ &key.local.Ipv4.sin_addr.WS_s_addr, &key.local.Ipv4.sin_port, &inode ) != 3)
+ continue;
+
+ key.local.Ipv4.sin_family = WS_AF_INET;
+ key.local.Ipv4.sin_port = htons( key.local.Ipv4.sin_port );
+
+ stat.pid = find_owning_pid( pid_map, pid_map_size, inode );
+ stat.create_time = 0; /* FIXME */
+ stat.flags = 0; /* FIXME */
+ stat.mod_info = 0; /* FIXME */
+
+ if (num < *count)
+ {
+ if (key_out) *key_out++ = key;
+ if (stat_out) *stat_out++ = stat;
+ }
+ num++;
+ }
+ fclose( fp );
+
+ if ((fp = fopen( "/proc/net/udp6", "r" )))
+ {
+ memset( &key, 0, sizeof(key) );
+ memset( &stat, 0, sizeof(stat) );
+
+ addr_scopes = get_ipv6_addr_scope_table( &addr_scopes_size );
+
+ /* skip header line */
+ ptr = fgets( buf, sizeof(buf), fp );
+ while ((ptr = fgets( buf, sizeof(buf), fp )))
+ {
+ DWORD *local_addr = (DWORD *)&key.local.Ipv6.sin6_addr;
+
+ if (sscanf( ptr, "%*u: %8x%8x%8x%8x:%hx %*s %*s %*s %*s %*s %*s %*s %d",
+ local_addr, local_addr + 1, local_addr + 2, local_addr + 3,
+ &key.local.Ipv6.sin6_port, &inode ) != 6)
+ continue;
+ key.local.Ipv6.sin6_family = WS_AF_INET6;
+ key.local.Ipv6.sin6_port = htons( key.local.Ipv6.sin6_port );
+ key.local.Ipv6.sin6_scope_id = find_ipv6_addr_scope( &key.local.Ipv6.sin6_addr, addr_scopes,
+ addr_scopes_size );
+
+ stat.pid = find_owning_pid( pid_map, pid_map_size, inode );
+ stat.create_time = 0; /* FIXME */
+ stat.flags = 0; /* FIXME */
+ stat.mod_info = 0; /* FIXME */
+
+ if (num < *count)
+ {
+ if (key_out) *key_out++ = key;
+ if (stat_out) *stat_out++ = stat;
+ }
+ num++;
+ }
+ fclose( fp );
+ }
+ }
+#elif defined(HAVE_SYS_SYSCTL_H) && defined(UDPCTL_PCBLIST) && defined(HAVE_STRUCT_XINPGEN)
+ {
+ int mib[] = { CTL_NET, PF_INET, IPPROTO_UDP, UDPCTL_PCBLIST };
+ size_t len = 0;
+ char *buf = NULL;
+ struct xinpgen *xig, *orig_xig;
+
+ if (sysctl( mib, ARRAY_SIZE(mib), NULL, &len, NULL, 0 ) < 0)
+ {
+ ERR( "Failure to read net.inet.udp.pcblist via sysctlbyname!\n" );
+ status = STATUS_NOT_SUPPORTED;
+ goto err;
+ }
+
+ buf = heap_alloc( len );
+ if (!buf)
+ {
+ status = STATUS_NO_MEMORY;
+ goto err;
+ }
+
+ if (sysctl( mib, ARRAY_SIZE(mib), buf, &len, NULL, 0 ) < 0)
+ {
+ ERR( "Failure to read net.inet.udp.pcblist via sysctlbyname!\n" );
+ status = STATUS_NOT_SUPPORTED;
+ goto err;
+ }
+
+ /* Might be nothing here; first entry is just a header it seems */
+ if (len <= sizeof(struct xinpgen)) goto err;
+
+ addr_scopes = get_ipv6_addr_scope_table( &addr_scopes_size );
+ pid_map = get_pid_map( &pid_map_size );
+
+ orig_xig = (struct xinpgen *)buf;
+ xig = orig_xig;
+
+ for (xig = (struct xinpgen *)((char *)xig + xig->xig_len);
+ xig->xig_len > sizeof (struct xinpgen);
+ xig = (struct xinpgen *)((char *)xig + xig->xig_len))
+ {
+#if __FreeBSD_version >= 1200026
+ struct xinpcb *in = (struct xinpcb *)xig;
+ struct xsocket *sock = &in->xi_socket;
+#else
+ struct inpcb *in = &((struct xinpcb *)xig)->xi_inp;
+ struct xsocket *sock = &((struct xinpcb *)xig)->xi_socket;
+#endif
+ static const struct in6_addr zero;
+
+ /* Ignore sockets for other protocols */
+ if (sock->xso_protocol != IPPROTO_UDP) continue;
+
+ /* Ignore PCBs that were freed while generating the data */
+ if (in->inp_gencnt > orig_xig->xig_gen) continue;
+
+ /* we're only interested in IPv4 and IPv6 addresses */
+ if (!(in->inp_vflag & (INP_IPV4 | INP_IPV6))) continue;
+
+ /* If all 0's, skip it */
+ if (in->inp_vflag & INP_IPV4 && !in->inp_laddr.s_addr) continue;
+ if (in->inp_vflag & INP_IPV6 && !memcmp( &in->in6p_laddr, &zero, sizeof(zero) ) && !in->inp_lport) continue;
+
+ if (in->inp_vflag & INP_IPV4)
+ {
+ key.local.Ipv4.sin_family = WS_AF_INET;
+ key.local.Ipv4.sin_addr.WS_s_addr = in->inp_laddr.s_addr;
+ key.local.Ipv4.sin_port = in->inp_lport;
+ }
+ else
+ {
+ key.local.Ipv6.sin6_family = WS_AF_INET6;
+ memcpy( &key.local.Ipv6.sin6_addr, &in->in6p_laddr, sizeof(in->in6p_laddr) );
+ key.local.Ipv6.sin6_port = in->inp_lport;
+ key.local.Ipv6.sin6_scope_id = find_ipv6_addr_scope( &key.local.Ipv6.sin6_addr, addr_scopes,
+ addr_scopes_size );
+ }
+
+ stat.pid = find_owning_pid( pid_map, pid_map_size, (UINT_PTR)sock->so_pcb );
+ stat.create_time = 0; /* FIXME */
+ stat.flags = !(in->inp_flags & INP_ANONPORT);
+ stat.mod_info = 0; /* FIXME */
+
+ if (num < *count)
+ {
+ if (key_out) *key_out++ = key;
+ if (stat_out) *stat_out++ = stat;
+ }
+ num++;
+ }
+ err:
+ heap_free( buf );
+ }
+#else
+ FIXME( "not implemented\n" );
+ return STATUS_NOT_IMPLEMENTED;
+#endif
+
+ if (!want_data || num <= *count) *count = num;
+ else status = STATUS_MORE_ENTRIES;
+
+ heap_free( pid_map );
+ heap_free( addr_scopes );
+ return status;
+}
+
+static struct module_table udp_tables[] =
+{
+ {
+ NSI_UDP_ENDPOINT_TABLE,
+ {
+ sizeof(struct nsi_udp_endpoint_key), 0,
+ 0, sizeof(struct nsi_udp_endpoint_static)
+ },
+ udp_endpoint_enumerate_all,
+ },
+ {
+ ~0u
+ }
+};
+
+const struct module udp_module =
+{
+ &NPI_MS_UDP_MODULEID,
+ udp_tables
+};
diff --git a/include/wine/nsi.h b/include/wine/nsi.h
index 39a1ecebda1..8bf3bc1d5d0 100644
--- a/include/wine/nsi.h
+++ b/include/wine/nsi.h
@@ -346,6 +346,24 @@ struct nsi_tcp_conn_static
ULONGLONG mod_info;
};
+/* Undocumented NSI UDP tables */
+#define NSI_UDP_ENDPOINT_TABLE 1
+
+struct nsi_udp_endpoint_key
+{
+ SOCKADDR_INET local;
+};
+
+struct nsi_udp_endpoint_static
+{
+ DWORD pid;
+ DWORD unk;
+ ULONGLONG create_time;
+ DWORD flags;
+ DWORD unk2;
+ ULONGLONG mod_info;
+};
+
/* Wine specific ioctl interface */
#define IOCTL_NSIPROXY_WINE_ENUMERATE_ALL CTL_CODE(FILE_DEVICE_NETWORK, 0x400, METHOD_BUFFERED, 0)
--
2.23.0
1
0
Aug. 18, 2021
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
Supersedes: 211680-211686
dlls/winebus.sys/bus.h | 1 +
dlls/winebus.sys/bus_iohid.c | 6 ++++++
dlls/winebus.sys/bus_sdl.c | 6 ++++++
dlls/winebus.sys/bus_udev.c | 12 ++++++++++++
dlls/winebus.sys/main.c | 33 ++++++++++++++++++++++++++++-----
5 files changed, 53 insertions(+), 5 deletions(-)
diff --git a/dlls/winebus.sys/bus.h b/dlls/winebus.sys/bus.h
index 72bd071135b..f46daa7144d 100644
--- a/dlls/winebus.sys/bus.h
+++ b/dlls/winebus.sys/bus.h
@@ -39,6 +39,7 @@ typedef struct
{
void (*free_device)(DEVICE_OBJECT *device);
int (*compare_platform_device)(DEVICE_OBJECT *device, void *platform_dev);
+ NTSTATUS (*start_device)(DEVICE_OBJECT *device);
NTSTATUS (*get_reportdescriptor)(DEVICE_OBJECT *device, BYTE *buffer, DWORD length, DWORD *out_length);
NTSTATUS (*get_string)(DEVICE_OBJECT *device, DWORD index, WCHAR *buffer, DWORD length);
NTSTATUS (*begin_report_processing)(DEVICE_OBJECT *device);
diff --git a/dlls/winebus.sys/bus_iohid.c b/dlls/winebus.sys/bus_iohid.c
index eb6765d6aac..9b9e93f5c49 100644
--- a/dlls/winebus.sys/bus_iohid.c
+++ b/dlls/winebus.sys/bus_iohid.c
@@ -148,6 +148,11 @@ static int compare_platform_device(DEVICE_OBJECT *device, void *platform_dev)
return 0;
}
+static NTSTATUS start_device(DEVICE_OBJECT *device)
+{
+ return STATUS_SUCCESS;
+}
+
static NTSTATUS get_reportdescriptor(DEVICE_OBJECT *device, BYTE *buffer, DWORD length, DWORD *out_length)
{
struct platform_private *private = impl_from_DEVICE_OBJECT(device);
@@ -274,6 +279,7 @@ static const platform_vtbl iohid_vtbl =
{
free_device,
compare_platform_device,
+ start_device,
get_reportdescriptor,
get_string,
begin_report_processing,
diff --git a/dlls/winebus.sys/bus_sdl.c b/dlls/winebus.sys/bus_sdl.c
index c833b4e4c06..e7b7c1fef22 100644
--- a/dlls/winebus.sys/bus_sdl.c
+++ b/dlls/winebus.sys/bus_sdl.c
@@ -487,6 +487,11 @@ static int compare_platform_device(DEVICE_OBJECT *device, void *context)
return impl_from_DEVICE_OBJECT(device)->id - PtrToUlong(context);
}
+static NTSTATUS start_device(DEVICE_OBJECT *device)
+{
+ return STATUS_SUCCESS;
+}
+
static NTSTATUS get_reportdescriptor(DEVICE_OBJECT *device, BYTE *buffer, DWORD length, DWORD *out_length)
{
struct platform_private *ext = impl_from_DEVICE_OBJECT(device);
@@ -596,6 +601,7 @@ static const platform_vtbl sdl_vtbl =
{
free_device,
compare_platform_device,
+ start_device,
get_reportdescriptor,
get_string,
begin_report_processing,
diff --git a/dlls/winebus.sys/bus_udev.c b/dlls/winebus.sys/bus_udev.c
index 9176dff69a7..eb6434ad2a5 100644
--- a/dlls/winebus.sys/bus_udev.c
+++ b/dlls/winebus.sys/bus_udev.c
@@ -558,6 +558,11 @@ static int compare_platform_device(DEVICE_OBJECT *device, void *platform_dev)
return strcmp(udev_device_get_syspath(dev1), udev_device_get_syspath(dev2));
}
+static NTSTATUS hidraw_start_device(DEVICE_OBJECT *device)
+{
+ return STATUS_SUCCESS;
+}
+
static NTSTATUS hidraw_get_reportdescriptor(DEVICE_OBJECT *device, BYTE *buffer, DWORD length, DWORD *out_length)
{
#ifdef HAVE_LINUX_HIDRAW_H
@@ -818,6 +823,7 @@ static const platform_vtbl hidraw_vtbl =
{
hidraw_free_device,
compare_platform_device,
+ hidraw_start_device,
hidraw_get_reportdescriptor,
hidraw_get_string,
begin_report_processing,
@@ -854,6 +860,11 @@ static void lnxev_free_device(DEVICE_OBJECT *device)
udev_device_unref(ext->base.udev_device);
}
+static NTSTATUS lnxev_start_device(DEVICE_OBJECT *device)
+{
+ return STATUS_SUCCESS;
+}
+
static NTSTATUS lnxev_get_reportdescriptor(DEVICE_OBJECT *device, BYTE *buffer, DWORD length, DWORD *out_length)
{
struct wine_input_private *ext = input_impl_from_DEVICE_OBJECT(device);
@@ -967,6 +978,7 @@ static NTSTATUS lnxev_set_feature_report(DEVICE_OBJECT *device, UCHAR id, BYTE *
static const platform_vtbl lnxev_vtbl = {
lnxev_free_device,
compare_platform_device,
+ lnxev_start_device,
lnxev_get_reportdescriptor,
lnxev_get_string,
lnxev_begin_report_processing,
diff --git a/dlls/winebus.sys/main.c b/dlls/winebus.sys/main.c
index a60e3cc9a2c..f15e7da47b2 100644
--- a/dlls/winebus.sys/main.c
+++ b/dlls/winebus.sys/main.c
@@ -109,11 +109,17 @@ struct pnp_device
DEVICE_OBJECT *device;
};
+enum device_state
+{
+ DEVICE_STATE_STOPPED,
+ DEVICE_STATE_STARTED,
+ DEVICE_STATE_REMOVED,
+};
+
struct device_extension
{
CRITICAL_SECTION cs;
-
- BOOL removed;
+ enum device_state state;
struct pnp_device *pnp_device;
@@ -480,6 +486,11 @@ static void mouse_free_device(DEVICE_OBJECT *device)
{
}
+static NTSTATUS mouse_start_device(DEVICE_OBJECT *device)
+{
+ return STATUS_SUCCESS;
+}
+
static NTSTATUS mouse_get_reportdescriptor(DEVICE_OBJECT *device, BYTE *buffer, DWORD length, DWORD *ret_length)
{
TRACE("buffer %p, length %u.\n", buffer, length);
@@ -528,6 +539,7 @@ static NTSTATUS mouse_set_feature_report(DEVICE_OBJECT *device, UCHAR id, BYTE *
static const platform_vtbl mouse_vtbl =
{
.free_device = mouse_free_device,
+ .start_device = mouse_start_device,
.get_reportdescriptor = mouse_get_reportdescriptor,
.get_string = mouse_get_string,
.begin_report_processing = mouse_begin_report_processing,
@@ -555,6 +567,11 @@ static void keyboard_free_device(DEVICE_OBJECT *device)
{
}
+static NTSTATUS keyboard_start_device(DEVICE_OBJECT *device)
+{
+ return STATUS_SUCCESS;
+}
+
static NTSTATUS keyboard_get_reportdescriptor(DEVICE_OBJECT *device, BYTE *buffer, DWORD length, DWORD *ret_length)
{
TRACE("buffer %p, length %u.\n", buffer, length);
@@ -603,6 +620,7 @@ static NTSTATUS keyboard_set_feature_report(DEVICE_OBJECT *device, UCHAR id, BYT
static const platform_vtbl keyboard_vtbl =
{
.free_device = keyboard_free_device,
+ .start_device = keyboard_start_device,
.get_reportdescriptor = keyboard_get_reportdescriptor,
.get_string = keyboard_get_string,
.begin_report_processing = keyboard_begin_report_processing,
@@ -695,13 +713,18 @@ static NTSTATUS pdo_pnp_dispatch(DEVICE_OBJECT *device, IRP *irp)
break;
case IRP_MN_START_DEVICE:
- status = STATUS_SUCCESS;
+ EnterCriticalSection(&ext->cs);
+ if (ext->state != DEVICE_STATE_STOPPED) status = STATUS_SUCCESS;
+ else if (ext->state == DEVICE_STATE_REMOVED) status = STATUS_DELETE_PENDING;
+ else if (!(status = ext->vtbl->start_device(device))) ext->state = DEVICE_STATE_STARTED;
+ else ERR("failed to start device %p, status %#x\n", device, status);
+ LeaveCriticalSection(&ext->cs);
break;
case IRP_MN_SURPRISE_REMOVAL:
EnterCriticalSection(&ext->cs);
remove_pending_irps(device);
- ext->removed = TRUE;
+ ext->state = DEVICE_STATE_REMOVED;
LeaveCriticalSection(&ext->cs);
status = STATUS_SUCCESS;
break;
@@ -834,7 +857,7 @@ static NTSTATUS WINAPI hid_internal_dispatch(DEVICE_OBJECT *device, IRP *irp)
EnterCriticalSection(&ext->cs);
- if (ext->removed)
+ if (ext->state == DEVICE_STATE_REMOVED)
{
LeaveCriticalSection(&ext->cs);
irp->IoStatus.Status = STATUS_DELETE_PENDING;
--
2.32.0
1
4
Hello All,
We are trying to build Wine Source 6.0.1 on AIX 7 but it is failing in winebuild command. In Wine website it mentioned that Wine works on PowerPC. Does anyone have any idea?
Assembler version:
bash-5.0$ /usr/bin/as -v
as V7.1
bash-5.0$ tools/winebuild/winebuild -v -w --implib -o dlls/ucrtbase/libucrtbase.a --export dlls/ucrtbase/ucrtbase.spec dlls/ucrtbase/crt_gccmain.o dlls/ucrtbase/crt_main.o dlls/ucrtbase/crt_winmain.o dlls/ucrtbase/crt_wmain.o dlls/ucrtbase/crt_wwinmain.o dlls/ucrtbase/mathf.o dlls/ucrtbase/printf.o
/usr/bin/as -o ucrtbase.I7tD9N.o dlls/ucrtbase/libucrtbase.WYBdSA.s
Assembler:
dlls/ucrtbase/libucrtbase.WYBdSA.s: line 1: 1252-016 The specified opcode or pseudo-op is not valid.
Use supported instructions or pseudo-ops only.
dlls/ucrtbase/libucrtbase.WYBdSA.s: line 4: 1252-211 Invalid relocation type: function.
dlls/ucrtbase/libucrtbase.WYBdSA.s: line 4: 1252-142 Syntax error.
dlls/ucrtbase/libucrtbase.WYBdSA.s: line 6: 1252-016 The specified opcode or pseudo-op is not valid.
Use supported instructions or pseudo-ops only.
dlls/ucrtbase/libucrtbase.WYBdSA.s: line 8: 1252-142 Syntax error.
dlls/ucrtbase/libucrtbase.WYBdSA.s: line 9: 1252-016 The specified opcode or pseudo-op is not valid.
Use supported instructions or pseudo-ops only.
dlls/ucrtbase/libucrtbase.WYBdSA.s: line 10: 1252-142 Syntax error.
dlls/ucrtbase/libucrtbase.WYBdSA.s: line 10: 1252-211 Invalid relocation type: progbits.
dlls/ucrtbase/libucrtbase.WYBdSA.s: line 10: 1252-142 Syntax error.
winebuild: /usr/bin/as failed with status 1
regards,
Mahin
5
7
Aug. 17, 2021
This patch series adds missing WinEvents to the message sequences used
in tests, as well as marking all WinEvents as optional until they've
been implemented. I'm not sure if this is the correct way to do it, it
may make more sense to add a new message flag to indicate that a
particular WinEvent hasn't been implemented.
Connor McAdams (27):
user32: Add definition for EVENT_OBJECT_INVOKED.
user32/tests: Fix SetParent/SetFocus message sequences to support
WinEvents.
user32/tests: Fix ShowWindow message sequences to support WinEvents.
user32/tests: Fix test_messages() message sequences to support
WinEvents.
user32/tests: Fix test_setwindowpos() message sequences to support
WinEvents.
user32/tests: Fix test_showwindow() message sequences to support
WinEvents.
user32/tests: Fix invisible_parent_tests() message sequences to
support WinEvents.
user32/tests: Fix test_mdi_messages() message sequences to support
WinEvents.
user32/tests: Fix test_button_messages() message sequences to support
WinEvents.
user32/tests: Fix test_autoradio message sequences to support
WinEvents.
user32/tests: Fix test_listbox_messages() message sequences to support
WinEvents.
user32/tests: Fix test_paint_messages() message sequences to support
WinEvents.
user32/tests: Fix test_accelerators() message sequences to support
WinEvents.
user32/tests: Fix test_DestroyWindow() message sequences to support
WinEvents.
user32/tests: Fix test_edit_messages() message sequences to support
WinEvents.
user32/tests: Fix test_quit_message() message sequences to support
WinEvents.
user32/tests: Fix test_SetActiveWindow() message sequences to support
WinEvents.
user32/tests: Fix test_restore_messages() message sequences to support
WinEvents.
user32/tests: Fix test_SetWindowRgn() message sequences to support
WinEvents.
user32/tests: Fix test_dialog_messages() message sequences to support
WinEvents.
user32/tests: Fix test_EndDialog() message sequences to support
WinEvents.
user32/tests: Fix test_menu_messages() message sequences to support
WinEvents.
user32/tests: Fix test_defwinproc() message sequences to support
WinEvents.
user32/tests: Store thread ID of thread we're watching for WinEvents.
user32/tests: Fix test_layered_window() message sequences to support
WinEvents.
user32/tests: Fix TrackPopupMenu message sequences to support
WinEvents.
user32/tests: Fix test_DoubleSetCapture() message sequences to support
WinEvents.
dlls/user32/tests/msg.c | 1088 +++++++++++++++++++++++++--------------
include/winuser.h | 1 +
2 files changed, 700 insertions(+), 389 deletions(-)
--
2.25.1
3
31
Aug. 17, 2021
Signed-off-by: Hugh McMaster <hugh.mcmaster(a)outlook.com>
---
Version 2:
* Call {Get|Set}CurrentConsoleFontEx() directly
* Fully initialize struct CONSOLE_FONT_INFOEX before testing
dlls/kernel32/tests/console.c | 117 ++++++++++++++++++++++++++++++++++
1 file changed, 117 insertions(+)
diff --git a/dlls/kernel32/tests/console.c b/dlls/kernel32/tests/console.c
index bd5cad428bc..4919ae9ddb9 100644
--- a/dlls/kernel32/tests/console.c
+++ b/dlls/kernel32/tests/console.c
@@ -3536,6 +3536,122 @@ static void test_GetCurrentConsoleFontEx(HANDLE std_output)
ok(cfix.dwFontSize.Y == cfi.dwFontSize.Y, "expected values to match\n");
}
+static void test_SetCurrentConsoleFontEx(HANDLE std_output)
+{
+ CONSOLE_FONT_INFOEX orig_cfix, cfix;
+ BOOL ret;
+ HANDLE pipe1, pipe2;
+ HANDLE std_input = GetStdHandle(STD_INPUT_HANDLE);
+
+ orig_cfix.cbSize = sizeof(CONSOLE_FONT_INFOEX);
+
+ ret = GetCurrentConsoleFontEx(std_output, FALSE, &orig_cfix);
+ ok(ret, "got %d, expected non-zero\n", ret);
+
+ cfix = orig_cfix;
+ cfix.cbSize = 0;
+
+ SetLastError(0xdeadbeef);
+ ret = SetCurrentConsoleFontEx(NULL, FALSE, &cfix);
+ ok(!ret, "got %d, expected 0\n", ret);
+ todo_wine ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %u, expected 87\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ ret = SetCurrentConsoleFontEx(NULL, TRUE, &cfix);
+ ok(!ret, "got %d, expected 0\n", ret);
+ todo_wine ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %u, expected 87\n", GetLastError());
+
+ CreatePipe(&pipe1, &pipe2, NULL, 0);
+ SetLastError(0xdeadbeef);
+ ret = SetCurrentConsoleFontEx(pipe1, FALSE, &cfix);
+ ok(!ret, "got %d, expected 0\n", ret);
+ todo_wine ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %u, expected 87\n", GetLastError());
+ CloseHandle(pipe1);
+ CloseHandle(pipe2);
+
+ CreatePipe(&pipe1, &pipe2, NULL, 0);
+ SetLastError(0xdeadbeef);
+ ret = SetCurrentConsoleFontEx(pipe1, TRUE, &cfix);
+ ok(!ret, "got %d, expected 0\n", ret);
+ todo_wine ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %u, expected 87\n", GetLastError());
+ CloseHandle(pipe1);
+ CloseHandle(pipe2);
+
+ SetLastError(0xdeadbeef);
+ ret = SetCurrentConsoleFontEx(std_input, FALSE, &cfix);
+ ok(!ret, "got %d, expected 0\n", ret);
+ todo_wine ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %u, expected 87\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ ret = SetCurrentConsoleFontEx(std_input, TRUE, &cfix);
+ ok(!ret, "got %d, expected 0\n", ret);
+ todo_wine ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %u, expected 87\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ ret = SetCurrentConsoleFontEx(std_output, FALSE, &cfix);
+ ok(!ret, "got %d, expected 0\n", ret);
+ todo_wine ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %u, expected 87\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ ret = SetCurrentConsoleFontEx(std_output, TRUE, &cfix);
+ ok(!ret, "got %d, expected 0\n", ret);
+ todo_wine ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %u, expected 87\n", GetLastError());
+
+ cfix = orig_cfix;
+
+ SetLastError(0xdeadbeef);
+ ret = SetCurrentConsoleFontEx(NULL, FALSE, &cfix);
+ ok(!ret, "got %d, expected 0\n", ret);
+ todo_wine ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ ret = SetCurrentConsoleFontEx(NULL, TRUE, &cfix);
+ ok(!ret, "got %d, expected 0\n", ret);
+ todo_wine ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError());
+
+ CreatePipe(&pipe1, &pipe2, NULL, 0);
+ SetLastError(0xdeadbeef);
+ ret = SetCurrentConsoleFontEx(pipe1, FALSE, &cfix);
+ ok(!ret, "got %d, expected 0\n", ret);
+ todo_wine ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError());
+ CloseHandle(pipe1);
+ CloseHandle(pipe2);
+
+ CreatePipe(&pipe1, &pipe2, NULL, 0);
+ SetLastError(0xdeadbeef);
+ ret = SetCurrentConsoleFontEx(pipe1, TRUE, &cfix);
+ ok(!ret, "got %d, expected 0\n", ret);
+ todo_wine ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError());
+ CloseHandle(pipe1);
+ CloseHandle(pipe2);
+
+ SetLastError(0xdeadbeef);
+ ret = SetCurrentConsoleFontEx(std_input, FALSE, &cfix);
+ ok(!ret, "got %d, expected 0\n", ret);
+ todo_wine ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ ret = SetCurrentConsoleFontEx(std_input, TRUE, &cfix);
+ ok(!ret, "got %d, expected 0\n", ret);
+ todo_wine ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ ret = SetCurrentConsoleFontEx(std_output, FALSE, &cfix);
+ todo_wine ok(ret, "got %d, expected non-zero\n", ret);
+ todo_wine ok(GetLastError() == 0xdeadbeef, "got %u, expected 0xdeadbeef\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ ret = SetCurrentConsoleFontEx(std_output, TRUE, &cfix);
+ todo_wine ok(ret, "got %d, expected non-zero\n", ret);
+ todo_wine ok(GetLastError() == 0xdeadbeef, "got %u, expected 0xdeadbeef\n", GetLastError());
+
+ /* Restore original console font parameters */
+ SetLastError(0xdeadbeef);
+ ret = SetCurrentConsoleFontEx(std_output, FALSE, &orig_cfix);
+ todo_wine ok(ret, "got %d, expected non-zero\n", ret);
+ todo_wine ok(GetLastError() == 0xdeadbeef, "got %u, expected 0xdeadbeef\n", GetLastError());
+}
+
static void test_GetConsoleFontSize(HANDLE std_output)
{
COORD c;
@@ -4688,6 +4804,7 @@ START_TEST(console)
{
test_GetCurrentConsoleFont(hConOut);
test_GetCurrentConsoleFontEx(hConOut);
+ test_SetCurrentConsoleFontEx(hConOut);
test_GetConsoleFontSize(hConOut);
test_GetLargestConsoleWindowSize(hConOut);
test_GetConsoleFontInfo(hConOut);
--
2.32.0
2
1
[PATCH 1/2] comctl32: If STM_SETIMAGE failed to assign the image don't repaint the control.
by Dmitry Timoshkov Aug. 17, 2021
by Dmitry Timoshkov Aug. 17, 2021
Aug. 17, 2021
Signed-off-by: Dmitry Timoshkov <dmitry(a)baikal.ru>
---
dlls/comctl32/static.c | 6 ++++--
dlls/comctl32/tests/static.c | 17 +++++++++++++++++
2 files changed, 21 insertions(+), 2 deletions(-)
diff --git a/dlls/comctl32/static.c b/dlls/comctl32/static.c
index 2bd2b22bc20..554e75aa194 100644
--- a/dlls/comctl32/static.c
+++ b/dlls/comctl32/static.c
@@ -607,12 +607,14 @@ static LRESULT CALLBACK STATIC_WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam,
FIXME("STM_SETIMAGE: Unhandled type %lx\n", wParam);
break;
}
- STATIC_TryPaintFcn( hwnd, full_style );
+ if (lResult)
+ STATIC_TryPaintFcn( hwnd, full_style );
break;
case STM_SETICON:
lResult = (LRESULT)STATIC_SetIcon( hwnd, (HICON)wParam, full_style );
- STATIC_TryPaintFcn( hwnd, full_style );
+ if (lResult)
+ STATIC_TryPaintFcn( hwnd, full_style );
break;
default:
diff --git a/dlls/comctl32/tests/static.c b/dlls/comctl32/tests/static.c
index 4efb7685790..9932538f9ce 100644
--- a/dlls/comctl32/tests/static.c
+++ b/dlls/comctl32/tests/static.c
@@ -263,6 +263,22 @@ static void test_set_image(void)
DeleteObject(image);
}
+static void test_set_image_on_text_control(void)
+{
+ HWND hwnd = create_static(SS_LEFT);
+ HICON image, old_image;
+
+ image = LoadIconW(NULL, (LPCWSTR)IDI_APPLICATION);
+
+ g_nReceivedColorStatic = 0;
+ old_image = (HICON)SendMessageW(hwnd, STM_SETIMAGE, IMAGE_ICON, (LPARAM)image);
+ ok(!old_image, "got %p\n", old_image);
+ ok(!g_nReceivedColorStatic, "Unexpected WM_CTLCOLORSTATIC value %d\n", g_nReceivedColorStatic);
+
+ DestroyIcon(image);
+ DestroyWindow(hwnd);
+}
+
START_TEST(static)
{
static const char classname[] = "testclass";
@@ -302,6 +318,7 @@ START_TEST(static)
test_updates(SS_ETCHEDVERT, TODO_COUNT);
test_set_text();
test_set_image();
+ test_set_image_on_text_control();
DestroyWindow(hMainWnd);
--
2.31.1
2
1
Aug. 17, 2021
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
dlls/setupapi/tests/devinst.c | 34 ++++++++++++++++++++++++++--------
1 file changed, 26 insertions(+), 8 deletions(-)
diff --git a/dlls/setupapi/tests/devinst.c b/dlls/setupapi/tests/devinst.c
index de302d21660..73e0086081d 100644
--- a/dlls/setupapi/tests/devinst.c
+++ b/dlls/setupapi/tests/devinst.c
@@ -2348,7 +2348,7 @@ static void test_driver_list(void)
char detail_buffer[1000];
SP_DRVINFO_DETAIL_DATA_A *detail = (SP_DRVINFO_DETAIL_DATA_A *)detail_buffer;
char short_path[MAX_PATH], inf_dir[MAX_PATH], inf_path[MAX_PATH + 10], inf_path2[MAX_PATH + 10];
- static const char hardware_id[] = "bogus_hardware_id\0";
+ static const char hardware_id[] = "bogus_hardware_id\0other_hardware_id\0";
static const char compat_id[] = "bogus_compat_id\0";
SP_DEVINSTALL_PARAMS_A params = {sizeof(params)};
SP_DRVINFO_DATA_A driver = {sizeof(driver)};
@@ -2357,6 +2357,7 @@ static void test_driver_list(void)
FILETIME filetime;
HDEVINFO set;
HANDLE file;
+ DWORD idx;
BOOL ret;
static const char inf_data[] = "[Version]\n"
@@ -2369,11 +2370,13 @@ static void test_driver_list(void)
"mfg2_wow=mfg2_key,NT" WOWEXT "\n"
"mfg3=mfg3_key,NT" WRONGEXT "\n"
"[mfg1_key.nt" MYEXT "]\n"
+ "desc0=,other_hardware_id,bogus_compat_id\n"
"desc1=install1,bogus_hardware_id\n"
"desc2=,bogus_hardware_id\n"
"desc3=,wrong_hardware_id\n"
"desc4=,wrong_hardware_id,bogus_compat_id\n"
"[mfg1_key.nt" WOWEXT "]\n"
+ "desc0=,other_hardware_id,bogus_compat_id\n"
"desc1=install1,bogus_hardware_id\n"
"desc2=,bogus_hardware_id\n"
"desc3=,wrong_hardware_id\n"
@@ -2444,10 +2447,25 @@ static void test_driver_list(void)
ret = SetupDiBuildDriverInfoList(set, &device, SPDIT_COMPATDRIVER);
ok(ret, "Failed to build driver list, error %#x.\n", GetLastError());
- ret = SetupDiEnumDriverInfoA(set, &device, SPDIT_COMPATDRIVER, 0, &driver);
+ idx = 0;
+ ret = SetupDiEnumDriverInfoA(set, &device, SPDIT_COMPATDRIVER, idx++, &driver);
ok(ret, "Failed to enumerate drivers, error %#x.\n", GetLastError());
ok(driver.DriverType == SPDIT_COMPATDRIVER, "Got wrong type %#x.\n", driver.DriverType);
- ok(!strcmp(driver.Description, "desc1"), "Got wrong description '%s'.\n", driver.Description);
+ ok(!strcmp(driver.Description, "desc0"), "Got wrong description '%s'.\n", driver.Description);
+ ok(!strcmp(driver.MfgName, wow64 ? "mfg1_wow" : "mfg1"), "Got wrong manufacturer '%s'.\n", driver.MfgName);
+ ok(!strcmp(driver.ProviderName, ""), "Got wrong provider '%s'.\n", driver.ProviderName);
+
+ ret = SetupDiEnumDriverInfoA(set, &device, SPDIT_COMPATDRIVER, idx++, &driver);
+ ok(ret, "Failed to enumerate drivers, error %#x.\n", GetLastError());
+ ok(driver.DriverType == SPDIT_COMPATDRIVER, "Got wrong type %#x.\n", driver.DriverType);
+ todo_wine ok(!strcmp(driver.Description, "desc1"), "Got wrong description '%s'.\n", driver.Description);
+ if (strcmp(driver.Description, "desc1"))
+ {
+ ret = SetupDiEnumDriverInfoA(set, &device, SPDIT_COMPATDRIVER, idx++, &driver);
+ ok(ret, "Failed to enumerate drivers, error %#x.\n", GetLastError());
+ ok(driver.DriverType == SPDIT_COMPATDRIVER, "Got wrong type %#x.\n", driver.DriverType);
+ ok(!strcmp(driver.Description, "desc1"), "Got wrong description '%s'.\n", driver.Description);
+ }
ok(!strcmp(driver.MfgName, wow64 ? "mfg1_wow" : "mfg1"), "Got wrong manufacturer '%s'.\n", driver.MfgName);
ok(!strcmp(driver.ProviderName, ""), "Got wrong provider '%s'.\n", driver.ProviderName);
@@ -2515,14 +2533,14 @@ static void test_driver_list(void)
ok(!detail->CompatIDsLength, "Got wrong compat IDs length %u.\n", detail->CompatIDsLength);
ok(!memcmp(detail->HardwareID, "bogus_hardware_id\0", sizeof("bogus_hardware_id\0")), "Got wrong ID list.\n");
- ret = SetupDiEnumDriverInfoA(set, &device, SPDIT_COMPATDRIVER, 1, &driver);
+ ret = SetupDiEnumDriverInfoA(set, &device, SPDIT_COMPATDRIVER, idx++, &driver);
ok(ret, "Failed to enumerate drivers, error %#x.\n", GetLastError());
ok(driver.DriverType == SPDIT_COMPATDRIVER, "Got wrong type %#x.\n", driver.DriverType);
ok(!strcmp(driver.Description, "desc2"), "Got wrong description '%s'.\n", driver.Description);
ok(!strcmp(driver.MfgName, wow64 ? "mfg1_wow" : "mfg1"), "Got wrong manufacturer '%s'.\n", driver.MfgName);
ok(!strcmp(driver.ProviderName, ""), "Got wrong provider '%s'.\n", driver.ProviderName);
- ret = SetupDiEnumDriverInfoA(set, &device, SPDIT_COMPATDRIVER, 2, &driver);
+ ret = SetupDiEnumDriverInfoA(set, &device, SPDIT_COMPATDRIVER, idx++, &driver);
ok(ret, "Failed to enumerate drivers, error %#x.\n", GetLastError());
ok(driver.DriverType == SPDIT_COMPATDRIVER, "Got wrong type %#x.\n", driver.DriverType);
ok(!strcmp(driver.Description, "desc4"), "Got wrong description '%s'.\n", driver.Description);
@@ -2542,7 +2560,7 @@ static void test_driver_list(void)
ok(!memcmp(detail->HardwareID, "wrong_hardware_id\0bogus_compat_id\0",
sizeof("wrong_hardware_id\0bogus_compat_id\0")), "Got wrong ID list.\n");
- ret = SetupDiEnumDriverInfoA(set, &device, SPDIT_COMPATDRIVER, 3, &driver);
+ ret = SetupDiEnumDriverInfoA(set, &device, SPDIT_COMPATDRIVER, idx++, &driver);
ok(ret, "Failed to enumerate drivers, error %#x.\n", GetLastError());
ok(driver.DriverType == SPDIT_COMPATDRIVER, "Got wrong type %#x.\n", driver.DriverType);
ok(!strcmp(driver.Description, "desc5"), "Got wrong description '%s'.\n", driver.Description);
@@ -2550,7 +2568,7 @@ static void test_driver_list(void)
ok(!strcmp(driver.ProviderName, ""), "Got wrong provider '%s'.\n", driver.ProviderName);
SetLastError(0xdeadbeef);
- ret = SetupDiEnumDriverInfoA(set, &device, SPDIT_COMPATDRIVER, 4, &driver);
+ ret = SetupDiEnumDriverInfoA(set, &device, SPDIT_COMPATDRIVER, idx++, &driver);
ok(!ret, "Expected failure.\n");
ok(GetLastError() == ERROR_NO_MORE_ITEMS, "Got unexpected error %#x.\n", GetLastError());
@@ -2564,7 +2582,7 @@ static void test_driver_list(void)
ret = SetupDiGetSelectedDriverA(set, &device, &driver);
ok(ret, "Failed to get selected driver, error %#x.\n", GetLastError());
ok(driver.DriverType == SPDIT_COMPATDRIVER, "Got wrong type %#x.\n", driver.DriverType);
- ok(!strcmp(driver.Description, "desc1"), "Got wrong description '%s'.\n", driver.Description);
+ todo_wine ok(!strcmp(driver.Description, "desc1"), "Got wrong description '%s'.\n", driver.Description);
ok(!strcmp(driver.MfgName, wow64 ? "mfg1_wow" : "mfg1"), "Got wrong manufacturer '%s'.\n", driver.MfgName);
ok(!strcmp(driver.ProviderName, ""), "Got wrong provider '%s'.\n", driver.ProviderName);
--
2.32.0
2
10
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/d3dx10_43/Makefile.in | 3 +-
dlls/d3dx10_43/d3dx10_43.spec | 2 +-
dlls/d3dx10_43/sprite.c | 205 ++++++++++++++++++++++++++++++++++
include/d3dx10core.h | 1 +
4 files changed, 209 insertions(+), 2 deletions(-)
create mode 100644 dlls/d3dx10_43/sprite.c
diff --git a/dlls/d3dx10_43/Makefile.in b/dlls/d3dx10_43/Makefile.in
index 1fae34191ee..6d74f586841 100644
--- a/dlls/d3dx10_43/Makefile.in
+++ b/dlls/d3dx10_43/Makefile.in
@@ -1,6 +1,6 @@
MODULE = d3dx10_43.dll
IMPORTLIB = d3dx10
-IMPORTS = d3d10_1 d3dcompiler dxguid
+IMPORTS = d3d10_1 d3dcompiler dxguid uuid
DELAYIMPORTS = windowscodecs
EXTRADLLFLAGS = -mno-cygwin -Wb,--prefer-native
@@ -9,6 +9,7 @@ C_SRCS = \
async.c \
compiler.c \
d3dx10_43_main.c \
+ sprite.c \
texture.c
RC_SRCS = version.rc
diff --git a/dlls/d3dx10_43/d3dx10_43.spec b/dlls/d3dx10_43/d3dx10_43.spec
index a00b3402a5a..99b142f34d5 100644
--- a/dlls/d3dx10_43/d3dx10_43.spec
+++ b/dlls/d3dx10_43/d3dx10_43.spec
@@ -41,7 +41,7 @@
@ stub D3DX10CreateShaderResourceViewFromResourceA(ptr long str ptr ptr ptr ptr)
@ stub D3DX10CreateShaderResourceViewFromResourceW(ptr long wstr ptr ptr ptr ptr)
@ stub D3DX10CreateSkinInfo(ptr)
-@ stub D3DX10CreateSprite(ptr long ptr)
+@ stdcall D3DX10CreateSprite(ptr long ptr)
@ stub D3DX10CreateTextureFromFileA(ptr str ptr ptr ptr ptr)
@ stub D3DX10CreateTextureFromFileW(ptr wstr ptr ptr ptr ptr)
@ stdcall D3DX10CreateTextureFromMemory(ptr ptr long ptr ptr ptr ptr)
diff --git a/dlls/d3dx10_43/sprite.c b/dlls/d3dx10_43/sprite.c
new file mode 100644
index 00000000000..c90185e0c0a
--- /dev/null
+++ b/dlls/d3dx10_43/sprite.c
@@ -0,0 +1,205 @@
+/*
+ * Copyright 2021 Nikolay Sivov 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
+ *
+ */
+
+#define COBJMACROS
+#include "d3dx10.h"
+
+#include "wine/debug.h"
+#include "wine/heap.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
+
+#define D3DERR_INVALIDCALL 0x8876086c
+
+struct d3dx10_sprite
+{
+ ID3DX10Sprite ID3DX10Sprite_iface;
+ LONG refcount;
+
+ ID3D10Device *device;
+};
+
+static inline struct d3dx10_sprite *impl_from_ID3DX10Sprite(ID3DX10Sprite *iface)
+{
+ return CONTAINING_RECORD(iface, struct d3dx10_sprite, ID3DX10Sprite_iface);
+}
+
+static HRESULT WINAPI d3dx10_sprite_QueryInterface(ID3DX10Sprite *iface, REFIID riid, void **out)
+{
+ TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
+
+ if (IsEqualGUID(riid, &IID_ID3DX10Sprite)
+ || IsEqualGUID(riid, &IID_IUnknown))
+ {
+ IUnknown_AddRef(iface);
+ *out = iface;
+ return S_OK;
+ }
+
+ WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
+
+ *out = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI d3dx10_sprite_AddRef(ID3DX10Sprite *iface)
+{
+ struct d3dx10_sprite *sprite = impl_from_ID3DX10Sprite(iface);
+ ULONG refcount = InterlockedIncrement(&sprite->refcount);
+
+ TRACE("%p increasing refcount to %u.\n", iface, refcount);
+
+ return refcount;
+}
+
+static ULONG WINAPI d3dx10_sprite_Release(ID3DX10Sprite *iface)
+{
+ struct d3dx10_sprite *sprite = impl_from_ID3DX10Sprite(iface);
+ ULONG refcount = InterlockedDecrement(&sprite->refcount);
+
+ TRACE("%p decreasing refcount to %u.\n", iface, refcount);
+
+ if (!refcount)
+ {
+ ID3D10Device_Release(sprite->device);
+ heap_free(sprite);
+ }
+
+ return refcount;
+}
+
+static HRESULT WINAPI d3dx10_sprite_Begin(ID3DX10Sprite *iface, UINT flags)
+{
+ FIXME("iface %p, flags %#x stub!\n", iface, flags);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI d3dx10_sprite_DrawSpritesBuffered(ID3DX10Sprite *iface,
+ D3DX10_SPRITE *sprites, UINT count)
+{
+ FIXME("iface %p, sprites %p, count %u stub!\n", iface, sprites, count);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI d3dx10_sprite_Flush(ID3DX10Sprite *iface)
+{
+ FIXME("iface %p stub!\n", iface);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI d3dx10_sprite_DrawSpritesImmediate(ID3DX10Sprite *iface,
+ D3DX10_SPRITE *sprites, UINT count, UINT size, UINT flags)
+{
+ FIXME("iface %p, sprites %p, count %u, size %u, flags %#x stub!\n",
+ iface, sprites, count, size, flags);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI d3dx10_sprite_End(ID3DX10Sprite *iface)
+{
+ FIXME("iface %p stub!\n", iface);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI d3dx10_sprite_GetViewTransform(ID3DX10Sprite *iface, D3DXMATRIX *transform)
+{
+ FIXME("iface %p, transform %p stub!\n", iface, transform);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI d3dx10_sprite_SetViewTransform(ID3DX10Sprite *iface, D3DXMATRIX *transform)
+{
+ FIXME("iface %p, transform %p stub!\n", iface, transform);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI d3dx10_sprite_GetProjectionTransform(ID3DX10Sprite *iface,
+ D3DXMATRIX *transform)
+{
+ FIXME("iface %p, transform %p stub!\n", iface, transform);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI d3dx10_sprite_SetProjectionTransform(ID3DX10Sprite *iface, D3DXMATRIX *transform)
+{
+ FIXME("iface %p, transform %p stub!\n", iface, transform);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI d3dx10_sprite_GetDevice(ID3DX10Sprite *iface, ID3D10Device **device)
+{
+ struct d3dx10_sprite *sprite = impl_from_ID3DX10Sprite(iface);
+
+ TRACE("iface %p, device %p.\n", iface, device);
+
+ *device = sprite->device;
+ ID3D10Device_AddRef(*device);
+
+ return S_OK;
+}
+
+static const ID3DX10SpriteVtbl d3dx10_sprite_vtbl =
+{
+ d3dx10_sprite_QueryInterface,
+ d3dx10_sprite_AddRef,
+ d3dx10_sprite_Release,
+ d3dx10_sprite_Begin,
+ d3dx10_sprite_DrawSpritesBuffered,
+ d3dx10_sprite_Flush,
+ d3dx10_sprite_DrawSpritesImmediate,
+ d3dx10_sprite_End,
+ d3dx10_sprite_GetViewTransform,
+ d3dx10_sprite_SetViewTransform,
+ d3dx10_sprite_GetProjectionTransform,
+ d3dx10_sprite_SetProjectionTransform,
+ d3dx10_sprite_GetDevice,
+};
+
+HRESULT WINAPI D3DX10CreateSprite(ID3D10Device *device, UINT size, ID3DX10Sprite **sprite)
+{
+ struct d3dx10_sprite *object;
+
+ TRACE("device %p, size %u, sprite %p.\n", device, size, sprite);
+
+ if (!device || !sprite)
+ return D3DERR_INVALIDCALL;
+
+ *sprite = NULL;
+
+ if (!(object = heap_alloc_zero(sizeof(*object))))
+ return E_OUTOFMEMORY;
+
+ object->ID3DX10Sprite_iface.lpVtbl = &d3dx10_sprite_vtbl;
+ object->refcount = 1;
+ object->device = device;
+ ID3D10Device_AddRef(device);
+
+ *sprite = &object->ID3DX10Sprite_iface;
+
+ return S_OK;
+}
diff --git a/include/d3dx10core.h b/include/d3dx10core.h
index 3ed6f6f2443..fa6ef2381b6 100644
--- a/include/d3dx10core.h
+++ b/include/d3dx10core.h
@@ -289,3 +289,4 @@ HRESULT WINAPI D3DX10CreateDeviceAndSwapChain(IDXGIAdapter *adapter, D3D10_DRIVE
ID3D10Device **device);
typedef interface ID3D10Device1 ID3D10Device1;
HRESULT WINAPI D3DX10GetFeatureLevel1(ID3D10Device *device, ID3D10Device1 **device1);
+HRESULT WINAPI D3DX10CreateSprite(ID3D10Device *device, UINT size, ID3DX10Sprite **sprite);
--
2.30.2
3
6