20#pragma comment(linker, "/SUBSYSTEM:windows")
29#define LOGS_TO_KEEP 10
38 LOG_WARN((
"missing mandatory command line argument"));
49 bool forceInstall = !lstrcmpi(argv[1], L
"forceinstall");
50 if (!lstrcmpi(argv[1], L
"install") || forceInstall)
55 LogInit(updatePath, L
"maintenanceservice-install.log");
62 LOG((
"Installing service with force specified..."));
66 LOG((
"Installing service..."));
72 LOG_WARN((
"Could not install service. (%d)", GetLastError()));
77 LOG((
"The service was installed successfully"));
82 if (!lstrcmpi(argv[1], L
"upgrade"))
87 LogInit(updatePath, L
"maintenanceservice-install.log");
90 LOG((
"Upgrading service if installed..."));
93 LOG_WARN((
"Could not upgrade service. (%d)", GetLastError()));
98 LOG((
"The service was upgraded successfully"));
103 if (!lstrcmpi(argv[1], L
"uninstall"))
108 LogInit(updatePath, L
"maintenanceservice-uninstall.log");
110 LOG((
"Uninstalling service..."));
113 LOG_WARN((
"Could not uninstall service. (%d)", GetLastError()));
117 LOG((
"The service was uninstalled successfully"));
122 SERVICE_TABLE_ENTRYW DispatchTable[] =
130 if (!StartServiceCtrlDispatcherW(DispatchTable))
132 LOG_WARN((
"StartServiceCtrlDispatcher failed. (%d)", GetLastError()));
147 HRESULT
hr = SHGetFolderPathW(
nullptr, CSIDL_COMMON_APPDATA,
nullptr,
148 SHGFP_TYPE_CURRENT, path);
160 CreateDirectoryW(path,
nullptr);
166 CreateDirectoryW(path,
nullptr);
181 WCHAR logName[64] = { L
'\0' };
182 wcsncpy(path, basePath,
sizeof(logName) /
sizeof(logName[0]) - 1);
185 swprintf(logName,
sizeof(logName) /
sizeof(logName[0]),
186 L
"maintenanceservice.log");
190 swprintf(logName,
sizeof(logName) /
sizeof(logName[0]),
191 L
"maintenanceservice-%d.log", logNumber);
212 for (
int i = numLogsToKeep;
i >= 1;
i--)
224 if (!MoveFileExW(oldPath, newPath, MOVEFILE_REPLACE_EXISTING))
258 nullptr, 0,
nullptr);
276 LogInit(updatePath, L
"maintenanceservice.log");
287 LOG_WARN((
"RegisterServiceCtrlHandler failed. (%d)", GetLastError()));
294 gSvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
344 static DWORD dwCheckPoint = 1;
350 if (SERVICE_START_PENDING == currentState ||
351 SERVICE_STOP_PENDING == currentState)
357 gSvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
358 SERVICE_ACCEPT_SHUTDOWN;
361 if ((SERVICE_RUNNING == currentState) ||
362 (SERVICE_STOPPED == currentState))
411 case SERVICE_CONTROL_SHUTDOWN:
412 case SERVICE_CONTROL_STOP:
419 HANDLE thread = CreateThread(
nullptr, 0,
421 nullptr, 0,
nullptr);
static BOOL DisablePrivileges(HANDLE token)
void WINAPI SvcMain(DWORD argc, LPWSTR *argv)
Main entry point when running as a service.
void BackupOldLogs(LPCWSTR basePath, int numLogsToKeep)
Moves the old log files out of the way before a new one is written.
DWORD WINAPI EnsureProcessTerminatedThread(LPVOID)
Ensures the service is shutdown once all work is complete.
bool gServiceControlStopping
void ReportSvcStatus(DWORD currentState, DWORD exitCode, DWORD waitHint)
Sets the current service status and reports it to the SCM.
BOOL GetBackupLogPath(LPWSTR path, LPCWSTR basePath, int logNumber)
Calculated a backup path based on the log number.
BOOL GetLogDirectoryPath(WCHAR *path)
Obtains the base path where logs should be stored.
void WINAPI SvcCtrlHandler(DWORD dwCtrl)
Called by SCM whenever a control code is sent to the service using the ControlService function.
int wmain(int argc, WCHAR **argv)
DWORD WINAPI StopServiceAndWaitForCommandThread(LPVOID)
Since the SvcCtrlHandler should only spend at most 30 seconds before returning, this function does th...
SERVICE_STATUS gSvcStatus
void StartTerminationThread()
SERVICE_STATUS_HANDLE gSvcStatusHandle
const wchar_t *typedef BOOL
BOOL PathAppendSafe(LPWSTR base, LPCWSTR extra)
BOOL SvcInstall(SvcInstallAction action)
Installs or upgrades the SVC_NAME service.
BOOL SvcUninstall()
Uninstalls the Maintenance service.
#define LogInit(PATHNAME_, FILENAME_)
BOOL ExecuteServiceCommand(int argc, LPWSTR *argv)
Executes a service command.