(file) Return to ServiceWindows.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Pegasus / Common

File: [Pegasus] / pegasus / src / Pegasus / Common / Attic / ServiceWindows.cpp (download)
Revision: 1.8, Fri May 31 23:56:37 2002 UTC (22 years, 1 month ago) by kumpf
Branch: MAIN
CVS Tags: test, pep_88, mday-merge-start, mday-merge-pegasus/src/Pegasus/Server, mday-merge-pegasus/src/Pegasus/Common, mday-2-0-patches, VERSION_2_1_RELEASE_HEAD, VERSION_2_1_RELEASE_BRANCH, VERSION_2_1_RELEASE, VERSION_2_1_1_RELEASE, VERSION_2_01_01, VERSION_2_00_RC_4, VERSION_2_00_RC_3, VERSION_2_00_RC_2, VERSION_2_00_RC_1, VERSION_2_00_BRANCH, VERSION_1_10, TEST, STABLE, RELEASE_2_3_0-msg-freeze, RELEASE_2_2_1-snapshot, RELEASE_2_2_0_0-release, RELEASE_2_2_0-root, RELEASE_2_2_0-branch, RELEASE_2_2-root, PRE_LICENSE_UPDATE_2003, PEGASUS_FC_VERSION_2_2, LOCAL_ASSOCPROV-ROOT, LOCAL_ASSOCPROV-BRANCH
Changes since 1.7: +9 -8 lines
HP-RK Update license header.

//%/////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2000, 2001, 2002 BMC Software, Hewlett-Packard Company, IBM,
// The Open Group, Tivoli Systems
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// 
// THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
// ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
// "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//==============================================================================
//
// Author: Mike Brasher (mbrasher@bmc.com)
//
// Modified By:
//
//%/////////////////////////////////////////////////////////////////////////////

#include <windows.h>
#include <cstdio>
#include <string>
#include <fstream>
#include <cstdlib>
#include "Service.h"

PEGASUS_NAMESPACE_BEGIN

using namespace std;

struct ClientData
{
    int argc;
    char** argv;
};

static const char* _serviceName = "";
static HANDLE _terminateEvent = NULL;
static SERVICE_STATUS_HANDLE _serviceStatusHandle = NULL;
static HANDLE _threadHandle = 0;
static BOOL _serviceRunning = FALSE;
static BOOL _servicePaused = FALSE;
static SERVICE_TABLE_ENTRY _serviceTable[2];
static ServiceHandler* _serviceHandler = 0;
static ClientData _clientData;

static void _stopService() 
{
    _serviceRunning = FALSE;
    SetEvent(_terminateEvent);
}

static BOOL _sendStatusToSCM(
    DWORD dwCurrentState,
    DWORD dwWin32ExitCode, 
    DWORD dwServiceSpecificExitCode,
    DWORD dwCheckPoint,
    DWORD dwWaitHint)
{
    SERVICE_STATUS serviceStatus;

    serviceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
    serviceStatus.dwCurrentState = dwCurrentState;

    if (dwCurrentState == SERVICE_START_PENDING)
	serviceStatus.dwControlsAccepted = 0;
    else
    {
	serviceStatus.dwControlsAccepted = 
	    SERVICE_ACCEPT_STOP |
	    SERVICE_ACCEPT_PAUSE_CONTINUE |
	    SERVICE_ACCEPT_SHUTDOWN;
    }

    if (dwServiceSpecificExitCode == 0)
	serviceStatus.dwWin32ExitCode = dwWin32ExitCode;
    else
	serviceStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;

    serviceStatus.dwServiceSpecificExitCode = dwServiceSpecificExitCode;
    serviceStatus.dwCheckPoint = dwCheckPoint;
    serviceStatus.dwWaitHint = dwWaitHint;

    BOOL success = SetServiceStatus(_serviceStatusHandle, &serviceStatus);

    if (!success)
	_stopService();

    return success;
}

static void _resumeService() 
{
    _servicePaused = FALSE;
    ResumeThread(_threadHandle);
}

static void _pauseService() 
{
    _servicePaused = TRUE;
    SuspendThread(_threadHandle);
}

static void _terminate(DWORD error)
{
    if (_terminateEvent)
	CloseHandle(_terminateEvent);

    if (_serviceStatusHandle)
	_sendStatusToSCM(SERVICE_STOPPED, error, 0, 0, 0);

    if (_threadHandle)
	CloseHandle(_threadHandle);
}

static DWORD _serviceThread(LPDWORD param)
{
    ClientData* clientData = (ClientData*)param;
    int status = _serviceHandler->main(clientData->argc, clientData->argv);
    return status;
}

static void _serviceCtrlHandler(DWORD controlCode) 
{
    DWORD  currentState = 0;

    switch(controlCode)
    {
	case SERVICE_CONTROL_STOP:
	{
	    SERVICE_STOP_PENDING;
	    _sendStatusToSCM( SERVICE_STOP_PENDING, NO_ERROR, 0, 1, 5000);
	    _stopService();
	    _serviceHandler->stop();
	    return;
	}

	case SERVICE_CONTROL_PAUSE:
	{
	    if (_serviceRunning && !_servicePaused)
	    {
		_sendStatusToSCM(SERVICE_PAUSE_PENDING, NO_ERROR, 0, 1, 1000);
		_pauseService();
		currentState = SERVICE_PAUSED;
		_serviceHandler->pause();
	    }
	    break;
	}

	case SERVICE_CONTROL_CONTINUE:
	{
	    if (_serviceRunning && _servicePaused)
	    {
		_sendStatusToSCM( 
		    SERVICE_CONTINUE_PENDING, NO_ERROR, 0, 1, 1000);
		_resumeService();
		currentState = SERVICE_RUNNING;
		_serviceHandler->resume();
	    }
	    break;
	}

	case SERVICE_CONTROL_INTERROGATE:
	case SERVICE_CONTROL_SHUTDOWN:
	default:
	    break;
    }

    _sendStatusToSCM(currentState, NO_ERROR, 0, 0, 0);
}

static void _serviceMain(DWORD argc, LPTSTR *argv) 
{
    // Register the service control handler:

    _serviceStatusHandle = RegisterServiceCtrlHandler(
	_serviceName, (LPHANDLER_FUNCTION)_serviceCtrlHandler);

    if (!_serviceStatusHandle)
    {
	_terminate(GetLastError()); 
	return;
    }

    if (!_sendStatusToSCM(SERVICE_START_PENDING, NO_ERROR, 0, 1, 5000))
    {
	_terminate(GetLastError()); 
	return;
    }

    if (!(_terminateEvent = CreateEvent (0, TRUE, FALSE, 0)))
    {
	_terminate(GetLastError());
	return;
    }

    if (!_sendStatusToSCM(SERVICE_START_PENDING, NO_ERROR, 0, 2, 1000))
    {
	_terminate(GetLastError()); 
	return;
    }

    if (!_sendStatusToSCM(SERVICE_START_PENDING, NO_ERROR, 0, 3, 5000))
    {
	_terminate(GetLastError()); 
	return;
    }

    // Create the service thread:

    _clientData.argc = argc;
    _clientData.argv = argv;
    DWORD id;

    _threadHandle = CreateThread(
	0, 0, (LPTHREAD_START_ROUTINE)_serviceThread, &_clientData, 0, &id); 

    if (_threadHandle)
	_serviceRunning = TRUE;
    else
    {
	_terminate(GetLastError());
	return;
    }

    // Send status to SCM:

    if (!_sendStatusToSCM( SERVICE_RUNNING, NO_ERROR, 0, 0, 0))
    {
	_terminate(GetLastError()); 
	return;
    }

    // Wait for termination!

    WaitForSingleObject(_terminateEvent, INFINITE);
    _terminate(0);
}

bool Service::run(
    int argc,
    char** argv,
    const char* serviceName, 
    ServiceHandler* serviceHandler,
    bool detach)
{
    if (!detach)
    {
        serviceHandler->main(argc, argv);
        return false;
    }

    _serviceHandler = serviceHandler;

    _serviceName = serviceName;
    _serviceTable[0].lpServiceName = (char*)serviceName;
    _serviceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)_serviceMain;
    _serviceTable[1].lpServiceName = NULL;
    _serviceTable[1].lpServiceProc = NULL;

    return StartServiceCtrlDispatcher(_serviceTable) ? true : false;
}

PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2