Пример #1
0
//	PURPOSE:  Installs the service on the local machine
void CNTService::CmdInstallService()
{
	char	szPath[_MAX_PATH * 2];
	char	szErr[256];

	ReportEvent(EVENTLOG_INFORMATION_TYPE, 0, "Installing Service.");

	// Try to determine the name and path of this application.
	if ( !GetModuleFileName(NULL, szPath, sizeof(szPath)) )
	{
		ReportEvent(EVENTLOG_ERROR_TYPE, 0, "Install GetModuleFileName", GetLastErrorText(szErr, sizeof(szErr)));
		return;
	}

	// Try to open the Service Control Manager
	SC_HANDLE schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
	if ( !schSCManager )
	{
		ReportEvent(EVENTLOG_ERROR_TYPE, 0, "Install OpenSCManager", GetLastErrorText(szErr, sizeof(szErr)));
		return;
	}

	// Try to create the service
	char szInternalName[_MAX_PATH];
	sprintf(szInternalName, SPHERE_TITLE " - %s", g_Serv.GetName());

	SC_HANDLE schService = CreateService(
		schSCManager,					// handle of the Service Control Manager
		szInternalName,				// Internal name of the service (used when controlling the service using "net start" or "netsvc")
		szInternalName,			// Display name of the service (displayed in the Control Panel | Services page)
		SERVICE_ALL_ACCESS,
		SERVICE_WIN32_OWN_PROCESS,
		SERVICE_AUTO_START,				// Start automatically when the OS starts
		SERVICE_ERROR_NORMAL,
		szPath,							// Path and filename of this executable
		NULL, NULL, NULL, NULL, NULL
	);
	if ( !schService )
	{
		ReportEvent(EVENTLOG_ERROR_TYPE, 0, "Install CreateService", GetLastErrorText(szErr, sizeof(szErr)));
bailout1:
		CloseServiceHandle(schSCManager);
		return;
	}

	// Configure service - Service description
	char szDescription[_MAX_PATH];
	sprintf(szDescription, "SphereServer Service for %s", g_Serv.GetName());

	SERVICE_DESCRIPTION sdDescription;
	sdDescription.lpDescription = szDescription;
	if ( !ChangeServiceConfig2(schService, SERVICE_CONFIG_DESCRIPTION, &sdDescription) )
	{
		// not critical, so no need to abort the service creation
		ReportEvent(EVENTLOG_WARNING_TYPE, 0, "Install SetDescription", GetLastErrorText(szErr, sizeof(szErr)));
	}

	// Configure service - Restart options
	SC_ACTION scAction[3];
	scAction[0].Type = SC_ACTION_RESTART;	// restart process on failure
	scAction[0].Delay = 10000;				// wait 10 seconds before restarting
	scAction[1].Type = SC_ACTION_RESTART;	
	scAction[1].Delay = 10000;				
	scAction[2].Type = SC_ACTION_RESTART;	// wait 2 minutes before restarting the third time
	scAction[2].Delay = 120000;

	SERVICE_FAILURE_ACTIONS sfaFailure;
	sfaFailure.dwResetPeriod = (1 * 60 * 60); // reset failure count after an hour passes with no fails
	sfaFailure.lpRebootMsg = NULL;	// no reboot message
	sfaFailure.lpCommand = NULL;	// no command executed
	sfaFailure.cActions = COUNTOF(scAction);		// number of actions
	sfaFailure.lpsaActions = scAction;	// 
	if ( !ChangeServiceConfig2(schService, SERVICE_CONFIG_FAILURE_ACTIONS, &sfaFailure) )
	{
		// not critical, so no need to abort the service creation
		ReportEvent(EVENTLOG_WARNING_TYPE, 0, "Install SetAutoRestart", GetLastErrorText(szErr, sizeof(szErr)));
	}

	HKEY	hKey;
	char	szKey[_MAX_PATH];

	// Register the application for event logging
	DWORD dwData;
	// Try to create the registry key containing information about this application
	strcpy(szKey, "System\\CurrentControlSet\\Services\\EventLog\\Application\\" SPHERE_FILE "svr");

	if (RegCreateKey(HKEY_LOCAL_MACHINE, szKey, &hKey))
		ReportEvent(EVENTLOG_ERROR_TYPE, 0, "Install RegCreateKey", GetLastErrorText(szErr, sizeof(szErr)));
	else
	{
		// Try to create the registry key containing the name of the EventMessageFile
		//  Replace the name of the exe with the name of the dll in the szPath variable
		if (RegSetValueEx(hKey, "EventMessageFile", 0, REG_EXPAND_SZ, (LPBYTE) szPath, strlen(szPath) + 1))
			ReportEvent(EVENTLOG_ERROR_TYPE, 0, "Install RegSetValueEx", GetLastErrorText(szErr, sizeof(szErr)));
		else
		{
			// Try to create the registry key containing the types of errors this application will generate
			dwData = EVENTLOG_ERROR_TYPE|EVENTLOG_INFORMATION_TYPE|EVENTLOG_WARNING_TYPE;
			if ( RegSetValueEx(hKey, "TypesSupported", 0, REG_DWORD, (LPBYTE) &dwData, sizeof(DWORD)) )
				ReportEvent(EVENTLOG_ERROR_TYPE, 0, "Install RegSetValueEx", GetLastErrorText(szErr, sizeof(szErr)));
		}
		RegCloseKey(hKey);
	}

	// Set the working path for the application
	sprintf(szKey, "System\\CurrentControlSet\\Services\\" SPHERE_TITLE " - %s\\Parameters", g_Serv.GetName());
	if ( RegCreateKey(HKEY_LOCAL_MACHINE, szKey, &hKey) )
	{
		ReportEvent(EVENTLOG_ERROR_TYPE, 0, "Install RegCreateKey", GetLastErrorText(szErr, sizeof(szErr)));
bailout2:
		CloseServiceHandle(schService);
		goto bailout1;
	}
	ExtractPath(szPath);

	if ( RegSetValueEx(hKey, "WorkingPath", 0, REG_SZ, (const unsigned char *) &szPath[0], strlen(szPath)) )
		ReportEvent(EVENTLOG_ERROR_TYPE, 0, "Install RegSetValueEx", GetLastErrorText(szErr, sizeof(szErr)));

	ReportEvent(EVENTLOG_INFORMATION_TYPE, 0, "Install OK", g_Serv.GetName());
	goto bailout2;
}
Пример #2
-1
//	PURPOSE:  starts the service. (synchronous)
int CNTService::ServiceStart(DWORD dwArgc, LPTSTR *lpszArgv)
{
	ReportEvent(EVENTLOG_INFORMATION_TYPE, 0, "Service start pending.");

	// Service initialization report status to the service control manager.
	int rc = -1;
	if ( !SetServiceStatus(SERVICE_START_PENDING, NO_ERROR, 3000) )
		return rc;

	// Create the event object.  The control handler function signals this event when it receives a "stop" control code
	m_hServerStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
	if ( !m_hServerStopEvent )
		return rc;

	if ( !SetServiceStatus(SERVICE_START_PENDING, NO_ERROR, 3000) )
	{
bailout1:
		CloseHandle(m_hServerStopEvent);
		return rc;
	}

	// Create the event object used in overlapped i/o
	HANDLE hEvents[2] = {NULL, NULL};
	hEvents[0] = m_hServerStopEvent;
	hEvents[1] = CreateEvent(NULL, TRUE, FALSE, NULL);
	if ( !hEvents[1] )
		goto bailout1;

	if ( !SetServiceStatus(SERVICE_START_PENDING, NO_ERROR, 3000) )
	{
bailout2:
		CloseHandle(hEvents[1]);
		goto bailout1;
	}

	// Create a security descriptor that allows anyone to write to the pipe
	PSECURITY_DESCRIPTOR pSD = (PSECURITY_DESCRIPTOR) malloc(SECURITY_DESCRIPTOR_MIN_LENGTH);
	if ( !pSD )
		goto bailout2;

	if ( !InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION) )
	{
bailout3:
		free(pSD);
		goto bailout2;
	}

	// Add a NULL descriptor ACL to the security descriptor
	if ( !SetSecurityDescriptorDacl(pSD, TRUE, NULL, FALSE) )
		goto bailout3;

	SECURITY_ATTRIBUTES sa;
	sa.nLength = sizeof(sa);
	sa.lpSecurityDescriptor = pSD;
	sa.bInheritHandle = TRUE;

	if ( !SetServiceStatus(SERVICE_START_PENDING, NO_ERROR, 3000) )
		goto bailout3;

	// Set the name of the named pipe this application uses.  We create a named pipe to ensure that
	// only one instance of this application runs on the machine at a time.  If there is an instance
	// running, it will own this pipe, and any further attempts to create the same named pipe will fail.
	char lpszPipeName[80];
	sprintf(lpszPipeName, "\\\\.\\pipe\\" SPHERE_FILE "svr\\%s", g_Serv.GetName());

	char szErr[256];

	// Open the named pipe
	HANDLE hPipe = CreateNamedPipe(lpszPipeName,
		FILE_FLAG_OVERLAPPED|PIPE_ACCESS_DUPLEX,
		PIPE_TYPE_MESSAGE|PIPE_READMODE_MESSAGE|PIPE_WAIT,
		1, 0, 0, 1000, &sa);
	if ( hPipe == INVALID_HANDLE_VALUE )
	{
		ReportEvent(EVENTLOG_ERROR_TYPE, 0, "Can't create named pipe. Check multi-instance?", GetLastErrorText(szErr, sizeof(szErr)));
		goto bailout3;
	}

	if ( SetServiceStatus(SERVICE_RUNNING, NO_ERROR, 0) )
	{
		rc = Sphere_MainEntryPoint(dwArgc, lpszArgv);

		if ( !rc )
			ReportEvent(EVENTLOG_INFORMATION_TYPE, 0, "service stopped", GetLastErrorText(szErr, sizeof(szErr)));
		else
		{
			char szMessage[80];
			sprintf(szMessage, "%d.", rc);
			ReportEvent(EVENTLOG_ERROR_TYPE, 0, "service stopped abnormally", szMessage);
		}
	}
	else
		ReportEvent(EVENTLOG_ERROR_TYPE, 0, "ServiceStart failed.");

	CloseHandle(hPipe);
	goto bailout3;
}