// NetTunnelSvr.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 // #include #include #include #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(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 文件