55#include " plugin.hpp"
66#include " game_addrs.hpp"
77#include < random>
8+ #include < miniupnpc.h>
9+ #include < upnpcommands.h>
10+ #include < WinSock2.h>
811
912class DemonwareServerOverride : public Hook
1013{
@@ -16,6 +19,60 @@ class DemonwareServerOverride : public Hook
1619 return ret;
1720 }
1821
22+ inline static SafetyHookInline InitNetwork = {};
23+ static void __cdecl InitNetwork_dest ()
24+ {
25+ InitNetwork.call ();
26+
27+ WSADATA tmp;
28+ WSAStartup (0x202 , &tmp);
29+
30+ int upnpError = UPNPDISCOVER_SUCCESS;
31+ UPNPDev* upnpDevice = upnpDiscover (2000 , NULL , NULL , 0 , 0 , 2 , &upnpError);
32+
33+ bool anyError = false ;
34+ int ret = 0 ;
35+ if (upnpError != UPNPDISCOVER_SUCCESS || !upnpDevice)
36+ {
37+ spdlog::error (" UPnP: upnpDiscover failed with error {}" , upnpError);
38+ return ;
39+ }
40+
41+ struct UPNPUrls urls;
42+ struct IGDdatas data;
43+ char lanaddr[16 ];
44+ char wanaddr[16 ];
45+
46+ ret = UPNP_GetValidIGD (upnpDevice, &urls, &data, lanaddr, sizeof (lanaddr), wanaddr, sizeof (wanaddr));
47+ if (ret != 1 && ret != 2 && ret != 3 ) // UPNP_GetValidIGD returning 1/2/3 should be fine
48+ {
49+ spdlog::error (" UPnP: UPNP_GetValidIGD failed with error {}" , ret);
50+ return ;
51+ }
52+
53+ std::list<int > portNums = { 41455 , 41456 , 41457 };
54+
55+ for (auto port : portNums)
56+ {
57+ for (int i = 0 ; i < 2 ; i++)
58+ {
59+ ret = UPNP_AddPortMapping (urls.controlURL , data.first .servicetype ,
60+ std::to_string (port).c_str (), std::to_string (port).c_str (),
61+ lanaddr, " OutRun2006" , i == 0 ? " TCP" : " UDP" , NULL , NULL );
62+ if (ret != UPNPCOMMAND_SUCCESS)
63+ {
64+ spdlog::error (" UPnP: UPNP_AddPortMapping failed for port {}/{}, error code {}" , port, i, ret);
65+ anyError = true ;
66+ }
67+ }
68+ }
69+
70+ if (ret == 0 && !anyError)
71+ {
72+ spdlog::info (" UPnP: port mappings succeeded" );
73+ }
74+ }
75+
1976public:
2077 std::string_view description () override
2178 {
@@ -29,8 +86,10 @@ class DemonwareServerOverride : public Hook
2986
3087 bool apply () override
3188 {
32- constexpr int bdPlatformSocket__getHostByName_Addr = 0x1349B0 ;
89+ constexpr int InitNetwork_Addr = 0x5ACB0 ;
90+ InitNetwork = safetyhook::create_inline (Module::exe_ptr (InitNetwork_Addr), InitNetwork_dest);
3391
92+ constexpr int bdPlatformSocket__getHostByName_Addr = 0x1349B0 ;
3493 bdPlatformSocket__getHostByName_hook = safetyhook::create_inline (Module::exe_ptr (bdPlatformSocket__getHostByName_Addr), destination);
3594
3695 // DW has a very simple check to see if hostname is an IP: if first digit is a number, it's an IP addr
0 commit comments