OCT 1. 移除 Wireguard Windows 程序依赖
This commit is contained in:
parent
d2a981746d
commit
1a4c76d333
|
@ -58,12 +58,6 @@
|
|||
"Entry"
|
||||
{
|
||||
"MsmKey" = "8:_3853091F559CDFEDEBC0DE9767664FD8"
|
||||
"OwnerKey" = "8:_00EB5BF3E5624995855CCF580A8AD1D5"
|
||||
"MsmSig" = "8:_UNDEFINED"
|
||||
}
|
||||
"Entry"
|
||||
{
|
||||
"MsmKey" = "8:_3853091F559CDFEDEBC0DE9767664FD8"
|
||||
"OwnerKey" = "8:_A2B46765ECF148F6B3BD76DC027D3B06"
|
||||
"MsmSig" = "8:_UNDEFINED"
|
||||
}
|
||||
|
@ -82,12 +76,6 @@
|
|||
"Entry"
|
||||
{
|
||||
"MsmKey" = "8:_4709F8F14ABE7B5983245A0461485A18"
|
||||
"OwnerKey" = "8:_00EB5BF3E5624995855CCF580A8AD1D5"
|
||||
"MsmSig" = "8:_UNDEFINED"
|
||||
}
|
||||
"Entry"
|
||||
{
|
||||
"MsmKey" = "8:_4709F8F14ABE7B5983245A0461485A18"
|
||||
"OwnerKey" = "8:_A2B46765ECF148F6B3BD76DC027D3B06"
|
||||
"MsmSig" = "8:_UNDEFINED"
|
||||
}
|
||||
|
@ -106,19 +94,13 @@
|
|||
"Entry"
|
||||
{
|
||||
"MsmKey" = "8:_6A8B2CA20D527217332BB0170E559DB9"
|
||||
"OwnerKey" = "8:_00EB5BF3E5624995855CCF580A8AD1D5"
|
||||
"MsmSig" = "8:_UNDEFINED"
|
||||
}
|
||||
"Entry"
|
||||
{
|
||||
"MsmKey" = "8:_6A8B2CA20D527217332BB0170E559DB9"
|
||||
"OwnerKey" = "8:_A2B46765ECF148F6B3BD76DC027D3B06"
|
||||
"MsmSig" = "8:_UNDEFINED"
|
||||
}
|
||||
"Entry"
|
||||
{
|
||||
"MsmKey" = "8:_8A5EF688505390205390D3ABE7EC7364"
|
||||
"OwnerKey" = "8:_00EB5BF3E5624995855CCF580A8AD1D5"
|
||||
"MsmKey" = "8:_84BB8455EE8B1AB05AA45633B9D70FD7"
|
||||
"OwnerKey" = "8:_A2B46765ECF148F6B3BD76DC027D3B06"
|
||||
"MsmSig" = "8:_UNDEFINED"
|
||||
}
|
||||
"Entry"
|
||||
|
@ -171,6 +153,12 @@
|
|||
}
|
||||
"Entry"
|
||||
{
|
||||
"MsmKey" = "8:_CEE2F747DF77425F8F8416259F5A60C6"
|
||||
"OwnerKey" = "8:_UNDEFINED"
|
||||
"MsmSig" = "8:_UNDEFINED"
|
||||
}
|
||||
"Entry"
|
||||
{
|
||||
"MsmKey" = "8:_CF70965F768635AE40F5A4648E193482"
|
||||
"OwnerKey" = "8:_451417C63FD78D938C6E04BB65EAA006"
|
||||
"MsmSig" = "8:_UNDEFINED"
|
||||
|
@ -183,12 +171,30 @@
|
|||
}
|
||||
"Entry"
|
||||
{
|
||||
"MsmKey" = "8:_DC143071B1794733B7955D905E8F722D"
|
||||
"OwnerKey" = "8:_UNDEFINED"
|
||||
"MsmSig" = "8:_UNDEFINED"
|
||||
}
|
||||
"Entry"
|
||||
{
|
||||
"MsmKey" = "8:_E128C35F6AE09A19D4BFECA45A1271B7"
|
||||
"OwnerKey" = "8:_10E071CF096B417C925C5E27E36CE39A"
|
||||
"MsmSig" = "8:_UNDEFINED"
|
||||
}
|
||||
"Entry"
|
||||
{
|
||||
"MsmKey" = "8:_E68F9AF277DA30F367774B24D4F4A4B0"
|
||||
"OwnerKey" = "8:_00EB5BF3E5624995855CCF580A8AD1D5"
|
||||
"MsmSig" = "8:_UNDEFINED"
|
||||
}
|
||||
"Entry"
|
||||
{
|
||||
"MsmKey" = "8:_FAA1AF88F72C4C469E6B4CE67FCCB8CB"
|
||||
"OwnerKey" = "8:_UNDEFINED"
|
||||
"MsmSig" = "8:_UNDEFINED"
|
||||
}
|
||||
"Entry"
|
||||
{
|
||||
"MsmKey" = "8:_UNDEFINED"
|
||||
"OwnerKey" = "8:_10E071CF096B417C925C5E27E36CE39A"
|
||||
"MsmSig" = "8:_UNDEFINED"
|
||||
|
@ -286,6 +292,14 @@
|
|||
"PrerequisitesLocation" = "2:1"
|
||||
"Url" = "8:"
|
||||
"ComponentsUrl" = "8:"
|
||||
"Items"
|
||||
{
|
||||
"{EDC2488A-8267-493A-A98E-7D9C3B36CDF3}:.NETFramework,Version=v4.7.2"
|
||||
{
|
||||
"Name" = "8:Microsoft .NET Framework 4.7.2 (x86 and x64)"
|
||||
"ProductCode" = "8:.NETFramework,Version=v4.7.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -529,6 +543,26 @@
|
|||
"IsDependency" = "11:TRUE"
|
||||
"IsolateTo" = "8:"
|
||||
}
|
||||
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_84BB8455EE8B1AB05AA45633B9D70FD7"
|
||||
{
|
||||
"SourcePath" = "8:CRYPT32.dll"
|
||||
"TargetName" = "8:CRYPT32.dll"
|
||||
"Tag" = "8:"
|
||||
"Folder" = "8:_A69AEF7ED77C4BB28FA87F3D7B5FF39A"
|
||||
"Condition" = "8:"
|
||||
"Transitive" = "11:FALSE"
|
||||
"Vital" = "11:TRUE"
|
||||
"ReadOnly" = "11:FALSE"
|
||||
"Hidden" = "11:FALSE"
|
||||
"System" = "11:FALSE"
|
||||
"Permanent" = "11:FALSE"
|
||||
"SharedLegacy" = "11:FALSE"
|
||||
"PackageAs" = "3:1"
|
||||
"Register" = "3:1"
|
||||
"Exclude" = "11:FALSE"
|
||||
"IsDependency" = "11:TRUE"
|
||||
"IsolateTo" = "8:"
|
||||
}
|
||||
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_8A5EF688505390205390D3ABE7EC7364"
|
||||
{
|
||||
"SourcePath" = "8:MSVCP140D.dll"
|
||||
|
@ -620,6 +654,26 @@
|
|||
"IsDependency" = "11:TRUE"
|
||||
"IsolateTo" = "8:"
|
||||
}
|
||||
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_CEE2F747DF77425F8F8416259F5A60C6"
|
||||
{
|
||||
"SourcePath" = "8:..\\x64\\Debug\\NetTunnelSvr.exe"
|
||||
"TargetName" = "8:NetTunnelSvr.exe"
|
||||
"Tag" = "8:"
|
||||
"Folder" = "8:_A69AEF7ED77C4BB28FA87F3D7B5FF39A"
|
||||
"Condition" = "8:"
|
||||
"Transitive" = "11:FALSE"
|
||||
"Vital" = "11:TRUE"
|
||||
"ReadOnly" = "11:FALSE"
|
||||
"Hidden" = "11:FALSE"
|
||||
"System" = "11:FALSE"
|
||||
"Permanent" = "11:FALSE"
|
||||
"SharedLegacy" = "11:FALSE"
|
||||
"PackageAs" = "3:1"
|
||||
"Register" = "3:1"
|
||||
"Exclude" = "11:FALSE"
|
||||
"IsDependency" = "11:FALSE"
|
||||
"IsolateTo" = "8:"
|
||||
}
|
||||
"{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_CF70965F768635AE40F5A4648E193482"
|
||||
{
|
||||
"AssemblyRegister" = "3:1"
|
||||
|
@ -651,6 +705,26 @@
|
|||
"IsDependency" = "11:TRUE"
|
||||
"IsolateTo" = "8:"
|
||||
}
|
||||
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_DC143071B1794733B7955D905E8F722D"
|
||||
{
|
||||
"SourcePath" = "8:..\\x64\\Debug\\wireguard.dll"
|
||||
"TargetName" = "8:wireguard.dll"
|
||||
"Tag" = "8:"
|
||||
"Folder" = "8:_A69AEF7ED77C4BB28FA87F3D7B5FF39A"
|
||||
"Condition" = "8:"
|
||||
"Transitive" = "11:FALSE"
|
||||
"Vital" = "11:TRUE"
|
||||
"ReadOnly" = "11:FALSE"
|
||||
"Hidden" = "11:FALSE"
|
||||
"System" = "11:FALSE"
|
||||
"Permanent" = "11:FALSE"
|
||||
"SharedLegacy" = "11:FALSE"
|
||||
"PackageAs" = "3:1"
|
||||
"Register" = "3:1"
|
||||
"Exclude" = "11:FALSE"
|
||||
"IsDependency" = "11:FALSE"
|
||||
"IsolateTo" = "8:"
|
||||
}
|
||||
"{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_E128C35F6AE09A19D4BFECA45A1271B7"
|
||||
{
|
||||
"AssemblyRegister" = "3:1"
|
||||
|
@ -682,6 +756,46 @@
|
|||
"IsDependency" = "11:TRUE"
|
||||
"IsolateTo" = "8:"
|
||||
}
|
||||
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_E68F9AF277DA30F367774B24D4F4A4B0"
|
||||
{
|
||||
"SourcePath" = "8:WinDivert.dll"
|
||||
"TargetName" = "8:WinDivert.dll"
|
||||
"Tag" = "8:"
|
||||
"Folder" = "8:_A69AEF7ED77C4BB28FA87F3D7B5FF39A"
|
||||
"Condition" = "8:"
|
||||
"Transitive" = "11:FALSE"
|
||||
"Vital" = "11:TRUE"
|
||||
"ReadOnly" = "11:FALSE"
|
||||
"Hidden" = "11:FALSE"
|
||||
"System" = "11:FALSE"
|
||||
"Permanent" = "11:FALSE"
|
||||
"SharedLegacy" = "11:FALSE"
|
||||
"PackageAs" = "3:1"
|
||||
"Register" = "3:1"
|
||||
"Exclude" = "11:FALSE"
|
||||
"IsDependency" = "11:TRUE"
|
||||
"IsolateTo" = "8:"
|
||||
}
|
||||
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_FAA1AF88F72C4C469E6B4CE67FCCB8CB"
|
||||
{
|
||||
"SourcePath" = "8:..\\x64\\Debug\\tunnel.dll"
|
||||
"TargetName" = "8:tunnel.dll"
|
||||
"Tag" = "8:"
|
||||
"Folder" = "8:_A69AEF7ED77C4BB28FA87F3D7B5FF39A"
|
||||
"Condition" = "8:"
|
||||
"Transitive" = "11:FALSE"
|
||||
"Vital" = "11:TRUE"
|
||||
"ReadOnly" = "11:FALSE"
|
||||
"Hidden" = "11:FALSE"
|
||||
"System" = "11:FALSE"
|
||||
"Permanent" = "11:FALSE"
|
||||
"SharedLegacy" = "11:FALSE"
|
||||
"PackageAs" = "3:1"
|
||||
"Register" = "3:1"
|
||||
"Exclude" = "11:FALSE"
|
||||
"IsDependency" = "11:FALSE"
|
||||
"IsolateTo" = "8:"
|
||||
}
|
||||
}
|
||||
"FileType"
|
||||
{
|
||||
|
|
|
@ -216,13 +216,14 @@ public partial class MainForm : Form
|
|||
|
||||
private void menuSetVPNPath_Click(object sender, EventArgs e)
|
||||
{
|
||||
DialogResult result = ofDlgWireGuard.ShowDialog();
|
||||
//DialogResult result = ofDlgWireGuard.ShowDialog();
|
||||
|
||||
if (result == DialogResult.OK)
|
||||
{
|
||||
_wireguardPath = ofDlgWireGuard.FileName;
|
||||
NetTunnelLib.SetWireguardPath(_wireguardPath);
|
||||
}
|
||||
//if (result == DialogResult.OK)
|
||||
//{
|
||||
// _wireguardPath = ofDlgWireGuard.FileName;
|
||||
// NetTunnelLib.SetWireguardPath(_wireguardPath);
|
||||
//}
|
||||
MessageBox.Show("Not Support");
|
||||
}
|
||||
|
||||
private void menuSetModeClient_Click(object sender, EventArgs e)
|
||||
|
|
|
@ -181,13 +181,7 @@ public class NetTunnelLib
|
|||
|
||||
[DllImport("NetTunnelSDK.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern int SetProtocolEncryptType(ProtoCryptoType type, String pProKey);
|
||||
|
||||
[DllImport("NetTunnelSDK.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern int FindWireguardExe(StringBuilder lpString, int maxSize);
|
||||
|
||||
[DllImport("NetTunnelSDK.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern int SetWireguardPath(String path);
|
||||
|
||||
|
||||
[DllImport("NetTunnelSDK.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern int GenerateWireguardKeyPairs(StringBuilder wgPubKey, int maxPubKey, StringBuilder wgPrivKey,
|
||||
int MaxPrivKey);
|
||||
|
|
|
@ -204,6 +204,12 @@ int CreateControlService(PUSER_SERVER_CONFIG pSvr) {
|
|||
}
|
||||
}
|
||||
|
||||
if (isSvrStart) {
|
||||
SPDLOG_INFO(TEXT("Tunnel Service Start Now: {0}"), GetGlobalCfgInfo()->userCfg.userName);
|
||||
} else {
|
||||
SPDLOG_INFO(TEXT("Tunnel Service Stoped: {0}"), GetGlobalCfgInfo()->userCfg.userName);
|
||||
}
|
||||
|
||||
HttpResponseError(res, ERR_SUCCESS, nullptr);
|
||||
g_InterfaceMutex.unlock();
|
||||
}
|
||||
|
|
|
@ -114,6 +114,7 @@
|
|||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
|
@ -149,6 +150,7 @@
|
|||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="AIGCJson.hpp" />
|
||||
<ClInclude Include="common.h" />
|
||||
<ClInclude Include="framework.h" />
|
||||
<ClInclude Include="globalcfg.h" />
|
||||
<ClInclude Include="httplib.h" />
|
||||
|
@ -187,6 +189,7 @@
|
|||
<ClCompile Include="wireguard.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Use</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="WireguardService.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
|
|
|
@ -81,6 +81,9 @@
|
|||
<ClInclude Include="WinDivert\include\windivert.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="common.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="dllmain.cpp">
|
||||
|
@ -125,6 +128,9 @@
|
|||
<ClCompile Include="ProxyService.cpp">
|
||||
<Filter>源文件\network</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="WireguardService.cpp">
|
||||
<Filter>源文件\wireguard</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
|
|
|
@ -6,15 +6,8 @@
|
|||
#include "globalcfg.h"
|
||||
#include "usrerr.h"
|
||||
|
||||
#include <winsock2.h>
|
||||
|
||||
#pragma comment(lib, "WinDivert.lib")
|
||||
|
||||
typedef enum {
|
||||
PROXY_TCP = 1 << 0,
|
||||
PROXY_UDP = 1 << 1,
|
||||
} PROXY_PORTO_TYPE;
|
||||
|
||||
typedef struct {
|
||||
bool isRunning;
|
||||
HANDLE proxyThread;
|
||||
|
@ -23,223 +16,21 @@ typedef struct {
|
|||
} UDP_PROXY_CTX, *PUDP_PROXY_CTX;
|
||||
|
||||
typedef struct {
|
||||
SOCKET proxySock;
|
||||
SOCKET reservePortSock;
|
||||
SOCKET altSock;
|
||||
bool isRunning;
|
||||
UINT16 proxyPort;
|
||||
UINT16 altPort;
|
||||
HANDLE proxyThread;
|
||||
HANDLE proxyHandle;
|
||||
bool isExitSvr;
|
||||
} TCP_PROXY_CTX, *PTCP_PORXY_CTX;
|
||||
|
||||
typedef struct {
|
||||
int proType;
|
||||
TCHAR streamFilter[1024];
|
||||
TCHAR targetIp[MAX_IP_LEN];
|
||||
UINT16 targetPort;
|
||||
int vmId;
|
||||
int svrId;
|
||||
TCP_PROXY_CTX tcpCtx;
|
||||
UDP_PROXY_CTX udpCtx;
|
||||
} PROXY_INFO, *PPROXY_INFO;
|
||||
|
||||
typedef struct {
|
||||
SOCKET s;
|
||||
PPROXY_INFO pCtx;
|
||||
bool inbound;
|
||||
in_addr dest;
|
||||
} PROXY_CONNECTION_CONFIG, *PPROXY_CONNECTION_CONFIG;
|
||||
|
||||
static std::unordered_map<std::string, PPROXY_INFO> g_ProxyColleagues;
|
||||
|
||||
static int NewAvaliableSocket(SOCKET *pSock, UINT16 *pPort) {
|
||||
const int reusedAddr = 1;
|
||||
sockaddr_in proxySvrAddr {};
|
||||
sockaddr_in bindAddr {};
|
||||
int ret;
|
||||
int addrSize = sizeof(sockaddr_in);
|
||||
const SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
if (sock == INVALID_SOCKET) {
|
||||
SPDLOG_ERROR(TEXT("Cretate TCP Socket error: {0}"), WSAGetLastError());
|
||||
return -ERR_SOCKET_BIND_PORT;
|
||||
}
|
||||
|
||||
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<const char *>(&reusedAddr), sizeof(int)) ==
|
||||
SOCKET_ERROR) {
|
||||
SPDLOG_ERROR(TEXT("Failed to set socket optino SO_REUSEADDR ({0}})"), WSAGetLastError());
|
||||
closesocket(sock);
|
||||
return -ERR_SOCKET_SET_OPT;
|
||||
}
|
||||
|
||||
proxySvrAddr.sin_family = AF_INET;
|
||||
proxySvrAddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
proxySvrAddr.sin_port = htons(0);
|
||||
|
||||
if (bind(sock, reinterpret_cast<SOCKADDR *>(&proxySvrAddr), sizeof(proxySvrAddr)) == SOCKET_ERROR) {
|
||||
SPDLOG_ERROR(TEXT("Failed to bind socket ({0})"), WSAGetLastError());
|
||||
closesocket(sock);
|
||||
return -ERR_SOCKET_BIND;
|
||||
}
|
||||
|
||||
if (getsockname(sock, reinterpret_cast<struct sockaddr *>(&bindAddr), &addrSize) != 0) {
|
||||
SPDLOG_ERROR(TEXT("Failed to get socket bind port ({0})"), WSAGetLastError());
|
||||
closesocket(sock);
|
||||
return -ERR_SOCKET_GET_OPT;
|
||||
}
|
||||
|
||||
*pSock = sock;
|
||||
*pPort = ntohs(bindAddr.sin_port);
|
||||
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
|
||||
static DWORD proxyForwardCb(LPVOID lpParameter) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static DWORD proxyConnCb(LPVOID lpParameter) {
|
||||
const auto p = static_cast<PPROXY_CONNECTION_CONFIG>(lpParameter);
|
||||
sockaddr_in altAddr {};
|
||||
SOCKET altSock;
|
||||
HANDLE thread;
|
||||
SOCKET connSock = p->s;
|
||||
in_addr dest = p->dest;
|
||||
PPROXY_INFO pInfo = p->pCtx;
|
||||
PPROXY_CONNECTION_CONFIG pCfgProxySvr, pCfgAltSvr;
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, p);
|
||||
|
||||
altSock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
if (altSock == INVALID_SOCKET) {
|
||||
SPDLOG_ERROR(TEXT("Cretate TCP Socket error: {0}"), WSAGetLastError());
|
||||
closesocket(connSock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(&altAddr, 0, sizeof(altAddr));
|
||||
altAddr.sin_family = AF_INET;
|
||||
altAddr.sin_port = htons(pInfo->tcpCtx.altPort);
|
||||
altAddr.sin_addr = dest;
|
||||
|
||||
if (connect(altSock, reinterpret_cast<SOCKADDR *>(&altAddr), sizeof(altAddr)) == SOCKET_ERROR) {
|
||||
SPDLOG_ERROR(TEXT("Failed to connect socket ({0})"), WSAGetLastError());
|
||||
closesocket(connSock);
|
||||
closesocket(altSock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pInfo->tcpCtx.altSock = altSock;
|
||||
|
||||
pCfgProxySvr = static_cast<PPROXY_CONNECTION_CONFIG>(
|
||||
HeapAlloc(GetProcessHeap(), 0, sizeof(PROXY_CONNECTION_CONFIG)));
|
||||
|
||||
if (pCfgProxySvr == nullptr) {
|
||||
SPDLOG_ERROR(TEXT("Malloc {0} bytes error."), sizeof(PROXY_CONNECTION_CONFIG));
|
||||
closesocket(connSock);
|
||||
closesocket(altSock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pCfgAltSvr = static_cast<PPROXY_CONNECTION_CONFIG>(HeapAlloc(GetProcessHeap(), 0, sizeof(PROXY_CONNECTION_CONFIG)));
|
||||
|
||||
if (pCfgAltSvr == nullptr) {
|
||||
SPDLOG_ERROR(TEXT("Malloc {0} bytes error."), sizeof(PROXY_CONNECTION_CONFIG));
|
||||
closesocket(connSock);
|
||||
closesocket(altSock);
|
||||
free(pCfgProxySvr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
thread = CreateThread(nullptr, // Thread attributes
|
||||
0, // Stack size (0 = use default)
|
||||
proxyForwardCb, // Thread start address
|
||||
pCfgProxySvr, // Parameter to pass to the thread
|
||||
0, // Creation flags
|
||||
nullptr); // Thread id
|
||||
|
||||
if (thread == nullptr) {
|
||||
SPDLOG_ERROR(TEXT("Failed to create thread ({0})"), GetLastError());
|
||||
closesocket(connSock);
|
||||
closesocket(altSock);
|
||||
free(pCfgProxySvr);
|
||||
free(pCfgAltSvr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int StartTcpProxyService(PPROXY_INFO pInfo) {
|
||||
pInfo->tcpCtx.isExitSvr = false;
|
||||
|
||||
if (listen(pInfo->tcpCtx.proxySock, SOMAXCONN) == SOCKET_ERROR) {
|
||||
SPDLOG_ERROR(TEXT("Failed to listen socket ({0})"), WSAGetLastError());
|
||||
closesocket(pInfo->tcpCtx.proxySock);
|
||||
return -ERR_SOCKET_LISTEN;
|
||||
}
|
||||
|
||||
pInfo->tcpCtx.proxyThread = CreateThread(
|
||||
nullptr, // Thread attributes
|
||||
0, // Stack size (0 = use default)
|
||||
[](LPVOID lpParameter) {
|
||||
const auto p = static_cast<PPROXY_INFO>(lpParameter);
|
||||
|
||||
while (!p->tcpCtx.isExitSvr) {
|
||||
PPROXY_CONNECTION_CONFIG pCfg;
|
||||
sockaddr_in connAddr {};
|
||||
int size = sizeof(connAddr);
|
||||
|
||||
SOCKET s = accept(p->tcpCtx.proxySock, reinterpret_cast<struct sockaddr *>(&connAddr), &size);
|
||||
|
||||
if (s == INVALID_SOCKET) {
|
||||
continue;
|
||||
}
|
||||
|
||||
pCfg = static_cast<PPROXY_CONNECTION_CONFIG>(
|
||||
HeapAlloc(GetProcessHeap(), 0, sizeof(PROXY_CONNECTION_CONFIG)));
|
||||
|
||||
if (pCfg) {
|
||||
HANDLE thread;
|
||||
pCfg->s = s;
|
||||
pCfg->dest = connAddr.sin_addr;
|
||||
pCfg->pCtx = p;
|
||||
|
||||
thread = CreateThread(nullptr,
|
||||
0,
|
||||
proxyConnCb, // Thread start address
|
||||
pCfg, // Parameter to pass to the thread
|
||||
0,
|
||||
nullptr);
|
||||
|
||||
if (thread == nullptr) {
|
||||
closesocket(s);
|
||||
HeapFree(GetProcessHeap(), 0, pCfg);
|
||||
continue;
|
||||
}
|
||||
|
||||
CloseHandle(thread);
|
||||
}
|
||||
}
|
||||
|
||||
return static_cast<DWORD>(0);
|
||||
}, // Thread start address
|
||||
pInfo, // Parameter to pass to the thread
|
||||
0, // Creation flags
|
||||
nullptr); // Thread id
|
||||
|
||||
if (pInfo->tcpCtx.proxyThread == nullptr) {
|
||||
SPDLOG_ERROR(TEXT("Create TCP Listen Thread Error ({0})"), GetLastError());
|
||||
return -ERR_CREATE_THREAD;
|
||||
}
|
||||
}
|
||||
|
||||
int CreatePorxyService(int proType, const TCHAR *pTargetIp, int targetPort, int vmId, int svrId) {
|
||||
int CreatePorxyService(const TCHAR *pTargetIp, int targetPort, int vmId, int svrId) {
|
||||
//int CreatePorxyService() {
|
||||
int ret;
|
||||
//int ret;
|
||||
static HANDLE hDriver;
|
||||
PPROXY_INFO pInfo;
|
||||
std::string key;
|
||||
|
@ -251,12 +42,11 @@ int CreatePorxyService(int proType, const TCHAR *pTargetIp, int targetPort, int
|
|||
if ((iter = g_ProxyColleagues.find(key)) != g_ProxyColleagues.end()) {
|
||||
pInfo = iter->second;
|
||||
// 如果配置完全相同则直接返回
|
||||
if (pInfo->vmId == vmId && pInfo->svrId == svrId && pInfo->proType == proType) {
|
||||
if (pInfo->vmId == vmId && pInfo->svrId == svrId) {
|
||||
return ERR_SUCCESS;
|
||||
} else {
|
||||
pInfo->vmId = vmId;
|
||||
pInfo->svrId = svrId;
|
||||
pInfo->proType = proType;
|
||||
}
|
||||
} else {
|
||||
// 创建新的代理配置
|
||||
|
@ -272,48 +62,7 @@ int CreatePorxyService(int proType, const TCHAR *pTargetIp, int targetPort, int
|
|||
|
||||
memset(pInfo->streamFilter, 0, 1024);
|
||||
|
||||
// 重构过滤器
|
||||
if (pInfo->proType & PROXY_UDP) {
|
||||
StringCbPrintf(pInfo->streamFilter, 1024, TEXT("(udp.DstPort == %d)"), targetPort);
|
||||
//StringCbPrintf(pFilter, 1024, TEXT("tcp && remotePort == 9276"));
|
||||
}
|
||||
|
||||
if (pInfo->proType & PROXY_TCP) {
|
||||
TCHAR tmpFilter[1024];
|
||||
|
||||
// 预先分配代理和转发 Socket
|
||||
if ((ret = NewAvaliableSocket(&pInfo->tcpCtx.proxySock, &pInfo->tcpCtx.proxyPort)) != ERR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((ret = NewAvaliableSocket(&pInfo->tcpCtx.reservePortSock, &pInfo->tcpCtx.altPort)) != ERR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
// 构建过滤器
|
||||
StringCbPrintf(tmpFilter,
|
||||
1024,
|
||||
TEXT("(tcp.DstPort == %d or tcp.DstPort == %d or tcp.DstPort == %d or tcp.SrcPort == %d or "
|
||||
"tcp.SrcPort == %d or tcp.SrcPort == %d)"),
|
||||
targetPort,
|
||||
pInfo->tcpCtx.proxyPort,
|
||||
pInfo->tcpCtx.altPort,
|
||||
targetPort,
|
||||
pInfo->tcpCtx.proxyPort,
|
||||
pInfo->tcpCtx.altPort);
|
||||
|
||||
if (lstrlen(pInfo->streamFilter) > 0) {
|
||||
StringCbCat(pInfo->streamFilter, 1024, TEXT(" or "));
|
||||
StringCbCat(pInfo->streamFilter, 1024, tmpFilter);
|
||||
} else {
|
||||
StringCbCopy(pInfo->streamFilter, 1024, tmpFilter);
|
||||
}
|
||||
}
|
||||
|
||||
// 启动代理服务
|
||||
if ((ret = StartTcpProxyService(pInfo)) != ERR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
StringCbPrintf(pInfo->streamFilter, 1024, TEXT("(udp.DstPort == %d and )"), targetPort);
|
||||
|
||||
hDriver = WinDivertOpen(pInfo->streamFilter, WINDIVERT_LAYER_NETWORK, 0, 0);
|
||||
|
||||
|
@ -328,7 +77,7 @@ int CreatePorxyService(int proType, const TCHAR *pTargetIp, int targetPort, int
|
|||
0, // Stack size (0 = use default)
|
||||
[](LPVOID lpParameter) {
|
||||
const HANDLE h = lpParameter;
|
||||
unsigned char packet[0xFFFF];
|
||||
unsigned char packet[2048];
|
||||
UINT packet_len;
|
||||
WINDIVERT_ADDRESS addr;
|
||||
|
||||
|
|
|
@ -423,12 +423,14 @@ int GetUserServerConfigure(const TCHAR *pUserName, const TCHAR *pToken, PUSER_SE
|
|||
if (pUserName && lstrlen(pUserName) > 0) {
|
||||
memset(pUser->userName, 0, MAX_PATH);
|
||||
StringCbCopy(pUser->userName, MAX_PATH, pUserName);
|
||||
} else {
|
||||
StringCbCopy(pUser->userName, MAX_PATH, TEXT("tunnel_svr"));
|
||||
}
|
||||
|
||||
StringCbCopy(pUser->userToken, MAX_PATH, pToken);
|
||||
|
||||
req.msgContent.token = pToken;
|
||||
req.msgContent.user = pUserName;
|
||||
req.msgContent.user = pUser->userName;
|
||||
|
||||
ret = ProtolPostMessage(GET_SERVERCFG_PATH, &req, &rsp);
|
||||
|
||||
|
@ -453,6 +455,11 @@ int GetUserClientConfigure(const TCHAR *pUserName, const TCHAR *pToken, PUSER_CL
|
|||
ProtocolRequest<ReqGetUserCfgParams> req;
|
||||
ProtocolResponse<RspUsrCliConfigParams> rsp;
|
||||
|
||||
if (pUserName == nullptr || lstrlen(pUserName) == 0) {
|
||||
SPDLOG_ERROR(TEXT("Input pUserName params error: {0}"), pUserName);
|
||||
return -ERR_INPUT_PARAMS;
|
||||
}
|
||||
|
||||
if (pToken == nullptr || lstrlen(pToken) == 0) {
|
||||
SPDLOG_ERROR(TEXT("Input pToken params error: {0}"), pToken);
|
||||
return -ERR_INPUT_PARAMS;
|
||||
|
|
|
@ -0,0 +1,251 @@
|
|||
#include "pch.h"
|
||||
#include "usrerr.h"
|
||||
#include "globalcfg.h"
|
||||
#include "tunnel.h"
|
||||
|
||||
#include <shlwapi.h>
|
||||
#include <strsafe.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
int GetWireGuardServiceStatus(const TCHAR *pTunnelName, bool *pIsRunning) {
|
||||
SC_HANDLE schSCManager;
|
||||
SC_HANDLE schService;
|
||||
TCHAR svrName[MAX_PATH];
|
||||
|
||||
if (pTunnelName == nullptr || lstrlen(pTunnelName) == 0) {
|
||||
SPDLOG_ERROR(TEXT("Input pTunnelName error: {0}"), pTunnelName);
|
||||
return -ERR_INPUT_PARAMS;
|
||||
}
|
||||
|
||||
if (pIsRunning == nullptr) {
|
||||
SPDLOG_ERROR(TEXT("Input pIsRunning params error"));
|
||||
return -ERR_INPUT_PARAMS;
|
||||
}
|
||||
|
||||
*pIsRunning = false;
|
||||
|
||||
StringCbPrintf(svrName, MAX_PATH, TEXT("WireGuardTunnel$%s"), pTunnelName);
|
||||
// Get a handle to the SCM database.
|
||||
schSCManager = OpenSCManager(nullptr, // local computer
|
||||
nullptr, // ServicesActive database
|
||||
SC_MANAGER_ALL_ACCESS); // full access rights
|
||||
|
||||
if (nullptr == schSCManager) {
|
||||
SPDLOG_ERROR(TEXT("OpenSCManager failed ({0})"), GetLastError());
|
||||
return -ERR_OPEN_SCM;
|
||||
}
|
||||
|
||||
// Get a handle to the service.
|
||||
schService = OpenService(schSCManager, // SCM database
|
||||
svrName, // name of service
|
||||
SERVICE_ALL_ACCESS); // full access
|
||||
|
||||
CloseServiceHandle(schService);
|
||||
|
||||
// 如果服务不存在则直接返回
|
||||
if (schService != nullptr) {
|
||||
*pIsRunning = true;
|
||||
}
|
||||
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
|
||||
int RemoveGuardService(const TCHAR *pTunnelName, bool bIsWaitStop) {
|
||||
SC_HANDLE schSCManager;
|
||||
SC_HANDLE schService;
|
||||
TCHAR svrName[MAX_PATH];
|
||||
SERVICE_STATUS svrStatus;
|
||||
|
||||
if (pTunnelName == nullptr || lstrlen(pTunnelName) == 0) {
|
||||
SPDLOG_ERROR(TEXT("Input pTunnelName error: {0}"), pTunnelName);
|
||||
return -ERR_INPUT_PARAMS;
|
||||
}
|
||||
|
||||
StringCbPrintf(svrName, MAX_PATH, TEXT("WireGuardTunnel$%s"), pTunnelName);
|
||||
// Get a handle to the SCM database.
|
||||
schSCManager = OpenSCManager(nullptr, // local computer
|
||||
nullptr, // ServicesActive database
|
||||
SC_MANAGER_ALL_ACCESS); // full access rights
|
||||
|
||||
if (nullptr == schSCManager) {
|
||||
SPDLOG_ERROR(TEXT("OpenSCManager failed ({0})"), GetLastError());
|
||||
return -ERR_OPEN_SCM;
|
||||
}
|
||||
|
||||
// Get a handle to the service.
|
||||
schService = OpenService(schSCManager, // SCM database
|
||||
svrName, // name of service
|
||||
SERVICE_ALL_ACCESS); // full access
|
||||
|
||||
// 如果服务不存在则直接返回
|
||||
if (schService == nullptr) {
|
||||
CloseServiceHandle(schSCManager);
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
|
||||
if (ControlService(schService, SERVICE_CONTROL_STOP, &svrStatus) == 0) {
|
||||
DWORD errCode = GetLastError();
|
||||
|
||||
if (errCode != ERROR_SERVICE_CANNOT_ACCEPT_CTRL && errCode != ERROR_SERVICE_NOT_ACTIVE) {
|
||||
SPDLOG_ERROR(TEXT("Stop Service {1} failed ({0})"), errCode, svrName);
|
||||
CloseServiceHandle(schService);
|
||||
CloseServiceHandle(schSCManager);
|
||||
return -ERR_STOP_SERVICE;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; bIsWaitStop && i < 10; i++) {
|
||||
SERVICE_STATUS_PROCESS ssStatus;
|
||||
DWORD dwBytesNeeded = 0;
|
||||
|
||||
if (QueryServiceStatusEx(schService, // handle to service
|
||||
SC_STATUS_PROCESS_INFO, // information level
|
||||
reinterpret_cast<LPBYTE>(&ssStatus), // address of structure
|
||||
sizeof(SERVICE_STATUS_PROCESS), // size of structure
|
||||
&dwBytesNeeded)) // size needed if buffer is too small
|
||||
{
|
||||
// 服务已经停止
|
||||
if (ssStatus.dwCurrentState == SERVICE_STOPPED) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//SPDLOG_ERROR(TEXT("Stop Service {1} retry times ({0})"), i + 1, svrName);
|
||||
Sleep(1000);
|
||||
}
|
||||
|
||||
if (!DeleteService(schService) && GetLastError() != ERROR_SERVICE_MARKED_FOR_DELETE) {
|
||||
SPDLOG_ERROR(TEXT("Delete Service {1} failed ({0})"), GetLastError(), svrName);
|
||||
CloseServiceHandle(schService);
|
||||
CloseServiceHandle(schSCManager);
|
||||
return -ERR_DELETE_SERVICE;
|
||||
}
|
||||
|
||||
CloseServiceHandle(schService);
|
||||
CloseServiceHandle(schSCManager);
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
|
||||
int CreateWireGuardService(const TCHAR *pInterfaceName, const TCHAR *pWGConfigFilePath) {
|
||||
//Service Name: "WireGuardTunnel$SomeTunnelName"
|
||||
//Display Name: "Some Service Name"
|
||||
//Service Type: SERVICE_WIN32_OWN_PROCESS
|
||||
//Start Type: StartAutomatic
|
||||
//Error Control: ErrorNormal,
|
||||
//Dependencies: [ "Nsi", "TcpIp" ]
|
||||
//Sid Type: SERVICE_SID_TYPE_UNRESTRICTED
|
||||
//Executable: "C:\path\to\example\vpnclient.exe /service configfile.conf"
|
||||
SC_HANDLE schSCManager;
|
||||
SC_HANDLE schService;
|
||||
TCHAR svrName[MAX_PATH];
|
||||
TCHAR displayName[MAX_PATH];
|
||||
TCHAR svrPath[MAX_PATH];
|
||||
TCHAR execParams[MAX_PATH * 2];
|
||||
|
||||
if (pInterfaceName == nullptr || lstrlen(pInterfaceName) == 0) {
|
||||
SPDLOG_ERROR(TEXT("Input pInterfaceName error: {0}"), pInterfaceName);
|
||||
return -ERR_INPUT_PARAMS;
|
||||
}
|
||||
|
||||
if (pWGConfigFilePath == nullptr || lstrlen(pWGConfigFilePath) == 0) {
|
||||
SPDLOG_ERROR(TEXT("Input pGUID error: {0}"), pWGConfigFilePath);
|
||||
return -ERR_INPUT_PARAMS;
|
||||
}
|
||||
|
||||
if (!PathFileExists(pWGConfigFilePath)) {
|
||||
SPDLOG_ERROR(TEXT("WireGuard Configure File Not Exist: {0}"), pWGConfigFilePath);
|
||||
return -ERR_ITEM_UNEXISTS;
|
||||
}
|
||||
|
||||
StringCbPrintf(svrName, MAX_PATH, TEXT("WireGuardTunnel$%s"), pInterfaceName);
|
||||
StringCbPrintf(displayName, MAX_PATH, TEXT("WireGuard Tunnel Service %s"), pInterfaceName);
|
||||
StringCbPrintf(svrPath, MAX_PATH, TEXT("%s\\NetTunnelSvr.exe"), GetGlobalCfgInfo()->workDirectory);
|
||||
StringCbPrintf(execParams, MAX_PATH * 2, TEXT("\"%s\" /service \"%s\""), svrPath, pWGConfigFilePath);
|
||||
//SPDLOG_DEBUG(TEXT("Params: {0}"), execParams);
|
||||
|
||||
if (!PathFileExists(svrPath)) {
|
||||
SPDLOG_ERROR(TEXT("WireGuard Service Not Exist: {0}"), svrPath);
|
||||
return -ERR_ITEM_UNEXISTS;
|
||||
}
|
||||
|
||||
// Get a handle to the SCM database.
|
||||
schSCManager = OpenSCManager(nullptr, // local computer
|
||||
nullptr, // ServicesActive database
|
||||
SC_MANAGER_ALL_ACCESS); // full access rights
|
||||
|
||||
if (nullptr == schSCManager) {
|
||||
SPDLOG_ERROR(TEXT("OpenSCManager failed ({0})"), GetLastError());
|
||||
return -ERR_OPEN_SCM;
|
||||
}
|
||||
|
||||
// Get a handle to the service.
|
||||
schService = OpenService(schSCManager, // SCM database
|
||||
svrName, // name of service
|
||||
SERVICE_ALL_ACCESS); // full access
|
||||
// 如果服务已经存在则关闭
|
||||
if (schService != nullptr) {
|
||||
int ret;
|
||||
CloseServiceHandle(schSCManager);
|
||||
CloseServiceHandle(schService);
|
||||
ret = RemoveGuardService(pInterfaceName, true);
|
||||
|
||||
if (ret != ERR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
schService = CreateService(schSCManager,
|
||||
svrName,
|
||||
displayName,
|
||||
SC_MANAGER_ALL_ACCESS,
|
||||
SERVICE_WIN32_OWN_PROCESS,
|
||||
SERVICE_DEMAND_START,
|
||||
SERVICE_ERROR_NORMAL,
|
||||
execParams,
|
||||
nullptr,
|
||||
nullptr,
|
||||
TEXT("Nsi\0TcpIp"),
|
||||
nullptr,
|
||||
nullptr);
|
||||
|
||||
if (schService == nullptr) {
|
||||
SPDLOG_ERROR(TEXT("Create Service {1} failed ({0})"), GetLastError(), svrName);
|
||||
CloseServiceHandle(schSCManager);
|
||||
return -ERR_CREATE_SERVICE;
|
||||
} else {
|
||||
SERVICE_SID_INFO info;
|
||||
SERVICE_DESCRIPTIONA desc;
|
||||
info.dwServiceSidType = SERVICE_SID_TYPE_UNRESTRICTED;
|
||||
|
||||
if (!ChangeServiceConfig2(schService, SERVICE_CONFIG_SERVICE_SID_INFO, &info)) {
|
||||
SPDLOG_ERROR(TEXT("Change Service {1} SERVICE_CONFIG_SERVICE_SID_INFO Configure failed ({0})"),
|
||||
GetLastError(),
|
||||
svrName);
|
||||
CloseServiceHandle(schService);
|
||||
CloseServiceHandle(schSCManager);
|
||||
return -ERR_CONFIG_SERVICE;
|
||||
}
|
||||
|
||||
desc.lpDescription = TEXT(const_cast<LPSTR>("SCC Tunnel Service over WireGuard"));
|
||||
|
||||
if (!ChangeServiceConfig2(schService, SERVICE_CONFIG_DESCRIPTION, &desc)) {
|
||||
SPDLOG_ERROR(TEXT("Change Service {1} SERVICE_CONFIG_DESCRIPTION Configure failed ({0})"),
|
||||
GetLastError(),
|
||||
svrName);
|
||||
CloseServiceHandle(schService);
|
||||
CloseServiceHandle(schSCManager);
|
||||
return -ERR_CONFIG_SERVICE;
|
||||
}
|
||||
|
||||
if (!StartService(schService, 0, nullptr)) {
|
||||
SPDLOG_ERROR(TEXT("Start Service {1} failed ({0})"), GetLastError(), svrName);
|
||||
CloseServiceHandle(schService);
|
||||
CloseServiceHandle(schSCManager);
|
||||
return -ERR_START_SERVICE;
|
||||
}
|
||||
}
|
||||
|
||||
CloseServiceHandle(schService);
|
||||
CloseServiceHandle(schSCManager);
|
||||
return ERR_SUCCESS;
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
#pragma once
|
||||
|
||||
/**
|
||||
* @brief WireGuard key 最大长度
|
||||
*/
|
||||
constexpr auto WG_KEY_MAX = (64);
|
||||
|
||||
/**
|
||||
* @brief 操作系统最大网卡数
|
||||
*/
|
||||
#define NET_CARD_MAX (32)
|
||||
|
||||
/**
|
||||
* @brief IP 字符串最大长度(支持IPv6)
|
||||
*/
|
||||
#define MAX_IP_LEN (48)
|
||||
|
||||
/**
|
||||
* @brief IP 字符串最小长度
|
||||
*/
|
||||
#define MIN_IP_LEN (7)
|
||||
|
||||
/**
|
||||
* @brief 网卡名称字符串最大长度(支持IPv6)
|
||||
*/
|
||||
#define MAX_NETCARD_NAME (64)
|
||||
|
||||
/**
|
||||
* @brief 协议加密类型
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
CRYPTO_NONE = 0, ///< 不加密
|
||||
CRYPTO_BASE64 = 1, ///< BASE64 字符串编码
|
||||
CRYPTO_AES128 = 2, ///< AES 128位秘钥 加密
|
||||
CRYPTO_3DES = 3, ///< 3DES 加密
|
||||
CRYPTO_AES256 = 4, ///< AES 256 位秘钥加密
|
||||
CRYPTO_MAX,
|
||||
} PROTO_CRYPTO_TYPE;
|
||||
|
||||
/**
|
||||
* @brief 日志等级
|
||||
*
|
||||
*/
|
||||
enum LOG_LEVEL {
|
||||
LOG_TRACE = 0, ///< TRACE 日志等级
|
||||
LOG_DEBUG, ///< DEBUG 日志等级
|
||||
LOG_INFO, ///< INFO 日志等级
|
||||
LOG_WARN, ///< WARN 日志等级
|
||||
LOG_ERROR, ///< ERROR 日志等级
|
||||
LOG_CRITICAL, ///< CRITICAL 日志等级
|
||||
LOG_OFF ///< 关闭日志
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Hash 算法类型
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
HASH_MD2 = 0, ///< MD2 HASH 算法
|
||||
HASH_MD4, ///< MD4 HASH 算法
|
||||
HASH_MD5, ///< MD5 HASH 算法
|
||||
HASH_SHA1, ///< SHA1 HASH 算法
|
||||
HASH_SHA256, ///< SHA256 HASH 算法
|
||||
HASH_SHA384, ///< SHA384 HASH 算法
|
||||
HASH_SHA512 ///< SHA512 HASH 算法
|
||||
} HASH_TYPE;
|
||||
|
||||
typedef enum {
|
||||
CHK_SYSTEM_INIT,
|
||||
CHK_WIREGUARD_CONFIG,
|
||||
CHK_WIREGUARD_SERVICE,
|
||||
CHK_WG_INTERFACE_PRIVATE,
|
||||
CHK_MAX
|
||||
} CHECK_FUNCTION;
|
|
@ -6,21 +6,9 @@
|
|||
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
|
||||
switch (ul_reason_for_call) {
|
||||
case DLL_PROCESS_ATTACH:
|
||||
CoInitialize(nullptr);
|
||||
CoInitializeSecurity(nullptr,
|
||||
-1,
|
||||
nullptr,
|
||||
nullptr,
|
||||
RPC_C_AUTHN_LEVEL_PKT,
|
||||
RPC_C_IMP_LEVEL_IMPERSONATE,
|
||||
nullptr,
|
||||
EOAC_NONE,
|
||||
nullptr);
|
||||
break;
|
||||
case DLL_THREAD_ATTACH:
|
||||
case DLL_THREAD_DETACH:
|
||||
case DLL_PROCESS_DETACH:
|
||||
CoFreeUnusedLibraries();
|
||||
case DLL_PROCESS_DETACH:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
#pragma once
|
||||
#include <spdlog/spdlog.h>
|
||||
#include "tunnel.h"
|
||||
#include "common.h"
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* @brief WireGuard 配置项
|
||||
*/
|
||||
|
@ -11,6 +12,7 @@ typedef struct {
|
|||
TCHAR wgPath[MAX_PATH]; ///< wg.exe 路径
|
||||
BOOL wgExists; ///< wg.exe 是否存在
|
||||
} WIREGUARD_CFG, *PWIREGUARD_CFG;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief WireGuard 网络接口配置项
|
||||
|
@ -80,7 +82,7 @@ typedef struct {
|
|||
BOOL enableLog; ///< 是否启用日志
|
||||
spdlog::level::level_enum logLevel; ///< 日志等级
|
||||
TCHAR cfgPath[MAX_PATH]; ///< 配置文件路径
|
||||
WIREGUARD_CFG wireguardCfg; ///< wireguard 配置项 @see WIREGUARD_CFG
|
||||
//WIREGUARD_CFG wireguardCfg; ///< wireguard 配置项 @see WIREGUARD_CFG
|
||||
WGINTERFACE_CFG wgServerCfg; ///< wireguard 服务端网络接口配置
|
||||
WGINTERFACE_CFG wgClientCfg; ///< wireguard 客户端网络接口配置
|
||||
USER_CONFIG userCfg; ///< 用户配置项
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "tunnel.h"
|
||||
#include "common.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
|
|
|
@ -1241,6 +1241,52 @@ int RemoveNATRule(const TCHAR *pInterfaceName) {
|
|||
return ERR_SUCCESS;
|
||||
}
|
||||
|
||||
int SetInterfaceIpAddress(const TCHAR *pInterfaceName, const TCHAR *pIpaddr, const TCHAR *pNetmask) {
|
||||
int ret;
|
||||
TCHAR cmdBuf[MAX_PATH];
|
||||
//int cidr;
|
||||
DWORD retCode;
|
||||
IP_INFO ipInfo {};
|
||||
|
||||
if (pInterfaceName == nullptr || lstrlen(pInterfaceName) == 0) {
|
||||
SPDLOG_ERROR("Input pInterfaceName params error: {0}", pInterfaceName);
|
||||
return -ERR_INPUT_PARAMS;
|
||||
}
|
||||
|
||||
if (pIpaddr == nullptr || lstrlen(pIpaddr) == 0) {
|
||||
SPDLOG_ERROR("Input pIpaddr params error: {0}", pIpaddr);
|
||||
return -ERR_INPUT_PARAMS;
|
||||
}
|
||||
|
||||
if (pNetmask == nullptr || lstrlen(pNetmask) == 0) {
|
||||
SPDLOG_WARN("Input pNetmask params error: {0}", pNetmask);
|
||||
return -ERR_INPUT_PARAMS;
|
||||
}
|
||||
|
||||
GetIpV4InfoFromNetmask(pIpaddr, pNetmask, &ipInfo);
|
||||
//cidr = NetmaskToCIDR(pNetmask);
|
||||
|
||||
if (FAILED(StringCbPrintf(
|
||||
cmdBuf,
|
||||
MAX_PATH,
|
||||
"PowerShell -Command \"& {New-NetIPAddress -InterfaceAlias %s -AddressFamily IPv4 -IPAddress %s -PrefixLength %d}\"",
|
||||
pInterfaceName,
|
||||
pIpaddr,
|
||||
ipInfo.prefix))) {
|
||||
SPDLOG_ERROR("Format String Error");
|
||||
return -ERR_MEMORY_STR;
|
||||
}
|
||||
|
||||
if ((ret = RunCommand(cmdBuf, nullptr, 0, &retCode)) != ERR_SUCCESS) {
|
||||
SPDLOG_ERROR("Run command [{0}] error: {1}", cmdBuf, ret);
|
||||
return -ERR_CALL_SHELL;
|
||||
}
|
||||
|
||||
SPDLOG_DEBUG("Run Set IP Command({1}): {0}", cmdBuf, retCode);
|
||||
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
|
||||
#if 0
|
||||
int GetWindowsHyperVStatus(int *pEnabled) {
|
||||
int ret;
|
||||
|
|
|
@ -234,7 +234,19 @@ TUNNEL_API int __cdecl SetNATRule(const TCHAR *pInterfaceName, const TCHAR *pCid
|
|||
*/
|
||||
TUNNEL_API int __cdecl RemoveNATRule(const TCHAR *pInterfaceName);
|
||||
|
||||
|
||||
/**
|
||||
* @brief 设置网络接口IP地址
|
||||
* @param[in] pInterfaceName 网卡名称
|
||||
* @param[in] pIpaddr IP 地址
|
||||
* @param[in] pNetmask 子网掩码
|
||||
* @return 函数执行结果 0: 成功, 小于0 失败 @see USER_ERRNO
|
||||
* - -ERR_INPUT_PARAMS 输入参数错误
|
||||
* - -ERR_MALLOC_MEMORY 分配内存失败
|
||||
* - -ERR_MEMORY_STR 字符串处理
|
||||
* - -ERR_CALL_SHELL 调用系统命令行失败
|
||||
* - ERR_SUCCESS 成功
|
||||
*/
|
||||
TUNNEL_API int __cdecl SetInterfaceIpAddress(const TCHAR *pInterfaceName, const TCHAR *pIpaddr, const TCHAR *pNetmask);
|
||||
TUNNEL_API int __cdecl CreatePorxyService();
|
||||
#if 0
|
||||
/**
|
||||
|
|
|
@ -95,7 +95,18 @@ int TunnelSDKInitEnv(const TCHAR *pWorkDir,
|
|||
LOG_LEVEL level,
|
||||
bool isWorkServer) {
|
||||
size_t length;
|
||||
|
||||
|
||||
CoInitialize(nullptr);
|
||||
CoInitializeSecurity(nullptr,
|
||||
-1,
|
||||
nullptr,
|
||||
nullptr,
|
||||
RPC_C_AUTHN_LEVEL_PKT,
|
||||
RPC_C_IMP_LEVEL_IMPERSONATE,
|
||||
nullptr,
|
||||
EOAC_NONE,
|
||||
nullptr);
|
||||
|
||||
memset(&g_globalConfig, 0, sizeof(SDK_CONFIG));
|
||||
|
||||
g_globalConfig.isWorkServer = isWorkServer;
|
||||
|
@ -145,10 +156,12 @@ int TunnelSDKInitEnv(const TCHAR *pWorkDir,
|
|||
|
||||
StringCbPrintf(g_globalConfig.cfgPath, MAX_PATH, TEXT("%s\\%s"), g_globalConfig.workDirectory, CONFIG_FILE_NAME);
|
||||
|
||||
#if 0
|
||||
if (FindWireguardExe(nullptr, 0) != ERR_SUCCESS) {
|
||||
SPDLOG_ERROR(TEXT("WireGuard not found, Please install WireGuard first or set the WireGuard Path."));
|
||||
return -ERR_ITEM_EXISTS;
|
||||
return -ERR_ITEM_UNEXISTS;
|
||||
}
|
||||
#endif
|
||||
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
|
@ -156,6 +169,7 @@ int TunnelSDKInitEnv(const TCHAR *pWorkDir,
|
|||
void TunnelSDKUnInit() {
|
||||
RemoteWireGuardControl(false);
|
||||
LocalWireGuardControl(false, false);
|
||||
CoFreeUnusedLibraries();
|
||||
}
|
||||
|
||||
void EnableSCGProxy(bool isEnable) {
|
||||
|
@ -210,26 +224,6 @@ int CheckSystemMinRequired(CHK_RESULT chkResult[CHK_MAX]) {
|
|||
SPDLOG_ERROR(pChk->errMsg);
|
||||
}
|
||||
break;
|
||||
case CHK_WIREGUARD_INSTALL:
|
||||
if (!g_globalConfig.wireguardCfg.wireguardExists) {
|
||||
pChk->result = false;
|
||||
StringCbCopy(
|
||||
pChk->errMsg,
|
||||
MAX_PATH,
|
||||
TEXT("错误: 系统未检测到 wireguard.exe 程序,请先下载并安装 WireGuard 最新版本,或者调用 "
|
||||
"SetWireguardPath 接口设置 WireGuard 程序路径。"));
|
||||
SPDLOG_ERROR(pChk->errMsg);
|
||||
}
|
||||
break;
|
||||
case CHK_WG_INSTALL:
|
||||
if (!g_globalConfig.wireguardCfg.wgExists) {
|
||||
pChk->result = false;
|
||||
StringCbCopy(pChk->errMsg,
|
||||
MAX_PATH,
|
||||
TEXT("错误: 系统未检测到 wg.exe 程序,请重新安装 WireGuard 或者修复 wg.exe 程序。"));
|
||||
SPDLOG_ERROR(pChk->errMsg);
|
||||
}
|
||||
break;
|
||||
case CHK_WIREGUARD_CONFIG: {
|
||||
TCHAR cfgVal[MAX_PATH];
|
||||
GetPrivateProfileString(CFG_WIREGUARD_SECTION,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
#include <Windows.h>
|
||||
|
||||
#ifdef NETTUNNELSDK_EXPORTS
|
||||
|
@ -8,82 +9,6 @@
|
|||
#define TUNNEL_API __declspec(dllimport)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief WireGuard key 最大长度
|
||||
*/
|
||||
constexpr auto WG_KEY_MAX = (64);
|
||||
|
||||
/**
|
||||
* @brief 操作系统最大网卡数
|
||||
*/
|
||||
#define NET_CARD_MAX (32)
|
||||
|
||||
/**
|
||||
* @brief IP 字符串最大长度(支持IPv6)
|
||||
*/
|
||||
#define MAX_IP_LEN (48)
|
||||
|
||||
/**
|
||||
* @brief IP 字符串最小长度
|
||||
*/
|
||||
#define MIN_IP_LEN (7)
|
||||
|
||||
/**
|
||||
* @brief 网卡名称字符串最大长度(支持IPv6)
|
||||
*/
|
||||
#define MAX_NETCARD_NAME (64)
|
||||
|
||||
/**
|
||||
* @brief 协议加密类型
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
CRYPTO_NONE = 0, ///< 不加密
|
||||
CRYPTO_BASE64 = 1, ///< BASE64 字符串编码
|
||||
CRYPTO_AES128 = 2, ///< AES 128位秘钥 加密
|
||||
CRYPTO_3DES = 3, ///< 3DES 加密
|
||||
CRYPTO_AES256 = 4, ///< AES 256 位秘钥加密
|
||||
CRYPTO_MAX,
|
||||
} PROTO_CRYPTO_TYPE;
|
||||
|
||||
/**
|
||||
* @brief 日志等级
|
||||
*
|
||||
*/
|
||||
enum LOG_LEVEL {
|
||||
LOG_TRACE = 0, ///< TRACE 日志等级
|
||||
LOG_DEBUG, ///< DEBUG 日志等级
|
||||
LOG_INFO, ///< INFO 日志等级
|
||||
LOG_WARN, ///< WARN 日志等级
|
||||
LOG_ERROR, ///< ERROR 日志等级
|
||||
LOG_CRITICAL, ///< CRITICAL 日志等级
|
||||
LOG_OFF ///< 关闭日志
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Hash 算法类型
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
HASH_MD2 = 0, ///< MD2 HASH 算法
|
||||
HASH_MD4, ///< MD4 HASH 算法
|
||||
HASH_MD5, ///< MD5 HASH 算法
|
||||
HASH_SHA1, ///< SHA1 HASH 算法
|
||||
HASH_SHA256, ///< SHA256 HASH 算法
|
||||
HASH_SHA384, ///< SHA384 HASH 算法
|
||||
HASH_SHA512 ///< SHA512 HASH 算法
|
||||
} HASH_TYPE;
|
||||
|
||||
typedef enum {
|
||||
CHK_SYSTEM_INIT,
|
||||
CHK_WIREGUARD_INSTALL,
|
||||
CHK_WG_INSTALL,
|
||||
CHK_WIREGUARD_CONFIG,
|
||||
CHK_WIREGUARD_SERVICE,
|
||||
CHK_WG_INTERFACE_PRIVATE,
|
||||
CHK_MAX
|
||||
} CHECK_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief 网络共享模式
|
||||
*
|
||||
|
@ -156,7 +81,8 @@ TUNNEL_API void __cdecl SetCurrentNetShareMode(NET_SHARE_MODE shareMode);
|
|||
* @return 函数执行结果 0: 成功, 小于0 失败 @see USER_ERRNO
|
||||
* - -ERR_ITEM_EXISTS 未找到 WireGuard 程序
|
||||
* - -ERR_SYS_CALL 获取配置本地配置文件存储目录失败
|
||||
* - -ERR_CREATE_FILE 创建用户配置文件目录失败
|
||||
* - -ERR_CREATE_FILE 创建用户配置文件目录失败
|
||||
* - -ERR_ITEM_UNEXISTS WireGuard 未安装
|
||||
* - ERR_SUCCESS 成功
|
||||
*/
|
||||
TUNNEL_API int __cdecl TunnelSDKInitEnv(const TCHAR *pWorkDir,
|
||||
|
@ -183,28 +109,6 @@ TUNNEL_API int __cdecl SetProtocolEncryptType(const PROTO_CRYPTO_TYPE type, cons
|
|||
*/
|
||||
TUNNEL_API void __cdecl TunnelLogEnable(bool enLog);
|
||||
|
||||
/**
|
||||
* @brief 查找 WireGuard 运行环境
|
||||
* @param[out] pFullPath wireguard.exe 程序路径
|
||||
* @param[in] maxSize pFullPath 缓冲区最大字节数
|
||||
* @return 函数执行结果 0: 成功, 小于0 失败 @see USER_ERRNO
|
||||
* - -ERR_INPUT_PARAMS 输入参数错误
|
||||
* - -ERR_MALLOC_MEMORY 分配内存失败
|
||||
* - -ERR_FILE_NOT_EXISTS 文件不存在
|
||||
* - ERR_SUCCESS 成功
|
||||
*/
|
||||
TUNNEL_API int __cdecl FindWireguardExe(TCHAR *pFullPath, int maxSize);
|
||||
|
||||
/**
|
||||
* @brief 设置 wireguard.exe 程序路径
|
||||
* @param[in] pPath wireguard.exe 程序路径
|
||||
* @return 函数执行结果 0: 成功, 小于0 失败 @see USER_ERRNO
|
||||
* - -ERR_INPUT_PARAMS 输入参数错误
|
||||
* - -ERR_ITEM_UNEXISTS 文件不存在
|
||||
* - ERR_SUCCESS 成功
|
||||
*/
|
||||
TUNNEL_API int __cdecl SetWireguardPath(const TCHAR *pPath);
|
||||
|
||||
/**
|
||||
* @brief 创建 WireGuard 密钥对
|
||||
* @param[out] pPubKey 公钥缓冲区
|
||||
|
@ -242,6 +146,49 @@ TUNNEL_API int __cdecl WireGuardCreateServerConfig(const PWGSERVER_CONFIG pWgCon
|
|||
*/
|
||||
TUNNEL_API int __cdecl WireGuardCreateClientConfig(const PWGCLIENT_CONFIG pWgConfig);
|
||||
|
||||
/**
|
||||
* @brief 通过 WireGuard 配置文件安装隧道服务
|
||||
* @param pInterfaceName 隧道服务名
|
||||
* @param pWGConfigFilePath 配置文件完整路径
|
||||
* @return 0: 成功, 小于0 失败 @see USER_ERRNO
|
||||
* - -ERR_INPUT_PARAMS 输入参数错误
|
||||
* - -ERR_ITEM_UNEXISTS 找不掉对应的服务
|
||||
* - -ERR_OPEN_SCM 打开服务管理器设备失败
|
||||
* - -ERR_OPEN_SERVICE 打开服务失败
|
||||
* - -ERR_CREATE_SERVICE 创建服务失败
|
||||
* - -ERR_CONFIG_SERVICE 配置服务失败
|
||||
* - -ERR_START_SERVICE 停止服务失败
|
||||
* - ERR_SUCCESS 成功
|
||||
*/
|
||||
TUNNEL_API int __cdecl CreateWireGuardService(const TCHAR *pInterfaceName, const TCHAR *pWGConfigFilePath);
|
||||
|
||||
/**
|
||||
* @brief 获取当前 WireGuard 服务隧道是否正则运行
|
||||
* @param pTunnelName 隧道服务名
|
||||
* @param pIsRunning pIsRunning WireGuard 服务隧道运行状态
|
||||
* - TRUE 已经安装
|
||||
* - FALSE 未安装
|
||||
* @return 函数执行结果 0: 成功, 小于0 失败 @see USER_ERRNO
|
||||
* - -ERR_INPUT_PARAMS 输入参数错误
|
||||
* - -ERR_OPEN_SCM 打开服务管理器设备失败
|
||||
* - ERR_SUCCESS 成功
|
||||
*/
|
||||
TUNNEL_API int __cdecl GetWireGuardServiceStatus(const TCHAR *pTunnelName, bool *pIsRunning);
|
||||
|
||||
/**
|
||||
* @brief 移除 WireGuard 隧道服务
|
||||
* @param pTunnelName 隧道服务名
|
||||
* @param bIsWaitStop 是否等待隧道服务结束 TRUE: 等待服务结束, FALSE: 不等待直接结束
|
||||
* @return 函数执行结果 0: 成功, 小于0 失败 @see USER_ERRNO
|
||||
* - -ERR_INPUT_PARAMS 输入参数错误
|
||||
* - -ERR_OPEN_SCM 打开服务管理器设备失败
|
||||
* - -ERR_OPEN_SERVICE 打开服务失败
|
||||
* - -ERR_STOP_SERVICE 停止服务失败
|
||||
* - -ERR_DELETE_SERVICE 删除服务失败
|
||||
* - ERR_SUCCESS 成功
|
||||
*/
|
||||
TUNNEL_API int __cdecl RemoveGuardService(const TCHAR *pTunnelName, bool bIsWaitStop);
|
||||
|
||||
/**
|
||||
* @brief 安装/卸载 WireGuard 服务
|
||||
* @param[in] bInstall TRUE 安装服务, FALSE 卸载服务
|
||||
|
@ -362,6 +309,29 @@ TUNNEL_API int __cdecl CalcFileHash(const HASH_TYPE type, const TCHAR *pPath, TC
|
|||
*/
|
||||
TUNNEL_API int __cdecl InstallWindowsNATCommand();
|
||||
TUNNEL_API int __cdecl WireGuardNetConnectionSharingEnable();
|
||||
|
||||
|
||||
/**
|
||||
* @brief 查找 WireGuard 运行环境
|
||||
* @param[out] pFullPath wireguard.exe 程序路径
|
||||
* @param[in] maxSize pFullPath 缓冲区最大字节数
|
||||
* @return 函数执行结果 0: 成功, 小于0 失败 @see USER_ERRNO
|
||||
* - -ERR_INPUT_PARAMS 输入参数错误
|
||||
* - -ERR_MALLOC_MEMORY 分配内存失败
|
||||
* - -ERR_FILE_NOT_EXISTS 文件不存在
|
||||
* - ERR_SUCCESS 成功
|
||||
*/
|
||||
TUNNEL_API int __cdecl FindWireguardExe(TCHAR *pFullPath, int maxSize);
|
||||
|
||||
/**
|
||||
* @brief 设置 wireguard.exe 程序路径
|
||||
* @param[in] pPath wireguard.exe 程序路径
|
||||
* @return 函数执行结果 0: 成功, 小于0 失败 @see USER_ERRNO
|
||||
* - -ERR_INPUT_PARAMS 输入参数错误
|
||||
* - -ERR_ITEM_UNEXISTS 文件不存在
|
||||
* - ERR_SUCCESS 成功
|
||||
*/
|
||||
TUNNEL_API int __cdecl SetWireguardPath(const TCHAR *pPath);
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -23,8 +23,13 @@ enum USER_ERRNO {
|
|||
ERR_GET_FILE_SIZE, ///< 获取文件大小失败
|
||||
ERR_FIND_FILE, ///< 查找文件失败
|
||||
ERR_COPY_FILE, ///< 复制文件失败
|
||||
ERR_OPEN_SCM, ///< 打开服务管理器设备
|
||||
ERR_OPEN_SCM, ///< 打开服务管理器设备失败
|
||||
ERR_OPEN_SERVICE, ///< 打开服务失败
|
||||
ERR_CREATE_SERVICE, ///< 创建服务失败
|
||||
ERR_START_SERVICE, ///< 启动服务失败
|
||||
ERR_STOP_SERVICE, ///< 停止服务失败
|
||||
ERR_DELETE_SERVICE, ///< 删除服务失败
|
||||
ERR_CONFIG_SERVICE, ///< 修改服务配置失败
|
||||
ERR_GET_SERVICESSTATUS, ///< 获取服务状态失败
|
||||
ERR_MALLOC_MEMORY, ///< 分配内存失败
|
||||
ERR_MMAP_MEMORY, ///< 共享内存失败
|
||||
|
@ -46,7 +51,7 @@ enum USER_ERRNO {
|
|||
ERR_BCRYPT_CREATEHASH, ///< 创建 Hash 算法失败
|
||||
ERR_BCRYPT_HASHDATA, ///< 计算 Hash 数据失败
|
||||
ERR_BCRYPT_FINISHHASH, ///< 计算 Hash 结果失败
|
||||
ERR_NET_UNCONNECT = 200, ///< 网络未连接
|
||||
ERR_NET_UNCONNECT = 200, ///< 网络未连接
|
||||
ERR_NET_CATEGORY_MODE, ///< 网络工作模式
|
||||
ERR_NET_INTELNEL_ICS, ///< 共享 Intelnet 网络 ICS 共享失败
|
||||
ERR_NET_WIREGUARD_ICS, ///< 共享 WireGuard 网络 ICS 共享失败
|
||||
|
|
|
@ -9,15 +9,13 @@
|
|||
#include "misc.h"
|
||||
#include "network.h"
|
||||
|
||||
#define USED_EMBEDDED_WG (1)
|
||||
|
||||
#pragma comment(lib, "Shlwapi.lib")
|
||||
#pragma comment(lib, "Winmm.lib")
|
||||
|
||||
#define WG_NIC_DISCRIPT TEXT("WireGuard Tunnel")
|
||||
|
||||
static NET_SHARE_MODE g_CurShareMode = ICS_SHARE_MODE;
|
||||
|
||||
constexpr auto WINENVBUF_SIZE = (4096);
|
||||
|
||||
NET_SHARE_MODE GetCurrentNetShareMode() {
|
||||
return g_CurShareMode;
|
||||
}
|
||||
|
@ -39,8 +37,7 @@ int GetWireGuardWorkMode(bool *pIsWorkServer) {
|
|||
|
||||
int WireGuardInstallDefaultServerService(bool bInstall) {
|
||||
TCHAR cfgVal[MAX_PATH];
|
||||
DWORD retCode;
|
||||
|
||||
|
||||
GetPrivateProfileString(CFG_WIREGUARD_SECTION,
|
||||
CFG_WGCFG_PATH,
|
||||
TEXT(""),
|
||||
|
@ -50,14 +47,20 @@ int WireGuardInstallDefaultServerService(bool bInstall) {
|
|||
|
||||
if (lstrlen(cfgVal) > 0) {
|
||||
if (PathFileExists(cfgVal)) {
|
||||
TCHAR cmdBuf[MAX_PATH];
|
||||
TCHAR svrName[MAX_PATH];
|
||||
int ret;
|
||||
TCHAR svrName[MAX_PATH];
|
||||
|
||||
StringCbCopy(svrName, MAX_PATH, cfgVal);
|
||||
PathStripPath(svrName);
|
||||
PathRemoveExtension(svrName);
|
||||
|
||||
#if USED_EMBEDDED_WG
|
||||
if (bInstall) {
|
||||
ret = WireGuardInstallServerService(cfgVal); //CreateWireGuardService(svrName, cfgVal);
|
||||
} else {
|
||||
ret = RemoveGuardService(svrName, true);
|
||||
}
|
||||
#else
|
||||
if (bInstall) {
|
||||
// 安装服务
|
||||
StringCbPrintf(cmdBuf,
|
||||
|
@ -81,8 +84,9 @@ int WireGuardInstallDefaultServerService(bool bInstall) {
|
|||
}
|
||||
|
||||
SPDLOG_DEBUG(TEXT("Run command [{0}]"), cmdBuf);
|
||||
#endif
|
||||
|
||||
if (bInstall) {
|
||||
if (bInstall && ret == ERR_SUCCESS) {
|
||||
int retry = 10;
|
||||
do {
|
||||
ret = WaitNetAdapterConnected(svrName, 1000);
|
||||
|
@ -102,9 +106,12 @@ int WireGuardInstallDefaultServerService(bool bInstall) {
|
|||
|
||||
int WireGuardInstallServerService(const TCHAR *pTunnelCfgPath) {
|
||||
// 卸载服务
|
||||
TCHAR cmdBuf[MAX_PATH];
|
||||
TCHAR svrName[MAX_PATH];
|
||||
int ret;
|
||||
DWORD retCode;
|
||||
|
||||
StringCbCopy(svrName, MAX_PATH, pTunnelCfgPath);
|
||||
PathStripPath(svrName);
|
||||
PathRemoveExtension(svrName);
|
||||
|
||||
if (pTunnelCfgPath == nullptr || lstrlen(pTunnelCfgPath) == 0) {
|
||||
SPDLOG_ERROR(TEXT("Input pTunnelCfgPath params error"));
|
||||
|
@ -115,6 +122,13 @@ int WireGuardInstallServerService(const TCHAR *pTunnelCfgPath) {
|
|||
return -ERR_ITEM_UNEXISTS;
|
||||
}
|
||||
|
||||
if ((ret = CreateWireGuardService(svrName, pTunnelCfgPath)) != ERR_SUCCESS) {
|
||||
SPDLOG_ERROR(TEXT("Create WireGuard Service Error({0}): {1}, {2} "), ret, svrName, pTunnelCfgPath);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
// 安装服务
|
||||
StringCbPrintf(cmdBuf,
|
||||
MAX_PATH,
|
||||
|
@ -128,26 +142,31 @@ int WireGuardInstallServerService(const TCHAR *pTunnelCfgPath) {
|
|||
}
|
||||
|
||||
SPDLOG_DEBUG(TEXT("Run command [{0}]"), cmdBuf);
|
||||
|
||||
#endif
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
|
||||
int WireGuardUnInstallServerService(const TCHAR *pTunnelName) {
|
||||
// 卸载服务
|
||||
TCHAR cmdBuf[MAX_PATH];
|
||||
TCHAR svrName[MAX_PATH];
|
||||
// 卸载服务
|
||||
int ret;
|
||||
DWORD retCode;
|
||||
|
||||
if (pTunnelName == nullptr || lstrlen(pTunnelName) == 0) {
|
||||
SPDLOG_ERROR(TEXT("Input pTunnelName params error"));
|
||||
return -ERR_INPUT_PARAMS;
|
||||
}
|
||||
|
||||
#if 0
|
||||
StringCbCopy(svrName, MAX_PATH, pTunnelName);
|
||||
PathStripPath(svrName);
|
||||
PathRemoveExtension(svrName);
|
||||
#endif
|
||||
|
||||
#if USED_EMBEDDED_WG
|
||||
if ((ret = RemoveGuardService(pTunnelName, true)) != ERR_SUCCESS) {
|
||||
SPDLOG_ERROR(TEXT("Stop WireGuard Service Error: {0}"), ret);
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
StringCbPrintf(cmdBuf,
|
||||
MAX_PATH,
|
||||
TEXT("\"%s\" /uninstalltunnelservice %s"),
|
||||
|
@ -160,7 +179,7 @@ int WireGuardUnInstallServerService(const TCHAR *pTunnelName) {
|
|||
}
|
||||
|
||||
SPDLOG_DEBUG(TEXT("Run command [{0}]"), cmdBuf);
|
||||
|
||||
#endif
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -194,9 +213,12 @@ int IsWireGuardServerInstalled(bool *pIsInstalled) {
|
|||
}
|
||||
|
||||
int IsWireGuardServerRunning(const TCHAR *pIfName, bool *pIsRunning) {
|
||||
int ret;
|
||||
#if USED_EMBEDDED_WG
|
||||
return GetWireGuardServiceStatus(pIfName, pIsRunning);
|
||||
#else
|
||||
int ret;
|
||||
PNIC_CONTENT pInfo = nullptr;
|
||||
int size = 0;
|
||||
int size = 0;
|
||||
|
||||
if (pIfName == nullptr || lstrlen(pIfName) == 0) {
|
||||
SPDLOG_ERROR(TEXT("Input pIfName params error"));
|
||||
|
@ -223,6 +245,7 @@ int IsWireGuardServerRunning(const TCHAR *pIfName, bool *pIsRunning) {
|
|||
}
|
||||
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
|
||||
int WireGuardCreateClientConfig(const PWGCLIENT_CONFIG pWgConfig) {
|
||||
|
@ -500,7 +523,9 @@ int WireGuardCreateServerConfig(const PWGSERVER_CONFIG pWgConfig) {
|
|||
return ERR_SUCCESS;
|
||||
}
|
||||
|
||||
// TODO: Change implement
|
||||
int GenerateWireguardKeyPairs(TCHAR *pPubKey, int pubkeySize, TCHAR *pPrivKey, int privKeySize) {
|
||||
#if 0
|
||||
int ret;
|
||||
DWORD retCode;
|
||||
TCHAR cmdBuffer[MAX_PATH];
|
||||
|
@ -540,10 +565,11 @@ int GenerateWireguardKeyPairs(TCHAR *pPubKey, int pubkeySize, TCHAR *pPrivKey, i
|
|||
|
||||
StringCbCopy(pPubKey, pubkeySize, cmdResult);
|
||||
SPDLOG_DEBUG(TEXT("Run command [{0}] resutl \'{1}\'"), cmdBuffer, cmdResult);
|
||||
|
||||
#endif
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
|
||||
#if 0
|
||||
int SetWireguardPath(const TCHAR *pPath) {
|
||||
if (pPath == nullptr) {
|
||||
return -ERR_INPUT_PARAMS;
|
||||
|
@ -573,6 +599,7 @@ int SetWireguardPath(const TCHAR *pPath) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
int FindWireguardExe(TCHAR *pFullPath, int maxSize) {
|
||||
TCHAR path[MAX_PATH];
|
||||
TCHAR wireguardPath[MAX_PATH];
|
||||
|
@ -708,7 +735,6 @@ int FindWireguardExe(TCHAR *pFullPath, int maxSize) {
|
|||
return -ERR_FILE_NOT_EXISTS;
|
||||
}
|
||||
|
||||
#if 0
|
||||
int InstallWindowsNATCommand() {
|
||||
TCHAR psCmdPath[MAX_PATH];
|
||||
|
||||
|
|
|
@ -0,0 +1,145 @@
|
|||
#include <Windows.h>
|
||||
#include <iostream>
|
||||
#include <comdef.h>
|
||||
#include <Wbemidl.h>
|
||||
|
||||
#pragma comment(lib, "wbemuuid.lib")
|
||||
|
||||
int net_nat() {
|
||||
HRESULT hr;
|
||||
|
||||
// Initialize COM
|
||||
hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
|
||||
if (FAILED(hr)) {
|
||||
std::cout << "Failed to initialize COM" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Initialize security
|
||||
hr = CoInitializeSecurity(NULL,
|
||||
-1,
|
||||
NULL,
|
||||
NULL,
|
||||
RPC_C_AUTHN_LEVEL_DEFAULT,
|
||||
RPC_C_IMP_LEVEL_IMPERSONATE,
|
||||
NULL,
|
||||
EOAC_NONE,
|
||||
NULL);
|
||||
if (FAILED(hr)) {
|
||||
std::cout << "Failed to initialize security" << std::endl;
|
||||
CoUninitialize();
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Obtain the initial locator to WMI
|
||||
IWbemLocator *pLocator = NULL;
|
||||
hr = CoCreateInstance(CLSID_WbemLocator,
|
||||
0,
|
||||
CLSCTX_INPROC_SERVER,
|
||||
IID_IWbemLocator,
|
||||
reinterpret_cast<LPVOID *>(&pLocator));
|
||||
if (FAILED(hr)) {
|
||||
std::cout << "Failed to create IWbemLocator object" << std::endl;
|
||||
CoUninitialize();
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Connect to the root\StandardCimv2 namespace with the current user
|
||||
IWbemServices *pServices = NULL;
|
||||
hr = pLocator->ConnectServer(_bstr_t(L"ROOT\\StandardCimv2"), NULL, NULL, 0, NULL, 0, 0, &pServices);
|
||||
if (FAILED(hr)) {
|
||||
std::cout << "Failed to connect to WMI namespace" << std::endl;
|
||||
pLocator->Release();
|
||||
CoUninitialize();
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Set the authentication information to the current user
|
||||
hr = CoSetProxyBlanket(pServices,
|
||||
RPC_C_AUTHN_WINNT,
|
||||
RPC_C_AUTHZ_NONE,
|
||||
NULL,
|
||||
RPC_C_AUTHN_LEVEL_CALL,
|
||||
RPC_C_IMP_LEVEL_IMPERSONATE,
|
||||
NULL,
|
||||
EOAC_NONE);
|
||||
if (FAILED(hr)) {
|
||||
std::cout << "Failed to set proxy blanket" << std::endl;
|
||||
pServices->Release();
|
||||
pLocator->Release();
|
||||
CoUninitialize();
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Get the NAT class object
|
||||
IWbemClassObject *pClass = NULL;
|
||||
hr = pServices->GetObject(_bstr_t("MSFT_NetNat"), 0, NULL, &pClass, NULL);
|
||||
if (FAILED(hr)) {
|
||||
std::cout << "Failed to get NAT class object" << std::endl;
|
||||
pServices->Release();
|
||||
pLocator->Release();
|
||||
CoUninitialize();
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Spawn an instance of the NAT class
|
||||
IWbemClassObject *pInstance = NULL;
|
||||
hr = pClass->SpawnInstance(0, &pInstance);
|
||||
if (FAILED(hr)) {
|
||||
std::cout << "Failed to spawn NAT instance" << std::endl;
|
||||
pClass->Release();
|
||||
pServices->Release();
|
||||
pLocator->Release();
|
||||
CoUninitialize();
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Set the properties of the NAT instance
|
||||
VARIANT var;
|
||||
VariantInit(&var);
|
||||
|
||||
// Set the name of the NAT instance
|
||||
var.vt = VT_BSTR;
|
||||
var.bstrVal = SysAllocString(L"MyNATRule");
|
||||
hr = pInstance->Put(L"Name", 0, &var, 0);
|
||||
if (FAILED(hr)) {
|
||||
std::cout << "Failed to set NAT instance name" << std::endl;
|
||||
VariantClear(&var);
|
||||
pInstance->Release();
|
||||
pClass->Release();
|
||||
pServices->Release();
|
||||
pLocator->Release();
|
||||
CoUninitialize();
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Set other properties as needed
|
||||
// ...
|
||||
|
||||
// Create the NAT instance
|
||||
IWbemCallResult *pResult = NULL;
|
||||
hr = pServices->PutInstance(pInstance, WBEM_FLAG_CREATE_ONLY, NULL, &pResult);
|
||||
if (FAILED(hr)) {
|
||||
std::cout << "Failed to create NAT instance" << std::endl;
|
||||
VariantClear(&var);
|
||||
pInstance->Release();
|
||||
pClass->Release();
|
||||
pServices->Release();
|
||||
pLocator->Release();
|
||||
CoUninitialize();
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
VariantClear(&var);
|
||||
pResult->Release();
|
||||
pInstance->Release();
|
||||
pClass->Release();
|
||||
pServices->Release();
|
||||
pLocator->Release();
|
||||
CoUninitialize();
|
||||
|
||||
std::cout << "NAT rule created successfully" << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -44,7 +44,7 @@ void test_socket() {
|
|||
|
||||
#if 0
|
||||
int service_test() {
|
||||
TCHAR szSvcName[] = _T("WireGuard");
|
||||
TCHAR szSvcName[] = TEXT("WireGuard");
|
||||
SC_HANDLE schSCManager = nullptr;
|
||||
SC_HANDLE schService = nullptr;
|
||||
|
||||
|
@ -55,7 +55,6 @@ int service_test() {
|
|||
DWORD dwBytesNeeded = 0;
|
||||
|
||||
// Get a handle to the SCM database.
|
||||
|
||||
schSCManager = OpenSCManager(nullptr, // local computer
|
||||
nullptr, // ServicesActive database
|
||||
SC_MANAGER_ALL_ACCESS); // full access rights
|
||||
|
@ -111,13 +110,47 @@ int service_test() {
|
|||
cin.get();
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool test_code() {
|
||||
char temp_path[MAX_PATH + 1] = { 0 };
|
||||
if (!::GetTempPathA(MAX_PATH, temp_path))
|
||||
{
|
||||
//LOG_ERROR("GetTempPathA failed! we use the default logger!");
|
||||
strcpy_s(temp_path, MAX_PATH, "c:\\windows\\temp\\");
|
||||
}
|
||||
|
||||
char log_file[MAX_PATH + 1] = { 0 };
|
||||
sprintf_s(log_file, MAX_PATH, "%s%s", temp_path, "tunnel.log");
|
||||
|
||||
#ifdef _DEBUG
|
||||
LOG_LEVEL log_level = LOG_DEBUG;
|
||||
#else
|
||||
LOG_LEVEL log_level = TUNNEL_LOG_INFO;
|
||||
#endif
|
||||
|
||||
int ret = TunnelSDKInitEnv(NULL, g_PlatformURL, log_file, log_level, true);
|
||||
if (ret != ERR_SUCCESS)
|
||||
{
|
||||
//LOG_ERROR("TunnelSDKInitEnv failed! err=%d!", ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string local_ip = "127.0.0.1";
|
||||
PUSER_SERVER_CONFIG server_config = NULL;
|
||||
ret = GetUserServerConfigure(NULL, local_ip.c_str(), &server_config);
|
||||
if (ret != ERR_SUCCESS)
|
||||
{
|
||||
//LOG_ERROR("GetUserServerConfigure failed! err=%d!", ret);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int tunnel_service() {
|
||||
PUSER_SERVER_CONFIG pSvrCfg;
|
||||
//TCHAR logPath[MAX_PATH];
|
||||
|
||||
TunnelSDKInitEnv(g_AppPath, g_PlatformURL, nullptr, LOG_DEBUG, true);
|
||||
TunnelSDKInitEnv(nullptr, g_PlatformURL, nullptr, LOG_DEBUG, true);
|
||||
|
||||
//StringCbPrintf(logPath, MAX_PATH, TEXT("%s\\TestApp.log"), g_AppPath);
|
||||
//InitTunnelSDKLog(nullptr, LOG_DEBUG);
|
||||
|
@ -144,8 +177,13 @@ int main() {
|
|||
//SetRouteTable();
|
||||
|
||||
//CreatePorxyService();
|
||||
//tunnel_service();
|
||||
test_socket();
|
||||
//test_code();
|
||||
//test_socket();
|
||||
tunnel_service();
|
||||
//net_nat();
|
||||
|
||||
//main_wireguard(true);
|
||||
//main_wireguard_getinfo();
|
||||
|
||||
while (true) {
|
||||
Sleep(100);
|
||||
|
|
|
@ -105,6 +105,7 @@
|
|||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<AdditionalIncludeDirectories>../NetTunnelSDK;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<LanguageStandard>Default</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
|
@ -132,6 +133,7 @@
|
|||
<ClCompile Include="CryptoExample.cpp" />
|
||||
<ClCompile Include="firewall.cpp" />
|
||||
<ClCompile Include="NetInterface.cpp" />
|
||||
<ClCompile Include="NetNat.cpp" />
|
||||
<ClCompile Include="NetShare.cpp" />
|
||||
<ClCompile Include="NetTunnelSDKTestApp.cpp" />
|
||||
<ClCompile Include="RouteTable.cpp" />
|
||||
|
|
|
@ -33,6 +33,9 @@
|
|||
<ClCompile Include="firewall.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="NetNat.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="common.h">
|
||||
|
|
|
@ -0,0 +1,718 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2018-2021 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
#include <winsock2.h>
|
||||
#include <Windows.h>
|
||||
#include <ws2ipdef.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <iphlpapi.h>
|
||||
#include <bcrypt.h>
|
||||
#include <wincrypt.h>
|
||||
#include <sysinfoapi.h>
|
||||
#include <winternl.h>
|
||||
#include <stdio.h>
|
||||
#include <wbemcli.h>
|
||||
#include "wireguard.h"
|
||||
#include "common.h"
|
||||
#include "tunnel.h"
|
||||
#include "network.h"
|
||||
|
||||
#include <strsafe.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
#pragma comment(lib, "Crypt32.lib")
|
||||
|
||||
#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
|
||||
#define FREE(x) HeapFree(GetProcessHeap(), 0, (x))
|
||||
|
||||
static WIREGUARD_CREATE_ADAPTER_FUNC *WireGuardCreateAdapter;
|
||||
static WIREGUARD_OPEN_ADAPTER_FUNC *WireGuardOpenAdapter;
|
||||
static WIREGUARD_CLOSE_ADAPTER_FUNC *WireGuardCloseAdapter;
|
||||
static WIREGUARD_GET_ADAPTER_LUID_FUNC *WireGuardGetAdapterLUID;
|
||||
static WIREGUARD_GET_RUNNING_DRIVER_VERSION_FUNC *WireGuardGetRunningDriverVersion;
|
||||
static WIREGUARD_DELETE_DRIVER_FUNC *WireGuardDeleteDriver;
|
||||
static WIREGUARD_SET_LOGGER_FUNC *WireGuardSetLogger;
|
||||
static WIREGUARD_SET_ADAPTER_LOGGING_FUNC *WireGuardSetAdapterLogging;
|
||||
static WIREGUARD_GET_ADAPTER_STATE_FUNC *WireGuardGetAdapterState;
|
||||
static WIREGUARD_SET_ADAPTER_STATE_FUNC *WireGuardSetAdapterState;
|
||||
static WIREGUARD_GET_CONFIGURATION_FUNC *WireGuardGetConfiguration;
|
||||
static WIREGUARD_SET_CONFIGURATION_FUNC *WireGuardSetConfiguration;
|
||||
|
||||
#if 0
|
||||
static int InitializeWMI()
|
||||
{
|
||||
IWbemLocator* p_instance_ = nullptr;
|
||||
IWbemServices* p_service_ = nullptr;
|
||||
IEnumWbemClassObject* p_enum_ = nullptr;
|
||||
IWbemClassObject *p_obj_ = nullptr;
|
||||
IWbemClassObject *p_config = nullptr;
|
||||
|
||||
// Step 1: Initialize COM.
|
||||
HRESULT hres = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
|
||||
if (FAILED(hres)) {
|
||||
SPDLOG_ERROR("CoInitializeEx Error: {0}", GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 3: Obtain the initial locator to WMI
|
||||
hres = CoCreateInstance(
|
||||
CLSID_WbemLocator,
|
||||
0,
|
||||
CLSCTX_INPROC_SERVER,
|
||||
IID_IWbemLocator,
|
||||
(LPVOID*)&p_instance_);
|
||||
if (FAILED(hres)) {
|
||||
SPDLOG_ERROR("CoCreateInstance Error: {0}", GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 4: Connect to the local root\cimv2 namespace and obtain pointer pSvc to make IWbemServices calls.
|
||||
hres = p_instance_->ConnectServer(
|
||||
_bstr_t(L"ROOT\\CIMV2"),
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
0,
|
||||
&p_service_
|
||||
);
|
||||
//ASSERT_THROW(SUCCEEDED(hres), "ConnectServer failed");
|
||||
if (FAILED(hres)) {
|
||||
#ifdef _DEBUG
|
||||
cout << "ConnectServer failed: " << hres << endl;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 5: Set security levels for the proxy
|
||||
hres = CoSetProxyBlanket(
|
||||
p_service_, // Indicates the proxy to set
|
||||
RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx
|
||||
RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx
|
||||
NULL, // Server principal name
|
||||
RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx
|
||||
RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
|
||||
NULL, // client identity
|
||||
EOAC_NONE // proxy capabilities
|
||||
);
|
||||
//ASSERT_THROW(SUCCEEDED(hres), "CoSetProxyBlanket failed");
|
||||
if (FAILED(hres)) {
|
||||
#ifdef _DEBUG
|
||||
cout << "CoSetProxyBlanket failed: " << hres << endl;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
// 通过适配器名称来找到指定的适配器对象.
|
||||
CComBSTR TheQuery = L"SELECT * FROM Win32_NetworkAdapterConfiguration WHERE SettingID = \"";
|
||||
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> conversion;
|
||||
TheQuery += conversion.from_bytes(key_).c_str();
|
||||
TheQuery += L"\"";
|
||||
// const BSTR lang = L"WQL";
|
||||
hres = p_service_->ExecQuery(
|
||||
SysAllocString(L"WQL"),
|
||||
// L"WQL",
|
||||
TheQuery,
|
||||
WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY,
|
||||
NULL,
|
||||
&p_enum_);
|
||||
//ASSERT_THROW(SUCCEEDED(hres), "ExecQuery failed");
|
||||
if (FAILED(hres)) {
|
||||
#ifdef _DEBUG
|
||||
cout << "ExecQuery failed: " << hres << endl;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the adapter object.
|
||||
ULONG num = 0;
|
||||
hres = p_enum_->Next(WBEM_INFINITE, 1, &p_obj_, &num);
|
||||
//ASSERT_THROW(SUCCEEDED(hres), "Next failed");
|
||||
if (FAILED(hres)) {
|
||||
#ifdef _DEBUG
|
||||
cout << "Next failed: " << hres << endl;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
//ASSERT_THROW(0 < num, "Next failed");
|
||||
if (num < 1) {
|
||||
#ifdef _DEBUG
|
||||
cout << "Next failed num < 1" << endl;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
VariantInit(&path_);
|
||||
hres = p_obj_->Get(L"__PATH", 0, &path_, NULL, NULL);
|
||||
//ASSERT_THROW(SUCCEEDED(hres), "Get path failed");
|
||||
if (FAILED(hres)) {
|
||||
#ifdef _DEBUG
|
||||
cout << "Get failed: " << hres << endl;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
hres = p_service_->GetObject(_bstr_t(L"Win32_NetworkAdapterConfiguration"), 0, NULL, &p_config, NULL);
|
||||
//ASSERT_THROW(SUCCEEDED(hres), "GetObject Win32_NetworkAdapterConfiguration failed");
|
||||
if (FAILED(hres)) {
|
||||
#ifdef _DEBUG
|
||||
cout << "GetObject failed: " << hres << endl;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
is_init_ = true;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
static HMODULE InitializeWireGuardNT(void) {
|
||||
HMODULE WireGuardDll = LoadLibraryExW(L"wireguard.dll",
|
||||
nullptr,
|
||||
LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32);
|
||||
if (!WireGuardDll) {
|
||||
return nullptr;
|
||||
}
|
||||
#define X(Name) ((*(FARPROC *)&Name = GetProcAddress(WireGuardDll, #Name)) == nullptr)
|
||||
if (X(WireGuardCreateAdapter) || X(WireGuardOpenAdapter) || X(WireGuardCloseAdapter) ||
|
||||
X(WireGuardGetAdapterLUID) || X(WireGuardGetRunningDriverVersion) || X(WireGuardDeleteDriver) ||
|
||||
X(WireGuardSetLogger) || X(WireGuardSetAdapterLogging) || X(WireGuardGetAdapterState) ||
|
||||
X(WireGuardSetAdapterState) || X(WireGuardGetConfiguration) || X(WireGuardSetConfiguration))
|
||||
#undef X
|
||||
{
|
||||
DWORD LastError = GetLastError();
|
||||
FreeLibrary(WireGuardDll);
|
||||
SetLastError(LastError);
|
||||
return nullptr;
|
||||
}
|
||||
return WireGuardDll;
|
||||
}
|
||||
|
||||
//
|
||||
//static void CALLBACK ConsoleLogger(_In_ WIREGUARD_LOGGER_LEVEL Level,
|
||||
// _In_ DWORD64 Timestamp,
|
||||
// _In_z_ const WCHAR *LogLine) {
|
||||
// SYSTEMTIME SystemTime;
|
||||
// GetSystemTime(&SystemTime);
|
||||
// //FileTimeToSystemTime((FILETIME *)&Timestamp, &SystemTime);
|
||||
// WCHAR LevelMarker;
|
||||
// switch (Level) {
|
||||
// case WIREGUARD_LOG_INFO:
|
||||
// LevelMarker = L'+';
|
||||
// break;
|
||||
// case WIREGUARD_LOG_WARN:
|
||||
// LevelMarker = L'-';
|
||||
// break;
|
||||
// case WIREGUARD_LOG_ERR:
|
||||
// LevelMarker = L'!';
|
||||
// break;
|
||||
// default:
|
||||
// return;
|
||||
// }
|
||||
// fwprintf(stderr,
|
||||
// L"%04u-%02u-%02u %02u:%02u:%02u.%04u [%c] %s\n",
|
||||
// SystemTime.wYear,
|
||||
// SystemTime.wMonth,
|
||||
// SystemTime.wDay,
|
||||
// SystemTime.wHour,
|
||||
// SystemTime.wMinute,
|
||||
// SystemTime.wSecond,
|
||||
// SystemTime.wMilliseconds,
|
||||
// LevelMarker,
|
||||
// LogLine);
|
||||
//}
|
||||
|
||||
static DWORD64 Now() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static DWORD LogError(_In_z_ const WCHAR *Prefix, _In_ DWORD Error) {
|
||||
WCHAR tMsg[MAX_PATH];
|
||||
StringCbPrintfW(tMsg, MAX_PATH, L"Error: %d", Error);
|
||||
ConsoleLogger(WIREGUARD_LOG_ERR, Now(), tMsg);
|
||||
return Error;
|
||||
}
|
||||
|
||||
static DWORD LogLastError(_In_z_ const WCHAR *Prefix) {
|
||||
DWORD LastError = GetLastError();
|
||||
LogError(Prefix, LastError);
|
||||
SetLastError(LastError);
|
||||
return LastError;
|
||||
}
|
||||
|
||||
static void Log(_In_ WIREGUARD_LOGGER_LEVEL Level, _In_z_ const WCHAR *Format, ...) {
|
||||
WCHAR LogLine[0x200];
|
||||
va_list args;
|
||||
va_start(args, Format);
|
||||
_vsnwprintf_s(LogLine, _countof(LogLine), _TRUNCATE, Format, args);
|
||||
va_end(args);
|
||||
ConsoleLogger(Level, Now(), LogLine);
|
||||
}
|
||||
#endif
|
||||
|
||||
_Must_inspect_result_ _Return_type_success_(return != FALSE) static BOOL
|
||||
GenerateKeyPair(_Out_writes_bytes_all_(WIREGUARD_KEY_LENGTH) BYTE PublicKey[WIREGUARD_KEY_LENGTH],
|
||||
_Out_writes_bytes_all_(WIREGUARD_KEY_LENGTH) BYTE PrivateKey[WIREGUARD_KEY_LENGTH]) {
|
||||
BCRYPT_ALG_HANDLE Algorithm;
|
||||
BCRYPT_KEY_HANDLE Key;
|
||||
NTSTATUS Status;
|
||||
|
||||
struct {
|
||||
BCRYPT_ECCKEY_BLOB Header;
|
||||
BYTE Public[32];
|
||||
BYTE Unused[32];
|
||||
BYTE Private[32];
|
||||
} ExportedKey;
|
||||
|
||||
ULONG Bytes;
|
||||
|
||||
Status = BCryptOpenAlgorithmProvider(&Algorithm, BCRYPT_ECDH_ALGORITHM, nullptr, 0);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
Status = BCryptSetProperty(Algorithm,
|
||||
BCRYPT_ECC_CURVE_NAME,
|
||||
(PUCHAR)BCRYPT_ECC_CURVE_25519,
|
||||
sizeof(BCRYPT_ECC_CURVE_25519),
|
||||
0);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
goto cleanupProvider;
|
||||
}
|
||||
|
||||
Status = BCryptGenerateKeyPair(Algorithm, &Key, 255, 0);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
goto cleanupProvider;
|
||||
}
|
||||
|
||||
Status = BCryptFinalizeKeyPair(Key, 0);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
goto cleanupKey;
|
||||
}
|
||||
|
||||
Status = BCryptExportKey(Key,
|
||||
nullptr,
|
||||
BCRYPT_ECCPRIVATE_BLOB,
|
||||
(PUCHAR)&ExportedKey,
|
||||
sizeof(ExportedKey),
|
||||
&Bytes,
|
||||
0);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
goto cleanupKey;
|
||||
}
|
||||
|
||||
memcpy(PublicKey, ExportedKey.Public, WIREGUARD_KEY_LENGTH);
|
||||
memcpy(PrivateKey, ExportedKey.Private, WIREGUARD_KEY_LENGTH);
|
||||
SecureZeroMemory(&ExportedKey, sizeof(ExportedKey));
|
||||
|
||||
cleanupKey:
|
||||
BCryptDestroyKey(Key);
|
||||
cleanupProvider:
|
||||
BCryptCloseAlgorithmProvider(Algorithm, 0);
|
||||
out:
|
||||
SetLastError(RtlNtStatusToDosError(Status));
|
||||
return NT_SUCCESS(Status);
|
||||
}
|
||||
|
||||
static HANDLE QuitEvent;
|
||||
|
||||
//static BOOL WINAPI CtrlHandler(_In_ DWORD CtrlType) {
|
||||
// switch (CtrlType) {
|
||||
// case CTRL_C_EVENT:
|
||||
// case CTRL_BREAK_EVENT:
|
||||
// case CTRL_CLOSE_EVENT:
|
||||
// case CTRL_LOGOFF_EVENT:
|
||||
// case CTRL_SHUTDOWN_EVENT:
|
||||
// SPDLOG_INFO("Cleaning up and shutting down");
|
||||
// SetEvent(QuitEvent);
|
||||
// return TRUE;
|
||||
// }
|
||||
// return FALSE;
|
||||
//}
|
||||
|
||||
static BOOL GetEndPoint(const TCHAR *Input, _Out_ SOCKADDR_INET *ResolvedDemoServer) {
|
||||
SOCKET Socket = INVALID_SOCKET;
|
||||
TCHAR name[MAX_PATH];
|
||||
ADDRINFOA Hints = {};
|
||||
ADDRINFOA *Resolution;
|
||||
|
||||
StringCbCopy(name, MAX_PATH, Input);
|
||||
TCHAR *Colon1 = strchr(name, ':');
|
||||
*Colon1 = '\0';
|
||||
|
||||
Hints.ai_family = AF_UNSPEC;
|
||||
Hints.ai_socktype = SOCK_STREAM;
|
||||
Hints.ai_protocol = IPPROTO_TCP;
|
||||
|
||||
if (GetAddrInfo(name, Colon1 + 1, &Hints, &Resolution)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for (const ADDRINFOA *Candidate = Resolution; Candidate; Candidate = Candidate->ai_next) {
|
||||
UINT16 port;
|
||||
if (Candidate->ai_family != AF_INET && Candidate->ai_family != AF_INET6) {
|
||||
continue;
|
||||
}
|
||||
memcpy(ResolvedDemoServer, Candidate->ai_addr, Candidate->ai_addrlen);
|
||||
port = static_cast<UINT16>(strtoul(Colon1 + 1, nullptr, 10));
|
||||
|
||||
if (ResolvedDemoServer->si_family == AF_INET) {
|
||||
ResolvedDemoServer->Ipv4.sin_port = htons(port);
|
||||
} else if (ResolvedDemoServer->si_family == AF_INET6) {
|
||||
ResolvedDemoServer->Ipv6.sin6_port = htons(port);
|
||||
}
|
||||
|
||||
closesocket(Socket);
|
||||
FreeAddrInfo(Resolution);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
closesocket(Socket);
|
||||
FreeAddrInfo(Resolution);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
_Return_type_success_(return != FALSE) static BOOL TalkToDemoServer(_In_reads_bytes_(InputLength) const CHAR *Input,
|
||||
_In_ DWORD InputLength,
|
||||
_Out_writes_bytes_(*OutputLength) CHAR *Output,
|
||||
_Inout_ DWORD *OutputLength,
|
||||
_Out_ SOCKADDR_INET *ResolvedDemoServer) {
|
||||
SOCKET Socket = INVALID_SOCKET;
|
||||
ADDRINFOW Hints = {};
|
||||
ADDRINFOW *Resolution;
|
||||
BOOL Ret = FALSE;
|
||||
|
||||
Hints.ai_family = AF_UNSPEC;
|
||||
Hints.ai_socktype = SOCK_STREAM;
|
||||
Hints.ai_protocol = IPPROTO_TCP;
|
||||
|
||||
if (GetAddrInfoW(L"demo.wireguard.com", L"42912", &Hints, &Resolution)) {
|
||||
return FALSE;
|
||||
}
|
||||
for (ADDRINFOW *Candidate = Resolution; Candidate; Candidate = Candidate->ai_next) {
|
||||
if (Candidate->ai_family != AF_INET && Candidate->ai_family != AF_INET6) {
|
||||
continue;
|
||||
}
|
||||
Socket = socket(Candidate->ai_family, Candidate->ai_socktype, Candidate->ai_protocol);
|
||||
if (Socket == INVALID_SOCKET) {
|
||||
goto cleanupResolution;
|
||||
}
|
||||
if (connect(Socket, Candidate->ai_addr, (int)Candidate->ai_addrlen) == SOCKET_ERROR) {
|
||||
closesocket(Socket);
|
||||
Socket = INVALID_SOCKET;
|
||||
}
|
||||
memcpy(ResolvedDemoServer, Candidate->ai_addr, Candidate->ai_addrlen);
|
||||
break;
|
||||
}
|
||||
if (Socket == INVALID_SOCKET) {
|
||||
goto cleanupResolution;
|
||||
}
|
||||
if (send(Socket, Input, InputLength, 0) == SOCKET_ERROR) {
|
||||
goto cleanupSocket;
|
||||
}
|
||||
if ((*OutputLength = recv(Socket, Output, *OutputLength, 0)) == SOCKET_ERROR) {
|
||||
goto cleanupSocket;
|
||||
}
|
||||
Ret = TRUE;
|
||||
cleanupSocket:
|
||||
closesocket(Socket);
|
||||
cleanupResolution:
|
||||
FreeAddrInfoW(Resolution);
|
||||
return Ret;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
WIREGUARD_INTERFACE Interface;
|
||||
WIREGUARD_PEER RemoteServer;
|
||||
WIREGUARD_ALLOWED_IP AllV4;
|
||||
WIREGUARD_ALLOWED_IP AllV4_2;
|
||||
} WG_CONFIG_INFO;
|
||||
|
||||
int main_wireguard_getinfo() {
|
||||
DWORD Bytes;
|
||||
WG_CONFIG_INFO Config {};
|
||||
HMODULE WireGuard = InitializeWireGuardNT();
|
||||
if (!WireGuard) {
|
||||
SPDLOG_ERROR("Failed to initialize WireGuardNT: {0}", GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* CryptStringToBinary(TEXT("WGAlqvys3O83VmWug6Z8NzUrxGr/PNHSeOVFnKLSe2k="),
|
||||
0,
|
||||
CRYPT_STRING_BASE64,
|
||||
Config.Interface.PublicKey,
|
||||
&Bytes,
|
||||
nullptr,
|
||||
nullptr);*/
|
||||
|
||||
WIREGUARD_ADAPTER_HANDLE Adapter = WireGuardOpenAdapter(L"admin");
|
||||
|
||||
if (!Adapter) {
|
||||
SPDLOG_ERROR("Failed to create adapter: {0}", GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
Bytes = sizeof(Config);
|
||||
if (!WireGuardGetConfiguration(Adapter, &Config.Interface, &Bytes)) {
|
||||
SPDLOG_ERROR("Failed to get configuration: {0}", GetLastError());
|
||||
//WireGuardCloseAdapter(Adapter);
|
||||
return -3;
|
||||
}
|
||||
|
||||
//WireGuardCloseAdapter(Adapter);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main_wireguard(bool isDelete) {
|
||||
WG_CONFIG_INFO Config {};
|
||||
DWORD LastError;
|
||||
WSADATA WsaData;
|
||||
MIB_IPINTERFACE_ROW IpInterface = {};
|
||||
DWORD Bytes;
|
||||
MIB_UNICASTIPADDRESS_ROW AddressRow;
|
||||
GUID ExampleGuid = {
|
||||
0xdeadc001,
|
||||
0xbeef,
|
||||
0xbabe,
|
||||
{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}
|
||||
};
|
||||
WIREGUARD_ADAPTER_HANDLE Adapter;
|
||||
DWORD Version;
|
||||
|
||||
if (WSAStartup(MAKEWORD(2, 2), &WsaData)) {
|
||||
SPDLOG_ERROR("Failed to initialize Winsock: {0}", GetLastError());
|
||||
return -1;
|
||||
}
|
||||
HMODULE WireGuard = InitializeWireGuardNT();
|
||||
if (!WireGuard) {
|
||||
SPDLOG_ERROR("Failed to initialize WireGuardNT: {0}", GetLastError());
|
||||
return -2;
|
||||
}
|
||||
|
||||
SPDLOG_INFO("WireGuardNT library loaded");
|
||||
|
||||
// 配置本地隧道接口
|
||||
Config.Interface.Flags = WIREGUARD_INTERFACE_HAS_PRIVATE_KEY;
|
||||
Config.Interface.PeersCount = 1;
|
||||
CryptStringToBinary(TEXT("WGAlqvys3O83VmWug6Z8NzUrxGr/PNHSeOVFnKLSe2k="),
|
||||
0,
|
||||
CRYPT_STRING_BASE64,
|
||||
Config.Interface.PrivateKey,
|
||||
&Bytes,
|
||||
nullptr,
|
||||
nullptr);
|
||||
|
||||
// 配置远程隧道接口
|
||||
Config.RemoteServer.Flags = static_cast<WIREGUARD_PEER_FLAG>(
|
||||
WIREGUARD_PEER_HAS_PUBLIC_KEY | WIREGUARD_PEER_HAS_PERSISTENT_KEEPALIVE | WIREGUARD_PEER_HAS_ENDPOINT);
|
||||
Config.RemoteServer.AllowedIPsCount = 2;
|
||||
Config.RemoteServer.PersistentKeepalive = 30;
|
||||
CryptStringToBinary(TEXT("q3ep8hN2v3VpHbcru+rTmvyBt13iH0DkEsVAyT2LpVo="),
|
||||
0,
|
||||
CRYPT_STRING_BASE64,
|
||||
Config.RemoteServer.PublicKey,
|
||||
&Bytes,
|
||||
nullptr,
|
||||
nullptr);
|
||||
|
||||
if (!GetEndPoint(TEXT("efc.xajhuang.com:10000"), &Config.RemoteServer.Endpoint)) {
|
||||
SPDLOG_ERROR("Failed to talk to demo server: {0}", GetLastError());
|
||||
goto cleanupWireGuard;
|
||||
}
|
||||
|
||||
Config.AllV4.AddressFamily = AF_INET;
|
||||
Config.AllV4.Cidr = 24;
|
||||
InetPtonA(AF_INET, TEXT("10.10.10.0"), &Config.AllV4.Address.V4.S_un.S_addr);
|
||||
|
||||
Config.AllV4_2.AddressFamily = AF_INET;
|
||||
Config.AllV4_2.Cidr = 24;
|
||||
InetPtonA(AF_INET, TEXT("192.168.100.0"), &Config.AllV4.Address.V4.S_un.S_addr);
|
||||
|
||||
InitializeUnicastIpAddressEntry(&AddressRow);
|
||||
AddressRow.Address.Ipv4.sin_family = AF_INET;
|
||||
AddressRow.OnLinkPrefixLength = 24; /* This is a /24 network */
|
||||
AddressRow.DadState = IpDadStatePreferred;
|
||||
InetPtonA(AF_INET, TEXT("10.10.10.1"), &AddressRow.Address.Ipv4.sin_addr);
|
||||
|
||||
#if 0
|
||||
Log(WIREGUARD_LOG_INFO, L"Generating keypair");
|
||||
if (!GenerateKeyPair(PublicKey, Config.Interface.PrivateKey)) {
|
||||
LastError = LogError(L"Failed to generate keypair", GetLastError());
|
||||
goto cleanupWireGuard;
|
||||
}
|
||||
|
||||
Bytes = sizeof(PublicKeyString);
|
||||
CryptBinaryToStringA(PublicKey,
|
||||
sizeof(PublicKey),
|
||||
CRYPT_STRING_BASE64 | CRYPT_STRING_NOCR,
|
||||
PublicKeyString,
|
||||
&Bytes);
|
||||
|
||||
Log(WIREGUARD_LOG_INFO, L"Talking to demo server");
|
||||
Bytes = sizeof(ServerResponse) - 1;
|
||||
if (!TalkToDemoServer(PublicKeyString,
|
||||
(DWORD)strlen(PublicKeyString),
|
||||
ServerResponse,
|
||||
&Bytes,
|
||||
&Config.RemoteServer.Endpoint)) {
|
||||
LastError = LogError(L"Failed to talk to demo server", GetLastError());
|
||||
goto cleanupWireGuard;
|
||||
}
|
||||
|
||||
Colon1 = strchr(ServerResponse, ':');
|
||||
Colon2 = Colon1 ? strchr(Colon1 + 1, ':') : nullptr;
|
||||
Colon3 = Colon2 ? strchr(Colon2 + 1, ':') : nullptr;
|
||||
|
||||
if (!Colon1 || !Colon2 || !Colon3) {
|
||||
LastError = LogError(L"Failed to parse demo server response", ERROR_UNDEFINED_CHARACTER);
|
||||
goto cleanupWireGuard;
|
||||
}
|
||||
if (Bytes && ServerResponse[--Bytes] == '\n') {
|
||||
ServerResponse[Bytes] = '\0';
|
||||
}
|
||||
*Colon1 = *Colon2 = *Colon3 = '\0';
|
||||
|
||||
|
||||
Bytes = sizeof(Config.RemoteServer.PublicKey);
|
||||
if (strcmp(ServerResponse, "OK") || != 1 ||
|
||||
!CryptStringToBinaryA(Colon1 + 1,
|
||||
0,
|
||||
CRYPT_STRING_BASE64,
|
||||
Config.RemoteServer.PublicKey,
|
||||
&Bytes,
|
||||
nullptr,
|
||||
nullptr)) {
|
||||
LastError = LogError(L"Failed to parse demo server response", ERROR_UNDEFINED_CHARACTER);
|
||||
goto cleanupWireGuard;
|
||||
}
|
||||
if (Config.RemoteServer.Endpoint.si_family == AF_INET) {
|
||||
Config.RemoteServer.Endpoint.Ipv4.sin_port = htons((u_short)atoi(Colon2 + 1));
|
||||
} else if (Config.RemoteServer.Endpoint.si_family == AF_INET6) {
|
||||
Config.RemoteServer.Endpoint.Ipv6.sin6_port = htons((u_short)atoi(Colon2 + 1));
|
||||
}
|
||||
#endif
|
||||
|
||||
QuitEvent = CreateEventW(nullptr, TRUE, FALSE, nullptr);
|
||||
if (!QuitEvent) {
|
||||
SPDLOG_ERROR("Failed to create event:{0}", GetLastError());
|
||||
goto cleanupWireGuard;
|
||||
}
|
||||
//if (!SetConsoleCtrlHandler(CtrlHandler, TRUE)) {
|
||||
// SPDLOG_ERROR("Failed to set console handler: {0}", GetLastError());
|
||||
// goto cleanupQuit;
|
||||
//}
|
||||
|
||||
Adapter = WireGuardOpenAdapter(L"Demo");
|
||||
|
||||
if (isDelete) {
|
||||
SPDLOG_INFO("Remove adapter: {0}", "Demo");
|
||||
WireGuardCloseAdapter(Adapter);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!Adapter) {
|
||||
Adapter = WireGuardCreateAdapter(L"Demo", L"Example", &ExampleGuid);
|
||||
if (!Adapter) {
|
||||
SPDLOG_ERROR("Failed to create adapter: {0}", LastError);
|
||||
goto cleanupQuit;
|
||||
}
|
||||
}
|
||||
|
||||
if (!WireGuardSetAdapterLogging(Adapter, WIREGUARD_ADAPTER_LOG_ON)) {
|
||||
SPDLOG_ERROR("Failed to enable adapter logging: {0}", GetLastError());
|
||||
}
|
||||
|
||||
Version = WireGuardGetRunningDriverVersion();
|
||||
SPDLOG_INFO("WireGuardNT v{0}.{1} loaded", (Version >> 16) & 0xff, (Version >> 0) & 0xff);
|
||||
|
||||
WireGuardGetAdapterLUID(Adapter, &AddressRow.InterfaceLuid);
|
||||
|
||||
SetInterfaceIpAddress("Demo", "10.10.10.1", "255.255.255.0");
|
||||
|
||||
#if 0
|
||||
InitializeIpForwardEntry(&DefaultRoute);
|
||||
DefaultRoute.InterfaceLuid = AddressRow.InterfaceLuid;
|
||||
DefaultRoute.DestinationPrefix.Prefix.si_family = AF_INET;
|
||||
DefaultRoute.NextHop.si_family = AF_INET;
|
||||
DefaultRoute.Metric = 0;
|
||||
LastError = CreateIpForwardEntry2(&DefaultRoute);
|
||||
if (LastError != ERROR_SUCCESS && LastError != ERROR_OBJECT_ALREADY_EXISTS) {
|
||||
SPDLOG_ERROR("Failed to set default route: {0}", LastError);
|
||||
goto cleanupAdapter;
|
||||
}
|
||||
LastError = CreateUnicastIpAddressEntry(&AddressRow);
|
||||
if (LastError != ERROR_SUCCESS && LastError != ERROR_OBJECT_ALREADY_EXISTS) {
|
||||
SPDLOG_ERROR("Failed to set IP address: {0}", LastError);
|
||||
goto cleanupAdapter;
|
||||
}
|
||||
#endif
|
||||
#if 1
|
||||
InitializeIpInterfaceEntry(&IpInterface);
|
||||
IpInterface.InterfaceLuid = AddressRow.InterfaceLuid;
|
||||
IpInterface.Family = AF_INET;
|
||||
LastError = GetIpInterfaceEntry(&IpInterface);
|
||||
if (LastError != ERROR_SUCCESS) {
|
||||
SPDLOG_ERROR("Failed to get IP interface: {0}", LastError);
|
||||
goto cleanupAdapter;
|
||||
}
|
||||
|
||||
/*if ((LastError = AddIpAddress(IpInterface.InterfaceIndex)) != 0) {
|
||||
SPDLOG_ERROR("Set interface IP Error: {0}", LastError);
|
||||
goto cleanupAdapter;
|
||||
}*/
|
||||
|
||||
IpInterface.UseAutomaticMetric = FALSE;
|
||||
IpInterface.Metric = 0;
|
||||
IpInterface.NlMtu = 1420;
|
||||
IpInterface.SitePrefixLength = 0;
|
||||
LastError = SetIpInterfaceEntry(&IpInterface);
|
||||
if (LastError != ERROR_SUCCESS) {
|
||||
SPDLOG_ERROR("Failed to set metric and MTU: {0}", LastError);
|
||||
goto cleanupAdapter;
|
||||
}
|
||||
#endif
|
||||
|
||||
SPDLOG_INFO("Setting configuration and adapter up");
|
||||
if (!WireGuardSetConfiguration(Adapter, &Config.Interface, sizeof(Config)) ||
|
||||
!WireGuardSetAdapterState(Adapter, WIREGUARD_ADAPTER_STATE_UP)) {
|
||||
SPDLOG_ERROR("Failed to set configuration and adapter up: {0}", GetLastError());
|
||||
goto cleanupAdapter;
|
||||
}
|
||||
|
||||
do {
|
||||
Bytes = sizeof(Config);
|
||||
if (!WireGuardGetConfiguration(Adapter, &Config.Interface, &Bytes) || !Config.Interface.PeersCount) {
|
||||
SPDLOG_ERROR("Failed to get configuration: {0}", GetLastError());
|
||||
goto cleanupAdapter;
|
||||
}
|
||||
DWORD64 Timestamp = Now();
|
||||
SYSTEMTIME SystemTime;
|
||||
FileTimeToSystemTime((FILETIME *)&Timestamp, &SystemTime);
|
||||
fwprintf(stderr,
|
||||
L"%04u-%02u-%02u %02u:%02u:%02u.%04u [#] RX: %llu, TX: %llu\r",
|
||||
SystemTime.wYear,
|
||||
SystemTime.wMonth,
|
||||
SystemTime.wDay,
|
||||
SystemTime.wHour,
|
||||
SystemTime.wMinute,
|
||||
SystemTime.wSecond,
|
||||
SystemTime.wMilliseconds,
|
||||
Config.RemoteServer.RxBytes,
|
||||
Config.RemoteServer.TxBytes);
|
||||
} while (WaitForSingleObject(QuitEvent, 1000) == WAIT_TIMEOUT);
|
||||
|
||||
cleanupAdapter:
|
||||
WireGuardCloseAdapter(Adapter);
|
||||
cleanupQuit:
|
||||
//SetConsoleCtrlHandler(CtrlHandler, FALSE);
|
||||
CloseHandle(QuitEvent);
|
||||
cleanupWireGuard:
|
||||
FreeLibrary(WireGuard);
|
||||
cleanupWinsock:
|
||||
WSACleanup();
|
||||
return 0;
|
||||
}
|
|
@ -3,4 +3,7 @@ int ShowRouteTable();
|
|||
int NetShare();
|
||||
int GetInterface();
|
||||
void CryptoExample();
|
||||
int SetRouteTable();
|
||||
int SetRouteTable();
|
||||
int main_wireguard(bool isDelete);
|
||||
int main_wireguard_getinfo();
|
||||
int net_nat();
|
|
@ -0,0 +1,308 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR MIT
|
||||
*
|
||||
* Copyright (C) 2018-2021 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#include <ipexport.h>
|
||||
#include <ifdef.h>
|
||||
#include <ws2ipdef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef ALIGNED
|
||||
# if defined(_MSC_VER)
|
||||
# define ALIGNED(n) __declspec(align(n))
|
||||
# elif defined(__GNUC__)
|
||||
# define ALIGNED(n) __attribute__((aligned(n)))
|
||||
# else
|
||||
# error "Unable to define ALIGNED"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* MinGW is missing this one, unfortunately. */
|
||||
#ifndef _Post_maybenull_
|
||||
# define _Post_maybenull_
|
||||
#endif
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4324) /* structure was padded due to alignment specifier */
|
||||
|
||||
/**
|
||||
* A handle representing WireGuard adapter
|
||||
*/
|
||||
typedef struct _WIREGUARD_ADAPTER *WIREGUARD_ADAPTER_HANDLE;
|
||||
|
||||
/**
|
||||
* Creates a new WireGuard adapter.
|
||||
*
|
||||
* @param Name The requested name of the adapter. Zero-terminated string of up to MAX_ADAPTER_NAME-1
|
||||
* characters.
|
||||
*
|
||||
* @param TunnelType Name of the adapter tunnel type. Zero-terminated string of up to MAX_ADAPTER_NAME-1
|
||||
* characters.
|
||||
*
|
||||
* @param RequestedGUID The GUID of the created network adapter, which then influences NLA generation deterministically.
|
||||
* If it is set to NULL, the GUID is chosen by the system at random, and hence a new NLA entry is
|
||||
* created for each new adapter. It is called "requested" GUID because the API it uses is
|
||||
* completely undocumented, and so there could be minor interesting complications with its usage.
|
||||
*
|
||||
* @return If the function succeeds, the return value is the adapter handle. Must be released with
|
||||
* WireGuardCloseAdapter. If the function fails, the return value is NULL. To get extended error information, call
|
||||
* GetLastError.
|
||||
*/
|
||||
typedef _Must_inspect_result_
|
||||
_Return_type_success_(return != NULL)
|
||||
_Post_maybenull_
|
||||
WIREGUARD_ADAPTER_HANDLE(WINAPI WIREGUARD_CREATE_ADAPTER_FUNC)
|
||||
(_In_z_ LPCWSTR Name, _In_z_ LPCWSTR TunnelType, _In_opt_ const GUID *RequestedGUID);
|
||||
|
||||
/**
|
||||
* Opens an existing WireGuard adapter.
|
||||
*
|
||||
* @param Name The requested name of the adapter. Zero-terminated string of up to MAX_ADAPTER_NAME-1
|
||||
* characters.
|
||||
*
|
||||
* @return If the function succeeds, the return value is the adapter handle. Must be released with
|
||||
* WireGuardCloseAdapter. If the function fails, the return value is NULL. To get extended error information, call
|
||||
* GetLastError.
|
||||
*/
|
||||
typedef _Must_inspect_result_
|
||||
_Return_type_success_(return != NULL)
|
||||
_Post_maybenull_
|
||||
WIREGUARD_ADAPTER_HANDLE(WINAPI WIREGUARD_OPEN_ADAPTER_FUNC)(_In_z_ LPCWSTR Name);
|
||||
|
||||
/**
|
||||
* Releases WireGuard adapter resources and, if adapter was created with WireGuardCreateAdapter, removes adapter.
|
||||
*
|
||||
* @param Adapter Adapter handle obtained with WireGuardCreateAdapter or WireGuardOpenAdapter.
|
||||
*/
|
||||
typedef VOID(WINAPI WIREGUARD_CLOSE_ADAPTER_FUNC)(_In_opt_ WIREGUARD_ADAPTER_HANDLE Adapter);
|
||||
|
||||
/**
|
||||
* Deletes the WireGuard driver if there are no more adapters in use.
|
||||
*
|
||||
* @return If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To
|
||||
* get extended error information, call GetLastError.
|
||||
*/
|
||||
typedef _Return_type_success_(return != FALSE)
|
||||
BOOL(WINAPI WIREGUARD_DELETE_DRIVER_FUNC)(VOID);
|
||||
|
||||
/**
|
||||
* Returns the LUID of the adapter.
|
||||
*
|
||||
* @param Adapter Adapter handle obtained with WireGuardCreateAdapter or WireGuardOpenAdapter
|
||||
*
|
||||
* @param Luid Pointer to LUID to receive adapter LUID.
|
||||
*/
|
||||
typedef VOID(WINAPI WIREGUARD_GET_ADAPTER_LUID_FUNC)(_In_ WIREGUARD_ADAPTER_HANDLE Adapter, _Out_ NET_LUID *Luid);
|
||||
|
||||
/**
|
||||
* Determines the version of the WireGuard driver currently loaded.
|
||||
*
|
||||
* @return If the function succeeds, the return value is the version number. If the function fails, the return value is
|
||||
* zero. To get extended error information, call GetLastError. Possible errors include the following:
|
||||
* ERROR_FILE_NOT_FOUND WireGuard not loaded
|
||||
*/
|
||||
typedef _Return_type_success_(return != 0)
|
||||
DWORD(WINAPI WIREGUARD_GET_RUNNING_DRIVER_VERSION_FUNC)(VOID);
|
||||
|
||||
/**
|
||||
* Determines the level of logging, passed to WIREGUARD_LOGGER_CALLBACK.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
WIREGUARD_LOG_INFO, /**< Informational */
|
||||
WIREGUARD_LOG_WARN, /**< Warning */
|
||||
WIREGUARD_LOG_ERR /**< Error */
|
||||
} WIREGUARD_LOGGER_LEVEL;
|
||||
|
||||
/**
|
||||
* Called by internal logger to report diagnostic messages
|
||||
*
|
||||
* @param Level Message level.
|
||||
*
|
||||
* @param Timestamp Message timestamp in in 100ns intervals since 1601-01-01 UTC.
|
||||
*
|
||||
* @param Message Message text.
|
||||
*/
|
||||
typedef VOID(CALLBACK *WIREGUARD_LOGGER_CALLBACK)(
|
||||
_In_ WIREGUARD_LOGGER_LEVEL Level,
|
||||
_In_ DWORD64 Timestamp,
|
||||
_In_z_ LPCWSTR Message);
|
||||
|
||||
/**
|
||||
* Sets logger callback function.
|
||||
*
|
||||
* @param NewLogger Pointer to callback function to use as a new global logger. NewLogger may be called from various
|
||||
* threads concurrently. Should the logging require serialization, you must handle serialization in
|
||||
* NewLogger. Set to NULL to disable.
|
||||
*/
|
||||
typedef VOID(WINAPI WIREGUARD_SET_LOGGER_FUNC)(_In_ WIREGUARD_LOGGER_CALLBACK NewLogger);
|
||||
|
||||
/**
|
||||
* Whether and how logs from the driver are collected for the callback function.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
WIREGUARD_ADAPTER_LOG_OFF, /**< No logs are generated from the driver. */
|
||||
WIREGUARD_ADAPTER_LOG_ON, /**< Logs are generated from the driver. */
|
||||
WIREGUARD_ADAPTER_LOG_ON_WITH_PREFIX /**< Logs are generated from the driver, index-prefixed. */
|
||||
} WIREGUARD_ADAPTER_LOG_STATE;
|
||||
|
||||
/**
|
||||
* Sets whether and how the adapter logs to the logger previously set up with WireGuardSetLogger.
|
||||
*
|
||||
* @param Adapter Adapter handle obtained with WireGuardCreateAdapter or WireGuardOpenAdapter
|
||||
*
|
||||
* @param LogState Adapter logging state.
|
||||
*
|
||||
* @return If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To
|
||||
* get extended error information, call GetLastError.
|
||||
*/
|
||||
typedef _Return_type_success_(return != FALSE)
|
||||
BOOL(WINAPI WIREGUARD_SET_ADAPTER_LOGGING_FUNC)
|
||||
(_In_ WIREGUARD_ADAPTER_HANDLE Adapter, _In_ WIREGUARD_ADAPTER_LOG_STATE LogState);
|
||||
|
||||
/**
|
||||
* Determines the state of the adapter.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
WIREGUARD_ADAPTER_STATE_DOWN, /**< Down */
|
||||
WIREGUARD_ADAPTER_STATE_UP, /**< Up */
|
||||
} WIREGUARD_ADAPTER_STATE;
|
||||
|
||||
/**
|
||||
* Sets the adapter state of the WireGuard adapter. Note: sockets are owned by the process that sets the state to up.
|
||||
*
|
||||
* @param Adapter Adapter handle obtained with WireGuardCreateAdapter or WireGuardOpenAdapter
|
||||
*
|
||||
* @param State Adapter state.
|
||||
*
|
||||
* @return If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To
|
||||
* get extended error information, call GetLastError.
|
||||
*/
|
||||
typedef _Return_type_success_(return != FALSE)
|
||||
BOOL(WINAPI WIREGUARD_SET_ADAPTER_STATE_FUNC)
|
||||
(_In_ WIREGUARD_ADAPTER_HANDLE Adapter, _In_ WIREGUARD_ADAPTER_STATE State);
|
||||
|
||||
/**
|
||||
* Gets the adapter state of the WireGuard adapter.
|
||||
*
|
||||
* @param Adapter Adapter handle obtained with WireGuardCreateAdapter or WireGuardOpenAdapter
|
||||
*
|
||||
* @param State Pointer to adapter state.
|
||||
*
|
||||
* @return If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To
|
||||
* get extended error information, call GetLastError.
|
||||
*/
|
||||
typedef _Must_inspect_result_
|
||||
_Return_type_success_(return != FALSE)
|
||||
BOOL(WINAPI WIREGUARD_GET_ADAPTER_STATE_FUNC)
|
||||
(_In_ WIREGUARD_ADAPTER_HANDLE Adapter, _Out_ WIREGUARD_ADAPTER_STATE *State);
|
||||
|
||||
#define WIREGUARD_KEY_LENGTH 32
|
||||
|
||||
typedef struct _WIREGUARD_ALLOWED_IP WIREGUARD_ALLOWED_IP;
|
||||
struct ALIGNED(8) _WIREGUARD_ALLOWED_IP
|
||||
{
|
||||
union
|
||||
{
|
||||
IN_ADDR V4;
|
||||
IN6_ADDR V6;
|
||||
} Address; /**< IP address */
|
||||
ADDRESS_FAMILY AddressFamily; /**< Address family, either AF_INET or AF_INET6 */
|
||||
BYTE Cidr; /**< CIDR of allowed IPs */
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
WIREGUARD_PEER_HAS_PUBLIC_KEY = 1 << 0, /**< The PublicKey field is set */
|
||||
WIREGUARD_PEER_HAS_PRESHARED_KEY = 1 << 1, /**< The PresharedKey field is set */
|
||||
WIREGUARD_PEER_HAS_PERSISTENT_KEEPALIVE = 1 << 2, /**< The PersistentKeepAlive field is set */
|
||||
WIREGUARD_PEER_HAS_ENDPOINT = 1 << 3, /**< The Endpoint field is set */
|
||||
WIREGUARD_PEER_REPLACE_ALLOWED_IPS = 1 << 5, /**< Remove all allowed IPs before adding new ones */
|
||||
WIREGUARD_PEER_REMOVE = 1 << 6, /**< Remove specified peer */
|
||||
WIREGUARD_PEER_UPDATE = 1 << 7 /**< Do not add a new peer */
|
||||
} WIREGUARD_PEER_FLAG;
|
||||
|
||||
typedef struct _WIREGUARD_PEER WIREGUARD_PEER;
|
||||
struct ALIGNED(8) _WIREGUARD_PEER
|
||||
{
|
||||
WIREGUARD_PEER_FLAG Flags; /**< Bitwise combination of flags */
|
||||
DWORD Reserved; /**< Reserved; must be zero */
|
||||
BYTE PublicKey[WIREGUARD_KEY_LENGTH]; /**< Public key, the peer's primary identifier */
|
||||
BYTE PresharedKey[WIREGUARD_KEY_LENGTH]; /**< Preshared key for additional layer of post-quantum resistance */
|
||||
WORD PersistentKeepalive; /**< Seconds interval, or 0 to disable */
|
||||
SOCKADDR_INET Endpoint; /**< Endpoint, with IP address and UDP port number*/
|
||||
DWORD64 TxBytes; /**< Number of bytes transmitted */
|
||||
DWORD64 RxBytes; /**< Number of bytes received */
|
||||
DWORD64 LastHandshake; /**< Time of the last handshake, in 100ns intervals since 1601-01-01 UTC */
|
||||
DWORD AllowedIPsCount; /**< Number of allowed IP structs following this struct */
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
WIREGUARD_INTERFACE_HAS_PUBLIC_KEY = (1 << 0), /**< The PublicKey field is set */
|
||||
WIREGUARD_INTERFACE_HAS_PRIVATE_KEY = (1 << 1), /**< The PrivateKey field is set */
|
||||
WIREGUARD_INTERFACE_HAS_LISTEN_PORT = (1 << 2), /**< The ListenPort field is set */
|
||||
WIREGUARD_INTERFACE_REPLACE_PEERS = (1 << 3) /**< Remove all peers before adding new ones */
|
||||
} WIREGUARD_INTERFACE_FLAG;
|
||||
|
||||
typedef struct _WIREGUARD_INTERFACE WIREGUARD_INTERFACE;
|
||||
struct ALIGNED(8) _WIREGUARD_INTERFACE
|
||||
{
|
||||
WIREGUARD_INTERFACE_FLAG Flags; /**< Bitwise combination of flags */
|
||||
WORD ListenPort; /**< Port for UDP listen socket, or 0 to choose randomly */
|
||||
BYTE PrivateKey[WIREGUARD_KEY_LENGTH]; /**< Private key of interface */
|
||||
BYTE PublicKey[WIREGUARD_KEY_LENGTH]; /**< Corresponding public key of private key */
|
||||
DWORD PeersCount; /**< Number of peer structs following this struct */
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the configuration of the WireGuard adapter.
|
||||
*
|
||||
* @param Adapter Adapter handle obtained with WireGuardCreateAdapter or WireGuardOpenAdapter
|
||||
*
|
||||
* @param Config Configuration for the adapter.
|
||||
*
|
||||
* @param Bytes Number of bytes in Config allocation.
|
||||
*
|
||||
* @return If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To
|
||||
* get extended error information, call GetLastError.
|
||||
*/
|
||||
typedef _Return_type_success_(return != FALSE)
|
||||
BOOL(WINAPI WIREGUARD_SET_CONFIGURATION_FUNC)
|
||||
(_In_ WIREGUARD_ADAPTER_HANDLE Adapter, _In_reads_bytes_(Bytes) const WIREGUARD_INTERFACE *Config, _In_ DWORD Bytes);
|
||||
|
||||
/**
|
||||
* Gets the configuration of the WireGuard adapter.
|
||||
*
|
||||
* @param Adapter Adapter handle obtained with WireGuardCreateAdapter or WireGuardOpenAdapter
|
||||
*
|
||||
* @param Config Configuration for the adapter.
|
||||
*
|
||||
* @param Bytes Pointer to number of bytes in Config allocation.
|
||||
*
|
||||
* @return If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To
|
||||
* get extended error information, call GetLastError, which if ERROR_MORE_DATA, Bytes is updated with the
|
||||
* required size.
|
||||
*/
|
||||
typedef _Must_inspect_result_
|
||||
_Return_type_success_(return != FALSE)
|
||||
BOOL(WINAPI WIREGUARD_GET_CONFIGURATION_FUNC)
|
||||
(_In_ WIREGUARD_ADAPTER_HANDLE Adapter,
|
||||
_Out_writes_bytes_all_(*Bytes) WIREGUARD_INTERFACE *Config,
|
||||
_Inout_ DWORD *Bytes);
|
||||
|
||||
#pragma warning(pop)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,120 @@
|
|||
// NetTunnelSvr.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
|
||||
//
|
||||
#include <Windows.h>
|
||||
#include <strsafe.h>
|
||||
#include <tchar.h>
|
||||
|
||||
#define WG_TUNNEL_SVR_NAME TEXT("WireGuard_DLL_SVR")
|
||||
|
||||
typedef BOOL(WINAPI WIREGUARD_TUNNEL_SERVICE_FUNC)(_In_z_ LPCWSTR Name);
|
||||
static WIREGUARD_TUNNEL_SERVICE_FUNC *WireGuardTunnelService;
|
||||
|
||||
static void LogToSystemEventLog(int wErrorType, int wCustumerCode, const TCHAR *szMsg) {
|
||||
HANDLE hEventSource;
|
||||
DWORD dwEventIdentifer;
|
||||
|
||||
switch (wErrorType) {
|
||||
case EVENTLOG_SUCCESS:
|
||||
case EVENTLOG_AUDIT_SUCCESS:
|
||||
dwEventIdentifer = 0x00;
|
||||
break;
|
||||
case EVENTLOG_INFORMATION_TYPE:
|
||||
dwEventIdentifer = 0x01;
|
||||
break;
|
||||
case EVENTLOG_WARNING_TYPE:
|
||||
dwEventIdentifer = 0x02;
|
||||
break;
|
||||
case EVENTLOG_ERROR_TYPE:
|
||||
case EVENTLOG_AUDIT_FAILURE:
|
||||
dwEventIdentifer = 0x03;
|
||||
break;
|
||||
default:
|
||||
dwEventIdentifer = 0;
|
||||
break;
|
||||
}
|
||||
// 移位获得Sev,前面给出的 wErrorType 为 EVENTLOG_ERROR_TYPE,对应着下图 “级别” 一列显示“错误”图标
|
||||
dwEventIdentifer <<= 30;
|
||||
dwEventIdentifer |= static_cast<WORD>(wCustumerCode); // 前面自定义了Code,对应着下图中 事件ID 20
|
||||
|
||||
hEventSource = RegisterEventSource(nullptr, WG_TUNNEL_SVR_NAME);
|
||||
|
||||
if (nullptr != hEventSource) {
|
||||
|
||||
LPCTSTR lpszStrings[2] = {
|
||||
WG_TUNNEL_SVR_NAME,
|
||||
szMsg}; //要写入日志的信息有两行,分别是 服务名,和前面给出的szMsg,对应着下图“以下是包含在事件中的信息”
|
||||
|
||||
ReportEvent(hEventSource, // event log handle
|
||||
wErrorType, // event type
|
||||
0, // event category
|
||||
dwEventIdentifer, // event identifier
|
||||
nullptr, // no security identifier
|
||||
2, // size of lpszStrings array
|
||||
0, // no binary data
|
||||
lpszStrings, // array of strings
|
||||
nullptr); // no binary data
|
||||
DeregisterEventSource(hEventSource);
|
||||
}
|
||||
}
|
||||
|
||||
static HMODULE InitializeWireGuardNT(void) {
|
||||
const HMODULE tunnel = LoadLibraryExW(L"tunnel.dll",
|
||||
nullptr,
|
||||
LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32);
|
||||
if (!tunnel) {
|
||||
TCHAR tMsg[MAX_PATH * sizeof(TCHAR)];
|
||||
StringCbPrintf(tMsg, MAX_PATH * sizeof(TCHAR), TEXT("LoadLibraryExW Error: %d\n"), GetLastError());
|
||||
LogToSystemEventLog(EVENTLOG_ERROR_TYPE, 0x01, tMsg);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#define X(Name) ((*(FARPROC *)&(Name) = GetProcAddress(tunnel, #Name)) == nullptr)
|
||||
if (X(WireGuardTunnelService))
|
||||
#undef X
|
||||
{
|
||||
const DWORD LastError = GetLastError();
|
||||
FreeLibrary(tunnel);
|
||||
SetLastError(LastError);
|
||||
return nullptr;
|
||||
}
|
||||
return tunnel;
|
||||
}
|
||||
|
||||
int _tmain(int wargc, _TCHAR *wargv[]) {
|
||||
TCHAR tMsg[MAX_PATH] = {};
|
||||
|
||||
if (wargc == 3 && !wcscmp(wargv[1], L"/service")) {
|
||||
BOOL ret;
|
||||
const HMODULE hModule = InitializeWireGuardNT();
|
||||
|
||||
if (!hModule || !WireGuardTunnelService) {
|
||||
StringCbPrintf(tMsg, MAX_PATH, TEXT("Init WireGuardTunnelService Service Error: %d\n"), GetLastError());
|
||||
LogToSystemEventLog(EVENTLOG_ERROR_TYPE, 0x01, tMsg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = WireGuardTunnelService(wargv[2]);
|
||||
|
||||
if (ret) {
|
||||
StringCbPrintf(tMsg, MAX_PATH, TEXT("Start WireGuardTunnelService Service Successed\n"));
|
||||
LogToSystemEventLog(EVENTLOG_INFORMATION_TYPE, 0x00, tMsg);
|
||||
} else {
|
||||
StringCbPrintf(tMsg, MAX_PATH, TEXT("Start WireGuardTunnelService Service failed: %d\n"), GetLastError());
|
||||
LogToSystemEventLog(EVENTLOG_ERROR_TYPE, 0x02, tMsg);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
|
||||
// 调试程序: F5 或调试 >“开始调试”菜单
|
||||
|
||||
// 入门使用技巧:
|
||||
// 1. 使用解决方案资源管理器窗口添加/管理文件
|
||||
// 2. 使用团队资源管理器窗口连接到源代码管理
|
||||
// 3. 使用输出窗口查看生成输出和其他消息
|
||||
// 4. 使用错误列表窗口查看错误
|
||||
// 5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目
|
||||
// 6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件
|
|
@ -0,0 +1,138 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{0a2eedaf-f4a8-41e0-a874-2f30d1eeb55e}</ProjectGuid>
|
||||
<RootNamespace>NetTunnelSvr</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>copy /y $(TargetDir)*.exe $(SolutionDir)\NetTunnelApp\bin\$(ConfigurationName)\</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="NetTunnelSvr.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="源文件">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="头文件">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="资源文件">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="NetTunnelSvr.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup />
|
||||
</Project>
|
|
@ -35,15 +35,7 @@ TEST_MODULE_CLEANUP(ModuleCleanup) {
|
|||
TEST_CLASS(TestNetTunnelSDK) {
|
||||
public:
|
||||
const int RET_OK = ERR_SUCCESS;
|
||||
|
||||
TEST_METHOD(TestFindWireguardExe) {
|
||||
Assert::AreEqual(RET_OK, FindWireguardExe(nullptr, 0));
|
||||
}
|
||||
|
||||
TEST_METHOD(TestSetWireguardPath) {
|
||||
Assert::AreEqual(RET_OK, SetWireguardPath(TEXT("C:\\Program Files\\WireGuard\\wireguard.exe")));
|
||||
}
|
||||
|
||||
|
||||
TEST_METHOD(TestRunPipeCmd) {
|
||||
#if 0
|
||||
TCHAR buf[1024];
|
||||
|
@ -208,8 +200,12 @@ public:
|
|||
Assert::IsNotNull(pCfg);
|
||||
|
||||
Assert::AreEqual(RET_OK, RemoteCtrlSvrCfgUserTunnel(2, TEXT("172.18.2.0/24")));
|
||||
|
||||
Assert::AreEqual(RET_OK, RemoteWireGuardControl(true));
|
||||
Assert::AreEqual(RET_OK, LocalWireGuardControl(true, true));
|
||||
|
||||
|
||||
Assert::AreEqual(RET_OK, RemoteWireGuardControl(false));
|
||||
Assert::AreEqual(RET_OK, LocalWireGuardControl(false, false));
|
||||
}
|
||||
};
|
||||
}
|
|
@ -7,6 +7,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NetTunnelSDK", "NetTunnelSD
|
|||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetTunnelApp", "NetTunnelApp\NetTunnelApp.csproj", "{79995848-FD05-46F5-A7FE-46265E540E32}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E} = {0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E}
|
||||
{1584BAD4-DBEC-43D2-BC06-08C23F02489A} = {1584BAD4-DBEC-43D2-BC06-08C23F02489A}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
|
@ -22,6 +23,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NetTunnelSDKTestApp", "NetT
|
|||
EndProject
|
||||
Project("{54435603-DBB4-11D2-8724-00A0C9A8B90C}") = "InstallTunnelSDK", "InstallTunnelSDK\InstallTunnelSDK.vdproj", "{FE91D4D0-29A6-4C58-874F-11F6AC1D50CD}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NetTunnelSvr", "NetTunnelSvr\NetTunnelSvr.vcxproj", "{0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug DLL|Any CPU = Debug DLL|Any CPU
|
||||
|
@ -152,6 +155,30 @@ Global
|
|||
{FE91D4D0-29A6-4C58-874F-11F6AC1D50CD}.Release|Any CPU.ActiveCfg = Release
|
||||
{FE91D4D0-29A6-4C58-874F-11F6AC1D50CD}.Release|x64.ActiveCfg = Release
|
||||
{FE91D4D0-29A6-4C58-874F-11F6AC1D50CD}.Release|x86.ActiveCfg = Release
|
||||
{0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E}.Debug DLL|Any CPU.ActiveCfg = Debug|x64
|
||||
{0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E}.Debug DLL|Any CPU.Build.0 = Debug|x64
|
||||
{0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E}.Debug DLL|x64.ActiveCfg = Debug|x64
|
||||
{0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E}.Debug DLL|x64.Build.0 = Debug|x64
|
||||
{0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E}.Debug DLL|x86.ActiveCfg = Debug|Win32
|
||||
{0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E}.Debug DLL|x86.Build.0 = Debug|Win32
|
||||
{0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E}.Debug|Any CPU.Build.0 = Debug|x64
|
||||
{0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E}.Debug|x64.Build.0 = Debug|x64
|
||||
{0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E}.Debug|x86.Build.0 = Debug|Win32
|
||||
{0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E}.Release DLL|Any CPU.ActiveCfg = Release|x64
|
||||
{0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E}.Release DLL|Any CPU.Build.0 = Release|x64
|
||||
{0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E}.Release DLL|x64.ActiveCfg = Release|x64
|
||||
{0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E}.Release DLL|x64.Build.0 = Release|x64
|
||||
{0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E}.Release DLL|x86.ActiveCfg = Release|Win32
|
||||
{0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E}.Release DLL|x86.Build.0 = Release|Win32
|
||||
{0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E}.Release|Any CPU.Build.0 = Release|x64
|
||||
{0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E}.Release|x64.ActiveCfg = Release|x64
|
||||
{0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E}.Release|x64.Build.0 = Release|x64
|
||||
{0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E}.Release|x86.ActiveCfg = Release|Win32
|
||||
{0A2EEDAF-F4A8-41E0-A874-2F30D1EEB55E}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
Loading…
Reference in New Issue