#include #include #include SERVICE_STATUS g_ServiceStatus; SERVICE_STATUS_HANDLE g_StatusHandle = NULL; void print(char const *fmt, ...); void CreateBridge(); LPTSTR GetErrorMessage(); extern BOOL IsLinux; void WINAPI ServiceCtrlHandler(DWORD CtrlCode) { switch (CtrlCode) { case SERVICE_CONTROL_STOP: case SERVICE_ACCEPT_SHUTDOWN: { g_ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING; SetServiceStatus(g_StatusHandle, &g_ServiceStatus); print("Stopping service\n"); /* ... */ g_ServiceStatus.dwCurrentState = SERVICE_STOPPED; SetServiceStatus(g_StatusHandle, &g_ServiceStatus); break; } default: { print("Unrecognized service control code %d\n", CtrlCode); } } } DWORD WINAPI ServiceWorkerThread(LPVOID lpParam) { print("Service started\n"); CreateBridge(); return ERROR_SUCCESS; } void ServiceMain(DWORD argc, LPTSTR *argv) { print("Starting service\n"); g_StatusHandle = RegisterServiceCtrlHandler("rpc-bridge", ServiceCtrlHandler); if (g_StatusHandle == NULL) { print("Failed to register service control handler\n"); return; } ZeroMemory(&g_ServiceStatus, sizeof(g_ServiceStatus)); g_ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; g_ServiceStatus.dwCurrentState = SERVICE_START_PENDING; SetServiceStatus(g_StatusHandle, &g_ServiceStatus); g_ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; g_ServiceStatus.dwCurrentState = SERVICE_START_PENDING; SetServiceStatus(g_StatusHandle, &g_ServiceStatus); g_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN; g_ServiceStatus.dwCurrentState = SERVICE_RUNNING; g_ServiceStatus.dwWin32ExitCode = 0; g_ServiceStatus.dwCheckPoint = 0; SetServiceStatus(g_StatusHandle, &g_ServiceStatus); HANDLE hThread = CreateThread(NULL, 0, ServiceWorkerThread, NULL, 0, NULL); WaitForSingleObject(hThread, INFINITE); g_ServiceStatus.dwControlsAccepted = 0; g_ServiceStatus.dwCurrentState = SERVICE_STOPPED; g_ServiceStatus.dwWin32ExitCode = 0; g_ServiceStatus.dwCheckPoint = 3; SetServiceStatus(g_StatusHandle, &g_ServiceStatus); print("Service stopped.\n"); return; } void InstallService(int ServiceStartType, LPCSTR Path) { print("Registering service\n"); // if (IsLinux == FALSE) // { // /* FIXME: I don't know how to get the TMPDIR without getenv */ // MessageBox(NULL, "Registering as a service is not supported on macOS at the moment.", // "Unsupported", MB_OK | MB_ICONINFORMATION); // ExitProcess(1); // } SC_HANDLE schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE); if (schSCManager == NULL) { print("Failed to open service manager\n"); MessageBox(NULL, GetErrorMessage(), "OpenSCManager", MB_OK | MB_ICONSTOP); ExitProcess(1); } DWORD dwTagId; SC_HANDLE schService = CreateService(schSCManager, "rpc-bridge", "Wine RPC Bridge", SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, ServiceStartType, SERVICE_ERROR_NORMAL, Path, NULL, &dwTagId, NULL, NULL, NULL); if (schService == NULL) { print("Failed to create service\n"); MessageBox(NULL, GetErrorMessage(), "CreateService", MB_OK | MB_ICONSTOP); ExitProcess(1); } print("Service installed successfully\n"); CloseServiceHandle(schService); CloseServiceHandle(schSCManager); } void RemoveService() { print("Unregistering from startup\n"); SC_HANDLE schSCManager, schService; SERVICE_STATUS ssSvcStatus; schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); if (schSCManager == NULL) { MessageBox(NULL, GetErrorMessage(), "OpenSCManager", MB_OK | MB_ICONSTOP); ExitProcess(1); } schService = OpenService(schSCManager, "rpc-bridge", SERVICE_STOP | SERVICE_QUERY_STATUS | DELETE); if (schService == NULL) { MessageBox(NULL, GetErrorMessage(), "OpenService", MB_OK | MB_ICONSTOP); ExitProcess(1); } if (ControlService(schService, SERVICE_CONTROL_STOP, &ssSvcStatus)) { print("Stopping service\n"); Sleep(1000); while (QueryServiceStatus(schService, &ssSvcStatus)) { if (ssSvcStatus.dwCurrentState == SERVICE_STOP_PENDING) { print("Waiting for service to stop\n"); Sleep(1000); } else break; } if (ssSvcStatus.dwCurrentState == SERVICE_STOPPED) print("Service stopped\n"); else print("Service failed to stop\n"); } if (!DeleteService(schService)) { MessageBox(NULL, GetErrorMessage(), "DeleteService", MB_OK | MB_ICONSTOP); ExitProcess(1); } DeleteFile("C:\\windows\\bridge.exe"); print("Service removed successfully\n"); CloseServiceHandle(schService); CloseServiceHandle(schSCManager); }