#include "pch.h" #include "tunnel.h" #include "usrerr.h" #include #include #include #include "globalcfg.h" #include "misc.h" #include "network.h" #pragma comment(lib, "Shlwapi.lib") #pragma comment(lib, "Winmm.lib") #define WG_NIC_DISCRIPT TEXT("WireGuard Tunnel") constexpr auto WINENVBUF_SIZE = (4096); int GetWireGuardWorkMode(bool *pIsWorkServer) { if (pIsWorkServer == nullptr) { SPDLOG_ERROR(TEXT("Input pIsWorkServer params error")); return -ERR_INPUT_PARAMS; } *pIsWorkServer = GetGlobalCfgInfo()->isWorkServer; return ERR_SUCCESS; } int WireGuardInstallDefaultServerService(bool bInstall) { TCHAR cfgVal[MAX_PATH]; DWORD retCode; GetPrivateProfileString(CFG_WIREGUARD_SECTION, CFG_WGCFG_PATH, TEXT(""), cfgVal, MAX_PATH, GetGlobalCfgInfo()->cfgPath); if (lstrlen(cfgVal) > 0) { if (PathFileExists(cfgVal)) { TCHAR cmdBuf[MAX_PATH]; TCHAR svrName[MAX_PATH]; int ret; StringCbCopy(svrName, MAX_PATH, cfgVal); PathStripPath(svrName); PathRemoveExtension(svrName); if (bInstall) { // 安装服务 StringCbPrintf(cmdBuf, MAX_PATH, TEXT("\"%s\" /installtunnelservice \"%s\""), GetGlobalCfgInfo()->wireguardCfg.wireguardPath, cfgVal); } else { // 卸载服务 StringCbPrintf(cmdBuf, MAX_PATH, TEXT("\"%s\" /uninstalltunnelservice %s"), GetGlobalCfgInfo()->wireguardCfg.wireguardPath, svrName); } if ((ret = RunCommand(cmdBuf, nullptr, 0, &retCode)) != ERR_SUCCESS) { SPDLOG_ERROR(TEXT("Run command [{0}] error: {1}"), cmdBuf, ret); return -ERR_CALL_SHELL; } SPDLOG_DEBUG(TEXT("Run command [{0}]"), cmdBuf); if (bInstall) { ret = WaitNetAdapterConnected(svrName, 10 * 1000); } return ret; } else { SPDLOG_ERROR(TEXT("WireGuard configure file [{0}] not found"), cfgVal); return -ERR_FILE_NOT_EXISTS; } } else { SPDLOG_ERROR(TEXT("Configure [{0}] = {1} not found"), CFG_WGCFG_PATH, cfgVal); return -ERR_ITEM_UNEXISTS; } } int WireGuardInstallServerService(const TCHAR *pTunnelCfgPath) { // 卸载服务 TCHAR cmdBuf[MAX_PATH]; int ret; DWORD retCode; if (pTunnelCfgPath == nullptr || lstrlen(pTunnelCfgPath) == 0) { SPDLOG_ERROR(TEXT("Input pTunnelCfgPath params error")); return -ERR_INPUT_PARAMS; } if (!PathFileExists(pTunnelCfgPath)) { SPDLOG_ERROR(TEXT("WireGuard configure file {0} unexists."), pTunnelCfgPath); return -ERR_ITEM_UNEXISTS; } // 安装服务 StringCbPrintf(cmdBuf, MAX_PATH, TEXT("\"%s\" /installtunnelservice \"%s\""), GetGlobalCfgInfo()->wireguardCfg.wireguardPath, pTunnelCfgPath); if ((ret = RunCommand(cmdBuf, nullptr, 0, &retCode)) != ERR_SUCCESS) { SPDLOG_ERROR(TEXT("Run command [{0}] error: {1}"), cmdBuf, ret); return -ERR_CALL_SHELL; } SPDLOG_DEBUG(TEXT("Run command [{0}]"), cmdBuf); 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; } StringCbCopy(svrName, MAX_PATH, pTunnelName); PathStripPath(svrName); PathRemoveExtension(svrName); StringCbPrintf(cmdBuf, MAX_PATH, TEXT("\"%s\" /uninstalltunnelservice %s"), GetGlobalCfgInfo()->wireguardCfg.wireguardPath, svrName); if ((ret = RunCommand(cmdBuf, nullptr, 0, &retCode)) != ERR_SUCCESS) { SPDLOG_ERROR(TEXT("Run command [{0}] error: {1}"), cmdBuf, ret); return -ERR_CALL_SHELL; } SPDLOG_DEBUG(TEXT("Run command [{0}]"), cmdBuf); return ERR_SUCCESS; } int IsWireGuardServerInstalled(bool *pIsInstalled) { DWORD dwStatus; int ret; if (pIsInstalled == nullptr) { SPDLOG_ERROR(TEXT("Input pIsInstalled params error")); return -ERR_INPUT_PARAMS; } *pIsInstalled = false; ret = GetWindowsServiceStatus(TEXT("WireGuard"), &dwStatus); if (ret == ERR_SUCCESS) { switch (dwStatus) { case SERVICE_CONTINUE_PENDING: case SERVICE_RUNNING: case SERVICE_START_PENDING: *pIsInstalled = true; break; default: *pIsInstalled = false; break; } } return ret; } int IsWireGuardServerRunning(const TCHAR *pIfName, bool *pIsRunning) { int ret; PNIC_CONTENT pInfo = nullptr; int size = 0; if (pIfName == nullptr || lstrlen(pIfName) == 0) { SPDLOG_ERROR(TEXT("Input pIfName params error")); return -ERR_INPUT_PARAMS; } if (pIsRunning == nullptr) { SPDLOG_ERROR(TEXT("Input pIsRunning params error")); return -ERR_INPUT_PARAMS; } *pIsRunning = false; ret = GetAllNICInfo(&pInfo, &size); if (ret != ERR_SUCCESS) { return ret; } for (int i = 0; i < size; i++) { if (StrNCmp(pInfo[i].NetCardDescription, WG_NIC_DISCRIPT, lstrlen(WG_NIC_DISCRIPT)) == 0 && StrCmp(pInfo[i].NetCardName, pIfName) == 0) { *pIsRunning = true; } } return ret; } int WireGuardCreateClientConfig(const PWGCLIENT_CONFIG pWgConfig) { const size_t bufSize = 4096 * sizeof(TCHAR); const TCHAR cfgFormat[] = TEXT( "[Interface]\nPrivateKey = %s\nAddress = %s\n\n[Peer]\nPublicKey = %s\nAllowedIPs = %s\nEndpoint = " "%s\nPersistentKeepalive = 30\n"); TCHAR cfgPath[MAX_PATH]; size_t length; HANDLE hFile; TCHAR *pBuf; #pragma region if (pWgConfig == nullptr) { return -ERR_INPUT_PARAMS; } if (FAILED(StringCbLength(pWgConfig->Name, 64, &length)) || 0 == length) { SPDLOG_ERROR(TEXT("WireGuard Name error: {0}"), pWgConfig->Name); return -ERR_INPUT_PARAMS; } if (FAILED(StringCbLength(pWgConfig->Address, 32, &length)) || 0 == length) { SPDLOG_ERROR(TEXT("WireGuard Address error: {0}"), pWgConfig->Address); return -ERR_INPUT_PARAMS; } if (FAILED(StringCbLength(pWgConfig->PrivateKey, 64, &length)) || 0 == length) { SPDLOG_ERROR(TEXT("WireGuard Private key error: {0}"), pWgConfig->PrivateKey); return -ERR_INPUT_PARAMS; } if (FAILED(StringCbLength(pWgConfig->SvrPubKey, 64, &length)) || 0 == length) { SPDLOG_ERROR(TEXT("WireGuard Server Public key error: {0}"), pWgConfig->SvrPubKey); return -ERR_INPUT_PARAMS; } if (FAILED(StringCbLength(pWgConfig->AllowNet, 256, &length)) || 0 == length) { SPDLOG_ERROR(TEXT("WireGuard Allow Client Network error: {0}"), pWgConfig->AllowNet); return -ERR_INPUT_PARAMS; } if (FAILED(StringCbLength(pWgConfig->ServerURL, 256, &length)) || 0 == length) { SPDLOG_ERROR(TEXT("WireGuard Server Network error: {0}"), pWgConfig->ServerURL); return -ERR_INPUT_PARAMS; } #pragma endregion 参数检查 pBuf = static_cast(malloc(bufSize)); if (pBuf == nullptr) { SPDLOG_ERROR(TEXT("Malloc {1} bytes memory error: {0}"), GetLastError(), bufSize); return -ERR_MALLOC_MEMORY; } memset(pBuf, 0, bufSize); StringCbPrintf(cfgPath, MAX_PATH, "%s\\%s", GetGlobalCfgInfo()->configDirectory, GetGlobalCfgInfo()->userCfg.userName); // 如果当前用户配置目录不存在则自动创建 if (!PathFileExists(cfgPath)) { if (!CreateDirectory(cfgPath, nullptr)) { SPDLOG_ERROR(TEXT("Create configure directory '{0}' error."), cfgPath); return -ERR_CREATE_FILE; } } StringCbPrintf(cfgPath, MAX_PATH, "%s\\%s\\%s.conf", GetGlobalCfgInfo()->configDirectory, GetGlobalCfgInfo()->userCfg.userName, pWgConfig->Name); hFile = CreateFile(cfgPath, // name of the write GENERIC_WRITE | GENERIC_READ, // open for writing FILE_SHARE_READ, // do not share nullptr, // default security CREATE_ALWAYS, // create new file only FILE_ATTRIBUTE_NORMAL, // normal file nullptr); // no attr. template if (hFile == INVALID_HANDLE_VALUE) { SPDLOG_ERROR(TEXT("CreatFile [{0}] error: {1}"), cfgPath, GetLastError()); free(pBuf); return -ERR_OPEN_FILE; } // 保存到配置文件中 WritePrivateProfileString(CFG_WIREGUARD_SECTION, CFG_WGCFG_PATH, cfgPath, GetGlobalCfgInfo()->cfgPath); if (FAILED(StringCbPrintf(pBuf, bufSize, cfgFormat, pWgConfig->PrivateKey, pWgConfig->Address, pWgConfig->SvrPubKey, pWgConfig->AllowNet, pWgConfig->ServerURL))) { SPDLOG_ERROR(TEXT("Format string error: {0}"), GetLastError()); free(pBuf); ::CloseHandle(hFile); return -ERR_MEMORY_STR; } if (FAILED(StringCbLength(pBuf, bufSize, &length))) { SPDLOG_ERROR(TEXT("Get string \'{0}\' length error: {1}"), pBuf, GetLastError()); free(pBuf); ::CloseHandle(hFile); return -ERR_MEMORY_STR; } SPDLOG_DEBUG(TEXT("WG Client Configure:\n{0}"), pBuf); if (!WriteFile(hFile, // open file handle pBuf, // start of data to write static_cast(length), // number of bytes to write nullptr, // number of bytes that were written nullptr)) { SPDLOG_ERROR(TEXT("WriteFile [{0}] error: {1}"), cfgPath, GetLastError()); free(pBuf); ::CloseHandle(hFile); return -ERR_OPEN_FILE; } StringCbCopy(GetGlobalCfgInfo()->wgClientCfg.wgName, 260, pWgConfig->Name); StringCbCopy(GetGlobalCfgInfo()->wgClientCfg.wgIpaddr, MAX_IP_LEN, pWgConfig->Address); StringCbCopy(GetGlobalCfgInfo()->wgClientCfg.wgCfgPath, MAX_PATH, cfgPath); ::CloseHandle(hFile); return ERR_SUCCESS; } int WireGuardCreateServerConfig(const PWGSERVER_CONFIG pWgConfig) { const size_t bufSize = 4096 * sizeof(TCHAR); const TCHAR cfgFormat[] = TEXT( "[Interface]\nAddress = %s\nListenPort = %d\nPrivateKey = %s\n\n[Peer]\nPublicKey = %s\nAllowedIPs = %s\n"); TCHAR cfgPath[MAX_PATH]; size_t length; HANDLE hFile; TCHAR *pBuf; #pragma region if (pWgConfig == nullptr) { return -ERR_INPUT_PARAMS; } if (FAILED(StringCbLength(pWgConfig->Name, 64, &length)) || 0 == length) { SPDLOG_ERROR(TEXT("WireGuard Name error: {0}"), pWgConfig->Name); return -ERR_INPUT_PARAMS; } if (FAILED(StringCbLength(pWgConfig->Address, 32, &length)) || 0 == length) { SPDLOG_ERROR(TEXT("WireGuard Address error: {0}"), pWgConfig->Address); return -ERR_INPUT_PARAMS; } if (FAILED(StringCbLength(pWgConfig->PrivateKey, 64, &length)) || 0 == length) { SPDLOG_ERROR(TEXT("WireGuard Private key error: {0}"), pWgConfig->PrivateKey); return -ERR_INPUT_PARAMS; } if (pWgConfig->ListenPort <= 1024 || pWgConfig->ListenPort >= 65535) { SPDLOG_ERROR(TEXT("WireGuard Listen port error: {0}, should be in arrange (1024, 65535)"), pWgConfig->ListenPort); return -ERR_INPUT_PARAMS; } if (FAILED(StringCbLength(pWgConfig->CliPubKey, 64, &length)) || 0 == length) { SPDLOG_ERROR(TEXT("WireGuard Client Public key error: {0}"), pWgConfig->CliPubKey); return -ERR_INPUT_PARAMS; } if (FAILED(StringCbLength(pWgConfig->AllowNet, 256, &length)) || 0 == length) { SPDLOG_ERROR(TEXT("WireGuard Allow Client Network error: {0}"), pWgConfig->AllowNet); return -ERR_INPUT_PARAMS; } #pragma endregion 参数检查 pBuf = static_cast(malloc(bufSize)); if (pBuf == nullptr) { SPDLOG_ERROR(TEXT("Malloc {1} bytes memory error: {0}"), GetLastError(), bufSize); return -ERR_MALLOC_MEMORY; } memset(pBuf, 0, bufSize); StringCbPrintf(cfgPath, MAX_PATH, "%s\\%s", GetGlobalCfgInfo()->configDirectory, GetGlobalCfgInfo()->userCfg.userName); // 如果当前用户配置目录不存在则自动创建 if (!PathFileExists(cfgPath)) { if (!CreateDirectory(cfgPath, nullptr)) { SPDLOG_ERROR(TEXT("Create configure directory '{0}' error."), cfgPath); return -ERR_CREATE_FILE; } } StringCbPrintf(cfgPath, MAX_PATH, "%s\\%s\\%s.conf", GetGlobalCfgInfo()->configDirectory, GetGlobalCfgInfo()->userCfg.userName, pWgConfig->Name); hFile = CreateFile(cfgPath, // name of the write GENERIC_WRITE | GENERIC_READ, // open for writing FILE_SHARE_READ, // do not share nullptr, // default security CREATE_ALWAYS, // create new file only FILE_ATTRIBUTE_NORMAL, // normal file nullptr); // no attr. template if (hFile == INVALID_HANDLE_VALUE) { SPDLOG_ERROR(TEXT("CreatFile [{0}] error: {1}"), cfgPath, GetLastError()); free(pBuf); return -ERR_OPEN_FILE; } // 清空文件 SetFilePointer(hFile, 0, nullptr, FILE_BEGIN); SetEndOfFile(hFile); WritePrivateProfileString(CFG_WIREGUARD_SECTION, CFG_WGCFG_PATH, cfgPath, GetGlobalCfgInfo()->cfgPath); if (FAILED(StringCbPrintf(pBuf, bufSize, cfgFormat, pWgConfig->Address, pWgConfig->ListenPort, pWgConfig->PrivateKey, pWgConfig->CliPubKey, pWgConfig->AllowNet))) { SPDLOG_ERROR(TEXT("Format string error: {0}"), GetLastError()); free(pBuf); ::CloseHandle(hFile); return -ERR_MEMORY_STR; } if (FAILED(StringCbLength(pBuf, bufSize, &length))) { SPDLOG_ERROR(TEXT("Get string \'{0}\' length error: {1}"), pBuf, GetLastError()); free(pBuf); ::CloseHandle(hFile); return -ERR_MEMORY_STR; } SPDLOG_DEBUG(TEXT("WG Server Configure:\n{0}"), pBuf); if (FALSE == WriteFile(hFile, // open file handle pBuf, // start of data to write static_cast(length), // number of bytes to write nullptr, // number of bytes that were written nullptr)) // no overlapped structure) { SPDLOG_ERROR(TEXT("WriteFile [{0}] error: {1}"), cfgPath, GetLastError()); free(pBuf); ::CloseHandle(hFile); return -ERR_OPEN_FILE; } ::CloseHandle(hFile); StringCbCopy(GetGlobalCfgInfo()->wgServerCfg.wgName, 260, pWgConfig->Name); StringCbCopy(GetGlobalCfgInfo()->wgServerCfg.wgIpaddr, MAX_IP_LEN, pWgConfig->Address); StringCbCopy(GetGlobalCfgInfo()->wgServerCfg.wgCfgPath, MAX_PATH, cfgPath); return ERR_SUCCESS; } int GenerateWireguardKeyPairs(TCHAR *pPubKey, int pubkeySize, TCHAR *pPrivKey, int privKeySize) { int ret; DWORD retCode; TCHAR cmdBuffer[MAX_PATH]; TCHAR cmdResult[MAX_PATH]; PSDK_CONFIG pCfg = GetGlobalCfgInfo(); // WireGuard 不存在或者未配置目录 if (!pCfg->wireguardCfg.wgExists || !pCfg->wireguardCfg.wireguardExists) { return -ERR_ITEM_UNEXISTS; } memset(cmdBuffer, 0, MAX_PATH); memset(cmdResult, 0, MAX_PATH); StringCbPrintf(cmdBuffer, MAX_PATH, TEXT("cmd.exe /C \"%s\" genkey"), pCfg->wireguardCfg.wgPath); if ((ret = RunCommand(cmdBuffer, cmdResult, MAX_PATH, &retCode)) != ERR_SUCCESS) { SPDLOG_ERROR(TEXT("Run command [{0}] error: {1}"), cmdBuffer, ret); return -ERR_CALL_SHELL; } SPDLOG_DEBUG(TEXT("Run command [{0}] resutl \'{1}\'"), cmdBuffer, cmdResult); StringCbCopy(pPrivKey, privKeySize, cmdResult); memset(cmdBuffer, 0, MAX_PATH); StringCbPrintf(cmdBuffer, MAX_PATH, TEXT("cmd.exe /C echo %s | \"%s\" pubkey"), cmdResult, pCfg->wireguardCfg.wgPath); memset(cmdResult, 0, MAX_PATH); if ((ret = RunCommand(cmdBuffer, cmdResult, MAX_PATH, &retCode)) != ERR_SUCCESS) { SPDLOG_ERROR(TEXT("Run command [{0}] error: {1}"), cmdBuffer, ret); return -ERR_CALL_SHELL; } StringCbCopy(pPubKey, pubkeySize, cmdResult); SPDLOG_DEBUG(TEXT("Run command [{0}] resutl \'{1}\'"), cmdBuffer, cmdResult); return ERR_SUCCESS; } int SetWireguardPath(const TCHAR *pPath) { if (pPath == nullptr) { return -ERR_INPUT_PARAMS; } if (PathFileExists(pPath)) { TCHAR wgPath[MAX_PATH]; SPDLOG_DEBUG(TEXT("Used configure file:{0}"), GetGlobalCfgInfo()->cfgPath); WritePrivateProfileString(CFG_WIREGUARD_SECTION, CFG_WIREGUARD_PATH, pPath, GetGlobalCfgInfo()->cfgPath); SPDLOG_DEBUG(TEXT("Save configure: {1} --> {0}"), pPath, CFG_WIREGUARD_PATH); StringCbCopy(wgPath, MAX_PATH, pPath); if (TCHAR *pIndex = _tcsrchr(wgPath, '\\')) { *pIndex = 0; StringCbCat(wgPath, MAX_PATH, "\\wg.exe"); WritePrivateProfileString(CFG_WIREGUARD_SECTION, CFG_WG_PATH, wgPath, GetGlobalCfgInfo()->cfgPath); SPDLOG_DEBUG(TEXT("Save configure: {1} --> {0}"), wgPath, CFG_WG_PATH); } return ERR_SUCCESS; } else { SPDLOG_ERROR(TEXT("WireGuard not found: {0}"), pPath); return -ERR_ITEM_UNEXISTS; } } int FindWireguardExe(TCHAR *pFullPath, int maxSize) { TCHAR path[MAX_PATH]; TCHAR wireguardPath[MAX_PATH]; DWORD dwRet; LPSTR pEnvBuf; TCHAR *token, *p = nullptr; GetPrivateProfileString(CFG_WIREGUARD_SECTION, CFG_WIREGUARD_PATH, TEXT(""), wireguardPath, MAX_PATH, GetGlobalCfgInfo()->cfgPath); if (PathFileExists(wireguardPath)) { if (pFullPath && maxSize > 0) { StringCbCopy(pFullPath, maxSize, wireguardPath); } StringCbCopy(GetGlobalCfgInfo()->wireguardCfg.wireguardPath, MAX_PATH, wireguardPath); GetGlobalCfgInfo()->wireguardCfg.wireguardExists = TRUE; SPDLOG_DEBUG(TEXT("Ini found WireGuard at: {0}"), wireguardPath); GetPrivateProfileString(CFG_WIREGUARD_SECTION, CFG_WG_PATH, TEXT(""), wireguardPath, MAX_PATH, GetGlobalCfgInfo()->cfgPath); if (PathFileExists(wireguardPath)) { StringCbCopy(GetGlobalCfgInfo()->wireguardCfg.wgPath, MAX_PATH, wireguardPath); GetGlobalCfgInfo()->wireguardCfg.wgExists = TRUE; SPDLOG_DEBUG(TEXT("Ini found WireGuard Tools at: {0}"), wireguardPath); } return ERR_SUCCESS; } StringCbCopy(wireguardPath, MAX_PATH, GetGlobalCfgInfo()->systemDirectory); PathStripToRoot(wireguardPath); StringCbCat(wireguardPath, MAX_PATH, TEXT("Program Files\\WireGuard\\wireguard.exe")); if (PathFileExists(wireguardPath)) { // 保存路径到配置文件 SetWireguardPath(wireguardPath); GetGlobalCfgInfo()->wireguardCfg.wireguardExists = TRUE; PathRemoveFileSpec(wireguardPath); StringCbCat(wireguardPath, MAX_PATH, TEXT("\\wg.exe")); if (PathFileExists(wireguardPath)) { GetGlobalCfgInfo()->wireguardCfg.wgExists = TRUE; } return ERR_SUCCESS; } // 从环境变量中查找 pEnvBuf = static_cast(malloc(WINENVBUF_SIZE)); if (nullptr == pEnvBuf) { SPDLOG_ERROR(TEXT("Malloc {0} bytes memory error"), WINENVBUF_SIZE); return -ERR_MALLOC_MEMORY; } dwRet = GetEnvironmentVariable(TEXT("path"), pEnvBuf, WINENVBUF_SIZE); if (0 == dwRet) { DWORD dwErr; dwErr = GetLastError(); if (ERROR_ENVVAR_NOT_FOUND == dwErr) { SPDLOG_DEBUG(TEXT("Environment variable path does not exist.")); free(pEnvBuf); return -ERR_FILE_NOT_EXISTS; } } else if (WINENVBUF_SIZE < dwRet) { const auto pBuf = static_cast(realloc(pEnvBuf, dwRet * sizeof(CHAR))); if (nullptr == pBuf) { SPDLOG_ERROR(TEXT("Malloc {0} bytes memory error"), dwRet * sizeof(CHAR)); free(pEnvBuf); return -ERR_MALLOC_MEMORY; } pEnvBuf = pBuf; dwRet = GetEnvironmentVariable("path", pEnvBuf, dwRet); if (!dwRet) { SPDLOG_ERROR(TEXT("GetEnvironmentVariable failed (%d)"), GetLastError()); free(pEnvBuf); return -ERR_FILE_NOT_EXISTS; } } token = strtok_s(pEnvBuf, TEXT(";"), &p); while (token != nullptr) { memset(path, 0, MAX_PATH); StringCbPrintfA(path, MAX_PATH, TEXT("%s\\wireguard.exe"), token); if (PathFileExists(path)) { if (pFullPath && maxSize > 0) { StringCbCopy(pFullPath, maxSize, path); } // 保存路径到配置文件 SetWireguardPath(path); SPDLOG_DEBUG(TEXT("Path Environment found WireGuard at: {0}"), path); StringCbCopy(GetGlobalCfgInfo()->wireguardCfg.wireguardPath, MAX_PATH, wireguardPath); GetGlobalCfgInfo()->wireguardCfg.wireguardExists = TRUE; memset(path, 0, MAX_PATH); StringCbPrintf(path, MAX_PATH, TEXT("%s\\wg.exe"), token); SPDLOG_DEBUG(TEXT("Find WireGuard tools at: {0}"), path); if (PathFileExists(path)) { StringCbCopy(GetGlobalCfgInfo()->wireguardCfg.wgPath, MAX_PATH, path); GetGlobalCfgInfo()->wireguardCfg.wgExists = TRUE; SPDLOG_DEBUG(TEXT("Path Environment found WireGuard tools at: {0}"), path); } //TODO: throw exception by C# call, why?????? //CloseHandle(hFind); free(pEnvBuf); return ERR_SUCCESS; } token = strtok_s(nullptr, TEXT(";"), &p); } free(pEnvBuf); return -ERR_FILE_NOT_EXISTS; } #if 0 int InstallWindowsNATCommand() { TCHAR psCmdPath[MAX_PATH]; // 如果已经安装则退出 if (IsCustomNatPSCmdInstalled()) { return ERR_SUCCESS; } StringCbPrintf(psCmdPath, MAX_PATH, TEXT("%s\\system32\\WindowsPowerShell\\v1.0\\Modules\\wireguard\\wireguard.psm1"), GetGlobalCfgInfo()->systemDirectory); const HANDLE hFile = CreateFile(psCmdPath, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); if (hFile == INVALID_HANDLE_VALUE) { SPDLOG_ERROR("CreatFile [{0}] error: {1}", psCmdPath, GetLastError()); return -ERR_OPEN_FILE; } const HMODULE hMod = GetModuleHandle(TEXT("NetTunnelSDK.dll")); if (nullptr == hMod) { SPDLOG_ERROR(TEXT("Load NetTunnelSDK.dll module error")); ::CloseHandle(hFile); return -ERR_ITEM_UNEXISTS; } const HRSRC hRsrc = FindResource(hMod, MAKEINTRESOURCE(PSCMD_RES_ID), TEXT("TXT")); if (nullptr == hRsrc) { SPDLOG_ERROR(TEXT("Donot found resource {0} of type {1}"), PSCMD_RES_ID, TEXT("TXT")); ::CloseHandle(hFile); return -ERR_ITEM_UNEXISTS; } const DWORD resSize = SizeofResource(hMod, hRsrc); if (resSize == 0) { SPDLOG_ERROR(TEXT("Resource {0} of type {1} is empty"), PSCMD_RES_ID, TEXT("TXT")); ::CloseHandle(hFile); return -ERR_ITEM_UNEXISTS; } const HGLOBAL hGlobal = LoadResource(hMod, hRsrc); if (hGlobal == hRsrc) { SPDLOG_ERROR(TEXT("Load resource {0} of type {1} error"), PSCMD_RES_ID, TEXT("TXT")); ::CloseHandle(hFile); return -ERR_ITEM_UNEXISTS; } if (const LPVOID pBuffer = LockResource(hGlobal)) { if (!WriteFile(hFile, // open file handle pBuffer, // start of data to write static_cast(resSize), // number of bytes to write nullptr, // number of bytes that were written nullptr)) { SPDLOG_ERROR("WriteFile [{0}] error: {1}", psCmdPath, GetLastError()); GlobalUnlock(hGlobal); ::CloseHandle(hFile); return -ERR_OPEN_FILE; } } GlobalUnlock(hGlobal); ::CloseHandle(hFile); return ERR_SUCCESS; } int WireGuardNetConnectionSharingEnable() { int ret; DWORD retCode; TCHAR cmdResult[MAX_PATH] = {}; TCHAR cmdBuf[] = TEXT("PowerShell -NoProfile -NonInteractive -WindowStyle Hidden -ExecutionPolicy Bypass Invoke-Command -ArgumentList 'wg_cli' -ScriptBlock {param($IFNAME);$netShare = New-Object -ComObject HNetCfg.HNetShare;" "$privateConnection = $netShare.EnumEveryConnection |? { $netShare.NetConnectionProps.Invoke($_).Name -eq 'wg_cli' };" "$privateConfig = $netShare.INetSharingConfigurationForINetConnection.Invoke($privateConnection);" "Write-Output $privateConfig}"); if ((ret = RunCommand(cmdBuf, cmdResult, MAX_PATH, &retCode)) != ERR_SUCCESS) { SPDLOG_ERROR("Run command [{0}] error: {1}", cmdBuf, ret); return -ERR_CALL_SHELL; } SPDLOG_DEBUG("Run command [{0}] resutl \'{1}\' return {2}", cmdBuf, cmdResult, retCode); return ERR_SUCCESS; } #endif