diff --git a/src/Syroot.Worms.sln b/src/Syroot.Worms.sln
index 93a211a..6428f0f 100644
--- a/src/Syroot.Worms.sln
+++ b/src/Syroot.Worms.sln
@@ -49,80 +49,240 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = " Solution Items", " Solut
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Syroot.Worms.Worms2.GameServer", "tool\Syroot.Worms.Worms2.GameServer\Syroot.Worms.Worms2.GameServer.csproj", "{13ABF717-5809-441D-A5D8-66E1EE75A390}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fkNetcode", "tool\fkNetcode\fkNetcode.vcxproj", "{C4138811-7CFA-4826-A3DD-AF2B618EAFC1}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FrontendKitWS", "tool\FrontendKitWS\FrontendKitWS.vcxproj", "{E391EA12-B929-466C-932F-DEF72B8CEB5D}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{DD76B6AA-5A5A-4FCD-95AA-9552977525A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DD76B6AA-5A5A-4FCD-95AA-9552977525A1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {DD76B6AA-5A5A-4FCD-95AA-9552977525A1}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {DD76B6AA-5A5A-4FCD-95AA-9552977525A1}.Debug|x64.Build.0 = Debug|Any CPU
+ {DD76B6AA-5A5A-4FCD-95AA-9552977525A1}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {DD76B6AA-5A5A-4FCD-95AA-9552977525A1}.Debug|x86.Build.0 = Debug|Any CPU
{DD76B6AA-5A5A-4FCD-95AA-9552977525A1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DD76B6AA-5A5A-4FCD-95AA-9552977525A1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {DD76B6AA-5A5A-4FCD-95AA-9552977525A1}.Release|x64.ActiveCfg = Release|Any CPU
+ {DD76B6AA-5A5A-4FCD-95AA-9552977525A1}.Release|x64.Build.0 = Release|Any CPU
+ {DD76B6AA-5A5A-4FCD-95AA-9552977525A1}.Release|x86.ActiveCfg = Release|Any CPU
+ {DD76B6AA-5A5A-4FCD-95AA-9552977525A1}.Release|x86.Build.0 = Release|Any CPU
{0D7F9DC3-7268-494E-BA1E-6C01525EB9AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0D7F9DC3-7268-494E-BA1E-6C01525EB9AB}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0D7F9DC3-7268-494E-BA1E-6C01525EB9AB}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {0D7F9DC3-7268-494E-BA1E-6C01525EB9AB}.Debug|x64.Build.0 = Debug|Any CPU
+ {0D7F9DC3-7268-494E-BA1E-6C01525EB9AB}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {0D7F9DC3-7268-494E-BA1E-6C01525EB9AB}.Debug|x86.Build.0 = Debug|Any CPU
{0D7F9DC3-7268-494E-BA1E-6C01525EB9AB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0D7F9DC3-7268-494E-BA1E-6C01525EB9AB}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0D7F9DC3-7268-494E-BA1E-6C01525EB9AB}.Release|x64.ActiveCfg = Release|Any CPU
+ {0D7F9DC3-7268-494E-BA1E-6C01525EB9AB}.Release|x64.Build.0 = Release|Any CPU
+ {0D7F9DC3-7268-494E-BA1E-6C01525EB9AB}.Release|x86.ActiveCfg = Release|Any CPU
+ {0D7F9DC3-7268-494E-BA1E-6C01525EB9AB}.Release|x86.Build.0 = Release|Any CPU
{510EE83E-9C52-40FD-AC7E-C4981EBF4182}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{510EE83E-9C52-40FD-AC7E-C4981EBF4182}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {510EE83E-9C52-40FD-AC7E-C4981EBF4182}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {510EE83E-9C52-40FD-AC7E-C4981EBF4182}.Debug|x64.Build.0 = Debug|Any CPU
+ {510EE83E-9C52-40FD-AC7E-C4981EBF4182}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {510EE83E-9C52-40FD-AC7E-C4981EBF4182}.Debug|x86.Build.0 = Debug|Any CPU
{510EE83E-9C52-40FD-AC7E-C4981EBF4182}.Release|Any CPU.ActiveCfg = Release|Any CPU
{510EE83E-9C52-40FD-AC7E-C4981EBF4182}.Release|Any CPU.Build.0 = Release|Any CPU
+ {510EE83E-9C52-40FD-AC7E-C4981EBF4182}.Release|x64.ActiveCfg = Release|Any CPU
+ {510EE83E-9C52-40FD-AC7E-C4981EBF4182}.Release|x64.Build.0 = Release|Any CPU
+ {510EE83E-9C52-40FD-AC7E-C4981EBF4182}.Release|x86.ActiveCfg = Release|Any CPU
+ {510EE83E-9C52-40FD-AC7E-C4981EBF4182}.Release|x86.Build.0 = Release|Any CPU
{D9694108-539C-4DEE-B5DD-284208D48B46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D9694108-539C-4DEE-B5DD-284208D48B46}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D9694108-539C-4DEE-B5DD-284208D48B46}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {D9694108-539C-4DEE-B5DD-284208D48B46}.Debug|x64.Build.0 = Debug|Any CPU
+ {D9694108-539C-4DEE-B5DD-284208D48B46}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {D9694108-539C-4DEE-B5DD-284208D48B46}.Debug|x86.Build.0 = Debug|Any CPU
{D9694108-539C-4DEE-B5DD-284208D48B46}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D9694108-539C-4DEE-B5DD-284208D48B46}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D9694108-539C-4DEE-B5DD-284208D48B46}.Release|x64.ActiveCfg = Release|Any CPU
+ {D9694108-539C-4DEE-B5DD-284208D48B46}.Release|x64.Build.0 = Release|Any CPU
+ {D9694108-539C-4DEE-B5DD-284208D48B46}.Release|x86.ActiveCfg = Release|Any CPU
+ {D9694108-539C-4DEE-B5DD-284208D48B46}.Release|x86.Build.0 = Release|Any CPU
{AC9F52FA-F552-49E0-83AE-79759BF44FED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AC9F52FA-F552-49E0-83AE-79759BF44FED}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {AC9F52FA-F552-49E0-83AE-79759BF44FED}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {AC9F52FA-F552-49E0-83AE-79759BF44FED}.Debug|x64.Build.0 = Debug|Any CPU
+ {AC9F52FA-F552-49E0-83AE-79759BF44FED}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {AC9F52FA-F552-49E0-83AE-79759BF44FED}.Debug|x86.Build.0 = Debug|Any CPU
{AC9F52FA-F552-49E0-83AE-79759BF44FED}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AC9F52FA-F552-49E0-83AE-79759BF44FED}.Release|Any CPU.Build.0 = Release|Any CPU
+ {AC9F52FA-F552-49E0-83AE-79759BF44FED}.Release|x64.ActiveCfg = Release|Any CPU
+ {AC9F52FA-F552-49E0-83AE-79759BF44FED}.Release|x64.Build.0 = Release|Any CPU
+ {AC9F52FA-F552-49E0-83AE-79759BF44FED}.Release|x86.ActiveCfg = Release|Any CPU
+ {AC9F52FA-F552-49E0-83AE-79759BF44FED}.Release|x86.Build.0 = Release|Any CPU
{4E124BBA-15B5-422E-93D5-96EA7D4180F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4E124BBA-15B5-422E-93D5-96EA7D4180F3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4E124BBA-15B5-422E-93D5-96EA7D4180F3}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {4E124BBA-15B5-422E-93D5-96EA7D4180F3}.Debug|x64.Build.0 = Debug|Any CPU
+ {4E124BBA-15B5-422E-93D5-96EA7D4180F3}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {4E124BBA-15B5-422E-93D5-96EA7D4180F3}.Debug|x86.Build.0 = Debug|Any CPU
{4E124BBA-15B5-422E-93D5-96EA7D4180F3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4E124BBA-15B5-422E-93D5-96EA7D4180F3}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4E124BBA-15B5-422E-93D5-96EA7D4180F3}.Release|x64.ActiveCfg = Release|Any CPU
+ {4E124BBA-15B5-422E-93D5-96EA7D4180F3}.Release|x64.Build.0 = Release|Any CPU
+ {4E124BBA-15B5-422E-93D5-96EA7D4180F3}.Release|x86.ActiveCfg = Release|Any CPU
+ {4E124BBA-15B5-422E-93D5-96EA7D4180F3}.Release|x86.Build.0 = Release|Any CPU
{BBCECFCC-F2FD-4C4D-A6E9-CC7AA5F10FDD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BBCECFCC-F2FD-4C4D-A6E9-CC7AA5F10FDD}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BBCECFCC-F2FD-4C4D-A6E9-CC7AA5F10FDD}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {BBCECFCC-F2FD-4C4D-A6E9-CC7AA5F10FDD}.Debug|x64.Build.0 = Debug|Any CPU
+ {BBCECFCC-F2FD-4C4D-A6E9-CC7AA5F10FDD}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {BBCECFCC-F2FD-4C4D-A6E9-CC7AA5F10FDD}.Debug|x86.Build.0 = Debug|Any CPU
{BBCECFCC-F2FD-4C4D-A6E9-CC7AA5F10FDD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BBCECFCC-F2FD-4C4D-A6E9-CC7AA5F10FDD}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BBCECFCC-F2FD-4C4D-A6E9-CC7AA5F10FDD}.Release|x64.ActiveCfg = Release|Any CPU
+ {BBCECFCC-F2FD-4C4D-A6E9-CC7AA5F10FDD}.Release|x64.Build.0 = Release|Any CPU
+ {BBCECFCC-F2FD-4C4D-A6E9-CC7AA5F10FDD}.Release|x86.ActiveCfg = Release|Any CPU
+ {BBCECFCC-F2FD-4C4D-A6E9-CC7AA5F10FDD}.Release|x86.Build.0 = Release|Any CPU
{BD8079D9-FDB5-4C7D-8AD4-C80ADC4A4B26}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BD8079D9-FDB5-4C7D-8AD4-C80ADC4A4B26}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BD8079D9-FDB5-4C7D-8AD4-C80ADC4A4B26}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {BD8079D9-FDB5-4C7D-8AD4-C80ADC4A4B26}.Debug|x64.Build.0 = Debug|Any CPU
+ {BD8079D9-FDB5-4C7D-8AD4-C80ADC4A4B26}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {BD8079D9-FDB5-4C7D-8AD4-C80ADC4A4B26}.Debug|x86.Build.0 = Debug|Any CPU
{BD8079D9-FDB5-4C7D-8AD4-C80ADC4A4B26}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BD8079D9-FDB5-4C7D-8AD4-C80ADC4A4B26}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BD8079D9-FDB5-4C7D-8AD4-C80ADC4A4B26}.Release|x64.ActiveCfg = Release|Any CPU
+ {BD8079D9-FDB5-4C7D-8AD4-C80ADC4A4B26}.Release|x64.Build.0 = Release|Any CPU
+ {BD8079D9-FDB5-4C7D-8AD4-C80ADC4A4B26}.Release|x86.ActiveCfg = Release|Any CPU
+ {BD8079D9-FDB5-4C7D-8AD4-C80ADC4A4B26}.Release|x86.Build.0 = Release|Any CPU
{239763CD-B7C9-4E8B-A84B-8F24DECF6D7B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{239763CD-B7C9-4E8B-A84B-8F24DECF6D7B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {239763CD-B7C9-4E8B-A84B-8F24DECF6D7B}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {239763CD-B7C9-4E8B-A84B-8F24DECF6D7B}.Debug|x64.Build.0 = Debug|Any CPU
+ {239763CD-B7C9-4E8B-A84B-8F24DECF6D7B}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {239763CD-B7C9-4E8B-A84B-8F24DECF6D7B}.Debug|x86.Build.0 = Debug|Any CPU
{239763CD-B7C9-4E8B-A84B-8F24DECF6D7B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{239763CD-B7C9-4E8B-A84B-8F24DECF6D7B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {239763CD-B7C9-4E8B-A84B-8F24DECF6D7B}.Release|x64.ActiveCfg = Release|Any CPU
+ {239763CD-B7C9-4E8B-A84B-8F24DECF6D7B}.Release|x64.Build.0 = Release|Any CPU
+ {239763CD-B7C9-4E8B-A84B-8F24DECF6D7B}.Release|x86.ActiveCfg = Release|Any CPU
+ {239763CD-B7C9-4E8B-A84B-8F24DECF6D7B}.Release|x86.Build.0 = Release|Any CPU
{748D16FF-35C6-4249-A1E8-04B2D239C954}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{748D16FF-35C6-4249-A1E8-04B2D239C954}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {748D16FF-35C6-4249-A1E8-04B2D239C954}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {748D16FF-35C6-4249-A1E8-04B2D239C954}.Debug|x64.Build.0 = Debug|Any CPU
+ {748D16FF-35C6-4249-A1E8-04B2D239C954}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {748D16FF-35C6-4249-A1E8-04B2D239C954}.Debug|x86.Build.0 = Debug|Any CPU
{748D16FF-35C6-4249-A1E8-04B2D239C954}.Release|Any CPU.ActiveCfg = Release|Any CPU
{748D16FF-35C6-4249-A1E8-04B2D239C954}.Release|Any CPU.Build.0 = Release|Any CPU
+ {748D16FF-35C6-4249-A1E8-04B2D239C954}.Release|x64.ActiveCfg = Release|Any CPU
+ {748D16FF-35C6-4249-A1E8-04B2D239C954}.Release|x64.Build.0 = Release|Any CPU
+ {748D16FF-35C6-4249-A1E8-04B2D239C954}.Release|x86.ActiveCfg = Release|Any CPU
+ {748D16FF-35C6-4249-A1E8-04B2D239C954}.Release|x86.Build.0 = Release|Any CPU
{3AAC4992-DDB9-4175-82B9-C57F22E12FF6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3AAC4992-DDB9-4175-82B9-C57F22E12FF6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3AAC4992-DDB9-4175-82B9-C57F22E12FF6}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {3AAC4992-DDB9-4175-82B9-C57F22E12FF6}.Debug|x64.Build.0 = Debug|Any CPU
+ {3AAC4992-DDB9-4175-82B9-C57F22E12FF6}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {3AAC4992-DDB9-4175-82B9-C57F22E12FF6}.Debug|x86.Build.0 = Debug|Any CPU
{3AAC4992-DDB9-4175-82B9-C57F22E12FF6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3AAC4992-DDB9-4175-82B9-C57F22E12FF6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {3AAC4992-DDB9-4175-82B9-C57F22E12FF6}.Release|x64.ActiveCfg = Release|Any CPU
+ {3AAC4992-DDB9-4175-82B9-C57F22E12FF6}.Release|x64.Build.0 = Release|Any CPU
+ {3AAC4992-DDB9-4175-82B9-C57F22E12FF6}.Release|x86.ActiveCfg = Release|Any CPU
+ {3AAC4992-DDB9-4175-82B9-C57F22E12FF6}.Release|x86.Build.0 = Release|Any CPU
{EF308D4E-26A0-471C-B764-9C4EB713BEAE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EF308D4E-26A0-471C-B764-9C4EB713BEAE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {EF308D4E-26A0-471C-B764-9C4EB713BEAE}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {EF308D4E-26A0-471C-B764-9C4EB713BEAE}.Debug|x64.Build.0 = Debug|Any CPU
+ {EF308D4E-26A0-471C-B764-9C4EB713BEAE}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {EF308D4E-26A0-471C-B764-9C4EB713BEAE}.Debug|x86.Build.0 = Debug|Any CPU
{EF308D4E-26A0-471C-B764-9C4EB713BEAE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EF308D4E-26A0-471C-B764-9C4EB713BEAE}.Release|Any CPU.Build.0 = Release|Any CPU
+ {EF308D4E-26A0-471C-B764-9C4EB713BEAE}.Release|x64.ActiveCfg = Release|Any CPU
+ {EF308D4E-26A0-471C-B764-9C4EB713BEAE}.Release|x64.Build.0 = Release|Any CPU
+ {EF308D4E-26A0-471C-B764-9C4EB713BEAE}.Release|x86.ActiveCfg = Release|Any CPU
+ {EF308D4E-26A0-471C-B764-9C4EB713BEAE}.Release|x86.Build.0 = Release|Any CPU
{351B93B0-301F-42E1-82A0-7FA217154F5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{351B93B0-301F-42E1-82A0-7FA217154F5D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {351B93B0-301F-42E1-82A0-7FA217154F5D}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {351B93B0-301F-42E1-82A0-7FA217154F5D}.Debug|x64.Build.0 = Debug|Any CPU
+ {351B93B0-301F-42E1-82A0-7FA217154F5D}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {351B93B0-301F-42E1-82A0-7FA217154F5D}.Debug|x86.Build.0 = Debug|Any CPU
{351B93B0-301F-42E1-82A0-7FA217154F5D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{351B93B0-301F-42E1-82A0-7FA217154F5D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {351B93B0-301F-42E1-82A0-7FA217154F5D}.Release|x64.ActiveCfg = Release|Any CPU
+ {351B93B0-301F-42E1-82A0-7FA217154F5D}.Release|x64.Build.0 = Release|Any CPU
+ {351B93B0-301F-42E1-82A0-7FA217154F5D}.Release|x86.ActiveCfg = Release|Any CPU
+ {351B93B0-301F-42E1-82A0-7FA217154F5D}.Release|x86.Build.0 = Release|Any CPU
{392E4CA2-61D9-4BE1-B065-8801A9F102B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{392E4CA2-61D9-4BE1-B065-8801A9F102B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {392E4CA2-61D9-4BE1-B065-8801A9F102B8}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {392E4CA2-61D9-4BE1-B065-8801A9F102B8}.Debug|x64.Build.0 = Debug|Any CPU
+ {392E4CA2-61D9-4BE1-B065-8801A9F102B8}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {392E4CA2-61D9-4BE1-B065-8801A9F102B8}.Debug|x86.Build.0 = Debug|Any CPU
{392E4CA2-61D9-4BE1-B065-8801A9F102B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{392E4CA2-61D9-4BE1-B065-8801A9F102B8}.Release|Any CPU.Build.0 = Release|Any CPU
+ {392E4CA2-61D9-4BE1-B065-8801A9F102B8}.Release|x64.ActiveCfg = Release|Any CPU
+ {392E4CA2-61D9-4BE1-B065-8801A9F102B8}.Release|x64.Build.0 = Release|Any CPU
+ {392E4CA2-61D9-4BE1-B065-8801A9F102B8}.Release|x86.ActiveCfg = Release|Any CPU
+ {392E4CA2-61D9-4BE1-B065-8801A9F102B8}.Release|x86.Build.0 = Release|Any CPU
{212F8090-9775-4098-BD44-9ABC01FBE553}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{212F8090-9775-4098-BD44-9ABC01FBE553}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {212F8090-9775-4098-BD44-9ABC01FBE553}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {212F8090-9775-4098-BD44-9ABC01FBE553}.Debug|x64.Build.0 = Debug|Any CPU
+ {212F8090-9775-4098-BD44-9ABC01FBE553}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {212F8090-9775-4098-BD44-9ABC01FBE553}.Debug|x86.Build.0 = Debug|Any CPU
{212F8090-9775-4098-BD44-9ABC01FBE553}.Release|Any CPU.ActiveCfg = Release|Any CPU
{212F8090-9775-4098-BD44-9ABC01FBE553}.Release|Any CPU.Build.0 = Release|Any CPU
+ {212F8090-9775-4098-BD44-9ABC01FBE553}.Release|x64.ActiveCfg = Release|Any CPU
+ {212F8090-9775-4098-BD44-9ABC01FBE553}.Release|x64.Build.0 = Release|Any CPU
+ {212F8090-9775-4098-BD44-9ABC01FBE553}.Release|x86.ActiveCfg = Release|Any CPU
+ {212F8090-9775-4098-BD44-9ABC01FBE553}.Release|x86.Build.0 = Release|Any CPU
{1FAB6B9F-2585-46DC-81C0-579DC808C389}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1FAB6B9F-2585-46DC-81C0-579DC808C389}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1FAB6B9F-2585-46DC-81C0-579DC808C389}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {1FAB6B9F-2585-46DC-81C0-579DC808C389}.Debug|x64.Build.0 = Debug|Any CPU
+ {1FAB6B9F-2585-46DC-81C0-579DC808C389}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {1FAB6B9F-2585-46DC-81C0-579DC808C389}.Debug|x86.Build.0 = Debug|Any CPU
{1FAB6B9F-2585-46DC-81C0-579DC808C389}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1FAB6B9F-2585-46DC-81C0-579DC808C389}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1FAB6B9F-2585-46DC-81C0-579DC808C389}.Release|x64.ActiveCfg = Release|Any CPU
+ {1FAB6B9F-2585-46DC-81C0-579DC808C389}.Release|x64.Build.0 = Release|Any CPU
+ {1FAB6B9F-2585-46DC-81C0-579DC808C389}.Release|x86.ActiveCfg = Release|Any CPU
+ {1FAB6B9F-2585-46DC-81C0-579DC808C389}.Release|x86.Build.0 = Release|Any CPU
{13ABF717-5809-441D-A5D8-66E1EE75A390}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{13ABF717-5809-441D-A5D8-66E1EE75A390}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {13ABF717-5809-441D-A5D8-66E1EE75A390}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {13ABF717-5809-441D-A5D8-66E1EE75A390}.Debug|x64.Build.0 = Debug|Any CPU
+ {13ABF717-5809-441D-A5D8-66E1EE75A390}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {13ABF717-5809-441D-A5D8-66E1EE75A390}.Debug|x86.Build.0 = Debug|Any CPU
{13ABF717-5809-441D-A5D8-66E1EE75A390}.Release|Any CPU.ActiveCfg = Release|Any CPU
{13ABF717-5809-441D-A5D8-66E1EE75A390}.Release|Any CPU.Build.0 = Release|Any CPU
+ {13ABF717-5809-441D-A5D8-66E1EE75A390}.Release|x64.ActiveCfg = Release|Any CPU
+ {13ABF717-5809-441D-A5D8-66E1EE75A390}.Release|x64.Build.0 = Release|Any CPU
+ {13ABF717-5809-441D-A5D8-66E1EE75A390}.Release|x86.ActiveCfg = Release|Any CPU
+ {13ABF717-5809-441D-A5D8-66E1EE75A390}.Release|x86.Build.0 = Release|Any CPU
+ {C4138811-7CFA-4826-A3DD-AF2B618EAFC1}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {C4138811-7CFA-4826-A3DD-AF2B618EAFC1}.Debug|x64.ActiveCfg = Debug|Win32
+ {C4138811-7CFA-4826-A3DD-AF2B618EAFC1}.Debug|x86.ActiveCfg = Debug|Win32
+ {C4138811-7CFA-4826-A3DD-AF2B618EAFC1}.Debug|x86.Build.0 = Debug|Win32
+ {C4138811-7CFA-4826-A3DD-AF2B618EAFC1}.Release|Any CPU.ActiveCfg = Release|Win32
+ {C4138811-7CFA-4826-A3DD-AF2B618EAFC1}.Release|x64.ActiveCfg = Release|Win32
+ {C4138811-7CFA-4826-A3DD-AF2B618EAFC1}.Release|x86.ActiveCfg = Release|Win32
+ {C4138811-7CFA-4826-A3DD-AF2B618EAFC1}.Release|x86.Build.0 = Release|Win32
+ {E391EA12-B929-466C-932F-DEF72B8CEB5D}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {E391EA12-B929-466C-932F-DEF72B8CEB5D}.Debug|x64.ActiveCfg = Debug|Win32
+ {E391EA12-B929-466C-932F-DEF72B8CEB5D}.Debug|x86.ActiveCfg = Debug|Win32
+ {E391EA12-B929-466C-932F-DEF72B8CEB5D}.Debug|x86.Build.0 = Debug|Win32
+ {E391EA12-B929-466C-932F-DEF72B8CEB5D}.Release|Any CPU.ActiveCfg = Release|Win32
+ {E391EA12-B929-466C-932F-DEF72B8CEB5D}.Release|x64.ActiveCfg = Release|Win32
+ {E391EA12-B929-466C-932F-DEF72B8CEB5D}.Release|x86.ActiveCfg = Release|Win32
+ {E391EA12-B929-466C-932F-DEF72B8CEB5D}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -145,6 +305,8 @@ Global
{212F8090-9775-4098-BD44-9ABC01FBE553} = {99E56312-A064-4AD3-8443-0B56A5F76E6B}
{1FAB6B9F-2585-46DC-81C0-579DC808C389} = {0B9B0B74-3EB1-46A4-BCCC-F2D6AE59A9EE}
{13ABF717-5809-441D-A5D8-66E1EE75A390} = {0B9B0B74-3EB1-46A4-BCCC-F2D6AE59A9EE}
+ {C4138811-7CFA-4826-A3DD-AF2B618EAFC1} = {0B9B0B74-3EB1-46A4-BCCC-F2D6AE59A9EE}
+ {E391EA12-B929-466C-932F-DEF72B8CEB5D} = {0B9B0B74-3EB1-46A4-BCCC-F2D6AE59A9EE}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {1CD4EDE2-A5FB-4A58-A850-3506AB7E7B69}
diff --git a/src/tool/FrontendKitWS/FrontendKitWS.vcxproj b/src/tool/FrontendKitWS/FrontendKitWS.vcxproj
new file mode 100644
index 0000000..08ed644
--- /dev/null
+++ b/src/tool/FrontendKitWS/FrontendKitWS.vcxproj
@@ -0,0 +1,103 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+
+
+
+
+
+
+
+
+
+
+ 16.0
+ Win32Proj
+ {e391ea12-b929-466c-932f-def72b8ceb5d}
+ FrontendKitWS
+ 10.0
+ FrontendKitWS
+
+
+
+ DynamicLibrary
+ true
+ v142
+ MultiByte
+
+
+ DynamicLibrary
+ false
+ v142
+ true
+ MultiByte
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ bin\$(Configuration)\
+ obj\$(Configuration)\
+ wsock32
+
+
+ false
+ bin\$(Configuration)\
+ obj\$(Configuration)\
+ wsock32
+
+
+
+ Level3
+ true
+ WIN32;_DEBUG;FRONTENDKITWS_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
+ true
+
+
+ Windows
+ true
+ false
+ main.def
+
+
+
+
+ Level3
+ true
+ true
+ true
+ WIN32;NDEBUG;FRONTENDKITWS_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
+ true
+
+
+ Windows
+ true
+ true
+ true
+ false
+ main.def
+
+
+
+
+
+
diff --git a/src/tool/FrontendKitWS/fk.h b/src/tool/FrontendKitWS/fk.h
new file mode 100644
index 0000000..55df0c1
--- /dev/null
+++ b/src/tool/FrontendKitWS/fk.h
@@ -0,0 +1,44 @@
+#define WIN32_LEAN_AND_MEAN
+#include
+#include
+
+std::vector modules;
+
+void fkAttach()
+{
+ // Get executable directory.
+ CHAR buffer[MAX_PATH];
+ GetModuleFileName(NULL, buffer, MAX_PATH);
+ *(strrchr(buffer, '\\') + 1) = '\0';
+
+ // Attempt to load all library files matching the fk*.dll search pattern.
+ lstrcat(buffer, "fk*.dll");
+ WIN32_FIND_DATA findFileData;
+ HANDLE hFindFile = FindFirstFile(buffer, &findFileData);
+ if (hFindFile == INVALID_HANDLE_VALUE)
+ return;
+ do
+ {
+ if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ continue;
+ HMODULE hLibrary = LoadLibrary(findFileData.cFileName);
+ if (hLibrary)
+ {
+ modules.push_back(hLibrary);
+ }
+ else
+ {
+ sprintf_s(buffer, "Could not load module %s.", findFileData.cFileName);
+ MessageBox(NULL, buffer, "FrontendKit", MB_ICONWARNING);
+ }
+ } while (FindNextFile(hFindFile, &findFileData));
+ FindClose(hFindFile);
+}
+
+void fkDetach()
+{
+ // Release all loaded modules.
+ for (HMODULE hModule : modules)
+ FreeLibrary(hModule);
+ modules.clear();
+}
\ No newline at end of file
diff --git a/src/tool/FrontendKitWS/main.cpp b/src/tool/FrontendKitWS/main.cpp
new file mode 100644
index 0000000..ed26580
--- /dev/null
+++ b/src/tool/FrontendKitWS/main.cpp
@@ -0,0 +1,272 @@
+#define WIN32_LEAN_AND_MEAN
+#include "fk.h"
+#include
+
+struct wsock32_dll
+{
+ HMODULE dll;
+ FARPROC AcceptEx;
+ FARPROC Arecv;
+ FARPROC Asend;
+ FARPROC EnumProtocolsA;
+ FARPROC EnumProtocolsW;
+ FARPROC GetAcceptExSockaddrs;
+ FARPROC GetAddressByNameA;
+ FARPROC GetAddressByNameW;
+ FARPROC GetNameByTypeA;
+ FARPROC GetNameByTypeW;
+ FARPROC GetServiceA;
+ FARPROC GetServiceW;
+ FARPROC GetTypeByNameA;
+ FARPROC GetTypeByNameW;
+ FARPROC MigrateWinsockConfiguration;
+ FARPROC NPLoadNameSpaces;
+ FARPROC NSPStartup;
+ FARPROC SetServiceA;
+ FARPROC SetServiceW;
+ FARPROC TransmitFile;
+ FARPROC WEP;
+ FARPROC WSAAsyncGetHostByAddr;
+ FARPROC WSAAsyncGetHostByName;
+ FARPROC WSAAsyncGetProtoByName;
+ FARPROC WSAAsyncGetProtoByNumber;
+ FARPROC WSAAsyncGetServByName;
+ FARPROC WSAAsyncGetServByPort;
+ FARPROC WSAAsyncSelect;
+ FARPROC WSACancelAsyncRequest;
+ FARPROC WSACancelBlockingCall;
+ FARPROC WSACleanup;
+ FARPROC WSAGetLastError;
+ FARPROC WSAIsBlocking;
+ FARPROC WSARecvEx;
+ FARPROC WSASetBlockingHook;
+ FARPROC WSASetLastError;
+ FARPROC WSAStartup;
+ FARPROC WSAUnhookBlockingHook;
+ FARPROC WSApSetPostRoutine;
+ FARPROC WSHEnumProtocols;
+ FARPROC WsControl;
+ FARPROC __WSAFDIsSet;
+ FARPROC accept;
+ FARPROC bind;
+ FARPROC closesocket;
+ FARPROC closesockinfo;
+ FARPROC connect;
+ FARPROC dn_expand;
+ FARPROC gethostbyaddr;
+ FARPROC gethostbyname;
+ FARPROC gethostname;
+ FARPROC getnetbyname;
+ FARPROC getpeername;
+ FARPROC getprotobyname;
+ FARPROC getprotobynumber;
+ FARPROC getservbyname;
+ FARPROC getservbyport;
+ FARPROC getsockname;
+ FARPROC getsockopt;
+ FARPROC htonl;
+ FARPROC htons;
+ FARPROC inet_addr;
+ FARPROC inet_network;
+ FARPROC inet_ntoa;
+ FARPROC ioctlsocket;
+ FARPROC listen;
+ FARPROC ntohl;
+ FARPROC ntohs;
+ FARPROC rcmd;
+ FARPROC recv;
+ FARPROC recvfrom;
+ FARPROC rexec;
+ FARPROC rresvport;
+ FARPROC s_perror;
+ FARPROC select;
+ FARPROC send;
+ FARPROC sendto;
+ FARPROC sethostname;
+ FARPROC setsockopt;
+ FARPROC shutdown;
+ FARPROC socket;
+} wsock32;
+
+__declspec(naked) void AcceptEx() { _asm { jmp[wsock32.AcceptEx] } }
+__declspec(naked) void Arecv() { _asm { jmp[wsock32.Arecv] } }
+__declspec(naked) void Asend() { _asm { jmp[wsock32.Asend] } }
+__declspec(naked) void EnumProtocolsA() { _asm { jmp[wsock32.EnumProtocolsA] } }
+__declspec(naked) void EnumProtocolsW() { _asm { jmp[wsock32.EnumProtocolsW] } }
+__declspec(naked) void GetAcceptExSockaddrs() { _asm { jmp[wsock32.GetAcceptExSockaddrs] } }
+__declspec(naked) void GetAddressByNameA() { _asm { jmp[wsock32.GetAddressByNameA] } }
+__declspec(naked) void GetAddressByNameW() { _asm { jmp[wsock32.GetAddressByNameW] } }
+__declspec(naked) void GetNameByTypeA() { _asm { jmp[wsock32.GetNameByTypeA] } }
+__declspec(naked) void GetNameByTypeW() { _asm { jmp[wsock32.GetNameByTypeW] } }
+__declspec(naked) void GetServiceA() { _asm { jmp[wsock32.GetServiceA] } }
+__declspec(naked) void GetServiceW() { _asm { jmp[wsock32.GetServiceW] } }
+__declspec(naked) void GetTypeByNameA() { _asm { jmp[wsock32.GetTypeByNameA] } }
+__declspec(naked) void GetTypeByNameW() { _asm { jmp[wsock32.GetTypeByNameW] } }
+__declspec(naked) void MigrateWinsockConfiguration() { _asm { jmp[wsock32.MigrateWinsockConfiguration] } }
+__declspec(naked) void NPLoadNameSpaces() { _asm { jmp[wsock32.NPLoadNameSpaces] } }
+__declspec(naked) void NSPStartup() { _asm { jmp[wsock32.NSPStartup] } }
+__declspec(naked) void SetServiceA() { _asm { jmp[wsock32.SetServiceA] } }
+__declspec(naked) void SetServiceW() { _asm { jmp[wsock32.SetServiceW] } }
+__declspec(naked) void TransmitFile() { _asm { jmp[wsock32.TransmitFile] } }
+__declspec(naked) void WEP() { _asm { jmp[wsock32.WEP] } }
+__declspec(naked) void WSAAsyncGetHostByAddr() { _asm { jmp[wsock32.WSAAsyncGetHostByAddr] } }
+__declspec(naked) void WSAAsyncGetHostByName() { _asm { jmp[wsock32.WSAAsyncGetHostByName] } }
+__declspec(naked) void WSAAsyncGetProtoByName() { _asm { jmp[wsock32.WSAAsyncGetProtoByName] } }
+__declspec(naked) void WSAAsyncGetProtoByNumber() { _asm { jmp[wsock32.WSAAsyncGetProtoByNumber] } }
+__declspec(naked) void WSAAsyncGetServByName() { _asm { jmp[wsock32.WSAAsyncGetServByName] } }
+__declspec(naked) void WSAAsyncGetServByPort() { _asm { jmp[wsock32.WSAAsyncGetServByPort] } }
+__declspec(naked) void WSAAsyncSelect() { _asm { jmp[wsock32.WSAAsyncSelect] } }
+__declspec(naked) void WSACancelAsyncRequest() { _asm { jmp[wsock32.WSACancelAsyncRequest] } }
+__declspec(naked) void WSACancelBlockingCall() { _asm { jmp[wsock32.WSACancelBlockingCall] } }
+__declspec(naked) void WSACleanup() { _asm { jmp[wsock32.WSACleanup] } }
+__declspec(naked) void WSAGetLastError() { _asm { jmp[wsock32.WSAGetLastError] } }
+__declspec(naked) void WSAIsBlocking() { _asm { jmp[wsock32.WSAIsBlocking] } }
+__declspec(naked) void WSARecvEx() { _asm { jmp[wsock32.WSARecvEx] } }
+__declspec(naked) void WSASetBlockingHook() { _asm { jmp[wsock32.WSASetBlockingHook] } }
+__declspec(naked) void WSASetLastError() { _asm { jmp[wsock32.WSASetLastError] } }
+__declspec(naked) void WSAStartup() { _asm { jmp[wsock32.WSAStartup] } }
+__declspec(naked) void WSAUnhookBlockingHook() { _asm { jmp[wsock32.WSAUnhookBlockingHook] } }
+__declspec(naked) void WSApSetPostRoutine() { _asm { jmp[wsock32.WSApSetPostRoutine] } }
+__declspec(naked) void WSHEnumProtocols() { _asm { jmp[wsock32.WSHEnumProtocols] } }
+__declspec(naked) void WsControl() { _asm { jmp[wsock32.WsControl] } }
+__declspec(naked) void __WSAFDIsSet() { _asm { jmp[wsock32.__WSAFDIsSet] } }
+__declspec(naked) void accept() { _asm { jmp[wsock32.accept] } }
+__declspec(naked) void bind() { _asm { jmp[wsock32.bind] } }
+__declspec(naked) void closesocket() { _asm { jmp[wsock32.closesocket] } }
+__declspec(naked) void closesockinfo() { _asm { jmp[wsock32.closesockinfo] } }
+__declspec(naked) void connect() { _asm { jmp[wsock32.connect] } }
+__declspec(naked) void dn_expand() { _asm { jmp[wsock32.dn_expand] } }
+__declspec(naked) void gethostbyaddr() { _asm { jmp[wsock32.gethostbyaddr] } }
+__declspec(naked) void gethostbyname() { _asm { jmp[wsock32.gethostbyname] } }
+__declspec(naked) void gethostname() { _asm { jmp[wsock32.gethostname] } }
+__declspec(naked) void getnetbyname() { _asm { jmp[wsock32.getnetbyname] } }
+__declspec(naked) void getpeername() { _asm { jmp[wsock32.getpeername] } }
+__declspec(naked) void getprotobyname() { _asm { jmp[wsock32.getprotobyname] } }
+__declspec(naked) void getprotobynumber() { _asm { jmp[wsock32.getprotobynumber] } }
+__declspec(naked) void getservbyname() { _asm { jmp[wsock32.getservbyname] } }
+__declspec(naked) void getservbyport() { _asm { jmp[wsock32.getservbyport] } }
+__declspec(naked) void getsockname() { _asm { jmp[wsock32.getsockname] } }
+__declspec(naked) void getsockopt() { _asm { jmp[wsock32.getsockopt] } }
+__declspec(naked) void htonl() { _asm { jmp[wsock32.htonl] } }
+__declspec(naked) void htons() { _asm { jmp[wsock32.htons] } }
+__declspec(naked) void inet_addr() { _asm { jmp[wsock32.inet_addr] } }
+__declspec(naked) void inet_network() { _asm { jmp[wsock32.inet_network] } }
+__declspec(naked) void inet_ntoa() { _asm { jmp[wsock32.inet_ntoa] } }
+__declspec(naked) void ioctlsocket() { _asm { jmp[wsock32.ioctlsocket] } }
+__declspec(naked) void listen() { _asm { jmp[wsock32.listen] } }
+__declspec(naked) void ntohl() { _asm { jmp[wsock32.ntohl] } }
+__declspec(naked) void ntohs() { _asm { jmp[wsock32.ntohs] } }
+__declspec(naked) void rcmd() { _asm { jmp[wsock32.rcmd] } }
+__declspec(naked) void recv() { _asm { jmp[wsock32.recv] } }
+__declspec(naked) void recvfrom() { _asm { jmp[wsock32.recvfrom] } }
+__declspec(naked) void rexec() { _asm { jmp[wsock32.rexec] } }
+__declspec(naked) void rresvport() { _asm { jmp[wsock32.rresvport] } }
+__declspec(naked) void s_perror() { _asm { jmp[wsock32.s_perror] } }
+__declspec(naked) void select() { _asm { jmp[wsock32.select] } }
+__declspec(naked) void send() { _asm { jmp[wsock32.send] } }
+__declspec(naked) void sendto() { _asm { jmp[wsock32.sendto] } }
+__declspec(naked) void sethostname() { _asm { jmp[wsock32.sethostname] } }
+__declspec(naked) void setsockopt() { _asm { jmp[wsock32.setsockopt] } }
+__declspec(naked) void shutdown() { _asm { jmp[wsock32.shutdown] } }
+__declspec(naked) void socket() { _asm { jmp[wsock32.socket] } }
+
+char path[MAX_PATH + 16];
+BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
+{
+ switch (ul_reason_for_call)
+ {
+ case DLL_PROCESS_ATTACH:
+ GetSystemDirectoryA(path, MAX_PATH);
+ lstrcatA(path, "\\WSOCK32.dll");
+ wsock32.dll = LoadLibraryA(path);
+ wsock32.AcceptEx = GetProcAddress(wsock32.dll, "AcceptEx");
+ wsock32.Arecv = GetProcAddress(wsock32.dll, "Arecv");
+ wsock32.Asend = GetProcAddress(wsock32.dll, "Asend");
+ wsock32.EnumProtocolsA = GetProcAddress(wsock32.dll, "EnumProtocolsA");
+ wsock32.EnumProtocolsW = GetProcAddress(wsock32.dll, "EnumProtocolsW");
+ wsock32.GetAcceptExSockaddrs = GetProcAddress(wsock32.dll, "GetAcceptExSockaddrs");
+ wsock32.GetAddressByNameA = GetProcAddress(wsock32.dll, "GetAddressByNameA");
+ wsock32.GetAddressByNameW = GetProcAddress(wsock32.dll, "GetAddressByNameW");
+ wsock32.GetNameByTypeA = GetProcAddress(wsock32.dll, "GetNameByTypeA");
+ wsock32.GetNameByTypeW = GetProcAddress(wsock32.dll, "GetNameByTypeW");
+ wsock32.GetServiceA = GetProcAddress(wsock32.dll, "GetServiceA");
+ wsock32.GetServiceW = GetProcAddress(wsock32.dll, "GetServiceW");
+ wsock32.GetTypeByNameA = GetProcAddress(wsock32.dll, "GetTypeByNameA");
+ wsock32.GetTypeByNameW = GetProcAddress(wsock32.dll, "GetTypeByNameW");
+ wsock32.MigrateWinsockConfiguration = GetProcAddress(wsock32.dll, "MigrateWinsockConfiguration");
+ wsock32.NPLoadNameSpaces = GetProcAddress(wsock32.dll, "NPLoadNameSpaces");
+ wsock32.NSPStartup = GetProcAddress(wsock32.dll, "NSPStartup");
+ wsock32.SetServiceA = GetProcAddress(wsock32.dll, "SetServiceA");
+ wsock32.SetServiceW = GetProcAddress(wsock32.dll, "SetServiceW");
+ wsock32.TransmitFile = GetProcAddress(wsock32.dll, "TransmitFile");
+ wsock32.WEP = GetProcAddress(wsock32.dll, "WEP");
+ wsock32.WSAAsyncGetHostByAddr = GetProcAddress(wsock32.dll, "WSAAsyncGetHostByAddr");
+ wsock32.WSAAsyncGetHostByName = GetProcAddress(wsock32.dll, "WSAAsyncGetHostByName");
+ wsock32.WSAAsyncGetProtoByName = GetProcAddress(wsock32.dll, "WSAAsyncGetProtoByName");
+ wsock32.WSAAsyncGetProtoByNumber = GetProcAddress(wsock32.dll, "WSAAsyncGetProtoByNumber");
+ wsock32.WSAAsyncGetServByName = GetProcAddress(wsock32.dll, "WSAAsyncGetServByName");
+ wsock32.WSAAsyncGetServByPort = GetProcAddress(wsock32.dll, "WSAAsyncGetServByPort");
+ wsock32.WSAAsyncSelect = GetProcAddress(wsock32.dll, "WSAAsyncSelect");
+ wsock32.WSACancelAsyncRequest = GetProcAddress(wsock32.dll, "WSACancelAsyncRequest");
+ wsock32.WSACancelBlockingCall = GetProcAddress(wsock32.dll, "WSACancelBlockingCall");
+ wsock32.WSACleanup = GetProcAddress(wsock32.dll, "WSACleanup");
+ wsock32.WSAGetLastError = GetProcAddress(wsock32.dll, "WSAGetLastError");
+ wsock32.WSAIsBlocking = GetProcAddress(wsock32.dll, "WSAIsBlocking");
+ wsock32.WSARecvEx = GetProcAddress(wsock32.dll, "WSARecvEx");
+ wsock32.WSASetBlockingHook = GetProcAddress(wsock32.dll, "WSASetBlockingHook");
+ wsock32.WSASetLastError = GetProcAddress(wsock32.dll, "WSASetLastError");
+ wsock32.WSAStartup = GetProcAddress(wsock32.dll, "WSAStartup");
+ wsock32.WSAUnhookBlockingHook = GetProcAddress(wsock32.dll, "WSAUnhookBlockingHook");
+ wsock32.WSApSetPostRoutine = GetProcAddress(wsock32.dll, "WSApSetPostRoutine");
+ wsock32.WSHEnumProtocols = GetProcAddress(wsock32.dll, "WSHEnumProtocols");
+ wsock32.WsControl = GetProcAddress(wsock32.dll, "WsControl");
+ wsock32.__WSAFDIsSet = GetProcAddress(wsock32.dll, "__WSAFDIsSet");
+ wsock32.accept = GetProcAddress(wsock32.dll, "accept");
+ wsock32.bind = GetProcAddress(wsock32.dll, "bind");
+ wsock32.closesocket = GetProcAddress(wsock32.dll, "closesocket");
+ wsock32.closesockinfo = GetProcAddress(wsock32.dll, "closesockinfo");
+ wsock32.connect = GetProcAddress(wsock32.dll, "connect");
+ wsock32.dn_expand = GetProcAddress(wsock32.dll, "dn_expand");
+ wsock32.gethostbyaddr = GetProcAddress(wsock32.dll, "gethostbyaddr");
+ wsock32.gethostbyname = GetProcAddress(wsock32.dll, "gethostbyname");
+ wsock32.gethostname = GetProcAddress(wsock32.dll, "gethostname");
+ wsock32.getnetbyname = GetProcAddress(wsock32.dll, "getnetbyname");
+ wsock32.getpeername = GetProcAddress(wsock32.dll, "getpeername");
+ wsock32.getprotobyname = GetProcAddress(wsock32.dll, "getprotobyname");
+ wsock32.getprotobynumber = GetProcAddress(wsock32.dll, "getprotobynumber");
+ wsock32.getservbyname = GetProcAddress(wsock32.dll, "getservbyname");
+ wsock32.getservbyport = GetProcAddress(wsock32.dll, "getservbyport");
+ wsock32.getsockname = GetProcAddress(wsock32.dll, "getsockname");
+ wsock32.getsockopt = GetProcAddress(wsock32.dll, "getsockopt");
+ wsock32.htonl = GetProcAddress(wsock32.dll, "htonl");
+ wsock32.htons = GetProcAddress(wsock32.dll, "htons");
+ wsock32.inet_addr = GetProcAddress(wsock32.dll, "inet_addr");
+ wsock32.inet_network = GetProcAddress(wsock32.dll, "inet_network");
+ wsock32.inet_ntoa = GetProcAddress(wsock32.dll, "inet_ntoa");
+ wsock32.ioctlsocket = GetProcAddress(wsock32.dll, "ioctlsocket");
+ wsock32.listen = GetProcAddress(wsock32.dll, "listen");
+ wsock32.ntohl = GetProcAddress(wsock32.dll, "ntohl");
+ wsock32.ntohs = GetProcAddress(wsock32.dll, "ntohs");
+ wsock32.rcmd = GetProcAddress(wsock32.dll, "rcmd");
+ wsock32.recv = GetProcAddress(wsock32.dll, "recv");
+ wsock32.recvfrom = GetProcAddress(wsock32.dll, "recvfrom");
+ wsock32.rexec = GetProcAddress(wsock32.dll, "rexec");
+ wsock32.rresvport = GetProcAddress(wsock32.dll, "rresvport");
+ wsock32.s_perror = GetProcAddress(wsock32.dll, "s_perror");
+ wsock32.select = GetProcAddress(wsock32.dll, "select");
+ wsock32.send = GetProcAddress(wsock32.dll, "send");
+ wsock32.sendto = GetProcAddress(wsock32.dll, "sendto");
+ wsock32.sethostname = GetProcAddress(wsock32.dll, "sethostname");
+ wsock32.setsockopt = GetProcAddress(wsock32.dll, "setsockopt");
+ wsock32.shutdown = GetProcAddress(wsock32.dll, "shutdown");
+ wsock32.socket = GetProcAddress(wsock32.dll, "socket");
+ fkAttach();
+ break;
+
+ case DLL_PROCESS_DETACH:
+ FreeLibrary(wsock32.dll);
+ fkDetach();
+ break;
+ }
+ return TRUE;
+}
diff --git a/src/tool/FrontendKitWS/main.def b/src/tool/FrontendKitWS/main.def
new file mode 100644
index 0000000..0225dc3
--- /dev/null
+++ b/src/tool/FrontendKitWS/main.def
@@ -0,0 +1,83 @@
+LIBRARY "wsock32"
+EXPORTS
+ AcceptEx @1141
+ Arecv @1003
+ Asend @1004
+ EnumProtocolsA @1111
+ EnumProtocolsW @1112
+ GetAcceptExSockaddrs @1142
+ GetAddressByNameA @1109
+ GetAddressByNameW @1110
+ GetNameByTypeA @1115
+ GetNameByTypeW @1116
+ GetServiceA @1119
+ GetServiceW @1120
+ GetTypeByNameA @1113
+ GetTypeByNameW @1114
+ MigrateWinsockConfiguration @24
+ NPLoadNameSpaces @1130
+ NSPStartup @1131
+ SetServiceA @1117
+ SetServiceW @1118
+ TransmitFile @1140
+ WEP @500
+ WSAAsyncGetHostByAddr @102
+ WSAAsyncGetHostByName @103
+ WSAAsyncGetProtoByName @105
+ WSAAsyncGetProtoByNumber @104
+ WSAAsyncGetServByName @107
+ WSAAsyncGetServByPort @106
+ WSAAsyncSelect @101
+ WSACancelAsyncRequest @108
+ WSACancelBlockingCall @113
+ WSACleanup @116
+ WSAGetLastError @111
+ WSAIsBlocking @114
+ WSARecvEx @1107
+ WSASetBlockingHook @109
+ WSASetLastError @112
+ WSAStartup @115
+ WSAUnhookBlockingHook @110
+ WSApSetPostRoutine @1000
+ WSHEnumProtocols @1005
+ WsControl @1001
+ __WSAFDIsSet @151
+ accept @1
+ bind @2
+ closesocket @3
+ closesockinfo @1002
+ connect @4
+ dn_expand @1106
+ gethostbyaddr @51
+ gethostbyname @52
+ gethostname @57
+ getnetbyname @1101
+ getpeername @5
+ getprotobyname @53
+ getprotobynumber @54
+ getservbyname @55
+ getservbyport @56
+ getsockname @6
+ getsockopt @7
+ htonl @8
+ htons @9
+ inet_addr @10
+ inet_network @1100
+ inet_ntoa @11
+ ioctlsocket @12
+ listen @13
+ ntohl @14
+ ntohs @15
+ rcmd @1102
+ recv @16
+ recvfrom @17
+ rexec @1103
+ rresvport @1104
+ s_perror @1108
+ select @18
+ send @19
+ sendto @20
+ sethostname @1105
+ setsockopt @21
+ shutdown @22
+ socket @23
diff --git a/src/tool/Syroot.Worms.Worms2.GameServer/Program.cs b/src/tool/Syroot.Worms.Worms2.GameServer/Program.cs
index 5a4df28..7843ced 100644
--- a/src/tool/Syroot.Worms.Worms2.GameServer/Program.cs
+++ b/src/tool/Syroot.Worms.Worms2.GameServer/Program.cs
@@ -12,20 +12,22 @@ namespace Syroot.Worms.Worms2.GameServer
private static void Main(string[] args)
{
- //Proxy.Run(); return;
+ string? argEndPoint = args.Length > 0 ? args[0] : null;
Server server = new Server();
- server.Run(ParseEndPoint(args.Length > 0 ? args[0] : null));
+ server.Run(ParseEndPoint(argEndPoint, new IPEndPoint(IPAddress.Any, 17000)));
+
+ //Proxy.Run(ParseEndPoint(argEndPoint, new IPEndPoint(IPAddress.Any, 17001)));
}
- private static IPEndPoint ParseEndPoint(string? s)
+ private static IPEndPoint ParseEndPoint(string? s, IPEndPoint fallback)
{
if (UInt16.TryParse(s, out ushort port))
- return new IPEndPoint(IPAddress.Any, port);
+ return new IPEndPoint(fallback.Address, port);
else if (IPEndPoint.TryParse(s, out IPEndPoint endPoint))
return endPoint;
else
- return new IPEndPoint(IPAddress.Any, 17000);
+ return fallback;
}
}
}
diff --git a/src/tool/Syroot.Worms.Worms2.GameServer/Proxy.cs b/src/tool/Syroot.Worms.Worms2.GameServer/Proxy.cs
index db5cc14..efc1f15 100644
--- a/src/tool/Syroot.Worms.Worms2.GameServer/Proxy.cs
+++ b/src/tool/Syroot.Worms.Worms2.GameServer/Proxy.cs
@@ -13,10 +13,9 @@ namespace Syroot.Worms.Worms2.GameServer
{
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
- internal static void Run()
+ internal static void Run(IPEndPoint localEndPoint)
{
// Start listening for clients to intercept.
- IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, 17000);
TcpListener listener = new TcpListener(localEndPoint);
listener.Start();
ColorConsole.WriteLine(Color.Orange, $"Proxy listening under {localEndPoint}...");
diff --git a/src/tool/fkNetcode/PEInfo.cpp b/src/tool/fkNetcode/PEInfo.cpp
new file mode 100644
index 0000000..6b40da2
--- /dev/null
+++ b/src/tool/fkNetcode/PEInfo.cpp
@@ -0,0 +1,32 @@
+#include "PEInfo.h"
+
+PEInfo::PEInfo(HMODULE hModule)
+{
+ Reset(hModule);
+}
+
+void PEInfo::Reset(HMODULE hModule)
+{
+ Handle = hModule == 0 ? GetModuleHandleA(0) : hModule;
+ DOS = (IMAGE_DOS_HEADER*)Handle;
+ NT = (IMAGE_NT_HEADERS*)((DWORD)DOS + DOS->e_lfanew);
+ FH = (IMAGE_FILE_HEADER*)&NT->FileHeader;
+ OPT = (IMAGE_OPTIONAL_HEADER*)&NT->OptionalHeader;
+}
+
+DWORD PEInfo::Offset(DWORD off)
+{
+ return (DWORD)Handle + off;
+}
+
+BOOL PEInfo::PtrInCode(PVOID ptr)
+{
+ return DWORD(ptr) >= Offset(OPT->BaseOfCode)
+ && DWORD(ptr) < Offset(OPT->BaseOfCode) + OPT->SizeOfCode;
+}
+
+BOOL PEInfo::PtrInData(PVOID ptr)
+{
+ return DWORD(ptr) >= Offset(OPT->BaseOfData)
+ && DWORD(ptr) < Offset(OPT->BaseOfData) + OPT->SizeOfInitializedData + OPT->SizeOfUninitializedData;
+}
diff --git a/src/tool/fkNetcode/PEInfo.h b/src/tool/fkNetcode/PEInfo.h
new file mode 100644
index 0000000..5b9733b
--- /dev/null
+++ b/src/tool/fkNetcode/PEInfo.h
@@ -0,0 +1,19 @@
+#pragma once
+#define WIN32_LEAN_AND_MEAN
+#include
+
+typedef struct PEInfo
+{
+ PEInfo(HMODULE hModule = 0);
+
+ void Reset(HMODULE hModule);
+ DWORD Offset(DWORD off);
+ BOOL PtrInCode(PVOID ptr);
+ BOOL PtrInData(PVOID ptr);
+
+ HANDLE Handle;
+ IMAGE_DOS_HEADER* DOS;
+ IMAGE_NT_HEADERS* NT;
+ IMAGE_FILE_HEADER* FH;
+ IMAGE_OPTIONAL_HEADER* OPT;
+} *PPEInfo;
diff --git a/src/tool/fkNetcode/fkNetcode.vcxproj b/src/tool/fkNetcode/fkNetcode.vcxproj
new file mode 100644
index 0000000..8e45033
--- /dev/null
+++ b/src/tool/fkNetcode/fkNetcode.vcxproj
@@ -0,0 +1,101 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+
+ 16.0
+ Win32Proj
+ {c4138811-7cfa-4826-a3dd-af2b618eafc1}
+ wkWorms2NetFix
+ 10.0
+ fkNetcode
+
+
+
+ DynamicLibrary
+ true
+ v142
+ MultiByte
+
+
+ DynamicLibrary
+ false
+ v142
+ true
+ MultiByte
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ bin\$(Configuration)\
+ obj\$(Configuration)\
+
+
+ false
+ bin\$(Configuration)\
+ obj\$(Configuration)\
+
+
+
+ Level3
+ true
+ WIN32;_DEBUG;FKNETCODE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
+ true
+
+
+ Windows
+ true
+ false
+ wininet.lib;%(AdditionalDependencies)
+
+
+
+
+ Level3
+ true
+ true
+ true
+ WIN32;NDEBUG;FKNETCODE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
+ true
+
+
+ Windows
+ true
+ true
+ true
+ false
+ wininet.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/tool/fkNetcode/main.cpp b/src/tool/fkNetcode/main.cpp
new file mode 100644
index 0000000..4762bac
--- /dev/null
+++ b/src/tool/fkNetcode/main.cpp
@@ -0,0 +1,98 @@
+#define WIN32_LEAN_AND_MEAN
+#include
+#include
+#include
+#include
+#include "PEInfo.h"
+#include "misc_tools.h"
+
+PEInfo pe;
+CHAR szFoundIP[16] = {};
+
+enum GameRegion
+{
+ GAME_REGION_NONE = -1,
+ GAME_REGION_BR,
+ GAME_REGION_EN, // Du, En, Fr, It, Po, Sp, Sw have the same executable
+ GAME_REGION_GE,
+ GAME_REGION_NA,
+ GAME_REGION_SA
+};
+
+int getRegion()
+{
+ switch (pe.FH->TimeDateStamp)
+ {
+ case 0x3528DAFA: return GAME_REGION_BR;
+ case 0x3528DCB1: return GAME_REGION_EN;
+ case 0x3528DB52: return GAME_REGION_GE;
+ case 0x3528DA98: return GAME_REGION_NA;
+ case 0x3528DBDA: return GAME_REGION_SA;
+ }
+ return GAME_REGION_NONE;
+}
+
+bool __stdcall getLabelIP(LPSTR buffer, int bufferLength)
+{
+ if (!szFoundIP[0])
+ {
+ // Initially resolve the external IP through a web service.
+ HINTERNET hInternet = 0, hFile = 0;
+ DWORD bytesRead = 0;
+ CHAR buffer[16];
+
+ if ((hInternet = InternetOpen(NULL, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0))
+ && (hFile = InternetOpenUrl(hInternet, "http://ip.syroot.com", NULL, 0,
+ INTERNET_FLAG_NO_COOKIES | INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_RELOAD, NULL))
+ && InternetReadFile(hFile, buffer, 16, &bytesRead) && bytesRead >= 8)
+ {
+ buffer[bytesRead] = '\0';
+ uint8_t temp;
+ if (sscanf_s(buffer, "%hhu.%hhu.%hhu.%hhu", &temp, &temp, &temp, &temp) == 4)
+ lstrcpy(szFoundIP, buffer);
+ }
+
+ if (hFile) InternetCloseHandle(hFile);
+ if (hInternet) InternetCloseHandle(hInternet);
+ }
+
+ // Return the detected IP.
+ lstrcpy(buffer, szFoundIP);
+ return buffer[0];
+}
+
+void applyPatches()
+{
+ // Replace NAT IP detection with web service.
+ InsertJump((PVOID)pe.Offset(0x00001799), 5, &getLabelIP, IJ_JUMP);
+
+ // Prevent overriding the resolved IP when connecting to server.
+ PatchMemNop(pe.Offset(0x00053E96), 5); // writes user name
+ PatchMemNop(pe.Offset(0x00054993), 5); // writes NAT IP
+
+ // Remove useless sleeps.
+ PatchMemNop(pe.Offset(0x00054935), 11);
+}
+
+BOOL WINAPI DllMain(HMODULE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+ switch (fdwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+ if (getRegion() == GAME_REGION_NONE)
+ {
+ MessageBox(NULL, "fkNetcode is incompatible with your game version or region and will not be able to "
+ "resolve your external IP address. Please install the Worms 2 1.05 patch or delete this module to "
+ "remove this warning.", "fkNetcode", MB_ICONWARNING);
+ }
+ else
+ {
+ applyPatches();
+ }
+ break;
+
+ case DLL_PROCESS_DETACH:
+ break;
+ }
+ return TRUE;
+}
diff --git a/src/tool/fkNetcode/misc_tools.cpp b/src/tool/fkNetcode/misc_tools.cpp
new file mode 100644
index 0000000..431545c
--- /dev/null
+++ b/src/tool/fkNetcode/misc_tools.cpp
@@ -0,0 +1,92 @@
+#include
+#include
+#include "misc_tools.h"
+
+BOOL WritePrivateProfileIntA(LPCSTR lpAppName, LPCSTR lpKeyName, int nInteger, LPCSTR lpFileName)
+{
+ CHAR lpString[32];
+ sprintf_s(lpString, "%d", nInteger);
+ return WritePrivateProfileStringA(lpAppName, lpKeyName, lpString, lpFileName);
+}
+
+LPSTR GetPathUnderModuleA(HMODULE hModule, LPSTR OutBuf, LPCSTR FileName)
+{
+ GetModuleFileNameA(hModule, OutBuf, MAX_PATH);
+ CHAR* dirend = strrchr(OutBuf, '\\') + 1;
+ strcpy_s(dirend, MAX_PATH, FileName);
+ return OutBuf;
+}
+
+BOOL __stdcall PatchMemData(ULONG dwAddr, ULONG dwBufLen, PVOID pNewData, ULONG dwDataLen)
+{
+ if (!dwDataLen || !pNewData || !dwAddr)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return 0;
+ }
+ DWORD dwLastProtection;
+ if (!VirtualProtect((void*)dwAddr, dwDataLen, PAGE_EXECUTE_READWRITE, &dwLastProtection))
+ return 0;
+
+ memcpy_s((PVOID)dwAddr, dwBufLen, pNewData, dwDataLen);
+
+ return VirtualProtect((void*)dwAddr, dwDataLen, dwLastProtection, &dwLastProtection);
+}
+
+BOOL __stdcall PatchMemQword(ULONG dwAddr, QWORD qNewValue) { return PatchMemData(dwAddr, 8, &qNewValue, 8); }
+BOOL __stdcall PatchMemDword(ULONG dwAddr, DWORD dwNewValue) { return PatchMemData(dwAddr, 4, &dwNewValue, 4); }
+BOOL __stdcall PatchMemWord(ULONG dwAddr, WORD wNewValue) { return PatchMemData(dwAddr, 2, &wNewValue, 2); }
+BOOL __stdcall PatchMemByte(ULONG dwAddr, BYTE bNewValue) { return PatchMemData(dwAddr, 1, &bNewValue, 1); }
+BOOL __stdcall PatchMemFloat(ULONG dwAddr, FLOAT fNewValue)
+{
+ DWORD dwLastProtection;
+ if (!VirtualProtect((void*)dwAddr, sizeof(FLOAT), PAGE_EXECUTE_READWRITE, &dwLastProtection))
+ return 0;
+ *(FLOAT*)dwAddr = fNewValue;
+ return VirtualProtect((void*)dwAddr, sizeof(FLOAT), dwLastProtection, &dwLastProtection);
+}
+
+BOOL __stdcall PatchMemNop(ULONG dwAddr, DWORD dwPatchSize)
+{
+ while (dwPatchSize-- && PatchMemByte(dwAddr++, 0x90));
+ return dwPatchSize == 0;
+}
+BOOL __stdcall InsertJump(PVOID pDest, DWORD dwPatchSize, PVOID pCallee, DWORD dwJumpType)
+{
+ if (dwPatchSize >= 5 && pDest)
+ {
+ DWORD OpSize, OpCode;
+ switch (dwJumpType)
+ {
+ case IJ_PUSHRET: OpSize = 6; OpCode = 0x68; break;
+ case IJ_FARJUMP: OpSize = 7; OpCode = 0xEA; break;
+ case IJ_FARCALL: OpSize = 7; OpCode = 0x9A; break;
+ case IJ_CALL: OpSize = 5; OpCode = 0xE8; break;
+ default: OpSize = 5; OpCode = 0xE9; break;
+ }
+
+ if (dwPatchSize < OpSize)
+ return 0;
+
+ PatchMemByte((ULONG)pDest, (BYTE)OpCode);
+
+ switch (OpSize)
+ {
+ case 7:
+ PatchMemDword((ULONG)pDest + 1, (ULONG)pCallee);
+ PatchMemWord((ULONG)pDest + 5, 0x23);
+ break;
+ case 6:
+ PatchMemDword((ULONG)pDest + 1, (ULONG)pCallee);
+ PatchMemByte((ULONG)pDest + 5, 0xC3);
+ break;
+ default:
+ PatchMemDword((ULONG)pDest + 1, (ULONG)pCallee - (ULONG)pDest - 5);
+ break;
+ }
+
+ for (ULONG i = OpSize; i < dwPatchSize; i++)
+ PatchMemByte((ULONG)pDest + i, 0x90);
+ }
+ return 0;
+}
diff --git a/src/tool/fkNetcode/misc_tools.h b/src/tool/fkNetcode/misc_tools.h
new file mode 100644
index 0000000..a84f3d8
--- /dev/null
+++ b/src/tool/fkNetcode/misc_tools.h
@@ -0,0 +1,27 @@
+#pragma once
+
+typedef unsigned long long QWORD;
+typedef QWORD *PQWORD, *LPQWORD;
+
+extern "C" IMAGE_DOS_HEADER __ImageBase;
+#define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase)
+
+#define IJ_JUMP 0 //Insert a jump (0xE9) with InsertJump
+#define IJ_CALL 1 //Insert a call (0xE8) with InsertJump
+#define IJ_FARJUMP 2 //Insert a farjump (0xEA) with InsertJump
+#define IJ_FARCALL 3 //Insert a farcall (0x9A) with InsertJump
+#define IJ_PUSHRET 4 //Insert a pushret with InsertJump
+
+BOOL WritePrivateProfileIntA(LPCSTR lpAppName, LPCSTR lpKeyName, int nInteger, LPCSTR lpFileName);
+LPSTR GetPathUnderModuleA(HMODULE hModule, LPSTR OutBuf, LPCSTR FileName);
+
+BOOL __stdcall PatchMemData(ULONG dwAddr, ULONG dwBufLen, PVOID pNewData, ULONG dwDataLen);
+BOOL __stdcall PatchMemQword(ULONG dwAddr, QWORD qNewValue);
+BOOL __stdcall PatchMemDword(ULONG dwAddr, DWORD dwNewValue);
+BOOL __stdcall PatchMemWord(ULONG dwAddr, WORD wNewValue);
+BOOL __stdcall PatchMemByte(ULONG dwAddr, BYTE bNewValue);
+BOOL __stdcall PatchMemFloat(ULONG dwAddr, FLOAT fNewValue);
+
+BOOL __stdcall PatchMemNop(ULONG dwAddr, DWORD dwPatchSize);
+
+BOOL __stdcall InsertJump(PVOID pDest, DWORD dwPatchSize, PVOID pCallee, DWORD dwJumpType = IJ_JUMP);