Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/iphlpapi/ipstats.c | 90 ++++++++++++++++++++++++----------------- 1 file changed, 54 insertions(+), 36 deletions(-)
diff --git a/dlls/iphlpapi/ipstats.c b/dlls/iphlpapi/ipstats.c index 11d52d4d651..58a02010124 100644 --- a/dlls/iphlpapi/ipstats.c +++ b/dlls/iphlpapi/ipstats.c @@ -1885,58 +1885,76 @@ struct pid_map unsigned int unix_pid; };
+static unsigned int align_offset(unsigned int offset, unsigned int alignment) +{ + return (offset + (alignment - 1)) & ~(alignment - 1); +} + static struct pid_map *get_pid_map( unsigned int *num_entries ) { - HANDLE snapshot = NULL; struct pid_map *map; - unsigned int i = 0, count = 16, size = count * sizeof(*map); + unsigned int i = 0, map_count = 16, buffer_len = 4096, process_count, pos = 0; NTSTATUS ret; + char *buffer = NULL, *new_buffer;
- if (!(map = HeapAlloc( GetProcessHeap(), 0, size ))) return NULL; + if (!(buffer = HeapAlloc( GetProcessHeap(), 0, buffer_len ))) return NULL;
- SERVER_START_REQ( create_snapshot ) + for (;;) { - req->flags = SNAP_PROCESS; - req->attributes = 0; - if (!(ret = wine_server_call( req ))) - snapshot = wine_server_ptr_handle( reply->handle ); + 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; + } } - SERVER_END_REQ;
- *num_entries = 0; - while (ret == STATUS_SUCCESS) + if (!(map = HeapAlloc( GetProcessHeap(), 0, map_count * sizeof(*map) ))) { - SERVER_START_REQ( next_process ) + HeapFree( GetProcessHeap(), 0, buffer ); + return NULL; + } + + for (i = 0; i < process_count; ++i) + { + const struct process_info *process; + + pos = align_offset( pos, TYPE_ALIGNMENT(struct process_info) ); + process = (const struct process_info *)(buffer + pos); + + if (i >= map_count) { - req->handle = wine_server_obj_handle( snapshot ); - req->reset = (i == 0); - if (!(ret = wine_server_call( req ))) + struct pid_map *new_map; + map_count *= 2; + if (!(new_map = HeapReAlloc( GetProcessHeap(), 0, map, map_count * sizeof(*map)))) { - if (i >= count) - { - struct pid_map *new_map; - count *= 2; - size = count * sizeof(*new_map); - - if (!(new_map = HeapReAlloc( GetProcessHeap(), 0, map, size ))) - { - HeapFree( GetProcessHeap(), 0, map ); - map = NULL; - goto done; - } - map = new_map; - } - map[i].pid = reply->pid; - map[i].unix_pid = reply->unix_pid; - (*num_entries)++; - i++; + HeapFree( GetProcessHeap(), 0, map ); + HeapFree( GetProcessHeap(), 0, buffer ); + return NULL; } + map = new_map; } - SERVER_END_REQ; + + map[i].pid = process->pid; + map[i].unix_pid = process->unix_pid; + + pos += sizeof(struct process_info) + process->name_len; + pos = align_offset( pos, TYPE_ALIGNMENT(struct thread_info) ); + pos += process->thread_count * sizeof(struct thread_info); }
-done: - NtClose( snapshot ); + HeapFree( GetProcessHeap(), 0, buffer ); + *num_entries = process_count; return map; }