//
//  Copyright (c) 2001, Reson, Inc. All Rights Reserved.
//
//  Filename:   Service.cpp
//
//  Project:    6046.
//
//  Author(s):  W. Arcus
//
//  Purpose:    Implements a service helper class.
//
//  Notes:

#include "StdAfx.h"
#include "Service.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// CComponentService class implementation - only relavent to a true NT service
// and not a console program.

LPHANDLER_FUNCTION CComponentService::m_lpHandler = NULL;

CComponentService::CComponentService( DWORD dwServiceType )
{
    m_lpHandler      = NULL;
    m_hServiceStatus = NULL;

    ::ZeroMemory( &m_ServiceStatus, sizeof( SERVICE_STATUS ) );

    m_ServiceStatus.dwServiceType = dwServiceType;
}

CComponentService::~CComponentService( void )
{
}

BOOL CComponentService::RegisterHandler(    LPCTSTR             lpszServiceName,
                                            LPHANDLER_FUNCTION  lpHandler )
{
    m_hServiceStatus = ::RegisterServiceCtrlHandler( lpszServiceName, lpHandler );

    return ( m_hServiceStatus != NULL );
}

BOOL CComponentService::ReportStatusChange( DWORD   dwCurrentState,
                                            DWORD   dwControlsAccepted,
                                            DWORD   dwWaitHint,
                                            DWORD   dwWin32ExitCode,
                                            DWORD   dwProcessSpecificExitCode )
{
    m_ServiceStatus.dwCurrentState            = dwCurrentState;
    m_ServiceStatus.dwControlsAccepted        = dwControlsAccepted;
    m_ServiceStatus.dwWin32ExitCode           = dwWin32ExitCode;
    m_ServiceStatus.dwServiceSpecificExitCode = dwProcessSpecificExitCode;

    switch ( dwCurrentState )
    {
        case SERVICE_START_PENDING:
        case SERVICE_STOP_PENDING:
        case SERVICE_PAUSE_PENDING:
        case SERVICE_CONTINUE_PENDING:

            // dwCheckPoint and dwWaitHint are used to periodically reassure the 
            // Service Control Manager. While you are in one of the pending states 
            // dwWaitHint is the number of milliseconds you expect the operation to take. 
            // After that much time, the Service Control Manager will ask you how you’re going.
            // If it does not receive an updated dwCheckPoint by then, it assumes you’ve failed and 
            // gives up.

            m_ServiceStatus.dwCheckPoint = 1;
            m_ServiceStatus.dwWaitHint   = dwWaitHint;

            break;

        default:

            m_ServiceStatus.dwCheckPoint = 0;
            m_ServiceStatus.dwWaitHint   = 0;

            break;
        }

    return SetStatus();
}

BOOL CComponentService::SetPendingStatus(   DWORD   dwCurrentState,
                                            DWORD   dwWaitHint,
                                            DWORD   dwCheckPoint )
{
    m_ServiceStatus.dwCurrentState            = dwCurrentState;

    // We set dwControlsAccepted to zero to disable control requests 
    // while in a transitional state.

    m_ServiceStatus.dwControlsAccepted        = 0;
    m_ServiceStatus.dwWin32ExitCode           = 0;
    m_ServiceStatus.dwServiceSpecificExitCode = 0;

    m_ServiceStatus.dwWaitHint                = dwWaitHint;
    m_ServiceStatus.dwCheckPoint              = dwCheckPoint;

    return SetStatus();
}

BOOL CComponentService::UpdateStatus( void )
{
    if ( m_ServiceStatus.dwCheckPoint > 0 )
    {
        ++m_ServiceStatus.dwCheckPoint;
    }

   return SetStatus();
}

BOOL CComponentService::SetStatus( void )
{
    return ( ::SetServiceStatus( m_hServiceStatus, &m_ServiceStatus ) );
}

