1
0
mirror of https://github.com/solemnwarning/ipxwrapper synced 2024-12-30 16:45:37 +01:00

Merge branch 'profiling'

This commit is contained in:
Daniel Collins 2023-12-10 12:59:39 +00:00
commit bbe0dbd4e1
22 changed files with 882 additions and 227 deletions

View File

@ -86,62 +86,62 @@ dist: all
IPXWRAPPER_OBJS := src/ipxwrapper.o src/winsock.o src/ipxwrapper_stubs.o src/log.o src/common.o \
src/interface.o src/interface2.o src/router.o src/ipxwrapper.def src/addrcache.o src/config.o src/addr.o \
src/firewall.o src/wpcap_stubs.o src/ethernet.o
src/firewall.o src/ethernet.o src/funcprof.o
ipxwrapper.dll: $(IPXWRAPPER_OBJS)
echo 'const char *version_string = "$(VERSION)", *compile_time = "'`date`'";' | $(CC) -c -x c -o version.o -
$(CC) $(CFLAGS) -Wl,--enable-stdcall-fixup -static-libgcc -shared -o $@ $^ version.o -liphlpapi -lversion -lole32 -loleaut32
src/ipxwrapper_stubs.s: src/ipxwrapper_stubs.txt
perl mkstubs.pl src/ipxwrapper_stubs.txt src/ipxwrapper_stubs.s 0
perl mkstubs.pl src/ipxwrapper_stubs.txt src/ipxwrapper_stubs.s ipxwrapper.dll
#
# WSOCK32.DLL
#
wsock32.dll: src/stubdll.o src/wsock32_stubs.o src/log.o src/common.o src/config.o src/addr.o src/wsock32.def
wsock32.dll: src/stubdll.o src/wsock32_stubs.o src/log.o src/common.o src/config.o src/addr.o src/funcprof.o src/wsock32.def
$(CC) $(CFLAGS) -Wl,--enable-stdcall-fixup -static-libgcc -shared -o $@ $^
src/wsock32_stubs.s: src/wsock32_stubs.txt
perl mkstubs.pl src/wsock32_stubs.txt src/wsock32_stubs.s 1
perl mkstubs.pl src/wsock32_stubs.txt src/wsock32_stubs.s wsock32.dll
#
# MSWSOCK.DLL
#
mswsock.dll: src/stubdll.o src/mswsock_stubs.o src/log.o src/common.o src/config.o src/addr.o src/mswsock.def
mswsock.dll: src/stubdll.o src/mswsock_stubs.o src/log.o src/common.o src/config.o src/addr.o src/funcprof.o src/mswsock.def
$(CC) $(CFLAGS) -Wl,--enable-stdcall-fixup -static-libgcc -shared -o $@ $^
src/mswsock_stubs.s: src/mswsock_stubs.txt
perl mkstubs.pl src/mswsock_stubs.txt src/mswsock_stubs.s 2
perl mkstubs.pl src/mswsock_stubs.txt src/mswsock_stubs.s mswsock.dll
#
# DPWSOCKX.DLL
#
dpwsockx.dll: src/directplay.o src/log.o src/dpwsockx_stubs.o src/common.o src/config.o src/addr.o src/dpwsockx.def
dpwsockx.dll: src/directplay.o src/log.o src/dpwsockx_stubs.o src/common.o src/config.o src/addr.o src/funcprof.o src/dpwsockx.def
$(CC) $(CFLAGS) -Wl,--enable-stdcall-fixup -static-libgcc -shared -o $@ $^ -lwsock32
src/dpwsockx_stubs.s: src/dpwsockx_stubs.txt
perl mkstubs.pl src/dpwsockx_stubs.txt src/dpwsockx_stubs.s 3
perl mkstubs.pl src/dpwsockx_stubs.txt src/dpwsockx_stubs.s dpwsockx.dll
#
# IPXCONFIG.EXE
#
IPXCONFIG_OBJS := src/ipxconfig.o icons/ipxconfig.o src/addr.o src/interface2.o src/common.o \
src/config.o src/wpcap_stubs.o
src/config.o src/ipxconfig_stubs.o src/funcprof.o
ipxconfig.exe: $(IPXCONFIG_OBJS)
$(CXX) $(CXXFLAGS) -Wl,--enable-stdcall-fixup -static-libgcc -static-libstdc++ -mwindows -o $@ $^ -liphlpapi -lcomctl32 -lws2_32
src/ipxconfig_stubs.s: src/ipxwrapper_stubs.txt
perl mkstubs.pl src/ipxconfig_stubs.txt src/ipxconfig_stubs.s ipxconfig.exe
#
# SHARED TARGETS
#
src/wpcap_stubs.s: src/wpcap_stubs.txt
perl mkstubs.pl src/wpcap_stubs.txt src/wpcap_stubs.s 5
icons/%.o: icons/%.rc icons/%.ico
$(WINDRES) $< -O coff -o $@

View File

@ -1,5 +1,5 @@
# IPXWrapper - Generate assembly stub functions
# Copyright (C) 2008-2011 Daniel Collins <solemnwarning@solemnwarning.net>
# Copyright (C) 2008-2023 Daniel Collins <solemnwarning@solemnwarning.net>
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 as published by
@ -18,74 +18,268 @@ use strict;
use warnings;
if(@ARGV != 3) {
print STDERR "Usage: mkdll.pl <function list> <output file> <dll number>\n";
print STDERR "Usage: mkdll.pl <stub definitions file> <asm output file> <dll name>\n";
exit(1);
}
my $stub_file = $ARGV[0];
my $asm_file = $ARGV[1];
my $dllnum = $ARGV[2];
my $do_logging = ($dllnum != 0);
# Must be kept in sync with dll_names in common.c!
my %DLL_INDICES = (
"ipxwrapper.dll" => 0,
"wsock32.dll" => 1,
"mswsock.dll" => 2,
"dpwsockx.dll" => 3,
"ws2_32.dll" => 4,
"wpcap.dll" => 5,
"ipxconfig.exe" => 6,
);
my ($stub_file, $asm_file, $dll_name) = @ARGV;
my $dll_index = $DLL_INDICES{$dll_name}
// die "Unknown DLL name: $dll_name";
open(STUBS, "<$stub_file") or die("Cannot open $stub_file: $!");
open(CODE, ">$asm_file") or die("Cannot open $asm_file: $!");
my @stubs = ();
my @stubs_dll = ();
foreach my $line(<STUBS>) {
# Skip over header
(scalar <STUBS>);
(scalar <STUBS>);
# Read in stub definitions
foreach my $line(<STUBS>)
{
$line =~ s/[\r\n]//g;
if($line ne "") {
my ($func, $dn) = split(/:/, $line);
$dn = $dllnum if(!defined($dn));
my ($name, $target_dll, $target_func, $params) = split(/\s+/, $line);
my $sym = $func;
$sym =~ s/^r_//;
my $target_dll_index = $DLL_INDICES{$target_dll}
// die "Unknown DLL: $target_dll\n";
push(@stubs, {"name" => $func, "sym" => $sym, "dllnum" => $dn});
push(@stubs, {
name => $name,
target_dll => $target_dll,
target_dll_index => $target_dll_index,
target_func => $target_func,
params => $params,
});
}
}
print CODE "section .rdata:\n";
print CODE <<"END";
extern _QueryPerformanceCounter\@4
foreach my $func(@stubs) {
print CODE "\t".$func->{"name"}."_sym:\tdb\t'".$func->{"sym"}."', 0\n";
extern _find_sym
extern _log_call
extern _fprof_record_timed
extern _fprof_record_untimed
struc FuncStats
.func_name: resd 1
.min_time: resd 1
.max_time: resd 1
.total_time: resd 1
.n_calls: resd 1
.cs: resb 24
endstruc
END
print CODE <<"END";
section .rdata
END
foreach my $func(@stubs)
{
print CODE <<"END";
$func->{name}_name: db '$func->{name}', 0
$func->{name}_target_func: db '$func->{target_func}', 0
END
}
print CODE "\nsection .data\n";
my $num_funcs = (scalar @stubs);
foreach my $func(@stubs) {
print CODE "\t".$func->{"name"}."_addr:\tdd\t0\n";
print CODE <<"END";
global _NUM_STUBS
_NUM_STUBS: dd $num_funcs
DLL_NAME: db '$dll_name', 0
global _STUBS_DLL_NAME
_STUBS_DLL_NAME: dd DLL_NAME
END
print CODE <<"END";
section .data
global _stubs_enable_profile
_stubs_enable_profile: db 0
END
foreach my $func(@stubs)
{
print CODE <<"END";
$func->{name}_addr: dd 0
END
}
print CODE "\nsection .text\n";
print CODE "\textern\t_find_sym\n";
print CODE "\textern\t_log_call\n" if($do_logging);
print CODE <<"END";
global _stub_fstats
_stub_fstats:
END
foreach my $func(@stubs) {
my $f_name = $func->{"name"};
print CODE "\nglobal\t_$f_name\n";
print CODE "_$f_name:\n";
if($do_logging) {
print CODE "\tpush\tdword ".$func->{"dllnum"}."\n";
print CODE "\tpush\t$f_name\_sym\n";
print CODE "\tpush\tdword $dllnum\n";
print CODE "\tcall\t_log_call\n";
foreach my $func(@stubs)
{
print CODE <<"END";
$func->{name}_fstats:
istruc FuncStats
at FuncStats.func_name, dd $func->{name}_name
iend
END
}
print CODE <<"END";
section .text
END
foreach my $func(@stubs)
{
if(defined $func->{params})
{
my $to_copy = $func->{params};
print CODE <<"END";
global _$func->{name}
_$func->{name}:
; Log the call
push dword $func->{target_dll_index}
push $func->{name}_target_func
push dword $dll_index
call _log_call
; Check if we have address cached
cmp dword [$func->{name}_addr], 0
jne $func->{name}_go
; Fetch target function address
push $func->{name}_target_func
push dword $func->{target_dll_index}
call _find_sym
mov dword [$func->{name}_addr], eax
$func->{name}_go:
; Bypass the profiling code and jump straight into the taget
; function when not profiling.
cmp byte [_stubs_enable_profile], 0
je $func->{name}_skip
push ebp
mov ebp, esp
; Push tick count onto stack (ebp - 8)
sub esp, 8
push esp
call _QueryPerformanceCounter\@4
; Copy original arguments ($to_copy bytes)
END
for(; $to_copy >= 4;)
{
$to_copy -= 4;
print CODE <<"END";
push dword [ebp + 4 + 4 + $to_copy]
END
}
for(; $to_copy >= 2;)
{
$to_copy -= 2;
print CODE <<"END";
push word [ebp + 4 + 4 + $to_copy]
END
}
for(; $to_copy >= 1;)
{
$to_copy -= 1;
print CODE <<"END";
push byte [ebp + 4 + 4 + $to_copy]
END
}
print CODE <<"END";
; Call target function
call [$func->{name}_addr]
; Push target function return value onto stack (ebp - 12)
push eax
; Push tick count onto stack (ebp - 20)
sub esp, 8
push esp
call _QueryPerformanceCounter\@4
; End tick parameter to _fprof_record_timed
push dword ebp
sub dword [esp], 20
; Start tick parameter to _fprof_record_timed
push dword ebp
sub dword [esp], 8
; FuncStats parameter to _fprof_record_timed
push dword $func->{name}_fstats
; Record profiling data
call _fprof_record_timed
add esp, 8 ; Pop end tick count
pop eax ; Pop return value
add esp, 8 ; Pop start tick count
pop ebp ; Restore caller's ebp
ret $func->{params}
$func->{name}_skip:
jmp [$func->{name}_addr]
END
}
else{
print CODE <<"END";
global _$func->{name}
_$func->{name}:
; Log the call
push dword $func->{target_dll_index}
push $func->{name}_target_func
push dword $dll_index
call _log_call
; Check if we have address cached
cmp dword [$func->{name}_addr], 0
jne $func->{name}_go
; Fetch target function address
push $func->{name}_target_func
push dword $func->{target_dll_index}
call _find_sym
mov dword [$func->{name}_addr], eax
$func->{name}_go:
; Record that we were called
push dword $func->{name}_fstats
call _fprof_record_untimed
; Jump into target function. We have left the stack as we found it
; so it can take over our frame.
jmp [$func->{name}_addr]
END
}
print CODE "\tcmp\tdword [$f_name\_addr], 0\n";
print CODE "\tjne\t$f_name\_jmp\n";
print CODE "\tpush\t$f_name\_sym\n";
print CODE "\tpush\tdword ".$func->{"dllnum"}."\n";
print CODE "\tcall\t_find_sym\n";
print CODE "\tmov\t[$f_name\_addr], eax\n";
print CODE "\t$f_name\_jmp:\n";
print CODE "\tjmp\t[$f_name\_addr]\n";
}
close(CODE);

View File

@ -1,5 +1,5 @@
/* IPXWrapper - Common functions
* Copyright (C) 2011-2021 Daniel Collins <solemnwarning@solemnwarning.net>
* Copyright (C) 2011-2023 Daniel Collins <solemnwarning@solemnwarning.net>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
@ -23,6 +23,7 @@
enum ipx_log_level min_log_level = LOG_INFO;
/* Must be kept in sync with DLL_INDICES in mkstubs.pl! */
static const char *dll_names[] = {
"ipxwrapper.dll",
"wsock32.dll",
@ -30,6 +31,7 @@ static const char *dll_names[] = {
"dpwsockx.dll",
"ws2_32.dll",
"wpcap.dll",
"ipxconfig.exe",
NULL
};

View File

@ -24,6 +24,7 @@
#include <stdbool.h>
#include "addr.h"
#include "funcprof.h"
#ifdef __cplusplus
extern "C" {
@ -39,6 +40,12 @@ enum ipx_log_level {
extern enum ipx_log_level min_log_level;
/* Defined by stubs */
extern struct FuncStats stub_fstats[];
extern const unsigned int NUM_STUBS;
extern const char *STUBS_DLL_NAME;
extern unsigned char stubs_enable_profile;
const char *w32_error(DWORD errnum);
HKEY reg_open_main(bool readwrite);

View File

@ -33,6 +33,7 @@ main_config_t get_main_config(void)
config.encap_type = ENCAP_TYPE_IPXWRAPPER;
config.frame_type = FRAME_TYPE_ETH_II;
config.log_level = LOG_INFO;
config.profile = false;
config.dosbox_server_addr = NULL;
config.dosbox_server_port = 213;
@ -59,6 +60,7 @@ main_config_t get_main_config(void)
config.encap_type = reg_get_dword(reg, "use_pcap", config.encap_type);
config.frame_type = reg_get_dword(reg, "frame_type", config.frame_type);
config.log_level = reg_get_dword(reg, "log_level", config.log_level);
config.profile = reg_get_dword(reg, "profile", config.profile);
config.dosbox_server_addr = reg_get_string(reg, "dosbox_server_addr", "");
config.dosbox_server_port = reg_get_dword(reg, "dosbox_server_port", config.dosbox_server_port);
@ -91,6 +93,7 @@ bool set_main_config(const main_config_t *config)
&& reg_set_dword(reg, "use_pcap", config->encap_type)
&& reg_set_dword(reg, "frame_type", config->frame_type)
&& reg_set_dword(reg, "log_level", config->log_level)
&& reg_set_dword(reg, "profile", config->profile)
&& reg_set_string(reg, "dosbox_server_addr", config->dosbox_server_addr)
&& reg_set_dword(reg, "dosbox_server_port", config->dosbox_server_port);

View File

@ -52,6 +52,7 @@ typedef struct main_config {
uint16_t dosbox_server_port;
enum ipx_log_level log_level;
bool profile;
} main_config_t;
struct v1_global_config {

View File

@ -1,5 +1,5 @@
/* ipxwrapper - DirectPlay service provider
* Copyright (C) 2011 Daniel Collins <solemnwarning@solemnwarning.net>
* Copyright (C) 2011-2019 Daniel Collins <solemnwarning@solemnwarning.net>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
@ -725,6 +725,8 @@ HRESULT WINAPI SPInit(LPSPINITDATA data) {
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
if(fdwReason == DLL_PROCESS_ATTACH)
{
fprof_init(stub_fstats, NUM_STUBS);
log_open("ipxwrapper.log");
min_log_level = get_main_config().log_level;
@ -743,6 +745,8 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
unload_dlls();
log_close();
fprof_cleanup(stub_fstats, NUM_STUBS);
}
return TRUE;

View File

@ -1,9 +1,10 @@
r_SPInit
DPWS_GetEnumPort
DPWS_BuildIPMessageHeader
WSACreateEvent:4
WSACloseEvent:4
WSAEventSelect:4
WSAResetEvent:4
WSASetEvent:4
Function name Target DLL Target function
------------------------------------------------------------
r_SPInit dpwsockx.dll SPInit
DPWS_GetEnumPort dpwsockx.dll DPWS_GetEnumPort
DPWS_BuildIPMessageHeader dpwsockx.dll DPWS_BuildIPMessageHeader
WSACreateEvent ws2_32.dll WSACreateEvent
WSACloseEvent ws2_32.dll WSACloseEvent
WSAEventSelect ws2_32.dll WSAEventSelect
WSAResetEvent ws2_32.dll WSAResetEvent
WSASetEvent ws2_32.dll WSASetEvent

129
src/funcprof.c Normal file
View File

@ -0,0 +1,129 @@
/* IPXWrapper - Function profiling functions
* Copyright (C) 2019 Daniel Collins <solemnwarning@solemnwarning.net>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* This program 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 General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <windows.h>
#include "common.h"
#include "funcprof.h"
void fprof_init(struct FuncStats *fstats, size_t n_fstats)
{
for(size_t i = 0; i < n_fstats; ++i)
{
fstats[i].min_time = 0.0;
fstats[i].max_time = 0.0;
fstats[i].total_time = 0.0;
fstats[i].n_calls = 0;
InitializeCriticalSectionAndSpinCount(&(fstats[i].cs), 0x80000000);
}
}
void fprof_cleanup(struct FuncStats *fstats, size_t n_fstats)
{
for(size_t i = 0; i < n_fstats; ++i)
{
DeleteCriticalSection(&(fstats[i].cs));
}
}
__stdcall void fprof_record_timed(struct FuncStats *fstats, const LARGE_INTEGER *start, const LARGE_INTEGER *end)
{
EnterCriticalSection(&(fstats->cs));
float this_time = end->QuadPart - start->QuadPart;
if(fstats->n_calls == 0)
{
fstats->min_time = this_time;
fstats->max_time = this_time;
fstats->total_time = this_time;
}
else{
if(fstats->min_time > this_time)
{
fstats->min_time = this_time;
}
if(fstats->max_time < this_time)
{
fstats->max_time = this_time;
}
fstats->total_time += this_time;
}
++(fstats->n_calls);
LeaveCriticalSection(&(fstats->cs));
}
__stdcall void fprof_record_untimed(struct FuncStats *fstats)
{
EnterCriticalSection(&(fstats->cs));
++(fstats->n_calls);
LeaveCriticalSection(&(fstats->cs));
}
void fprof_report(const char *dll_name, struct FuncStats *fstats, size_t n_fstats)
{
LARGE_INTEGER freq; /* TODO: Cache somewhere */
QueryPerformanceFrequency(&freq);
const float TICKS_PER_USEC = freq.QuadPart / 1000000.0;
for(size_t i = 0; i < n_fstats; ++i)
{
EnterCriticalSection(&(fstats[i].cs));
float min_time = fstats[i].min_time;
float max_time = fstats[i].max_time;
float total_time = fstats[i].total_time;
unsigned int n_calls = fstats[i].n_calls;
fstats[i].n_calls = 0;
LeaveCriticalSection(&(fstats[i].cs));
if(n_calls > 0)
{
if(total_time > 0.0)
{
log_printf(LOG_INFO,
"%s:%s was called %u times duration total %fus min %fus max %fus avg %fus",
dll_name,
fstats[i].func_name,
n_calls,
(total_time / TICKS_PER_USEC),
(min_time / TICKS_PER_USEC),
(max_time / TICKS_PER_USEC),
((total_time / (float)(n_calls)) / TICKS_PER_USEC));
}
else{
log_printf(LOG_INFO,
"%s:%s was called %u times",
dll_name,
fstats[i].func_name,
n_calls);
}
}
}
}

64
src/funcprof.h Normal file
View File

@ -0,0 +1,64 @@
/* IPXWrapper - Function profiling functions
* Copyright (C) 2019 Daniel Collins <solemnwarning@solemnwarning.net>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* This program 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 General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef IPXWRAPPER_FUNCPROF_H
#define IPXWRAPPER_FUNCPROF_H
#include <windows.h>
#ifdef __cplusplus
extern "C" {
#endif
struct FuncStats
{
const char *func_name;
float min_time, max_time, total_time;
unsigned int n_calls;
CRITICAL_SECTION cs;
};
void fprof_init(struct FuncStats *fstats, size_t n_fstats);
void fprof_cleanup(struct FuncStats *fstats, size_t n_fstats);
__stdcall void fprof_record_timed(struct FuncStats *fstats, const LARGE_INTEGER *start, const LARGE_INTEGER *end);
__stdcall void fprof_record_untimed(struct FuncStats *fstats);
void fprof_report(const char *dll_name, struct FuncStats *fstats, size_t n_fstats);
#define FPROF_RECORD_SCOPE(fstats) \
__attribute__((cleanup (_fprof_record_scope_exit))) struct _fprof_record_scope_ctx fstats_scoped_ctx = { fstats }; \
QueryPerformanceCounter(&(fstats_scoped_ctx.enter_time));
struct _fprof_record_scope_ctx {
struct FuncStats *fstats;
LARGE_INTEGER enter_time;
};
static inline void _fprof_record_scope_exit(struct _fprof_record_scope_ctx *ctx)
{
LARGE_INTEGER leave_time;
QueryPerformanceCounter(&leave_time);
fprof_record_timed(ctx->fstats, &(ctx->enter_time), &leave_time);
}
#ifdef __cplusplus
}
#endif
#endif /* !IPXWRAPPER_FUNCPROF_H */

View File

@ -1,5 +1,5 @@
/* IPXWrapper - Configuration tool
* Copyright (C) 2011-2022 Daniel Collins <solemnwarning@solemnwarning.net>
* Copyright (C) 2011-2023 Daniel Collins <solemnwarning@solemnwarning.net>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
@ -41,6 +41,7 @@ enum {
ID_OPT_W95 = 22,
ID_OPT_LOG_DEBUG = 25,
ID_OPT_LOG_TRACE = 26,
ID_OPT_PROFILE = 27,
ID_OK = 31,
ID_CANCEL = 32,
@ -142,6 +143,7 @@ static struct {
HWND opt_w95;
HWND opt_log_debug;
HWND opt_log_trace;
HWND opt_profile;
HWND ok_btn;
HWND can_btn;
@ -257,6 +259,8 @@ static LRESULT CALLBACK groupbox_wproc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp
int main()
{
fprof_init(stub_fstats, NUM_STUBS);
INITCOMMONCONTROLSEX common_controls;
common_controls.dwSize = sizeof(common_controls);
common_controls.dwICC = ICC_LISTVIEW_CLASSES;
@ -316,6 +320,8 @@ int main()
}
}
fprof_cleanup(stub_fstats, NUM_STUBS);
return msg.wParam;
}
@ -584,6 +590,8 @@ static bool save_config()
}
}
main_config.profile = get_checkbox(wh.opt_profile);
if(main_config.encap_type == ENCAP_TYPE_IPXWRAPPER || main_config.encap_type == ENCAP_TYPE_PCAP)
{
for(auto i = nics.begin(); i != nics.end(); i++)
@ -792,6 +800,7 @@ static void main_window_init()
* | Enable Windows 95 SO_BROADCAST bug |
* | Log debugging messages |
* | Log WinSock API calls |
* | Log profiling counters |
* +---------------------------------------------------------+
*/
@ -801,10 +810,12 @@ static void main_window_init()
wh.opt_w95 = create_checkbox(wh.box_options, "Enable Windows 95 SO_BROADCAST bug", ID_OPT_W95);
wh.opt_log_debug = create_checkbox(wh.box_options, "Log debugging messages", ID_OPT_LOG_DEBUG);
wh.opt_log_trace = create_checkbox(wh.box_options, "Log WinSock API calls", ID_OPT_LOG_TRACE);
wh.opt_profile = create_checkbox(wh.box_options, "Log profiling counters", ID_OPT_PROFILE);
set_checkbox(wh.opt_w95, main_config.w95_bug);
set_checkbox(wh.opt_log_debug, main_config.log_level <= LOG_DEBUG);
set_checkbox(wh.opt_log_trace, main_config.log_level <= LOG_CALL);
set_checkbox(wh.opt_profile, main_config.profile);
}
wh.ok_btn = create_child(wh.main, "BUTTON", "OK", BS_PUSHBUTTON | WS_TABSTOP, 0, ID_OK);
@ -978,6 +989,9 @@ static void main_window_init()
MoveWindow(wh.opt_log_trace, BOX_SIDE_PAD, box_options_y, BOX_INNER_WIDTH, text_h, TRUE);
box_options_y += text_h + 2;
MoveWindow(wh.opt_profile, BOX_SIDE_PAD, box_options_y, BOX_INNER_WIDTH, text_h, TRUE);
box_options_y += text_h + 2;
int box_options_h = box_options_y + BOX_BOTTOM_PAD;
MoveWindow(wh.box_options, BOX_SIDE_MARGIN, 0, BOX_WIDTH, box_options_h, TRUE);

10
src/ipxconfig_stubs.txt Normal file
View File

@ -0,0 +1,10 @@
Function name Target DLL Target function Parameters (bytes)
-----------------------------------------------------------------------------
pcap_open wpcap.dll pcap_open
pcap_close wpcap.dll pcap_close
pcap_findalldevs_ex wpcap.dll pcap_findalldevs_ex
pcap_freealldevs wpcap.dll pcap_freealldevs
pcap_getevent wpcap.dll pcap_getevent
pcap_dispatch wpcap.dll pcap_dispatch
pcap_geterr wpcap.dll pcap_geterr
pcap_sendpacket wpcap.dll pcap_sendpacket

View File

@ -30,6 +30,7 @@
#include "ipxwrapper.h"
#include "common.h"
#include "funcprof.h"
#include "interface.h"
#include "router.h"
#include "addrcache.h"
@ -50,6 +51,17 @@ static CRITICAL_SECTION sockets_cs;
typedef ULONGLONG WINAPI (*GetTickCount64_t)(void);
static HMODULE kernel32 = NULL;
struct FuncStats ipxwrapper_fstats[] = {
#define FPROF_DECL(func) { #func },
#include "ipxwrapper_prof_defs.h"
#undef FPROF_DECL
};
const unsigned int ipxwrapper_fstats_size = sizeof(ipxwrapper_fstats) / sizeof(*ipxwrapper_fstats);
unsigned int send_packets = 0, send_bytes = 0; /* Sent from emulated socket */
unsigned int recv_packets = 0, recv_bytes = 0; /* Forwarded to emulated socket */
static void init_cs(CRITICAL_SECTION *cs)
{
if(!InitializeCriticalSectionAndSpinCount(cs, 0x80000000))
@ -59,10 +71,42 @@ static void init_cs(CRITICAL_SECTION *cs)
}
}
static HANDLE prof_thread_handle = NULL;
static HANDLE prof_thread_exit = NULL;
static void report_packet_stats(void)
{
unsigned int my_send_packets = __atomic_exchange_n(&send_packets, 0, __ATOMIC_RELAXED);
unsigned int my_send_bytes = __atomic_exchange_n(&send_bytes, 0, __ATOMIC_RELAXED);
unsigned int my_recv_packets = __atomic_exchange_n(&recv_packets, 0, __ATOMIC_RELAXED);
unsigned int my_recv_bytes = __atomic_exchange_n(&recv_bytes, 0, __ATOMIC_RELAXED);
log_printf(LOG_INFO, "IPX sockets sent %u packets (%u bytes)", my_send_packets, my_send_bytes);
log_printf(LOG_INFO, "IPX sockets received %u packets (%u bytes)", my_recv_packets, my_recv_bytes);
}
static DWORD WINAPI prof_thread_main(LPVOID lpParameter)
{
static const int PROF_INTERVAL_MS = 10000;
while(WaitForSingleObject(prof_thread_exit, PROF_INTERVAL_MS) == WAIT_TIMEOUT)
{
fprof_report(STUBS_DLL_NAME, stub_fstats, NUM_STUBS);
fprof_report("ipxwrapper.dll", ipxwrapper_fstats, ipxwrapper_fstats_size);
report_packet_stats();
}
return 0;
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
if(fdwReason == DLL_PROCESS_ATTACH)
{
fprof_init(stub_fstats, NUM_STUBS);
fprof_init(ipxwrapper_fstats, ipxwrapper_fstats_size);
log_open("ipxwrapper.log");
log_printf(LOG_INFO, "IPXWrapper %s", version_string);
@ -104,6 +148,35 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
}
router_init();
if(main_config.profile)
{
stubs_enable_profile = true;
prof_thread_exit = CreateEvent(NULL, FALSE, FALSE, NULL);
if(prof_thread_exit != NULL)
{
prof_thread_handle = CreateThread(
NULL, /* lpThreadAttributes */
0, /* dwStackSize */
&prof_thread_main, /* lpStartAddress */
NULL, /* lpParameter */
0, /* dwCreationFlags */
NULL); /* lpThreadId */
if(prof_thread_handle == NULL)
{
log_printf(LOG_ERROR,
"Unable to create prof_thread_main thread: %s",
w32_error(GetLastError()));
}
}
else{
log_printf(LOG_ERROR,
"Unable to create prof_thread_exit event object: %s",
w32_error(GetLastError()));
}
}
}
else if(fdwReason == DLL_PROCESS_DETACH)
{
@ -117,6 +190,22 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
return TRUE;
}
if(prof_thread_exit != NULL)
{
SetEvent(prof_thread_exit);
if(prof_thread_handle != NULL)
{
WaitForSingleObject(prof_thread_handle, INFINITE);
CloseHandle(prof_thread_handle);
prof_thread_handle = NULL;
}
CloseHandle(prof_thread_exit);
prof_thread_exit = NULL;
}
router_cleanup();
WSACleanup();
@ -129,6 +218,14 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
unload_dlls();
if(main_config.profile)
{
fprof_report(STUBS_DLL_NAME, stub_fstats, NUM_STUBS);
fprof_report("ipxwrapper.dll", ipxwrapper_fstats, ipxwrapper_fstats_size);
report_packet_stats();
}
log_close();
if(kernel32)
@ -136,6 +233,9 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
FreeLibrary(kernel32);
kernel32 = NULL;
}
fprof_cleanup(ipxwrapper_fstats, ipxwrapper_fstats_size);
fprof_cleanup(stub_fstats, NUM_STUBS);
}
return TRUE;
@ -181,6 +281,7 @@ ipx_socket *get_socket_wait_for_ready(SOCKET sockfd, int timeout_ms)
/* Lock the mutex */
void lock_sockets(void)
{
FPROF_RECORD_SCOPE(&(ipxwrapper_fstats[IPXWRAPPER_FSTATS_lock_sockets]));
EnterCriticalSection(&sockets_cs);
}

View File

@ -27,6 +27,7 @@
#include <uthash.h>
#include "config.h"
#include "funcprof.h"
#include "router.h"
/* The standard Windows driver (in XP) only allows 1467 bytes anyway */
@ -188,6 +189,17 @@ struct spxinit
extern ipx_socket *sockets;
extern main_config_t main_config;
extern struct FuncStats ipxwrapper_fstats[];
enum {
#define FPROF_DECL(func) IPXWRAPPER_FSTATS_ ## func,
#include "ipxwrapper_prof_defs.h"
#undef FPROF_DECL
};
extern unsigned int send_packets, send_bytes; /* Sent from emulated socket */
extern unsigned int recv_packets, recv_bytes; /* Forwarded to emulated socket */
ipx_socket *get_socket(SOCKET sockfd);
ipx_socket *get_socket_wait_for_ready(SOCKET sockfd, int timeout_ms);
void lock_sockets(void);

View File

@ -0,0 +1,5 @@
FPROF_DECL(_deliver_packet)
FPROF_DECL(_handle_udp_recv)
FPROF_DECL(_handle_dosbox_recv)
FPROF_DECL(_handle_pcap_frame)
FPROF_DECL(lock_sockets)

View File

@ -1,38 +1,49 @@
inet_addr:4
WSAStartup:4
WSACleanup:4
WSASetLastError:4
WSAGetLastError:4
htonl:4
ntohl:4
htons:4
ntohs:4
r_select:4
r_listen:4
r_accept:4
WSACreateEvent:4
WSAEventSelect:4
WSACloseEvent:4
WSAResetEvent:4
WSASetEvent:4
r_EnumProtocolsA:2
r_EnumProtocolsW:2
r_WSARecvEx:2
r_bind:4
r_closesocket:4
r_getsockname:4
r_getsockopt:4
r_recv:4
r_recvfrom:4
r_sendto:4
r_setsockopt:4
r_shutdown:4
r_socket:4
r_ioctlsocket:4
r_connect:4
r_send:4
r_getpeername:4
inet_ntoa:4
__WSAFDIsSet:4
r_WSAAsyncSelect:4
gethostbyname:4
Function name Target DLL Target function Parameters (bytes)
-------------------------------------------------------------------------------
inet_addr ws2_32.dll inet_addr 4
WSAStartup ws2_32.dll WSAStartup 8
WSACleanup ws2_32.dll WSACleanup 0
WSASetLastError ws2_32.dll WSASetLastError 4
WSAGetLastError ws2_32.dll WSAGetLastError 0
htonl ws2_32.dll htonl 4
ntohl ws2_32.dll ntohl 4
htons ws2_32.dll htons 4
ntohs ws2_32.dll ntohs 4
r_select ws2_32.dll select 20
r_listen ws2_32.dll listen 8
r_accept ws2_32.dll accept 12
WSACreateEvent ws2_32.dll WSACreateEvent 0
WSAEventSelect ws2_32.dll WSAEventSelect 12
WSACloseEvent ws2_32.dll WSACloseEvent 4
WSAResetEvent ws2_32.dll WSAResetEvent 4
WSASetEvent ws2_32.dll WSASetEvent 4
r_EnumProtocolsA mswsock.dll EnumProtocolsA 12
r_EnumProtocolsW mswsock.dll EnumProtocolsW 12
r_WSARecvEx mswsock.dll WSARecvEx 16
r_bind ws2_32.dll bind 12
r_closesocket ws2_32.dll closesocket 4
r_getsockname ws2_32.dll getsockname 12
r_getsockopt ws2_32.dll getsockopt 20
r_recv ws2_32.dll recv 16
r_recvfrom ws2_32.dll recvfrom 24
r_sendto ws2_32.dll sendto 24
r_setsockopt ws2_32.dll setsockopt 20
r_shutdown ws2_32.dll shutdown 8
r_socket ws2_32.dll socket 12
r_ioctlsocket ws2_32.dll ioctlsocket 12
r_connect ws2_32.dll connect 12
r_send ws2_32.dll send 16
r_getpeername ws2_32.dll getpeername 12
inet_ntoa ws2_32.dll inet_ntoa 4
__WSAFDIsSet ws2_32.dll __WSAFDIsSet 8
r_WSAAsyncSelect ws2_32.dll WSAAsyncSelect 16
gethostbyname ws2_32.dll gethostbyname 4
pcap_open wpcap.dll pcap_open
pcap_close wpcap.dll pcap_close
pcap_findalldevs_ex wpcap.dll pcap_findalldevs_ex
pcap_freealldevs wpcap.dll pcap_freealldevs
pcap_getevent wpcap.dll pcap_getevent
pcap_dispatch wpcap.dll pcap_dispatch
pcap_geterr wpcap.dll pcap_geterr
pcap_sendpacket wpcap.dll pcap_sendpacket

View File

@ -1,35 +1,37 @@
ServiceMain
SvchostPushServiceGlobals
AcceptEx
EnumProtocolsA:0
EnumProtocolsW:0
GetAcceptExSockaddrs
GetAddressByNameA
GetAddressByNameW
GetNameByTypeA
GetNameByTypeW
GetServiceA
GetServiceW
GetTypeByNameA
GetTypeByNameW
MigrateWinsockConfiguration
NPLoadNameSpaces
NSPStartup
SetServiceA
SetServiceW
StartWsdpService
StopWsdpService
TransmitFile
WSARecvEx:0
WSPStartup
dn_expand
getnetbyname
inet_network
rcmd
rexec
rresvport
s_perror
sethostname
inet_addr
WSHEnumProtocols:0
ntohs:1
Function name Target DLL Target function Parameters (bytes)
--------------------------------------------------------------------------------------------------
ServiceMain mswsock.dll ServiceMain
SvchostPushServiceGlobals mswsock.dll SvchostPushServiceGlobals
AcceptEx mswsock.dll AcceptEx 32
EnumProtocolsA ipxwrapper.dll EnumProtocolsA 12
EnumProtocolsW ipxwrapper.dll EnumProtocolsW 12
GetAcceptExSockaddrs mswsock.dll GetAcceptExSockaddrs 32
GetAddressByNameA mswsock.dll GetAddressByNameA 40
GetAddressByNameW mswsock.dll GetAddressByNameW 40
GetNameByTypeA mswsock.dll GetNameByTypeA 12
GetNameByTypeW mswsock.dll GetNameByTypeW 12
GetServiceA mswsock.dll GetServiceA 28
GetServiceW mswsock.dll GetServiceW 28
GetTypeByNameA mswsock.dll GetTypeByNameA 8
GetTypeByNameW mswsock.dll GetTypeByNameW 8
MigrateWinsockConfiguration mswsock.dll MigrateWinsockConfiguration
NPLoadNameSpaces mswsock.dll NPLoadNameSpaces
NSPStartup mswsock.dll NSPStartup 8
SetServiceA mswsock.dll SetServiceA 24
SetServiceW mswsock.dll SetServiceW 24
StartWsdpService mswsock.dll StartWsdpService
StopWsdpService mswsock.dll StopWsdpService
TransmitFile mswsock.dll TransmitFile 28
WSARecvEx ipxwrapper.dll WSARecvEx 16
WSPStartup mswsock.dll WSPStartup 76
dn_expand mswsock.dll dn_expand
getnetbyname mswsock.dll getnetbyname
inet_network mswsock.dll inet_network
rcmd mswsock.dll rcmd
rexec mswsock.dll rexec
rresvport mswsock.dll rresvport
s_perror mswsock.dll s_perror
sethostname mswsock.dll sethostname
inet_addr mswsock.dll inet_addr 4
WSHEnumProtocols ipxwrapper.dll WSHEnumProtocols 16
ntohs wsock32.dll ntohs 4

View File

@ -26,6 +26,7 @@
#include "router.h"
#include "common.h"
#include "funcprof.h"
#include "ipxwrapper.h"
#include "interface.h"
#include "addrcache.h"
@ -230,6 +231,8 @@ static void _deliver_packet(
const void *data,
size_t data_size)
{
FPROF_RECORD_SCOPE(&(ipxwrapper_fstats[IPXWRAPPER_FSTATS__deliver_packet]));
{
IPX_STRING_ADDR(src_addr, src_net, src_node, src_socket);
IPX_STRING_ADDR(dest_addr, dest_net, dest_node, dest_socket);
@ -344,6 +347,10 @@ static void _deliver_packet(
{
log_printf(LOG_ERROR, "Error relaying packet: %s", w32_error(WSAGetLastError()));
}
else{
__atomic_add_fetch(&recv_packets, 1, __ATOMIC_RELAXED);
__atomic_add_fetch(&recv_bytes, data_size, __ATOMIC_RELAXED);
}
free(packet);
}
@ -353,6 +360,8 @@ static void _deliver_packet(
static void _handle_udp_recv(ipx_packet *packet, size_t packet_size, struct sockaddr_in src_ip)
{
FPROF_RECORD_SCOPE(&(ipxwrapper_fstats[IPXWRAPPER_FSTATS__handle_udp_recv]));
size_t data_size = ntohs(packet->size);
if(packet_size < sizeof(ipx_packet) - 1 || data_size > MAX_DATA_SIZE || data_size + sizeof(ipx_packet) - 1 != packet_size)
@ -536,6 +545,8 @@ static void _handle_dosbox_registration_response(novell_ipx_packet *packet, size
static void _handle_dosbox_recv(novell_ipx_packet *packet, size_t packet_size)
{
FPROF_RECORD_SCOPE(&(ipxwrapper_fstats[IPXWRAPPER_FSTATS__handle_dosbox_recv]));
if(packet_size < sizeof(novell_ipx_packet) || ntohs(packet->length) != packet_size)
{
/* Doesn't look valid. */
@ -617,6 +628,8 @@ static bool _do_udp_recv(int fd)
static void _handle_pcap_frame(u_char *user, const struct pcap_pkthdr *pkt_header, const u_char *pkt_data)
{
FPROF_RECORD_SCOPE(&(ipxwrapper_fstats[IPXWRAPPER_FSTATS__handle_pcap_frame]));
ipx_interface_t *iface = (ipx_interface_t*)(user);
const novell_ipx_packet *ipx;

View File

@ -1,5 +1,5 @@
/* IPXWrapper - Stub DLL functions
* Copyright (C) 2008-2011 Daniel Collins <solemnwarning@solemnwarning.net>
* Copyright (C) 2008-2023 Daniel Collins <solemnwarning@solemnwarning.net>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
@ -21,13 +21,52 @@
#include "common.h"
#include "config.h"
#include "funcprof.h"
static DWORD WINAPI prof_thread_main(LPVOID lpParameter);
static HANDLE prof_thread_handle = NULL;
static HANDLE prof_thread_exit = NULL;
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
if(fdwReason == DLL_PROCESS_ATTACH)
{
fprof_init(stub_fstats, NUM_STUBS);
log_open("ipxwrapper.log");
min_log_level = get_main_config().log_level;
main_config_t config = get_main_config();
min_log_level = config.log_level;
if(config.profile)
{
stubs_enable_profile = true;
prof_thread_exit = CreateEvent(NULL, FALSE, FALSE, NULL);
if(prof_thread_exit != NULL)
{
prof_thread_handle = CreateThread(
NULL, /* lpThreadAttributes */
0, /* dwStackSize */
&prof_thread_main, /* lpStartAddress */
NULL, /* lpParameter */
0, /* dwCreationFlags */
NULL); /* lpThreadId */
if(prof_thread_handle == NULL)
{
log_printf(LOG_ERROR,
"Unable to create prof_thread_main thread: %s",
w32_error(GetLastError()));
}
}
else{
log_printf(LOG_ERROR,
"Unable to create prof_thread_exit event object: %s",
w32_error(GetLastError()));
}
}
}
else if(fdwReason == DLL_PROCESS_DETACH)
{
@ -41,9 +80,45 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
return TRUE;
}
if(prof_thread_exit != NULL)
{
SetEvent(prof_thread_exit);
if(prof_thread_handle != NULL)
{
WaitForSingleObject(prof_thread_handle, INFINITE);
CloseHandle(prof_thread_handle);
prof_thread_handle = NULL;
}
CloseHandle(prof_thread_exit);
prof_thread_exit = NULL;
}
unload_dlls();
if(stubs_enable_profile)
{
fprof_report(STUBS_DLL_NAME, stub_fstats, NUM_STUBS);
}
log_close();
fprof_cleanup(stub_fstats, NUM_STUBS);
}
return TRUE;
}
static DWORD WINAPI prof_thread_main(LPVOID lpParameter)
{
static const int PROF_INTERVAL_MS = 10000;
while(WaitForSingleObject(prof_thread_exit, PROF_INTERVAL_MS) == WAIT_TIMEOUT)
{
fprof_report(STUBS_DLL_NAME, stub_fstats, NUM_STUBS);
}
return 0;
}

View File

@ -1475,6 +1475,9 @@ static DWORD ipx_send_packet(
if(pcap_sendpacket(iface->pcap, (void*)(frame), frame_size) == 0)
{
__atomic_add_fetch(&send_packets, 1, __ATOMIC_RELAXED);
__atomic_add_fetch(&send_bytes, data_size, __ATOMIC_RELAXED);
free(frame);
return ERROR_SUCCESS;
}
@ -1531,6 +1534,10 @@ static DWORD ipx_send_packet(
error = WSAGetLastError();
log_printf(LOG_ERROR, "Error sending DOSBox IPX packet: %s", w32_error(error));
}
else{
__atomic_add_fetch(&send_packets, 1, __ATOMIC_RELAXED);
__atomic_add_fetch(&send_bytes, data_size, __ATOMIC_RELAXED);
}
free(packet);
@ -1635,6 +1642,12 @@ static DWORD ipx_send_packet(
free(packet);
if(send_ok)
{
__atomic_add_fetch(&send_packets, 1, __ATOMIC_RELAXED);
__atomic_add_fetch(&send_bytes, data_size, __ATOMIC_RELAXED);
}
return send_ok
? ERROR_SUCCESS
: send_error;

View File

@ -1,8 +0,0 @@
pcap_open
pcap_close
pcap_findalldevs_ex
pcap_freealldevs
pcap_getevent
pcap_dispatch
pcap_geterr
pcap_sendpacket

View File

@ -1,76 +1,78 @@
accept:0
bind:0
closesocket:0
connect:0
getpeername:0
getsockname:0
getsockopt:0
htonl
htons
inet_addr
inet_ntoa
ioctlsocket:0
listen:0
ntohl
ntohs
recv:0
recvfrom:0
select:0
send:0
sendto:0
setsockopt:0
shutdown:0
socket:0
MigrateWinsockConfiguration
gethostbyaddr
gethostbyname
getprotobyname
getprotobynumber
getservbyname
getservbyport
gethostname
WSAAsyncSelect:0
WSAAsyncGetHostByAddr
WSAAsyncGetHostByName
WSAAsyncGetProtoByNumber
WSAAsyncGetProtoByName
WSAAsyncGetServByPort
WSAAsyncGetServByName
WSACancelAsyncRequest
WSASetBlockingHook
WSAUnhookBlockingHook
WSAGetLastError
WSASetLastError
WSACancelBlockingCall
WSAIsBlocking
WSAStartup
WSACleanup
__WSAFDIsSet
WEP
WSApSetPostRoutine
inet_network
getnetbyname
rcmd
rexec
rresvport
sethostname
dn_expand
WSARecvEx:0
s_perror
GetAddressByNameA
GetAddressByNameW
EnumProtocolsA:0
EnumProtocolsW:0
GetTypeByNameA
GetTypeByNameW
GetNameByTypeA
GetNameByTypeW
SetServiceA
SetServiceW
GetServiceA
GetServiceW
NPLoadNameSpaces
TransmitFile
AcceptEx
GetAcceptExSockaddrs
WSHEnumProtocols:0
Function name Target DLL Target function Parameters (bytes)
--------------------------------------------------------------------------------------------------
accept ipxwrapper.dll accept 12
bind ipxwrapper.dll bind 12
closesocket ipxwrapper.dll closesocket 4
connect ipxwrapper.dll connect 12
getpeername ipxwrapper.dll getpeername 12
getsockname ipxwrapper.dll getsockname 12
getsockopt ipxwrapper.dll getsockopt 20
htonl wsock32.dll htonl 4
htons wsock32.dll htons 4
inet_addr wsock32.dll inet_addr 4
inet_ntoa wsock32.dll inet_ntoa 4
ioctlsocket ipxwrapper.dll ioctlsocket 12
listen ipxwrapper.dll listen 8
ntohl wsock32.dll ntohl 4
ntohs wsock32.dll ntohs 4
recv ipxwrapper.dll recv 16
recvfrom ipxwrapper.dll recvfrom 24
select ipxwrapper.dll select 20
send ipxwrapper.dll send 16
sendto ipxwrapper.dll sendto 24
setsockopt ipxwrapper.dll setsockopt 20
shutdown ipxwrapper.dll shutdown 8
socket ipxwrapper.dll socket 12
MigrateWinsockConfiguration wsock32.dll MigrateWinsockConfiguration
gethostbyaddr wsock32.dll gethostbyaddr 12
gethostbyname wsock32.dll gethostbyname 4
getprotobyname wsock32.dll getprotobyname 4
getprotobynumber wsock32.dll getprotobynumber 4
getservbyname wsock32.dll getservbyname 8
getservbyport wsock32.dll getservbyport 8
gethostname wsock32.dll gethostname 8
WSAAsyncSelect ipxwrapper.dll WSAAsyncSelect 16
WSAAsyncGetHostByAddr wsock32.dll WSAAsyncGetHostByAddr 28
WSAAsyncGetHostByName wsock32.dll WSAAsyncGetHostByName 20
WSAAsyncGetProtoByNumber wsock32.dll WSAAsyncGetProtoByNumber 20
WSAAsyncGetProtoByName wsock32.dll WSAAsyncGetProtoByName 20
WSAAsyncGetServByPort wsock32.dll WSAAsyncGetServByPort 24
WSAAsyncGetServByName wsock32.dll WSAAsyncGetServByName 24
WSACancelAsyncRequest wsock32.dll WSACancelAsyncRequest 4
WSASetBlockingHook wsock32.dll WSASetBlockingHook 4
WSAUnhookBlockingHook wsock32.dll WSAUnhookBlockingHook 0
WSAGetLastError wsock32.dll WSAGetLastError 0
WSASetLastError wsock32.dll WSASetLastError 4
WSACancelBlockingCall wsock32.dll WSACancelBlockingCall 0
WSAIsBlocking wsock32.dll WSAIsBlocking 0
WSAStartup wsock32.dll WSAStartup 8
WSACleanup wsock32.dll WSACleanup 0
__WSAFDIsSet wsock32.dll __WSAFDIsSet 8
WEP wsock32.dll WEP
WSApSetPostRoutine wsock32.dll WSApSetPostRoutine
inet_network wsock32.dll inet_network
getnetbyname wsock32.dll getnetbyname
rcmd wsock32.dll rcmd
rexec wsock32.dll rexec
rresvport wsock32.dll rresvport
sethostname wsock32.dll sethostname
dn_expand wsock32.dll dn_expand
WSARecvEx ipxwrapper.dll WSARecvEx 16
s_perror wsock32.dll s_perror
GetAddressByNameA wsock32.dll GetAddressByNameA 40
GetAddressByNameW wsock32.dll GetAddressByNameW 40
EnumProtocolsA ipxwrapper.dll EnumProtocolsA 12
EnumProtocolsW ipxwrapper.dll EnumProtocolsW 12
GetTypeByNameA wsock32.dll GetTypeByNameA 8
GetTypeByNameW wsock32.dll GetTypeByNameW 8
GetNameByTypeA wsock32.dll GetNameByTypeA 12
GetNameByTypeW wsock32.dll GetNameByTypeW 12
SetServiceA wsock32.dll SetServiceA 24
SetServiceW wsock32.dll SetServiceW 24
GetServiceA wsock32.dll GetServiceA 28
GetServiceW wsock32.dll GetServiceW 28
NPLoadNameSpaces wsock32.dll NPLoadNameSpaces
TransmitFile wsock32.dll TransmitFile 28
AcceptEx wsock32.dll AcceptEx 32
GetAcceptExSockaddrs wsock32.dll GetAcceptExSockaddrs 32
WSHEnumProtocols ipxwrapper.dll WSHEnumProtocols 16