/// Creates a description of the service for registering with the service control /// manager. /// /// @return the table static SERVICE_TABLE_ENTRY *_CreateDispatchTable () { CSettings oSettings; PCTSTR pszServiceName = oSettings.GetServiceName (); size_t cchServiceName = _tcslen (pszServiceName); SERVICE_TABLE_ENTRY *pEntry = (SERVICE_TABLE_ENTRY*)malloc (sizeof (SERVICE_TABLE_ENTRY) * 2 + (cchServiceName + 1) * sizeof (TCHAR)); if (!pEntry) { LOGFATAL (TEXT ("Out of memory")); return NULL; } memcpy (pEntry[0].lpServiceName = (PTSTR)(pEntry + 1), pszServiceName, cchServiceName * sizeof (TCHAR)); pEntry[0].lpServiceProc = ServiceMain; pEntry[1].lpServiceName = NULL; pEntry[1].lpServiceProc = NULL; return pEntry; }
/// Prelude actions to start up the service, e.g. to set any global variables from the settings or perform /// any system specific actions. E.g. the Windows implementation registers with the service control manager /// and can optionally set the security descriptor on the process to allow clients to kill/restart it. /// /// @param[in] nReason how the startup is occuring (e.g. SERVICE_RUN_INLINE) - different actions may be /// required depending on whether the code is running direct from main() or through another mechansim static void _ServiceStartup (int nReason) { CSettings oSettings; #ifdef _WIN32 if (nReason == SERVICE_RUN_SCM) { g_hServiceStatus = RegisterServiceCtrlHandler (oSettings.GetServiceName (), ServiceHandler); } PCTSTR pszSDDL = oSettings.GetServiceSDDL (); if (pszSDDL) { LOGDEBUG (TEXT ("Setting security descriptor ") << pszSDDL); PSECURITY_DESCRIPTOR psdRelative; if (ConvertStringSecurityDescriptorToSecurityDescriptor (pszSDDL, SDDL_REVISION_1, &psdRelative, NULL)) { DWORD cbAbsolute = 1024; PSECURITY_DESCRIPTOR psdAbsolute = (PSECURITY_DESCRIPTOR)malloc (cbAbsolute); DWORD cbD = 1024; PACL paclD = (PACL)malloc (cbD); DWORD cbS = 1024; PACL paclS = (PACL)malloc (cbS); DWORD cbOwner = 1024; PSID psidOwner = (PSID)malloc (cbOwner); DWORD cbPGroup = 1024; PSID psidPGroup = (PSID)malloc (cbPGroup); if (MakeAbsoluteSD (psdRelative, psdAbsolute, &cbAbsolute, paclD, &cbD, paclS, &cbS, psidOwner, &cbOwner, psidPGroup, &cbPGroup)) { DWORD dwError = SetSecurityInfo (GetCurrentProcess (), SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, paclD, NULL); if (dwError == ERROR_SUCCESS) { LOGINFO (TEXT ("Security descriptor set on process handle")); } else { LOGWARN (TEXT ("Couldn't set security descriptor on process handle, error ") << GetLastError ()); } } else { LOGWARN (TEXT ("Couldn't create absolute security description, error ") << GetLastError ()); } free (psdAbsolute); free (paclD); free (paclS); free (psidOwner); free (psidPGroup); LocalFree (psdRelative); } else { LOGWARN (TEXT ("Couldn't parse SDDL ") << pszSDDL << TEXT (", error ") << GetLastError ()); } } else { LOGDEBUG (TEXT ("No security descriptor specified")); } #endif /* ifdef _WIN32 */ g_lBusyTimeout = oSettings.GetBusyTimeout (); _ReportStateStarting (); }
/// Prelude actions to start up the service, e.g. to set any global variables from the settings or perform /// any system specific actions. E.g. the Windows implementation registers with the service control manager /// and can optionally set the security descriptor on the process to allow clients to kill/restart it. /// /// @param[in] nReason how the startup is occuring (e.g. SERVICE_RUN_INLINE) - different actions may be /// required depending on whether the code is running direct from main() or through another mechansim static void _ServiceStartup (int nReason) { CSettings oSettings; #ifdef _WIN32 if (nReason == SERVICE_RUN_SCM) { g_hServiceStatus = RegisterServiceCtrlHandler (oSettings.GetServiceName (), ServiceHandler); } PCTSTR pszSDDL = oSettings.GetServiceSDDL (); if (pszSDDL) { LOGDEBUG (TEXT ("Setting security descriptor ") << pszSDDL); PSECURITY_DESCRIPTOR psdRelative; if (ConvertStringSecurityDescriptorToSecurityDescriptor (pszSDDL, SDDL_REVISION_1, &psdRelative, NULL)) { DWORD cbAbsolute = 1024; PSECURITY_DESCRIPTOR psdAbsolute = (PSECURITY_DESCRIPTOR)malloc (cbAbsolute); DWORD cbD = 1024; PACL paclD = (PACL)malloc (cbD); DWORD cbS = 1024; PACL paclS = (PACL)malloc (cbS); DWORD cbOwner = 1024; PSID psidOwner = (PSID)malloc (cbOwner); DWORD cbPGroup = 1024; PSID psidPGroup = (PSID)malloc (cbPGroup); if (MakeAbsoluteSD (psdRelative, psdAbsolute, &cbAbsolute, paclD, &cbD, paclS, &cbS, psidOwner, &cbOwner, psidPGroup, &cbPGroup)) { DWORD dwError = SetSecurityInfo (GetCurrentProcess (), SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, paclD, NULL); if (dwError == ERROR_SUCCESS) { LOGINFO (TEXT ("Security descriptor set on process handle")); } else { LOGWARN (TEXT ("Couldn't set security descriptor on process handle, error ") << GetLastError ()); } if (nReason == SERVICE_RUN_SCM) { SC_HANDLE hSCM = OpenSCManager (NULL, NULL, GENERIC_READ); if (hSCM) { SC_HANDLE hService = OpenService (hSCM, oSettings.GetServiceName (), GENERIC_WRITE | WRITE_DAC); if (hService) { dwError = SetSecurityInfo (hService, SE_SERVICE, DACL_SECURITY_INFORMATION, NULL, NULL, paclD, NULL); if (dwError == ERROR_SUCCESS) { LOGINFO (TEXT ("Security descriptor set on service")); } else { LOGWARN (TEXT ("Couldn't set security descriptor on service, error ") << GetLastError ()); } CloseServiceHandle (hService); } else { LOGWARN (TEXT ("Couldn't open service, error ") << GetLastError ()); } CloseServiceHandle (hSCM); } else { LOGWARN (TEXT ("Couldn't open SCM, error ") << GetLastError ()); } } } else { LOGWARN (TEXT ("Couldn't create absolute security description, error ") << GetLastError ()); } free (psdAbsolute); free (paclD); free (paclS); free (psidOwner); free (psidPGroup); LocalFree (psdRelative); } else { LOGWARN (TEXT ("Couldn't parse SDDL ") << pszSDDL << TEXT (", error ") << GetLastError ()); } } else { LOGDEBUG (TEXT ("No security descriptor specified")); } #else /* ifdef _WIN32 */ if (nReason == SERVICE_RUN_DAEMON) { const TCHAR *pszPID = oSettings.GetPidFile (); if (pszPID) { LOGINFO (TEXT ("Creating PID file ") << pszPID); FILE *f = fopen (pszPID, "wt"); if (f) { fprintf (f, "%d", getpid ()); fclose (f); } else { LOGWARN (TEXT ("Couldn't write to PID file ") << pszPID << TEXT (", error ") << GetLastError ()); } } else { LOGWARN (TEXT ("No PID file")); } } #endif /* ifdef _WIN32 */ g_lBusyTimeout = oSettings.GetBusyTimeout (); _ReportStateStarting (); }