From b8887625381fb2d6ef3fe0d2cda1c97b529637de Mon Sep 17 00:00:00 2001 From: Daniel Collins Date: Sun, 11 Sep 2011 13:28:41 +0000 Subject: [PATCH] Rewrote DLL loading code to avoid corrupting the system error code. --- Makefile | 12 +++--- mkstubs.pl | 86 +++++++++++++++++++--------------------- src/common.c | 72 ++++++++++++++++++++++++++------- src/common.h | 7 +++- src/directplay.c | 25 +----------- src/dpwsockx_stubs.txt | 6 +++ src/ipxwrapper.c | 34 +--------------- src/ipxwrapper.def | 6 --- src/ipxwrapper.h | 1 - src/ipxwrapper_stubs.txt | 66 +++++++++++++++--------------- src/mswsock_stubs.txt | 6 +-- src/stubdll.c | 49 +---------------------- src/wsock32_stubs.txt | 28 ++++++------- 13 files changed, 169 insertions(+), 229 deletions(-) diff --git a/Makefile b/Makefile index 5cc75e4..ccd6f71 100644 --- a/Makefile +++ b/Makefile @@ -60,23 +60,23 @@ ipxwrapper.dll: $(IPXWRAPPER_DEPS) ipxconfig.exe: src/ipxconfig.cpp $(CXX) $(CXXFLAGS) -static-libgcc -static-libstdc++ -D_WIN32_IE=0x0400 -mwindows -o ipxconfig.exe src/ipxconfig.cpp -liphlpapi -dpwsockx.dll: src/directplay.o src/log.o src/dpwsockx_stubs.o src/common.o ipxwrapper.dll - $(CC) $(CFLAGS) -Wl,--enable-stdcall-fixup -shared -o dpwsockx.dll src/directplay.o src/log.o src/common.o src/dpwsockx_stubs.o src/dpwsockx.def -L. -lipxwrapper -lwsock32 +dpwsockx.dll: src/directplay.o src/log.o src/dpwsockx_stubs.o src/common.o + $(CC) $(CFLAGS) -Wl,--enable-stdcall-fixup -shared -o dpwsockx.dll src/directplay.o src/log.o src/common.o src/dpwsockx_stubs.o src/dpwsockx.def -lwsock32 ipxrouter.exe: src/router-exe.o src/router.o src/interface.o src/common.o $(CC) $(CFLAGS) -static-libgcc -o ipxrouter.exe $^ -lws2_32 -liphlpapi src/ipxwrapper_stubs.s: src/ipxwrapper_stubs.txt - perl mkstubs.pl src/ipxwrapper_stubs.txt src/ipxwrapper_stubs.s + perl mkstubs.pl src/ipxwrapper_stubs.txt src/ipxwrapper_stubs.s 0 src/wsock32_stubs.s: src/wsock32_stubs.txt - perl mkstubs.pl src/wsock32_stubs.txt src/wsock32_stubs.s wsock32.dll + perl mkstubs.pl src/wsock32_stubs.txt src/wsock32_stubs.s 1 src/mswsock_stubs.s: src/mswsock_stubs.txt - perl mkstubs.pl src/mswsock_stubs.txt src/mswsock_stubs.s mswsock.dll + perl mkstubs.pl src/mswsock_stubs.txt src/mswsock_stubs.s 2 src/dpwsockx_stubs.s: src/dpwsockx_stubs.txt - perl mkstubs.pl src/dpwsockx_stubs.txt src/dpwsockx_stubs.s dpwsockx.dll + perl mkstubs.pl src/dpwsockx_stubs.txt src/dpwsockx_stubs.s 3 %.dll: src/stubdll.o src/%_stubs.o src/log.o src/common.o src/%.def $(CC) $(CFLAGS) -Wl,--enable-stdcall-fixup -shared -o $@ $^ diff --git a/mkstubs.pl b/mkstubs.pl index e781070..9be892a 100644 --- a/mkstubs.pl +++ b/mkstubs.pl @@ -14,83 +14,77 @@ # this program; if not, write to the Free Software Foundation, Inc., 51 # Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -if(@ARGV != 2 && @ARGV != 3) { - print STDERR "Usage: mkdll.pl []\n"; +use strict; +use warnings; + +if(@ARGV != 3) { + print STDERR "Usage: mkdll.pl \n"; exit(1); } -open(STUBS, "<".$ARGV[0]) or die("Cannot open ".$ARGV[0].": $!"); -open(CODE, ">".$ARGV[1]) or die("Cannot open ".$ARGV[1].": $!"); +my $stub_file = $ARGV[0]; +my $asm_file = $ARGV[1]; +my $dllnum = $ARGV[2]; +my $do_logging = ($dllnum != 0); + +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() { $line =~ s/[\r\n]//g; if($line ne "") { - push @stubs, $line; + my ($func, $dn) = split(/:/, $line); + $dn = $dllnum if(!defined($dn)); + + my $sym = $func; + $sym =~ s/^r_//; + + push(@stubs, {"name" => $func, "sym" => $sym, "dllnum" => $dn}); } } print CODE "section .rdata:\n"; -if(@ARGV == 3) { - print CODE "\tglobal\t_dllname\n"; - print CODE "\tdllname_s:\tdb\t'".$ARGV[2]."', 0\n"; - print CODE "\t_dllname:\tdd\tdllname_s\n"; - print CODE "\tcall_fmt\tdb\t'\%s:\%s', 0\n"; -} - foreach my $func(@stubs) { - my $real_func = $func; - $real_func =~ s/^r_//; - - print CODE "\t$func\_sym:\tdb\t'$real_func', 0\n"; + print CODE "\t".$func->{"name"}."_sym:\tdb\t'".$func->{"sym"}."', 0\n"; } print CODE "\nsection .data\n"; -if(@ARGV == 3) { - print CODE "\textern\t_log_calls\n"; -} - foreach my $func(@stubs) { - print CODE "\t$func\_addr:\tdd\t0\n"; + print CODE "\t".$func->{"name"}."_addr:\tdd\t0\n"; } print CODE "\nsection .text\n"; print CODE "\textern\t_find_sym\n"; - -if(@ARGV == 3) { - print CODE "\textern\t_log_printf\n"; -} +print CODE "\textern\t_log_call\n" if($do_logging); foreach my $func(@stubs) { - print CODE "\nglobal\t_$func\n"; - print CODE "_$func:\n"; + my $f_name = $func->{"name"}; - if(@ARGV == 3) { - print CODE "\tcmp\tbyte [_log_calls], 0\n"; - print CODE "\tje\t$func\_nolog\n"; - - # Write DLL and symbol name to log - # - print CODE "\tpush\t$func\_sym\n"; - print CODE "\tpush\tdllname_s\n"; - print CODE "\tpush\tcall_fmt\n"; - print CODE "\tcall\t_log_printf\n"; - print CODE "\tadd esp, 12\n"; - - print CODE "\t$func\_nolog:\n"; + print CODE "\nglobal\t_$f_name\n"; + print CODE "_$f_name:\n"; + + if($do_logging) { + print CODE "\tpush\t$f_name\_sym\n"; + print CODE "\tpush\tdword ".$func->{"dllnum"}."\n"; + print CODE "\tcall\t_log_call\n"; } - print CODE "\tcmp\tdword [$func\_addr], 0\n"; - print CODE "\tjne\t$func\_jmp\n"; - print CODE "\tpush\t$func\_sym\n"; + 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[$func\_addr], eax\n"; - print CODE "\t$func\_jmp:\n"; - print CODE "\tjmp\t[$func\_addr]\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); diff --git a/src/common.c b/src/common.c index 5ea9c6e..e8b3e01 100644 --- a/src/common.c +++ b/src/common.c @@ -23,6 +23,19 @@ HKEY regkey = NULL; +unsigned char log_calls = 0; + +static const char *dll_names[] = { + "ipxwrapper.dll", + "wsock32.dll", + "mswsock.dll", + "dpwsockx.dll", + "ws2_32.dll", + NULL +}; + +static HANDLE dll_handles[] = {NULL, NULL, NULL, NULL, NULL}; + /* Convert a windows error number to an error message */ const char *w32_error(DWORD errnum) { static char buf[1024] = {'\0'}; @@ -85,24 +98,55 @@ DWORD reg_get_bin(const char *val_name, void *buf, DWORD size) { return size; } -/* Load a system DLL */ -HMODULE load_sysdll(const char *name) { - char path[1024]; +void load_dll(unsigned int dllnum) { + char path[512]; - GetSystemDirectory(path, sizeof(path)); - - if(strlen(path) + strlen(name) + 2 > sizeof(path)) { - log_printf("Path buffer too small, cannot load %s", name); - return NULL; + if(dllnum) { + GetSystemDirectory(path, sizeof(path)); + + if(strlen(path) + strlen(dll_names[dllnum]) + 2 > sizeof(path)) { + log_printf("Path buffer too small, cannot load %s", dll_names[dllnum]); + abort(); + } + + strcat(path, "\\"); + strcat(path, dll_names[dllnum]); } - strcat(path, "\\"); - strcat(path, name); - - HMODULE dll = LoadLibrary(path); - if(!dll) { + dll_handles[dllnum] = LoadLibrary(dllnum ? path : dll_names[dllnum]); + if(!dll_handles[dllnum]) { log_printf("Error loading %s: %s", path, w32_error(GetLastError())); + abort(); + } +} + +void unload_dlls(void) { + int i; + + for(i = 0; dll_names[i]; i++) { + if(dll_handles[i]) { + FreeLibrary(dll_handles[i]); + dll_handles[i] = NULL; + } + } +} + +void __stdcall *find_sym(unsigned int dllnum, const char *symbol) { + if(!dll_handles[dllnum]) { + load_dll(dllnum); } - return dll; + void *ptr = GetProcAddress(dll_handles[dllnum], symbol); + if(!ptr) { + log_printf("Missing symbol in %s: %s", dll_names[dllnum], symbol); + abort(); + } + + return ptr; +} + +void __stdcall log_call(unsigned int dllnum, const char *symbol) { + if(log_calls) { + log_printf("%s:%s", dll_names[dllnum], symbol); + } } diff --git a/src/common.h b/src/common.h index 538a421..d0113e2 100644 --- a/src/common.h +++ b/src/common.h @@ -44,6 +44,8 @@ extern HKEY regkey; +extern unsigned char log_calls; + void log_printf(const char *fmt, ...); const char *w32_error(DWORD errnum); @@ -54,6 +56,9 @@ void reg_close(void); char reg_get_char(const char *val_name, char default_val); DWORD reg_get_bin(const char *val_name, void *buf, DWORD size); -HMODULE load_sysdll(const char *name); +void load_dll(unsigned int dllnum); +void unload_dlls(void); +void __stdcall *find_sym(unsigned int dllnum, const char *symbol); +void __stdcall log_call(unsigned int dllnum, const char *symbol); #endif /* !IPXWRAPPER_COMMON_H */ diff --git a/src/directplay.c b/src/directplay.c index ab87e97..8cad6b4 100644 --- a/src/directplay.c +++ b/src/directplay.c @@ -50,10 +50,6 @@ struct sp_data_cont { #define CALL(n) if(log_calls) { log_printf("DirectPlay: %s", n); } -extern char const *dllname; -unsigned char log_calls = 0; -static HMODULE sysdll = NULL; - /* Lock the object mutex and return the data pointer */ static struct sp_data *get_sp_data(IDirectPlaySP *sp) { struct sp_data_cont *cont; @@ -570,28 +566,9 @@ BOOL WINAPI DllMain(HINSTANCE me, DWORD why, LPVOID res) { reg_close(); }else if(why == DLL_PROCESS_DETACH) { - if(sysdll) { - FreeLibrary(sysdll); - sysdll = NULL; - } - + unload_dlls(); log_close(); } return TRUE; } - -void __stdcall *find_sym(char const *symbol) { - if(!sysdll) { - sysdll = load_sysdll(dllname); - } - - void *ptr = GetProcAddress(sysdll, symbol); - - if(!ptr) { - log_printf("Missing symbol in %s: %s", dllname, symbol); - abort(); - } - - return ptr; -} diff --git a/src/dpwsockx_stubs.txt b/src/dpwsockx_stubs.txt index a73cf69..d179ac0 100644 --- a/src/dpwsockx_stubs.txt +++ b/src/dpwsockx_stubs.txt @@ -1,3 +1,9 @@ r_SPInit DPWS_GetEnumPort DPWS_BuildIPMessageHeader + +WSACreateEvent:4 +WSACloseEvent:4 +WSAEventSelect:4 +WSAResetEvent:4 +WSASetEvent:4 diff --git a/src/ipxwrapper.c b/src/ipxwrapper.c index 98c61e3..81bccf0 100644 --- a/src/ipxwrapper.c +++ b/src/ipxwrapper.c @@ -43,10 +43,6 @@ ipx_host *hosts = NULL; SOCKET send_fd = -1; struct reg_global global_conf; -HMODULE winsock2_dll = NULL; -HMODULE mswsock_dll = NULL; -HMODULE wsock32_dll = NULL; - struct rclient g_rclient; static CRITICAL_SECTION sockets_cs; @@ -74,14 +70,6 @@ BOOL WINAPI DllMain(HINSTANCE me, DWORD why, LPVOID res) { return FALSE; } - winsock2_dll = load_sysdll("ws2_32.dll"); - mswsock_dll = load_sysdll("mswsock.dll"); - wsock32_dll = load_sysdll("wsock32.dll"); - - if(!winsock2_dll || !mswsock_dll || !wsock32_dll) { - return FALSE; - } - reg_open(KEY_QUERY_VALUE); if(reg_get_bin("global", &global_conf, sizeof(global_conf)) != sizeof(global_conf)) { @@ -150,9 +138,7 @@ BOOL WINAPI DllMain(HINSTANCE me, DWORD why, LPVOID res) { reg_close(); - DLL_UNLOAD(winsock2_dll); - DLL_UNLOAD(mswsock_dll); - DLL_UNLOAD(wsock32_dll); + unload_dlls(); log_close(); } @@ -160,24 +146,6 @@ BOOL WINAPI DllMain(HINSTANCE me, DWORD why, LPVOID res) { return TRUE; } -void __stdcall *find_sym(char const *symbol) { - void *addr = GetProcAddress(winsock2_dll, symbol); - - if(!addr) { - addr = GetProcAddress(mswsock_dll, symbol); - } - if(!addr) { - addr = GetProcAddress(wsock32_dll, symbol); - } - - if(!addr) { - log_printf("Unknown symbol: %s", symbol); - abort(); - } - - return addr; -} - /* Lock the mutex and search the sockets list for an ipx_socket structure with * the requested fd, if no matching fd is found, unlock the mutex * diff --git a/src/ipxwrapper.def b/src/ipxwrapper.def index be45be5..d373277 100644 --- a/src/ipxwrapper.def +++ b/src/ipxwrapper.def @@ -14,9 +14,3 @@ EXPORTS EnumProtocolsW WSARecvEx ioctlsocket - - WSACreateEvent - WSACloseEvent - WSAEventSelect - WSAResetEvent - WSASetEvent diff --git a/src/ipxwrapper.h b/src/ipxwrapper.h index 5165a20..20bd7eb 100644 --- a/src/ipxwrapper.h +++ b/src/ipxwrapper.h @@ -109,7 +109,6 @@ extern HMODULE winsock2_dll; extern HMODULE mswsock_dll; extern HMODULE wsock32_dll; -void __stdcall *find_sym(char const *sym); ipx_socket *get_socket(SOCKET fd); void lock_sockets(void); void unlock_sockets(void); diff --git a/src/ipxwrapper_stubs.txt b/src/ipxwrapper_stubs.txt index 91a1e8d..771bae2 100644 --- a/src/ipxwrapper_stubs.txt +++ b/src/ipxwrapper_stubs.txt @@ -1,33 +1,33 @@ -inet_addr -WSAStartup -WSACleanup -WSASetLastError -WSAGetLastError -htonl -ntohl -htons -ntohs -select -listen -accept -send -connect -WSACreateEvent -WSAEventSelect -WSACloseEvent -WSAResetEvent -WSASetEvent -r_EnumProtocolsA -r_EnumProtocolsW -r_WSARecvEx -r_bind -r_closesocket -r_getsockname -r_getsockopt -r_recv -r_recvfrom -r_sendto -r_setsockopt -r_shutdown -r_socket -r_ioctlsocket +inet_addr:4 +WSAStartup:4 +WSACleanup:4 +WSASetLastError:4 +WSAGetLastError:4 +htonl:4 +ntohl:4 +htons:4 +ntohs:4 +select:4 +listen:4 +accept:4 +send:4 +connect:4 +WSACreateEvent:4 +WSAEventSelect:4 +WSACloseEvent:4 +WSAResetEvent:4 +WSASetEvent:4 +r_EnumProtocolsA:4 +r_EnumProtocolsW:4 +r_WSARecvEx:4 +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 diff --git a/src/mswsock_stubs.txt b/src/mswsock_stubs.txt index c8cff38..e7f9373 100644 --- a/src/mswsock_stubs.txt +++ b/src/mswsock_stubs.txt @@ -1,8 +1,8 @@ ServiceMain SvchostPushServiceGlobals AcceptEx -EnumProtocolsA -EnumProtocolsW +EnumProtocolsA:0 +EnumProtocolsW:0 GetAcceptExSockaddrs GetAddressByNameA GetAddressByNameW @@ -20,7 +20,7 @@ SetServiceW StartWsdpService StopWsdpService TransmitFile -WSARecvEx +WSARecvEx:0 WSPStartup dn_expand getnetbyname diff --git a/src/stubdll.c b/src/stubdll.c index 5f9bb8b..ddc3145 100644 --- a/src/stubdll.c +++ b/src/stubdll.c @@ -21,29 +21,10 @@ #include "common.h" -static HMODULE ipxdll = NULL; -static HMODULE sysdll = NULL; -extern char const *dllname; - -unsigned char log_calls = 0; - void log_open(); void log_close(); void log_printf(const char *fmt, ...); -static void load_dlls() { - ipxdll = LoadLibrary("ipxwrapper.dll"); - if(!ipxdll) { - log_printf("Error loading ipxwrapper.dll: %s", w32_error(GetLastError())); - abort(); - } - - sysdll = load_sysdll(dllname); - if(!sysdll) { - abort(); - } -} - BOOL WINAPI DllMain(HINSTANCE me, DWORD why, LPVOID res) { if(why == DLL_PROCESS_ATTACH) { log_open(); @@ -54,37 +35,9 @@ BOOL WINAPI DllMain(HINSTANCE me, DWORD why, LPVOID res) { reg_close(); }else if(why == DLL_PROCESS_DETACH) { - if(sysdll) { - FreeLibrary(sysdll); - sysdll = NULL; - } - - if(ipxdll) { - FreeLibrary(ipxdll); - ipxdll = NULL; - } - + unload_dlls(); log_close(); } return TRUE; } - -void __stdcall *find_sym(char const *symbol) { - if(!ipxdll) { - load_dlls(); - } - - void *ptr = GetProcAddress(ipxdll, symbol); - - if(!ptr) { - ptr = GetProcAddress(sysdll, symbol); - } - - if(!ptr) { - log_printf("Missing symbol in %s: %s", dllname, symbol); - abort(); - } - - return ptr; -} diff --git a/src/wsock32_stubs.txt b/src/wsock32_stubs.txt index 88ce718..d396e83 100644 --- a/src/wsock32_stubs.txt +++ b/src/wsock32_stubs.txt @@ -1,26 +1,26 @@ accept -bind -closesocket +bind:0 +closesocket:0 connect getpeername -getsockname -getsockopt +getsockname:0 +getsockopt:0 htonl htons inet_addr inet_ntoa -ioctlsocket +ioctlsocket:0 listen ntohl ntohs -recv -recvfrom +recv:0 +recvfrom:0 select send -sendto -setsockopt -shutdown -socket +sendto:0 +setsockopt:0 +shutdown:0 +socket:0 MigrateWinsockConfiguration gethostbyaddr gethostbyname @@ -55,12 +55,12 @@ rexec rresvport sethostname dn_expand -WSARecvEx +WSARecvEx:0 s_perror GetAddressByNameA GetAddressByNameW -EnumProtocolsA -EnumProtocolsW +EnumProtocolsA:0 +EnumProtocolsW:0 GetTypeByNameA GetTypeByNameW GetNameByTypeA