NetTunnelWindows/NetTunnelSvr/NetTunnelSvr.cpp

120 lines
4.6 KiB
C++
Raw Permalink Normal View History

// 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 InitializeTunnelLibrary() {
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 = InitializeTunnelLibrary();
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 文件