mirror of
https://github.com/solemnwarning/ipxwrapper
synced 2024-12-30 16:45:37 +01:00
Merge branch 'profiling'
This commit is contained in:
commit
bbe0dbd4e1
24
Makefile
24
Makefile
@ -86,62 +86,62 @@ dist: all
|
|||||||
|
|
||||||
IPXWRAPPER_OBJS := src/ipxwrapper.o src/winsock.o src/ipxwrapper_stubs.o src/log.o src/common.o \
|
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/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)
|
ipxwrapper.dll: $(IPXWRAPPER_OBJS)
|
||||||
echo 'const char *version_string = "$(VERSION)", *compile_time = "'`date`'";' | $(CC) -c -x c -o version.o -
|
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
|
$(CC) $(CFLAGS) -Wl,--enable-stdcall-fixup -static-libgcc -shared -o $@ $^ version.o -liphlpapi -lversion -lole32 -loleaut32
|
||||||
|
|
||||||
src/ipxwrapper_stubs.s: src/ipxwrapper_stubs.txt
|
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
|
||||||
#
|
#
|
||||||
|
|
||||||
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 $@ $^
|
$(CC) $(CFLAGS) -Wl,--enable-stdcall-fixup -static-libgcc -shared -o $@ $^
|
||||||
|
|
||||||
src/wsock32_stubs.s: src/wsock32_stubs.txt
|
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
|
||||||
#
|
#
|
||||||
|
|
||||||
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 $@ $^
|
$(CC) $(CFLAGS) -Wl,--enable-stdcall-fixup -static-libgcc -shared -o $@ $^
|
||||||
|
|
||||||
src/mswsock_stubs.s: src/mswsock_stubs.txt
|
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
|
||||||
#
|
#
|
||||||
|
|
||||||
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
|
$(CC) $(CFLAGS) -Wl,--enable-stdcall-fixup -static-libgcc -shared -o $@ $^ -lwsock32
|
||||||
|
|
||||||
src/dpwsockx_stubs.s: src/dpwsockx_stubs.txt
|
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.EXE
|
||||||
#
|
#
|
||||||
|
|
||||||
IPXCONFIG_OBJS := src/ipxconfig.o icons/ipxconfig.o src/addr.o src/interface2.o src/common.o \
|
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)
|
ipxconfig.exe: $(IPXCONFIG_OBJS)
|
||||||
$(CXX) $(CXXFLAGS) -Wl,--enable-stdcall-fixup -static-libgcc -static-libstdc++ -mwindows -o $@ $^ -liphlpapi -lcomctl32 -lws2_32
|
$(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
|
# 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
|
icons/%.o: icons/%.rc icons/%.ico
|
||||||
$(WINDRES) $< -O coff -o $@
|
$(WINDRES) $< -O coff -o $@
|
||||||
|
|
||||||
|
282
mkstubs.pl
282
mkstubs.pl
@ -1,5 +1,5 @@
|
|||||||
# IPXWrapper - Generate assembly stub functions
|
# 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
|
# 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
|
# under the terms of the GNU General Public License version 2 as published by
|
||||||
@ -18,74 +18,268 @@ use strict;
|
|||||||
use warnings;
|
use warnings;
|
||||||
|
|
||||||
if(@ARGV != 3) {
|
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);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
my $stub_file = $ARGV[0];
|
# Must be kept in sync with dll_names in common.c!
|
||||||
my $asm_file = $ARGV[1];
|
my %DLL_INDICES = (
|
||||||
my $dllnum = $ARGV[2];
|
"ipxwrapper.dll" => 0,
|
||||||
my $do_logging = ($dllnum != 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(STUBS, "<$stub_file") or die("Cannot open $stub_file: $!");
|
||||||
open(CODE, ">$asm_file") or die("Cannot open $asm_file: $!");
|
open(CODE, ">$asm_file") or die("Cannot open $asm_file: $!");
|
||||||
|
|
||||||
my @stubs = ();
|
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;
|
$line =~ s/[\r\n]//g;
|
||||||
|
|
||||||
if($line ne "") {
|
if($line ne "") {
|
||||||
my ($func, $dn) = split(/:/, $line);
|
my ($name, $target_dll, $target_func, $params) = split(/\s+/, $line);
|
||||||
$dn = $dllnum if(!defined($dn));
|
|
||||||
|
|
||||||
my $sym = $func;
|
my $target_dll_index = $DLL_INDICES{$target_dll}
|
||||||
$sym =~ s/^r_//;
|
// 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) {
|
extern _find_sym
|
||||||
print CODE "\t".$func->{"name"}."_sym:\tdb\t'".$func->{"sym"}."', 0\n";
|
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 <<"END";
|
||||||
print CODE "\t".$func->{"name"}."_addr:\tdd\t0\n";
|
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 <<"END";
|
||||||
print CODE "\textern\t_find_sym\n";
|
global _stub_fstats
|
||||||
print CODE "\textern\t_log_call\n" if($do_logging);
|
_stub_fstats:
|
||||||
|
END
|
||||||
|
|
||||||
foreach my $func(@stubs) {
|
foreach my $func(@stubs)
|
||||||
my $f_name = $func->{"name"};
|
{
|
||||||
|
print CODE <<"END";
|
||||||
print CODE "\nglobal\t_$f_name\n";
|
$func->{name}_fstats:
|
||||||
print CODE "_$f_name:\n";
|
istruc FuncStats
|
||||||
|
at FuncStats.func_name, dd $func->{name}_name
|
||||||
if($do_logging) {
|
iend
|
||||||
print CODE "\tpush\tdword ".$func->{"dllnum"}."\n";
|
END
|
||||||
print CODE "\tpush\t$f_name\_sym\n";
|
}
|
||||||
print CODE "\tpush\tdword $dllnum\n";
|
|
||||||
print CODE "\tcall\t_log_call\n";
|
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);
|
close(CODE);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* IPXWrapper - Common functions
|
/* 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
|
* 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
|
* 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;
|
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[] = {
|
static const char *dll_names[] = {
|
||||||
"ipxwrapper.dll",
|
"ipxwrapper.dll",
|
||||||
"wsock32.dll",
|
"wsock32.dll",
|
||||||
@ -30,6 +31,7 @@ static const char *dll_names[] = {
|
|||||||
"dpwsockx.dll",
|
"dpwsockx.dll",
|
||||||
"ws2_32.dll",
|
"ws2_32.dll",
|
||||||
"wpcap.dll",
|
"wpcap.dll",
|
||||||
|
"ipxconfig.exe",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
#include "addr.h"
|
#include "addr.h"
|
||||||
|
#include "funcprof.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -39,6 +40,12 @@ enum ipx_log_level {
|
|||||||
|
|
||||||
extern enum ipx_log_level min_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);
|
const char *w32_error(DWORD errnum);
|
||||||
|
|
||||||
HKEY reg_open_main(bool readwrite);
|
HKEY reg_open_main(bool readwrite);
|
||||||
|
@ -33,6 +33,7 @@ main_config_t get_main_config(void)
|
|||||||
config.encap_type = ENCAP_TYPE_IPXWRAPPER;
|
config.encap_type = ENCAP_TYPE_IPXWRAPPER;
|
||||||
config.frame_type = FRAME_TYPE_ETH_II;
|
config.frame_type = FRAME_TYPE_ETH_II;
|
||||||
config.log_level = LOG_INFO;
|
config.log_level = LOG_INFO;
|
||||||
|
config.profile = false;
|
||||||
|
|
||||||
config.dosbox_server_addr = NULL;
|
config.dosbox_server_addr = NULL;
|
||||||
config.dosbox_server_port = 213;
|
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.encap_type = reg_get_dword(reg, "use_pcap", config.encap_type);
|
||||||
config.frame_type = reg_get_dword(reg, "frame_type", config.frame_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.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_addr = reg_get_string(reg, "dosbox_server_addr", "");
|
||||||
config.dosbox_server_port = reg_get_dword(reg, "dosbox_server_port", config.dosbox_server_port);
|
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, "use_pcap", config->encap_type)
|
||||||
&& reg_set_dword(reg, "frame_type", config->frame_type)
|
&& reg_set_dword(reg, "frame_type", config->frame_type)
|
||||||
&& reg_set_dword(reg, "log_level", config->log_level)
|
&& 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_string(reg, "dosbox_server_addr", config->dosbox_server_addr)
|
||||||
&& reg_set_dword(reg, "dosbox_server_port", config->dosbox_server_port);
|
&& reg_set_dword(reg, "dosbox_server_port", config->dosbox_server_port);
|
||||||
|
@ -52,6 +52,7 @@ typedef struct main_config {
|
|||||||
uint16_t dosbox_server_port;
|
uint16_t dosbox_server_port;
|
||||||
|
|
||||||
enum ipx_log_level log_level;
|
enum ipx_log_level log_level;
|
||||||
|
bool profile;
|
||||||
} main_config_t;
|
} main_config_t;
|
||||||
|
|
||||||
struct v1_global_config {
|
struct v1_global_config {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ipxwrapper - DirectPlay service provider
|
/* 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
|
* 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
|
* 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) {
|
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
|
||||||
if(fdwReason == DLL_PROCESS_ATTACH)
|
if(fdwReason == DLL_PROCESS_ATTACH)
|
||||||
{
|
{
|
||||||
|
fprof_init(stub_fstats, NUM_STUBS);
|
||||||
|
|
||||||
log_open("ipxwrapper.log");
|
log_open("ipxwrapper.log");
|
||||||
|
|
||||||
min_log_level = get_main_config().log_level;
|
min_log_level = get_main_config().log_level;
|
||||||
@ -743,6 +745,8 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
|
|||||||
|
|
||||||
unload_dlls();
|
unload_dlls();
|
||||||
log_close();
|
log_close();
|
||||||
|
|
||||||
|
fprof_cleanup(stub_fstats, NUM_STUBS);
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
r_SPInit
|
Function name Target DLL Target function
|
||||||
DPWS_GetEnumPort
|
------------------------------------------------------------
|
||||||
DPWS_BuildIPMessageHeader
|
r_SPInit dpwsockx.dll SPInit
|
||||||
|
DPWS_GetEnumPort dpwsockx.dll DPWS_GetEnumPort
|
||||||
WSACreateEvent:4
|
DPWS_BuildIPMessageHeader dpwsockx.dll DPWS_BuildIPMessageHeader
|
||||||
WSACloseEvent:4
|
WSACreateEvent ws2_32.dll WSACreateEvent
|
||||||
WSAEventSelect:4
|
WSACloseEvent ws2_32.dll WSACloseEvent
|
||||||
WSAResetEvent:4
|
WSAEventSelect ws2_32.dll WSAEventSelect
|
||||||
WSASetEvent:4
|
WSAResetEvent ws2_32.dll WSAResetEvent
|
||||||
|
WSASetEvent ws2_32.dll WSASetEvent
|
||||||
|
129
src/funcprof.c
Normal file
129
src/funcprof.c
Normal 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
64
src/funcprof.h
Normal 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 */
|
@ -1,5 +1,5 @@
|
|||||||
/* IPXWrapper - Configuration tool
|
/* 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
|
* 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
|
* 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_W95 = 22,
|
||||||
ID_OPT_LOG_DEBUG = 25,
|
ID_OPT_LOG_DEBUG = 25,
|
||||||
ID_OPT_LOG_TRACE = 26,
|
ID_OPT_LOG_TRACE = 26,
|
||||||
|
ID_OPT_PROFILE = 27,
|
||||||
|
|
||||||
ID_OK = 31,
|
ID_OK = 31,
|
||||||
ID_CANCEL = 32,
|
ID_CANCEL = 32,
|
||||||
@ -142,6 +143,7 @@ static struct {
|
|||||||
HWND opt_w95;
|
HWND opt_w95;
|
||||||
HWND opt_log_debug;
|
HWND opt_log_debug;
|
||||||
HWND opt_log_trace;
|
HWND opt_log_trace;
|
||||||
|
HWND opt_profile;
|
||||||
|
|
||||||
HWND ok_btn;
|
HWND ok_btn;
|
||||||
HWND can_btn;
|
HWND can_btn;
|
||||||
@ -257,6 +259,8 @@ static LRESULT CALLBACK groupbox_wproc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp
|
|||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
|
fprof_init(stub_fstats, NUM_STUBS);
|
||||||
|
|
||||||
INITCOMMONCONTROLSEX common_controls;
|
INITCOMMONCONTROLSEX common_controls;
|
||||||
common_controls.dwSize = sizeof(common_controls);
|
common_controls.dwSize = sizeof(common_controls);
|
||||||
common_controls.dwICC = ICC_LISTVIEW_CLASSES;
|
common_controls.dwICC = ICC_LISTVIEW_CLASSES;
|
||||||
@ -316,6 +320,8 @@ int main()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fprof_cleanup(stub_fstats, NUM_STUBS);
|
||||||
|
|
||||||
return msg.wParam;
|
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)
|
if(main_config.encap_type == ENCAP_TYPE_IPXWRAPPER || main_config.encap_type == ENCAP_TYPE_PCAP)
|
||||||
{
|
{
|
||||||
for(auto i = nics.begin(); i != nics.end(); i++)
|
for(auto i = nics.begin(); i != nics.end(); i++)
|
||||||
@ -792,6 +800,7 @@ static void main_window_init()
|
|||||||
* | □ Enable Windows 95 SO_BROADCAST bug |
|
* | □ Enable Windows 95 SO_BROADCAST bug |
|
||||||
* | □ Log debugging messages |
|
* | □ Log debugging messages |
|
||||||
* | □ Log WinSock API calls |
|
* | □ 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_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_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_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_w95, main_config.w95_bug);
|
||||||
set_checkbox(wh.opt_log_debug, main_config.log_level <= LOG_DEBUG);
|
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_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);
|
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);
|
MoveWindow(wh.opt_log_trace, BOX_SIDE_PAD, box_options_y, BOX_INNER_WIDTH, text_h, TRUE);
|
||||||
box_options_y += text_h + 2;
|
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;
|
int box_options_h = box_options_y + BOX_BOTTOM_PAD;
|
||||||
|
|
||||||
MoveWindow(wh.box_options, BOX_SIDE_MARGIN, 0, BOX_WIDTH, box_options_h, TRUE);
|
MoveWindow(wh.box_options, BOX_SIDE_MARGIN, 0, BOX_WIDTH, box_options_h, TRUE);
|
||||||
|
10
src/ipxconfig_stubs.txt
Normal file
10
src/ipxconfig_stubs.txt
Normal 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
|
101
src/ipxwrapper.c
101
src/ipxwrapper.c
@ -30,6 +30,7 @@
|
|||||||
|
|
||||||
#include "ipxwrapper.h"
|
#include "ipxwrapper.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "funcprof.h"
|
||||||
#include "interface.h"
|
#include "interface.h"
|
||||||
#include "router.h"
|
#include "router.h"
|
||||||
#include "addrcache.h"
|
#include "addrcache.h"
|
||||||
@ -50,6 +51,17 @@ static CRITICAL_SECTION sockets_cs;
|
|||||||
typedef ULONGLONG WINAPI (*GetTickCount64_t)(void);
|
typedef ULONGLONG WINAPI (*GetTickCount64_t)(void);
|
||||||
static HMODULE kernel32 = NULL;
|
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)
|
static void init_cs(CRITICAL_SECTION *cs)
|
||||||
{
|
{
|
||||||
if(!InitializeCriticalSectionAndSpinCount(cs, 0x80000000))
|
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)
|
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
||||||
{
|
{
|
||||||
if(fdwReason == DLL_PROCESS_ATTACH)
|
if(fdwReason == DLL_PROCESS_ATTACH)
|
||||||
{
|
{
|
||||||
|
fprof_init(stub_fstats, NUM_STUBS);
|
||||||
|
fprof_init(ipxwrapper_fstats, ipxwrapper_fstats_size);
|
||||||
|
|
||||||
log_open("ipxwrapper.log");
|
log_open("ipxwrapper.log");
|
||||||
|
|
||||||
log_printf(LOG_INFO, "IPXWrapper %s", version_string);
|
log_printf(LOG_INFO, "IPXWrapper %s", version_string);
|
||||||
@ -104,6 +148,35 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
|||||||
}
|
}
|
||||||
|
|
||||||
router_init();
|
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)
|
else if(fdwReason == DLL_PROCESS_DETACH)
|
||||||
{
|
{
|
||||||
@ -117,6 +190,22 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
|||||||
return TRUE;
|
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();
|
router_cleanup();
|
||||||
|
|
||||||
WSACleanup();
|
WSACleanup();
|
||||||
@ -129,6 +218,14 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
|||||||
|
|
||||||
unload_dlls();
|
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();
|
log_close();
|
||||||
|
|
||||||
if(kernel32)
|
if(kernel32)
|
||||||
@ -136,6 +233,9 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
|||||||
FreeLibrary(kernel32);
|
FreeLibrary(kernel32);
|
||||||
kernel32 = NULL;
|
kernel32 = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fprof_cleanup(ipxwrapper_fstats, ipxwrapper_fstats_size);
|
||||||
|
fprof_cleanup(stub_fstats, NUM_STUBS);
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -181,6 +281,7 @@ ipx_socket *get_socket_wait_for_ready(SOCKET sockfd, int timeout_ms)
|
|||||||
/* Lock the mutex */
|
/* Lock the mutex */
|
||||||
void lock_sockets(void)
|
void lock_sockets(void)
|
||||||
{
|
{
|
||||||
|
FPROF_RECORD_SCOPE(&(ipxwrapper_fstats[IPXWRAPPER_FSTATS_lock_sockets]));
|
||||||
EnterCriticalSection(&sockets_cs);
|
EnterCriticalSection(&sockets_cs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include <uthash.h>
|
#include <uthash.h>
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "funcprof.h"
|
||||||
#include "router.h"
|
#include "router.h"
|
||||||
|
|
||||||
/* The standard Windows driver (in XP) only allows 1467 bytes anyway */
|
/* The standard Windows driver (in XP) only allows 1467 bytes anyway */
|
||||||
@ -188,6 +189,17 @@ struct spxinit
|
|||||||
extern ipx_socket *sockets;
|
extern ipx_socket *sockets;
|
||||||
extern main_config_t main_config;
|
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(SOCKET sockfd);
|
||||||
ipx_socket *get_socket_wait_for_ready(SOCKET sockfd, int timeout_ms);
|
ipx_socket *get_socket_wait_for_ready(SOCKET sockfd, int timeout_ms);
|
||||||
void lock_sockets(void);
|
void lock_sockets(void);
|
||||||
|
5
src/ipxwrapper_prof_defs.h
Normal file
5
src/ipxwrapper_prof_defs.h
Normal 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)
|
@ -1,38 +1,49 @@
|
|||||||
inet_addr:4
|
Function name Target DLL Target function Parameters (bytes)
|
||||||
WSAStartup:4
|
-------------------------------------------------------------------------------
|
||||||
WSACleanup:4
|
inet_addr ws2_32.dll inet_addr 4
|
||||||
WSASetLastError:4
|
WSAStartup ws2_32.dll WSAStartup 8
|
||||||
WSAGetLastError:4
|
WSACleanup ws2_32.dll WSACleanup 0
|
||||||
htonl:4
|
WSASetLastError ws2_32.dll WSASetLastError 4
|
||||||
ntohl:4
|
WSAGetLastError ws2_32.dll WSAGetLastError 0
|
||||||
htons:4
|
htonl ws2_32.dll htonl 4
|
||||||
ntohs:4
|
ntohl ws2_32.dll ntohl 4
|
||||||
r_select:4
|
htons ws2_32.dll htons 4
|
||||||
r_listen:4
|
ntohs ws2_32.dll ntohs 4
|
||||||
r_accept:4
|
r_select ws2_32.dll select 20
|
||||||
WSACreateEvent:4
|
r_listen ws2_32.dll listen 8
|
||||||
WSAEventSelect:4
|
r_accept ws2_32.dll accept 12
|
||||||
WSACloseEvent:4
|
WSACreateEvent ws2_32.dll WSACreateEvent 0
|
||||||
WSAResetEvent:4
|
WSAEventSelect ws2_32.dll WSAEventSelect 12
|
||||||
WSASetEvent:4
|
WSACloseEvent ws2_32.dll WSACloseEvent 4
|
||||||
r_EnumProtocolsA:2
|
WSAResetEvent ws2_32.dll WSAResetEvent 4
|
||||||
r_EnumProtocolsW:2
|
WSASetEvent ws2_32.dll WSASetEvent 4
|
||||||
r_WSARecvEx:2
|
r_EnumProtocolsA mswsock.dll EnumProtocolsA 12
|
||||||
r_bind:4
|
r_EnumProtocolsW mswsock.dll EnumProtocolsW 12
|
||||||
r_closesocket:4
|
r_WSARecvEx mswsock.dll WSARecvEx 16
|
||||||
r_getsockname:4
|
r_bind ws2_32.dll bind 12
|
||||||
r_getsockopt:4
|
r_closesocket ws2_32.dll closesocket 4
|
||||||
r_recv:4
|
r_getsockname ws2_32.dll getsockname 12
|
||||||
r_recvfrom:4
|
r_getsockopt ws2_32.dll getsockopt 20
|
||||||
r_sendto:4
|
r_recv ws2_32.dll recv 16
|
||||||
r_setsockopt:4
|
r_recvfrom ws2_32.dll recvfrom 24
|
||||||
r_shutdown:4
|
r_sendto ws2_32.dll sendto 24
|
||||||
r_socket:4
|
r_setsockopt ws2_32.dll setsockopt 20
|
||||||
r_ioctlsocket:4
|
r_shutdown ws2_32.dll shutdown 8
|
||||||
r_connect:4
|
r_socket ws2_32.dll socket 12
|
||||||
r_send:4
|
r_ioctlsocket ws2_32.dll ioctlsocket 12
|
||||||
r_getpeername:4
|
r_connect ws2_32.dll connect 12
|
||||||
inet_ntoa:4
|
r_send ws2_32.dll send 16
|
||||||
__WSAFDIsSet:4
|
r_getpeername ws2_32.dll getpeername 12
|
||||||
r_WSAAsyncSelect:4
|
inet_ntoa ws2_32.dll inet_ntoa 4
|
||||||
gethostbyname: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
|
||||||
|
@ -1,35 +1,37 @@
|
|||||||
ServiceMain
|
Function name Target DLL Target function Parameters (bytes)
|
||||||
SvchostPushServiceGlobals
|
--------------------------------------------------------------------------------------------------
|
||||||
AcceptEx
|
ServiceMain mswsock.dll ServiceMain
|
||||||
EnumProtocolsA:0
|
SvchostPushServiceGlobals mswsock.dll SvchostPushServiceGlobals
|
||||||
EnumProtocolsW:0
|
AcceptEx mswsock.dll AcceptEx 32
|
||||||
GetAcceptExSockaddrs
|
EnumProtocolsA ipxwrapper.dll EnumProtocolsA 12
|
||||||
GetAddressByNameA
|
EnumProtocolsW ipxwrapper.dll EnumProtocolsW 12
|
||||||
GetAddressByNameW
|
GetAcceptExSockaddrs mswsock.dll GetAcceptExSockaddrs 32
|
||||||
GetNameByTypeA
|
GetAddressByNameA mswsock.dll GetAddressByNameA 40
|
||||||
GetNameByTypeW
|
GetAddressByNameW mswsock.dll GetAddressByNameW 40
|
||||||
GetServiceA
|
GetNameByTypeA mswsock.dll GetNameByTypeA 12
|
||||||
GetServiceW
|
GetNameByTypeW mswsock.dll GetNameByTypeW 12
|
||||||
GetTypeByNameA
|
GetServiceA mswsock.dll GetServiceA 28
|
||||||
GetTypeByNameW
|
GetServiceW mswsock.dll GetServiceW 28
|
||||||
MigrateWinsockConfiguration
|
GetTypeByNameA mswsock.dll GetTypeByNameA 8
|
||||||
NPLoadNameSpaces
|
GetTypeByNameW mswsock.dll GetTypeByNameW 8
|
||||||
NSPStartup
|
MigrateWinsockConfiguration mswsock.dll MigrateWinsockConfiguration
|
||||||
SetServiceA
|
NPLoadNameSpaces mswsock.dll NPLoadNameSpaces
|
||||||
SetServiceW
|
NSPStartup mswsock.dll NSPStartup 8
|
||||||
StartWsdpService
|
SetServiceA mswsock.dll SetServiceA 24
|
||||||
StopWsdpService
|
SetServiceW mswsock.dll SetServiceW 24
|
||||||
TransmitFile
|
StartWsdpService mswsock.dll StartWsdpService
|
||||||
WSARecvEx:0
|
StopWsdpService mswsock.dll StopWsdpService
|
||||||
WSPStartup
|
TransmitFile mswsock.dll TransmitFile 28
|
||||||
dn_expand
|
WSARecvEx ipxwrapper.dll WSARecvEx 16
|
||||||
getnetbyname
|
WSPStartup mswsock.dll WSPStartup 76
|
||||||
inet_network
|
dn_expand mswsock.dll dn_expand
|
||||||
rcmd
|
getnetbyname mswsock.dll getnetbyname
|
||||||
rexec
|
inet_network mswsock.dll inet_network
|
||||||
rresvport
|
rcmd mswsock.dll rcmd
|
||||||
s_perror
|
rexec mswsock.dll rexec
|
||||||
sethostname
|
rresvport mswsock.dll rresvport
|
||||||
inet_addr
|
s_perror mswsock.dll s_perror
|
||||||
WSHEnumProtocols:0
|
sethostname mswsock.dll sethostname
|
||||||
ntohs:1
|
inet_addr mswsock.dll inet_addr 4
|
||||||
|
WSHEnumProtocols ipxwrapper.dll WSHEnumProtocols 16
|
||||||
|
ntohs wsock32.dll ntohs 4
|
||||||
|
13
src/router.c
13
src/router.c
@ -26,6 +26,7 @@
|
|||||||
|
|
||||||
#include "router.h"
|
#include "router.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "funcprof.h"
|
||||||
#include "ipxwrapper.h"
|
#include "ipxwrapper.h"
|
||||||
#include "interface.h"
|
#include "interface.h"
|
||||||
#include "addrcache.h"
|
#include "addrcache.h"
|
||||||
@ -230,6 +231,8 @@ static void _deliver_packet(
|
|||||||
const void *data,
|
const void *data,
|
||||||
size_t data_size)
|
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(src_addr, src_net, src_node, src_socket);
|
||||||
IPX_STRING_ADDR(dest_addr, dest_net, dest_node, dest_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()));
|
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);
|
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)
|
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);
|
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)
|
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)
|
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)
|
if(packet_size < sizeof(novell_ipx_packet) || ntohs(packet->length) != packet_size)
|
||||||
{
|
{
|
||||||
/* Doesn't look valid. */
|
/* 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)
|
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);
|
ipx_interface_t *iface = (ipx_interface_t*)(user);
|
||||||
|
|
||||||
const novell_ipx_packet *ipx;
|
const novell_ipx_packet *ipx;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* IPXWrapper - Stub DLL functions
|
/* 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
|
* 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
|
* under the terms of the GNU General Public License version 2 as published by
|
||||||
@ -21,13 +21,52 @@
|
|||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "config.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) {
|
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
|
||||||
if(fdwReason == DLL_PROCESS_ATTACH)
|
if(fdwReason == DLL_PROCESS_ATTACH)
|
||||||
{
|
{
|
||||||
|
fprof_init(stub_fstats, NUM_STUBS);
|
||||||
|
|
||||||
log_open("ipxwrapper.log");
|
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)
|
else if(fdwReason == DLL_PROCESS_DETACH)
|
||||||
{
|
{
|
||||||
@ -41,9 +80,45 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
|
|||||||
return TRUE;
|
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();
|
unload_dlls();
|
||||||
|
|
||||||
|
if(stubs_enable_profile)
|
||||||
|
{
|
||||||
|
fprof_report(STUBS_DLL_NAME, stub_fstats, NUM_STUBS);
|
||||||
|
}
|
||||||
|
|
||||||
log_close();
|
log_close();
|
||||||
|
|
||||||
|
fprof_cleanup(stub_fstats, NUM_STUBS);
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
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;
|
||||||
|
}
|
||||||
|
@ -1475,6 +1475,9 @@ static DWORD ipx_send_packet(
|
|||||||
|
|
||||||
if(pcap_sendpacket(iface->pcap, (void*)(frame), frame_size) == 0)
|
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);
|
free(frame);
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -1531,6 +1534,10 @@ static DWORD ipx_send_packet(
|
|||||||
error = WSAGetLastError();
|
error = WSAGetLastError();
|
||||||
log_printf(LOG_ERROR, "Error sending DOSBox IPX packet: %s", w32_error(error));
|
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);
|
free(packet);
|
||||||
|
|
||||||
@ -1635,6 +1642,12 @@ static DWORD ipx_send_packet(
|
|||||||
|
|
||||||
free(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
|
return send_ok
|
||||||
? ERROR_SUCCESS
|
? ERROR_SUCCESS
|
||||||
: send_error;
|
: send_error;
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
pcap_open
|
|
||||||
pcap_close
|
|
||||||
pcap_findalldevs_ex
|
|
||||||
pcap_freealldevs
|
|
||||||
pcap_getevent
|
|
||||||
pcap_dispatch
|
|
||||||
pcap_geterr
|
|
||||||
pcap_sendpacket
|
|
@ -1,76 +1,78 @@
|
|||||||
accept:0
|
Function name Target DLL Target function Parameters (bytes)
|
||||||
bind:0
|
--------------------------------------------------------------------------------------------------
|
||||||
closesocket:0
|
accept ipxwrapper.dll accept 12
|
||||||
connect:0
|
bind ipxwrapper.dll bind 12
|
||||||
getpeername:0
|
closesocket ipxwrapper.dll closesocket 4
|
||||||
getsockname:0
|
connect ipxwrapper.dll connect 12
|
||||||
getsockopt:0
|
getpeername ipxwrapper.dll getpeername 12
|
||||||
htonl
|
getsockname ipxwrapper.dll getsockname 12
|
||||||
htons
|
getsockopt ipxwrapper.dll getsockopt 20
|
||||||
inet_addr
|
htonl wsock32.dll htonl 4
|
||||||
inet_ntoa
|
htons wsock32.dll htons 4
|
||||||
ioctlsocket:0
|
inet_addr wsock32.dll inet_addr 4
|
||||||
listen:0
|
inet_ntoa wsock32.dll inet_ntoa 4
|
||||||
ntohl
|
ioctlsocket ipxwrapper.dll ioctlsocket 12
|
||||||
ntohs
|
listen ipxwrapper.dll listen 8
|
||||||
recv:0
|
ntohl wsock32.dll ntohl 4
|
||||||
recvfrom:0
|
ntohs wsock32.dll ntohs 4
|
||||||
select:0
|
recv ipxwrapper.dll recv 16
|
||||||
send:0
|
recvfrom ipxwrapper.dll recvfrom 24
|
||||||
sendto:0
|
select ipxwrapper.dll select 20
|
||||||
setsockopt:0
|
send ipxwrapper.dll send 16
|
||||||
shutdown:0
|
sendto ipxwrapper.dll sendto 24
|
||||||
socket:0
|
setsockopt ipxwrapper.dll setsockopt 20
|
||||||
MigrateWinsockConfiguration
|
shutdown ipxwrapper.dll shutdown 8
|
||||||
gethostbyaddr
|
socket ipxwrapper.dll socket 12
|
||||||
gethostbyname
|
MigrateWinsockConfiguration wsock32.dll MigrateWinsockConfiguration
|
||||||
getprotobyname
|
gethostbyaddr wsock32.dll gethostbyaddr 12
|
||||||
getprotobynumber
|
gethostbyname wsock32.dll gethostbyname 4
|
||||||
getservbyname
|
getprotobyname wsock32.dll getprotobyname 4
|
||||||
getservbyport
|
getprotobynumber wsock32.dll getprotobynumber 4
|
||||||
gethostname
|
getservbyname wsock32.dll getservbyname 8
|
||||||
WSAAsyncSelect:0
|
getservbyport wsock32.dll getservbyport 8
|
||||||
WSAAsyncGetHostByAddr
|
gethostname wsock32.dll gethostname 8
|
||||||
WSAAsyncGetHostByName
|
WSAAsyncSelect ipxwrapper.dll WSAAsyncSelect 16
|
||||||
WSAAsyncGetProtoByNumber
|
WSAAsyncGetHostByAddr wsock32.dll WSAAsyncGetHostByAddr 28
|
||||||
WSAAsyncGetProtoByName
|
WSAAsyncGetHostByName wsock32.dll WSAAsyncGetHostByName 20
|
||||||
WSAAsyncGetServByPort
|
WSAAsyncGetProtoByNumber wsock32.dll WSAAsyncGetProtoByNumber 20
|
||||||
WSAAsyncGetServByName
|
WSAAsyncGetProtoByName wsock32.dll WSAAsyncGetProtoByName 20
|
||||||
WSACancelAsyncRequest
|
WSAAsyncGetServByPort wsock32.dll WSAAsyncGetServByPort 24
|
||||||
WSASetBlockingHook
|
WSAAsyncGetServByName wsock32.dll WSAAsyncGetServByName 24
|
||||||
WSAUnhookBlockingHook
|
WSACancelAsyncRequest wsock32.dll WSACancelAsyncRequest 4
|
||||||
WSAGetLastError
|
WSASetBlockingHook wsock32.dll WSASetBlockingHook 4
|
||||||
WSASetLastError
|
WSAUnhookBlockingHook wsock32.dll WSAUnhookBlockingHook 0
|
||||||
WSACancelBlockingCall
|
WSAGetLastError wsock32.dll WSAGetLastError 0
|
||||||
WSAIsBlocking
|
WSASetLastError wsock32.dll WSASetLastError 4
|
||||||
WSAStartup
|
WSACancelBlockingCall wsock32.dll WSACancelBlockingCall 0
|
||||||
WSACleanup
|
WSAIsBlocking wsock32.dll WSAIsBlocking 0
|
||||||
__WSAFDIsSet
|
WSAStartup wsock32.dll WSAStartup 8
|
||||||
WEP
|
WSACleanup wsock32.dll WSACleanup 0
|
||||||
WSApSetPostRoutine
|
__WSAFDIsSet wsock32.dll __WSAFDIsSet 8
|
||||||
inet_network
|
WEP wsock32.dll WEP
|
||||||
getnetbyname
|
WSApSetPostRoutine wsock32.dll WSApSetPostRoutine
|
||||||
rcmd
|
inet_network wsock32.dll inet_network
|
||||||
rexec
|
getnetbyname wsock32.dll getnetbyname
|
||||||
rresvport
|
rcmd wsock32.dll rcmd
|
||||||
sethostname
|
rexec wsock32.dll rexec
|
||||||
dn_expand
|
rresvport wsock32.dll rresvport
|
||||||
WSARecvEx:0
|
sethostname wsock32.dll sethostname
|
||||||
s_perror
|
dn_expand wsock32.dll dn_expand
|
||||||
GetAddressByNameA
|
WSARecvEx ipxwrapper.dll WSARecvEx 16
|
||||||
GetAddressByNameW
|
s_perror wsock32.dll s_perror
|
||||||
EnumProtocolsA:0
|
GetAddressByNameA wsock32.dll GetAddressByNameA 40
|
||||||
EnumProtocolsW:0
|
GetAddressByNameW wsock32.dll GetAddressByNameW 40
|
||||||
GetTypeByNameA
|
EnumProtocolsA ipxwrapper.dll EnumProtocolsA 12
|
||||||
GetTypeByNameW
|
EnumProtocolsW ipxwrapper.dll EnumProtocolsW 12
|
||||||
GetNameByTypeA
|
GetTypeByNameA wsock32.dll GetTypeByNameA 8
|
||||||
GetNameByTypeW
|
GetTypeByNameW wsock32.dll GetTypeByNameW 8
|
||||||
SetServiceA
|
GetNameByTypeA wsock32.dll GetNameByTypeA 12
|
||||||
SetServiceW
|
GetNameByTypeW wsock32.dll GetNameByTypeW 12
|
||||||
GetServiceA
|
SetServiceA wsock32.dll SetServiceA 24
|
||||||
GetServiceW
|
SetServiceW wsock32.dll SetServiceW 24
|
||||||
NPLoadNameSpaces
|
GetServiceA wsock32.dll GetServiceA 28
|
||||||
TransmitFile
|
GetServiceW wsock32.dll GetServiceW 28
|
||||||
AcceptEx
|
NPLoadNameSpaces wsock32.dll NPLoadNameSpaces
|
||||||
GetAcceptExSockaddrs
|
TransmitFile wsock32.dll TransmitFile 28
|
||||||
WSHEnumProtocols:0
|
AcceptEx wsock32.dll AcceptEx 32
|
||||||
|
GetAcceptExSockaddrs wsock32.dll GetAcceptExSockaddrs 32
|
||||||
|
WSHEnumProtocols ipxwrapper.dll WSHEnumProtocols 16
|
||||||
|
Loading…
x
Reference in New Issue
Block a user