I am a beginner in C/C++, and I need to embed Wireguard in a service for an app. I followed the docs of Wireguard and used embeddable-dll-service to build a little program as a test:
#include <iostream>
#include <Windows.h>
#include <winsvc.h>
bool checkAdmin()
{
BOOL isAdmin = FALSE;
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
PSID AdministratorsGroup;
if (!AllocateAndInitializeSid(&NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &AdministratorsGroup))
{
std::cout << "Failed to allocate and initialize SID\n";
return false;
}
if (!CheckTokenMembership(NULL, AdministratorsGroup, &isAdmin))
{
std::cout << "Failed to check token membership\n";
FreeSid(AdministratorsGroup);
return false;
}
FreeSid(AdministratorsGroup);
return isAdmin == TRUE;
}
bool checkService()
{
SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (hSCManager == NULL)
{
std::cout << "Failed to open service control manager\n";
return false;
}
SC_HANDLE hService = OpenServiceW(hSCManager, L"MooncloudTunnelService", SERVICE_ALL_ACCESS);
if (hService == NULL)
{
CloseServiceHandle(hSCManager);
return false;
}
CloseServiceHandle(hService);
CloseServiceHandle(hSCManager);
return true;
}
int createService()
{
std::cout << "Creating service\n";
SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (hSCManager == NULL)
{
std::cout << "Failed to open service control manager\n";
return 1;
}
wchar_t szPath[MAX_PATH];
GetModuleFileNameW(NULL, szPath, MAX_PATH);
SC_HANDLE hService = CreateServiceW(
hSCManager,
L"MooncloudTunnelService",
L"Mooncloud Tunnel Service",
SERVICE_ALL_ACCESS,
SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START,
SERVICE_ERROR_NORMAL,
szPath,
NULL,
NULL,
L"Nsi\0TcpIp",
NULL,
NULL
);
if (hService == NULL)
{
std::cout << "Failed to create service\n";
CloseServiceHandle(hSCManager);
return 1;
}
SERVICE_SID_INFO sidInfo;
sidInfo.dwServiceSidType = SERVICE_SID_TYPE_UNRESTRICTED;
if (!ChangeServiceConfig2(hService, SERVICE_CONFIG_SERVICE_SID_INFO, &sidInfo))
{
std::cout << "Failed to change service SID type\n";
CloseServiceHandle(hService);
CloseServiceHandle(hSCManager);
return 1;
}
std::cout << "Service created successfully\n";
CloseServiceHandle(hService);
CloseServiceHandle(hSCManager);
return 0;
}
int destroyService()
{
// Supprimer le service
SC_HANDLE hSCManagerDelete = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (hSCManagerDelete == NULL)
{
std::cout << "Failed to open service control manager for deletion\n";
return 1;
}
SC_HANDLE hServiceDelete = OpenServiceW(hSCManagerDelete, L"MooncloudTunnelService", SERVICE_ALL_ACCESS);
if (hServiceDelete == NULL)
{
std::cout << "Failed to open service for deletion\n";
CloseServiceHandle(hSCManagerDelete);
return 1;
}
if (!DeleteService(hServiceDelete))
{
std::cout << "Failed to delete service\n";
CloseServiceHandle(hServiceDelete);
CloseServiceHandle(hSCManagerDelete);
return 1;
}
std::cout << "Service deleted successfully\n";
CloseServiceHandle(hServiceDelete);
CloseServiceHandle(hSCManagerDelete);
return 0;
}
int main(int argc, char* argv[])
{
std::cout << "Hello World!\n";
if (checkAdmin() == false)
{
std::cout << "This program requires administrator privileges\n";
return 1;
}
if (argc == 3 && !strcmp(argv[1], "/service"))
{
if (checkService() == false) {
createService();
}
else {
std::cout << "Service already exists\n";
destroyService();
std::cout << "Old service destroyed\n";
createService();
}
HMODULE tunnel_lib = LoadLibrary(L"tunnel.dll");
if (!tunnel_lib)
abort();
BOOL(_cdecl * tunnel_proc)(_In_ LPCSTR conf_file);
*(FARPROC*)&tunnel_proc = GetProcAddress(tunnel_lib, "WireGuardTunnelService");
if (!tunnel_proc)
abort();
return tunnel_proc(argv[2]);
}
else if (argc == 2 && !strcmp(argv[1], "/unistall"))
{
if (checkService() == false) {
std::cout << "Service does not exist\n";
return 1;
}
else {
destroyService();
}
return 0;
}
else
{
std::cout << "Bad Arguments\n";
return 1;
}
return 0;
}
The service runs well, the /unistall command works fine too.
But I get this message in the prompt everytime I run the program with the /service command and a wireguard config file : Service run error: Path must end in either .conf.dpapi or .conf
I debugged the app and the argv[2] value is the good path to my config file, this one is correct and ends with a .conf extension.
I tried to put the whole path, quoted or non-quoted, double or single \\ in the path but I still get the same thing.