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
$(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 $@ $^

View File

@ -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 <function list> <output code> [<dll name>]\n";
use strict;
use warnings;
if(@ARGV != 3) {
print STDERR "Usage: mkdll.pl <function list> <output file> <dll number>\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(<STUBS>) {
$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);

View File

@ -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);
}
}

View File

@ -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 */

View File

@ -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;
}

View File

@ -1,3 +1,9 @@
r_SPInit
DPWS_GetEnumPort
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;
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
*

View File

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

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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