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

Rewrote DLL loading code to avoid corrupting the system error code.

This commit is contained in:
Daniel Collins 2011-09-11 13:28:41 +00:00
parent ee30a6200f
commit b888762538
13 changed files with 169 additions and 229 deletions

View File

@ -60,23 +60,23 @@ ipxwrapper.dll: $(IPXWRAPPER_DEPS)
ipxconfig.exe: src/ipxconfig.cpp ipxconfig.exe: src/ipxconfig.cpp
$(CXX) $(CXXFLAGS) -static-libgcc -static-libstdc++ -D_WIN32_IE=0x0400 -mwindows -o ipxconfig.exe src/ipxconfig.cpp -liphlpapi $(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 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 -L. -lipxwrapper -lwsock32 $(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 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 $(CC) $(CFLAGS) -static-libgcc -o ipxrouter.exe $^ -lws2_32 -liphlpapi
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 perl mkstubs.pl src/ipxwrapper_stubs.txt src/ipxwrapper_stubs.s 0
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 wsock32.dll perl mkstubs.pl src/wsock32_stubs.txt src/wsock32_stubs.s 1
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 mswsock.dll perl mkstubs.pl src/mswsock_stubs.txt src/mswsock_stubs.s 2
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 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 %.dll: src/stubdll.o src/%_stubs.o src/log.o src/common.o src/%.def
$(CC) $(CFLAGS) -Wl,--enable-stdcall-fixup -shared -o $@ $^ $(CC) $(CFLAGS) -Wl,--enable-stdcall-fixup -shared -o $@ $^

View File

@ -14,83 +14,77 @@
# this program; if not, write to the Free Software Foundation, Inc., 51 # this program; if not, write to the Free Software Foundation, Inc., 51
# Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
if(@ARGV != 2 && @ARGV != 3) { use strict;
print STDERR "Usage: mkdll.pl <function list> <output code> [<dll name>]\n"; use warnings;
if(@ARGV != 3) {
print STDERR "Usage: mkdll.pl <function list> <output file> <dll number>\n";
exit(1); exit(1);
} }
open(STUBS, "<".$ARGV[0]) or die("Cannot open ".$ARGV[0].": $!"); my $stub_file = $ARGV[0];
open(CODE, ">".$ARGV[1]) or die("Cannot open ".$ARGV[1].": $!"); 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 = ();
my @stubs_dll = ();
foreach my $line(<STUBS>) { foreach my $line(<STUBS>) {
$line =~ s/[\r\n]//g; $line =~ s/[\r\n]//g;
if($line ne "") { 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"; 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) { foreach my $func(@stubs) {
my $real_func = $func; print CODE "\t".$func->{"name"}."_sym:\tdb\t'".$func->{"sym"}."', 0\n";
$real_func =~ s/^r_//;
print CODE "\t$func\_sym:\tdb\t'$real_func', 0\n";
} }
print CODE "\nsection .data\n"; print CODE "\nsection .data\n";
if(@ARGV == 3) {
print CODE "\textern\t_log_calls\n";
}
foreach my $func(@stubs) { 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 "\nsection .text\n";
print CODE "\textern\t_find_sym\n"; print CODE "\textern\t_find_sym\n";
print CODE "\textern\t_log_call\n" if($do_logging);
if(@ARGV == 3) {
print CODE "\textern\t_log_printf\n";
}
foreach my $func(@stubs) { foreach my $func(@stubs) {
print CODE "\nglobal\t_$func\n"; my $f_name = $func->{"name"};
print CODE "_$func:\n";
if(@ARGV == 3) { print CODE "\nglobal\t_$f_name\n";
print CODE "\tcmp\tbyte [_log_calls], 0\n"; print CODE "_$f_name:\n";
print CODE "\tje\t$func\_nolog\n";
if($do_logging) {
# Write DLL and symbol name to log print CODE "\tpush\t$f_name\_sym\n";
# print CODE "\tpush\tdword ".$func->{"dllnum"}."\n";
print CODE "\tpush\t$func\_sym\n"; print CODE "\tcall\t_log_call\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 "\tcmp\tdword [$func\_addr], 0\n"; print CODE "\tcmp\tdword [$f_name\_addr], 0\n";
print CODE "\tjne\t$func\_jmp\n"; print CODE "\tjne\t$f_name\_jmp\n";
print CODE "\tpush\t$func\_sym\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 "\tcall\t_find_sym\n";
print CODE "\tmov\t[$func\_addr], eax\n"; print CODE "\tmov\t[$f_name\_addr], eax\n";
print CODE "\t$func\_jmp:\n";
print CODE "\tjmp\t[$func\_addr]\n"; print CODE "\t$f_name\_jmp:\n";
print CODE "\tjmp\t[$f_name\_addr]\n";
} }
close(CODE); close(CODE);

View File

@ -23,6 +23,19 @@
HKEY regkey = NULL; 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 */ /* Convert a windows error number to an error message */
const char *w32_error(DWORD errnum) { const char *w32_error(DWORD errnum) {
static char buf[1024] = {'\0'}; static char buf[1024] = {'\0'};
@ -85,24 +98,55 @@ DWORD reg_get_bin(const char *val_name, void *buf, DWORD size) {
return size; return size;
} }
/* Load a system DLL */ void load_dll(unsigned int dllnum) {
HMODULE load_sysdll(const char *name) { char path[512];
char path[1024];
GetSystemDirectory(path, sizeof(path)); if(dllnum) {
GetSystemDirectory(path, sizeof(path));
if(strlen(path) + strlen(name) + 2 > sizeof(path)) {
log_printf("Path buffer too small, cannot load %s", name); if(strlen(path) + strlen(dll_names[dllnum]) + 2 > sizeof(path)) {
return NULL; log_printf("Path buffer too small, cannot load %s", dll_names[dllnum]);
abort();
}
strcat(path, "\\");
strcat(path, dll_names[dllnum]);
} }
strcat(path, "\\"); dll_handles[dllnum] = LoadLibrary(dllnum ? path : dll_names[dllnum]);
strcat(path, name); if(!dll_handles[dllnum]) {
HMODULE dll = LoadLibrary(path);
if(!dll) {
log_printf("Error loading %s: %s", path, w32_error(GetLastError())); 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);
}
} }

View File

@ -44,6 +44,8 @@
extern HKEY regkey; extern HKEY regkey;
extern unsigned char log_calls;
void log_printf(const char *fmt, ...); void log_printf(const char *fmt, ...);
const char *w32_error(DWORD errnum); 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); char reg_get_char(const char *val_name, char default_val);
DWORD reg_get_bin(const char *val_name, void *buf, DWORD size); 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 */ #endif /* !IPXWRAPPER_COMMON_H */

View File

@ -50,10 +50,6 @@ struct sp_data_cont {
#define CALL(n) if(log_calls) { log_printf("DirectPlay: %s", n); } #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 */ /* Lock the object mutex and return the data pointer */
static struct sp_data *get_sp_data(IDirectPlaySP *sp) { static struct sp_data *get_sp_data(IDirectPlaySP *sp) {
struct sp_data_cont *cont; struct sp_data_cont *cont;
@ -570,28 +566,9 @@ BOOL WINAPI DllMain(HINSTANCE me, DWORD why, LPVOID res) {
reg_close(); reg_close();
}else if(why == DLL_PROCESS_DETACH) { }else if(why == DLL_PROCESS_DETACH) {
if(sysdll) { unload_dlls();
FreeLibrary(sysdll);
sysdll = NULL;
}
log_close(); log_close();
} }
return TRUE; 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;
}

View File

@ -1,3 +1,9 @@
r_SPInit r_SPInit
DPWS_GetEnumPort DPWS_GetEnumPort
DPWS_BuildIPMessageHeader DPWS_BuildIPMessageHeader
WSACreateEvent:4
WSACloseEvent:4
WSAEventSelect:4
WSAResetEvent:4
WSASetEvent:4

View File

@ -43,10 +43,6 @@ ipx_host *hosts = NULL;
SOCKET send_fd = -1; SOCKET send_fd = -1;
struct reg_global global_conf; struct reg_global global_conf;
HMODULE winsock2_dll = NULL;
HMODULE mswsock_dll = NULL;
HMODULE wsock32_dll = NULL;
struct rclient g_rclient; struct rclient g_rclient;
static CRITICAL_SECTION sockets_cs; static CRITICAL_SECTION sockets_cs;
@ -74,14 +70,6 @@ BOOL WINAPI DllMain(HINSTANCE me, DWORD why, LPVOID res) {
return FALSE; 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); reg_open(KEY_QUERY_VALUE);
if(reg_get_bin("global", &global_conf, sizeof(global_conf)) != sizeof(global_conf)) { 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(); reg_close();
DLL_UNLOAD(winsock2_dll); unload_dlls();
DLL_UNLOAD(mswsock_dll);
DLL_UNLOAD(wsock32_dll);
log_close(); log_close();
} }
@ -160,24 +146,6 @@ BOOL WINAPI DllMain(HINSTANCE me, DWORD why, LPVOID res) {
return TRUE; 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 /* 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 * the requested fd, if no matching fd is found, unlock the mutex
* *

View File

@ -14,9 +14,3 @@ EXPORTS
EnumProtocolsW EnumProtocolsW
WSARecvEx WSARecvEx
ioctlsocket ioctlsocket
WSACreateEvent
WSACloseEvent
WSAEventSelect
WSAResetEvent
WSASetEvent

View File

@ -109,7 +109,6 @@ extern HMODULE winsock2_dll;
extern HMODULE mswsock_dll; extern HMODULE mswsock_dll;
extern HMODULE wsock32_dll; extern HMODULE wsock32_dll;
void __stdcall *find_sym(char const *sym);
ipx_socket *get_socket(SOCKET fd); ipx_socket *get_socket(SOCKET fd);
void lock_sockets(void); void lock_sockets(void);
void unlock_sockets(void); void unlock_sockets(void);

View File

@ -1,33 +1,33 @@
inet_addr inet_addr:4
WSAStartup WSAStartup:4
WSACleanup WSACleanup:4
WSASetLastError WSASetLastError:4
WSAGetLastError WSAGetLastError:4
htonl htonl:4
ntohl ntohl:4
htons htons:4
ntohs ntohs:4
select select:4
listen listen:4
accept accept:4
send send:4
connect connect:4
WSACreateEvent WSACreateEvent:4
WSAEventSelect WSAEventSelect:4
WSACloseEvent WSACloseEvent:4
WSAResetEvent WSAResetEvent:4
WSASetEvent WSASetEvent:4
r_EnumProtocolsA r_EnumProtocolsA:4
r_EnumProtocolsW r_EnumProtocolsW:4
r_WSARecvEx r_WSARecvEx:4
r_bind r_bind:4
r_closesocket r_closesocket:4
r_getsockname r_getsockname:4
r_getsockopt r_getsockopt:4
r_recv r_recv:4
r_recvfrom r_recvfrom:4
r_sendto r_sendto:4
r_setsockopt r_setsockopt:4
r_shutdown r_shutdown:4
r_socket r_socket:4
r_ioctlsocket r_ioctlsocket:4

View File

@ -1,8 +1,8 @@
ServiceMain ServiceMain
SvchostPushServiceGlobals SvchostPushServiceGlobals
AcceptEx AcceptEx
EnumProtocolsA EnumProtocolsA:0
EnumProtocolsW EnumProtocolsW:0
GetAcceptExSockaddrs GetAcceptExSockaddrs
GetAddressByNameA GetAddressByNameA
GetAddressByNameW GetAddressByNameW
@ -20,7 +20,7 @@ SetServiceW
StartWsdpService StartWsdpService
StopWsdpService StopWsdpService
TransmitFile TransmitFile
WSARecvEx WSARecvEx:0
WSPStartup WSPStartup
dn_expand dn_expand
getnetbyname getnetbyname

View File

@ -21,29 +21,10 @@
#include "common.h" #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_open();
void log_close(); void log_close();
void log_printf(const char *fmt, ...); 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) { BOOL WINAPI DllMain(HINSTANCE me, DWORD why, LPVOID res) {
if(why == DLL_PROCESS_ATTACH) { if(why == DLL_PROCESS_ATTACH) {
log_open(); log_open();
@ -54,37 +35,9 @@ BOOL WINAPI DllMain(HINSTANCE me, DWORD why, LPVOID res) {
reg_close(); reg_close();
}else if(why == DLL_PROCESS_DETACH) { }else if(why == DLL_PROCESS_DETACH) {
if(sysdll) { unload_dlls();
FreeLibrary(sysdll);
sysdll = NULL;
}
if(ipxdll) {
FreeLibrary(ipxdll);
ipxdll = NULL;
}
log_close(); log_close();
} }
return TRUE; 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;
}

View File

@ -1,26 +1,26 @@
accept accept
bind bind:0
closesocket closesocket:0
connect connect
getpeername getpeername
getsockname getsockname:0
getsockopt getsockopt:0
htonl htonl
htons htons
inet_addr inet_addr
inet_ntoa inet_ntoa
ioctlsocket ioctlsocket:0
listen listen
ntohl ntohl
ntohs ntohs
recv recv:0
recvfrom recvfrom:0
select select
send send
sendto sendto:0
setsockopt setsockopt:0
shutdown shutdown:0
socket socket:0
MigrateWinsockConfiguration MigrateWinsockConfiguration
gethostbyaddr gethostbyaddr
gethostbyname gethostbyname
@ -55,12 +55,12 @@ rexec
rresvport rresvport
sethostname sethostname
dn_expand dn_expand
WSARecvEx WSARecvEx:0
s_perror s_perror
GetAddressByNameA GetAddressByNameA
GetAddressByNameW GetAddressByNameW
EnumProtocolsA EnumProtocolsA:0
EnumProtocolsW EnumProtocolsW:0
GetTypeByNameA GetTypeByNameA
GetTypeByNameW GetTypeByNameW
GetNameByTypeA GetNameByTypeA