diff --git a/Makefile b/Makefile index dbd1d83..36b84c2 100644 --- a/Makefile +++ b/Makefile @@ -32,8 +32,8 @@ endif INCLUDE := -I./include/ -CFLAGS := -std=c99 -Wall -D_WIN32_WINNT=0x0500 -DHAVE_REMOTE $(DBG_OPT) $(INCLUDE) -CXXFLAGS := -std=c++0x -Wall -DHAVE_REMOTE $(DBG_OPT) $(INCLUDE) +CFLAGS := -std=c99 -mno-ms-bitfields -Wall -D_WIN32_WINNT=0x0500 -DHAVE_REMOTE $(DBG_OPT) $(INCLUDE) +CXXFLAGS := -std=c++0x -mno-ms-bitfields -Wall -DHAVE_REMOTE $(DBG_OPT) $(INCLUDE) # Used by mkdeps.pl # @@ -104,13 +104,13 @@ Makefile.dep: src/*.c src/*.cpp ipxwrapper.dll: $(IPXWRAPPER_DEPS) echo 'const char *version_string = "$(VERSION)", *compile_time = "'`date`'";' | $(CC) -c -x c -o version.o - - $(CC) $(CFLAGS) -Wl,--enable-stdcall-fixup -shared -o ipxwrapper.dll $(IPXWRAPPER_DEPS) version.o -liphlpapi -lversion -lole32 -loleaut32 + $(CC) $(CFLAGS) -Wl,--enable-stdcall-fixup -static-libgcc -shared -o ipxwrapper.dll $(IPXWRAPPER_DEPS) version.o -liphlpapi -lversion -lole32 -loleaut32 ipxconfig.exe: src/ipxconfig.cpp icons/ipxconfig.o src/addr.o src/interface.o src/common.o src/config.o src/wpcap_stubs.o $(CXX) $(CXXFLAGS) -Wl,--enable-stdcall-fixup -static-libgcc -static-libstdc++ -D_WIN32_IE=0x0500 -mwindows -o ipxconfig.exe $^ -liphlpapi -lcomctl32 -lws2_32 dpwsockx.dll: src/directplay.o src/log.o src/dpwsockx_stubs.o src/common.o src/config.o src/addr.o src/dpwsockx.def - $(CC) $(CFLAGS) -Wl,--enable-stdcall-fixup -shared -o $@ $^ -lwsock32 + $(CC) $(CFLAGS) -Wl,--enable-stdcall-fixup -static-libgcc -shared -o $@ $^ -lwsock32 src/ipxwrapper_stubs.s: src/ipxwrapper_stubs.txt perl mkstubs.pl src/ipxwrapper_stubs.txt src/ipxwrapper_stubs.s 0 @@ -131,7 +131,7 @@ icons/%.o: icons/%.rc icons/%.ico $(WINDRES) $< -O coff -o $@ %.dll: src/stubdll.o src/%_stubs.o src/log.o src/common.o src/config.o src/addr.o src/%.def - $(CC) $(CFLAGS) -Wl,--enable-stdcall-fixup -shared -o $@ $^ + $(CC) $(CFLAGS) -Wl,--enable-stdcall-fixup -static-libgcc -shared -o $@ $^ src/%_stubs.o: src/%_stubs.s nasm -f win32 -o $@ $< diff --git a/src/directplay.c b/src/directplay.c index 6a092f9..5f95df3 100644 --- a/src/directplay.c +++ b/src/directplay.c @@ -722,15 +722,25 @@ HRESULT WINAPI SPInit(LPSPINITDATA data) { return DPERR_UNAVAILABLE; } -BOOL WINAPI DllMain(HINSTANCE me, DWORD why, LPVOID res) { - if(why == DLL_PROCESS_ATTACH) +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { + if(fdwReason == DLL_PROCESS_ATTACH) { log_open("ipxwrapper.log"); min_log_level = get_main_config().log_level; } - else if(why == DLL_PROCESS_DETACH) + else if(fdwReason == DLL_PROCESS_DETACH) { + /* When the "lpvReserved" parameter is non-NULL, the process is terminating rather + * than the DLL being unloaded dynamically and any threads will have been terminated + * at unknown points, meaning any global data may be in an inconsistent state and we + * cannot (safely) clean up. MSDN states we should do nothing. + */ + if(lpvReserved != NULL) + { + return TRUE; + } + unload_dlls(); log_close(); } diff --git a/src/interface.c b/src/interface.c index 46fd805..6bff6ec 100644 --- a/src/interface.c +++ b/src/interface.c @@ -706,7 +706,8 @@ int ipx_interface_count(void) return count; } -#define PCAP_NAME_PREFIX "rpcap://\\Device\\NPF_" +#define PCAP_NAME_PREFIX_OLD "rpcap://\\Device\\NPF_" +#define PCAP_NAME_PREFIX_NEW "rpcap://" ipx_pcap_interface_t *ipx_get_pcap_interfaces(void) { @@ -726,10 +727,23 @@ ipx_pcap_interface_t *ipx_get_pcap_interfaces(void) for(pcap_if_t *pcap_if = pcap_interfaces; pcap_if; pcap_if = pcap_if->next) { - if(strncmp(pcap_if->name, PCAP_NAME_PREFIX, strlen(PCAP_NAME_PREFIX)) == 0) + const char *ifname = NULL; + + if(strncmp(pcap_if->name, PCAP_NAME_PREFIX_OLD, strlen(PCAP_NAME_PREFIX_OLD)) == 0) + { + ifname = pcap_if->name + strlen(PCAP_NAME_PREFIX_OLD); + } + else if(strncmp(pcap_if->name, PCAP_NAME_PREFIX_NEW, strlen(PCAP_NAME_PREFIX_NEW)) == 0) + { + ifname = pcap_if->name + strlen(PCAP_NAME_PREFIX_NEW); + } + else{ + log_printf(LOG_WARNING, "WinPcap interface with unexpected name format: '%s'", pcap_if->name); + log_printf(LOG_WARNING, "This interface will not be available for IPX use"); + } + + if(ifname != NULL) { - char *ifname = pcap_if->name + strlen(PCAP_NAME_PREFIX); - IP_ADAPTER_INFO *ip_if = ip_interfaces; while(ip_if && strcmp(ip_if->AdapterName, ifname)) { @@ -769,10 +783,6 @@ ipx_pcap_interface_t *ipx_get_pcap_interfaces(void) log_printf(LOG_WARNING, "This interface will not be available for IPX use"); } } - else{ - log_printf(LOG_WARNING, "WinPcap interface with unexpected name format: '%s'", pcap_if->name); - log_printf(LOG_WARNING, "This interface will not be available for IPX use"); - } } pcap_freealldevs(pcap_interfaces); diff --git a/src/ipxwrapper.c b/src/ipxwrapper.c index 25ae94d..48c0d90 100644 --- a/src/ipxwrapper.c +++ b/src/ipxwrapper.c @@ -59,9 +59,9 @@ static void init_cs(CRITICAL_SECTION *cs) } } -BOOL WINAPI DllMain(HINSTANCE me, DWORD why, LPVOID res) +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { - if(why == DLL_PROCESS_ATTACH) + if(fdwReason == DLL_PROCESS_ATTACH) { log_open("ipxwrapper.log"); @@ -105,8 +105,18 @@ BOOL WINAPI DllMain(HINSTANCE me, DWORD why, LPVOID res) router_init(); } - else if(why == DLL_PROCESS_DETACH) + else if(fdwReason == DLL_PROCESS_DETACH) { + /* When the "lpvReserved" parameter is non-NULL, the process is terminating rather + * than the DLL being unloaded dynamically and any threads will have been terminated + * at unknown points, meaning any global data may be in an inconsistent state and we + * cannot (safely) clean up. MSDN states we should do nothing. + */ + if(lpvReserved != NULL) + { + return TRUE; + } + router_cleanup(); WSACleanup(); diff --git a/src/stubdll.c b/src/stubdll.c index b7324d0..19074a5 100644 --- a/src/stubdll.c +++ b/src/stubdll.c @@ -22,15 +22,25 @@ #include "common.h" #include "config.h" -BOOL WINAPI DllMain(HINSTANCE me, DWORD why, LPVOID res) { - if(why == DLL_PROCESS_ATTACH) +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { + if(fdwReason == DLL_PROCESS_ATTACH) { log_open("ipxwrapper.log"); min_log_level = get_main_config().log_level; } - else if(why == DLL_PROCESS_DETACH) + else if(fdwReason == DLL_PROCESS_DETACH) { + /* When the "lpvReserved" parameter is non-NULL, the process is terminating rather + * than the DLL being unloaded dynamically and any threads will have been terminated + * at unknown points, meaning any global data may be in an inconsistent state and we + * cannot (safely) clean up. MSDN states we should do nothing. + */ + if(lpvReserved != NULL) + { + return TRUE; + } + unload_dlls(); log_close(); } diff --git a/tests/50-dplay.t b/tests/50-dplay.t index f06be9d..024c107 100644 --- a/tests/50-dplay.t +++ b/tests/50-dplay.t @@ -88,7 +88,9 @@ describe "A single DirectPlay client" => sub { my ($host, $client) = $single_client_common_init->(); - my $host_player = $host->create_player("host"); + my $host_player = $host->create_player("host"); + sleep(PROP_TIME); + my %client_players = $client->list_players(); cmp_deeply(\%client_players, { @@ -101,7 +103,9 @@ describe "A single DirectPlay client" => sub my ($host, $client) = $single_client_common_init->(); my $client_player = $client->create_player("client"); - my %host_players = $host->list_players(); + sleep(PROP_TIME); + + my %host_players = $host->list_players(); cmp_deeply(\%host_players, { $client_player => "client", @@ -114,6 +118,7 @@ describe "A single DirectPlay client" => sub my $host_player = $host->create_player("host"); my $client_player = $client->create_player("client"); + sleep(PROP_TIME); $host->send_message($host_player, $client_player, "foreordainment"); @@ -142,6 +147,7 @@ describe "A single DirectPlay client" => sub my $host_player = $host->create_player("host"); my $client_player = $client->create_player("client"); + sleep(PROP_TIME); $client->send_message($client_player, $host_player, "iskenderun"); @@ -250,6 +256,7 @@ describe "Concurrent DirectPlay clients" => sub my $host_player = $host->create_player("host"); my $ca_player = $client_a->create_player("client_a"); my $cb_player = $client_b->create_player("client_b"); + sleep(PROP_TIME); $host->send_message($host_player, $ca_player, "myrmecophilous"); $host->send_message($host_player, $cb_player, "indigestibly"); @@ -289,10 +296,9 @@ describe "Concurrent DirectPlay clients" => sub my $host_player = $host->create_player("host"); my $ca_player = $client_a->create_player("client_a"); my $cb_player = $client_b->create_player("client_b"); - - $client_a->send_message($ca_player, $host_player, "unvivid"); sleep(PROP_TIME); + $client_a->send_message($ca_player, $host_player, "unvivid"); $client_b->send_message($cb_player, $host_player, "matrilateral"); sleep(PROP_TIME); @@ -328,6 +334,7 @@ describe "Concurrent DirectPlay clients" => sub my $host_player = $host->create_player("host"); my $ca_player = $client_a->create_player("client_a"); my $cb_player = $client_b->create_player("client_b"); + sleep(PROP_TIME); $client_a->send_message($ca_player, $cb_player, "postpuberty"); $client_b->send_message($cb_player, $ca_player, "veridic"); @@ -367,10 +374,9 @@ describe "Concurrent DirectPlay clients" => sub my $host_player = $host->create_player("host"); my $ca_player = $client_a->create_player("client_a"); my $cb_player = $client_b->create_player("client_b"); - - $client_a->send_message($ca_player, DPID_ALLPLAYERS, "kendrew"); sleep(PROP_TIME); + $client_a->send_message($ca_player, DPID_ALLPLAYERS, "kendrew"); $client_b->send_message($cb_player, DPID_ALLPLAYERS, "derivation"); sleep(PROP_TIME);