Link to home
Start Free TrialLog in
Avatar of 10Pints
10Pints

asked on

c++ Service wont start error 1053 after a short time

Hi folks
I have written a servie (good ol VC++6) All worked fine then suddenbly I am getting a 1053 error
ERROR_SERVICE_REQUEST_TIMEOUT

So i stripped thecode to a minimum.
It happens after i create theservice and when i try to start it. this all worked fine. Tried a reboot.

It happens in the install method as it tries to start the service.
anybody got any ideas?
Ta

10Pints


//								_Service.cpp
#include "stdafx.h"
#include "resource.h"
#include <Objbase.h>
#include "_Service.h"
#include "Hook.h"

CServiceModule _Module;

BOOL __stdcall StopDependentServices();

// Although some of these functions are big they are declared inline since they are only used once
/*inline */
HRESULT CServiceModule::RegisterServer(BOOL bRegTypeLib, BOOL bService)
{
    HRESULT hr = CoInitialize(NULL);

    if (FAILED(hr))
        return hr;

    // Remove any previous service since it may point to
    // the incorrect file
    Uninstall();
    // Add service entries
    UpdateRegistryFromResource(IDR_Service, TRUE);
    // Adjust the AppID for Local Server or Service
    CRegKey keyAppID;
    LONG lRes = keyAppID.Open(HKEY_CLASSES_ROOT, _T("AppID"), KEY_WRITE);
 
	if (lRes != ERROR_SUCCESS)
        return lRes;

    CRegKey key;
    lRes = key.Open(keyAppID, _T("{AFF20158-2607-4600-A404-A46E17297F2B}"), KEY_WRITE);
 
	if (lRes != ERROR_SUCCESS)
        return lRes;

    key.DeleteValue(_T("LocalService"));
    
    if (bService)
    {
        key.SetValue(_T("Service"), _T("LocalService"));
        key.SetValue(_T("-Service"), _T("ServiceParameters"));
        // Create service
        Install();
    }

    // Add object entries
    hr = CComModule::RegisterServer(bRegTypeLib);
    CoUninitialize();
    return hr;
}


/*inline */ HRESULT CServiceModule::UnregisterServer()
{
    HRESULT hr = CoInitialize(NULL);
 
	if (FAILED(hr))
        return hr;

    // Remove service entries
    UpdateRegistryFromResource(IDR_Service, FALSE);
    // Remove service
    Uninstall();
    // Remove object entries
    CComModule::UnregisterServer(TRUE);
    CoUninitialize();
    return S_OK;
}


void CServiceModule::Init(_ATL_OBJMAP_ENTRY* p, HINSTANCE h, const char* service_name, const GUID* plibid /*= NULL*/)
{
    CComModule::Init(p, h, plibid);
    m_bService = TRUE;

	strcpy( m_szServiceName, service_name);

    //LoadString(h, nServiceNameID, m_szServiceName, sizeof(m_szServiceName) / sizeof(TCHAR));
    // set up the initial service status 
    m_hServiceStatus = NULL;
    m_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
    m_status.dwCurrentState = SERVICE_STOPPED;
    m_status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
    m_status.dwWin32ExitCode = 0;
    m_status.dwServiceSpecificExitCode = 0;
    m_status.dwCheckPoint = 0;
    m_status.dwWaitHint = 0;
}

void CServiceModule::Init(_ATL_OBJMAP_ENTRY* p, HINSTANCE h, UINT nServiceNameID, const GUID* plibid)
{
    CComModule::Init(p, h, plibid);
    m_bService = TRUE;
    LoadString(h, nServiceNameID, m_szServiceName, sizeof(m_szServiceName) / sizeof(TCHAR));
    // set up the initial service status 
    m_hServiceStatus = NULL;
    m_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
    m_status.dwCurrentState = SERVICE_STOPPED;
    m_status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
    m_status.dwWin32ExitCode = 0;
    m_status.dwServiceSpecificExitCode = 0;
    m_status.dwCheckPoint = 0;
    m_status.dwWaitHint = 0;
}


LONG CServiceModule::Unlock()
{
    LONG l = CComModule::Unlock();

    if (l == 0 && !m_bService)
        PostThreadMessage(dwThreadID, WM_QUIT, 0, 0);

    return l;
}


BOOL CServiceModule::IsRunning( void)
{
	BOOL ret = FALSE;
	SERVICE_STATUS ss = {0};

	if(!IsInstalled())
		return FALSE;

    SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);

    if (hSCM != NULL)
    {
        SC_HANDLE hService = ::OpenService(hSCM, m_szServiceName, SERVICE_QUERY_STATUS );

        if (hService != NULL)
        {

			if( QueryServiceStatus( hService, &ss))
			{
				ret = (ss.dwCurrentState == SERVICE_RUNNING) ? TRUE : FALSE;
			}
			else
			{
				DWORD dw = GetLastError();
			}

            ::CloseServiceHandle(hService);
        }

        ::CloseServiceHandle(hSCM);
    }

	return ret;
}


BOOL CServiceModule::IsInstalled()
{
    BOOL bResult = FALSE;

    SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);

    if (hSCM != NULL)
    {
        SC_HANDLE hService = ::OpenService(hSCM, m_szServiceName, SERVICE_QUERY_CONFIG);

        if (hService != NULL)
        {
            bResult = TRUE;
            ::CloseServiceHandle(hService);
        }

        ::CloseServiceHandle(hSCM);
    }

    return bResult;
}


BOOL CServiceModule::Install()
{
	BOOL ret = FALSE;
	char* p = NULL;
	SERVICE_STATUS ssStatus; 
	SERVICE_DESCRIPTION sd;
    DWORD dwOldCheckPoint; 
    DWORD dwStartTickCount;
	DWORD dwWaitTime;
	char buffer[256];

    if (IsInstalled())
        return TRUE;

    SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
   
	if (hSCM == NULL)
    {
        MessageBox(NULL, _T("Couldn't open service manager"), m_szServiceName, MB_OK);
        return FALSE;
    }

    // Get the executable file path: service and Monitor must be together
    TCHAR szFilePath[_MAX_PATH];
    ::GetModuleFileName(NULL, szFilePath, _MAX_PATH);
	
	p = strrchr(szFilePath, '\\');

	if(!p)
		return FALSE;

	*++p=0;
	strcat(p, "DepMonService.exe");

    SC_HANDLE hService = ::CreateService(	hSCM, 
											m_szServiceName, 
											m_szServiceName,
											SERVICE_ALL_ACCESS, 
											SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
											SERVICE_AUTO_START, 
											SERVICE_ERROR_NORMAL,
											szFilePath, 
											NULL, 
											NULL, 
											_T("RPCSS\0"), 
											NULL, 
											NULL);

    if (hService == NULL)
    {
        ::CloseServiceHandle(hSCM);
        MessageBox(NULL, _T("Couldn't create service"), m_szServiceName, MB_OK);
        return FALSE;
    }

	// Change the service description.

    sd.lpDescription = "Monitors Depcon Import/Export and populates the file name according to the item selected in the tree";

    if( !ChangeServiceConfig2(	hService,					// handle to service
								SERVICE_CONFIG_DESCRIPTION, // change: description
								&sd) )                      // new description
    {
         MessageBox(NULL, _T("Couldn't add service description"), m_szServiceName, MB_OK);
    }
    
	SetLastError(0);


	//------------------------------------------------------------------------------------
    // Attempt to start the service.  Bug occurs here: returns ERROR_SERVICE_REQUEST_TIMEOUT  1053 
	//------------------------------------------------------------------------------------
    if (!::StartService( hService, 0, NULL) )  
    {
		// ERROR_SERVICE_REQUEST_TIMEOUT  1053 
		DWORD error = GetLastError();
		sprintf(buffer, _T("Couldn't start service %s, (error 0x%08x (%d)) please manually start in services panel, also ensure start type is automatic"), m_szServiceName, error, error);
		LogEvent(EVENTLOG_ERROR_TYPE, buffer);
        MessageBox(NULL, buffer, m_szServiceName, MB_OK);
        CloseServiceHandle(hService); 
        CloseServiceHandle(hSCM);
        return FALSE; 
    }
    
	// Service start pending...

    // Check the status until the service is no longer start pending. 
    if (!QueryServiceStatus( hService, &ssStatus) ) 
    {
		
		sprintf(buffer, "Failed to query service status: error code(%d)\n", GetLastError());
        MessageBox(NULL, buffer, m_szServiceName, MB_OK);
        CloseServiceHandle(hService); 
        CloseServiceHandle(hSCM);
        return FALSE; 
    }

	// see if started OK:
	// Save the tick count and initial checkpoint.

    dwStartTickCount = GetTickCount();
    dwOldCheckPoint  = ssStatus.dwCheckPoint;

    while (ssStatus.dwCurrentState == SERVICE_START_PENDING) 
    { 
        // Do not wait longer than the wait hint. A good interval is 
        // one-tenth the wait hint, but no less than 1 second and no 
        // more than 10 seconds. 
 
        dwWaitTime = ssStatus.dwWaitHint / 10;

        if( dwWaitTime < 1000 )
            dwWaitTime = 1000;
        else if ( dwWaitTime > 10000 )
            dwWaitTime = 10000;

        Sleep( dwWaitTime );

        // Check the status again. 
 
        if (!QueryServiceStatus( hService, &ssStatus) ) 
        {
            printf("QueryServiceStatus failed (%d)\n", GetLastError());
			sprintf(buffer, "Failed to query service status(2): error code(%d)\n", GetLastError());
			MessageBox(NULL, buffer, m_szServiceName, MB_OK);
            break; 
        }
 
        if ( ssStatus.dwCheckPoint > dwOldCheckPoint )
        {
            // Continue to wait and check.
            dwStartTickCount = GetTickCount();
            dwOldCheckPoint = ssStatus.dwCheckPoint;
        }
        else
        {
            if(GetTickCount()-dwStartTickCount > ssStatus.dwWaitHint)
            {
                // No progress made within the wait hint.
                break;
            }
        }
    } 

    // Determine whether the service is running.
    if (ssStatus.dwCurrentState == SERVICE_RUNNING) 
    {
		ret = TRUE;
        printf("Service started successfully.\n"); 
    }
    else 
    { 
		ret = FALSE;
		printf("Service not started. \n");
    } 

    ::CloseServiceHandle(hService);
    ::CloseServiceHandle(hSCM);
    return ret;
}


BOOL CServiceModule::StartService( void)
{
    BOOL bResult = FALSE;
	SC_HANDLE hService = NULL;
	SERVICE_STATUS ssStatus;
	char buffer[256];
	DWORD dwStartTickCount;
	DWORD dwOldCheckPoint;
	DWORD dwWaitTime;
	DWORD error = 0;

    SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);

    if (hSCM != NULL)
    {
        hService = ::OpenService(hSCM, m_szServiceName, SERVICE_START | SERVICE_QUERY_STATUS  );

        if (hService == NULL)
        {
            ::CloseServiceHandle(hSCM);
			return FALSE;
        }
    }

     // Attempt to start the service.
    if (!::StartService(	hService, 0, NULL) )
    {
		error = GetLastError();

		if(error == 1056)
		{
			sprintf(buffer, "Service already started");
		}
		else
		{
			sprintf(buffer, "Couldn't start service error: %d, please manually start in services panel, also ensure start type is automatic", error);
		}

        MessageBox(NULL, buffer, m_szServiceName, MB_OK);
        CloseServiceHandle(hService); 
        CloseServiceHandle(hSCM);
        return FALSE; 
    }
    
	// Service start pending...

    // Check the status until the service is no longer start pending. 
    if (!QueryServiceStatus( hService, &ssStatus) ) 
    {
		
		sprintf(buffer, "Failed to query service status: error code(%d)\n", GetLastError());
        MessageBox(NULL, buffer, m_szServiceName, MB_OK);
        CloseServiceHandle(hService); 
        CloseServiceHandle(hSCM);
        return FALSE; 
    }

	// see if started OK:
	// Save the tick count and initial checkpoint.

    dwStartTickCount = GetTickCount();
    dwOldCheckPoint  = ssStatus.dwCheckPoint;

    while (ssStatus.dwCurrentState == SERVICE_START_PENDING) 
    { 
        // Do not wait longer than the wait hint. A good interval is 
        // one-tenth the wait hint, but no less than 1 second and no 
        // more than 10 seconds. 
 
        dwWaitTime = ssStatus.dwWaitHint / 10;

        if( dwWaitTime < 1000 )
            dwWaitTime = 1000;
        else if ( dwWaitTime > 10000 )
            dwWaitTime = 10000;

        Sleep( dwWaitTime );

        // Check the status again. 
 
        if (!QueryServiceStatus( hService, &ssStatus) ) 
        {
            printf("QueryServiceStatus failed (%d)\n", GetLastError());
			sprintf(buffer, "Failed to query service status(2): error code(%d)\n", GetLastError());
			MessageBox(NULL, buffer, m_szServiceName, MB_OK);
            break; 
        }
 
        if ( ssStatus.dwCheckPoint > dwOldCheckPoint )
        {
            // Continue to wait and check.
            dwStartTickCount = GetTickCount();
            dwOldCheckPoint = ssStatus.dwCheckPoint;
        }
        else
        {
            if(GetTickCount()-dwStartTickCount > ssStatus.dwWaitHint)
            {
                // No progress made within the wait hint.
                break;
            }
        }
    } 

    ::CloseServiceHandle(hService);
    ::CloseServiceHandle(hSCM);
	return TRUE;
}


BOOL CServiceModule::Uninstall()
{
	DWORD	error		= 0;
	BOOL	_delete	= TRUE;

    if (!IsInstalled())
        return TRUE;

    SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);

    if (hSCM == NULL)
    {
        MessageBox(NULL, _T("Couldn't open service manager"), m_szServiceName, MB_OK);
        return FALSE;
    }

    SC_HANDLE hService = ::OpenService(hSCM, m_szServiceName, SERVICE_STOP | DELETE);

    if (hService == NULL)
    {
        ::CloseServiceHandle(hSCM);
        MessageBox(NULL, _T("Couldn't open service"), m_szServiceName, MB_OK);
        return FALSE;
    }

    SERVICE_STATUS status;
    
	if(!::ControlService( hService, SERVICE_CONTROL_STOP, &status))
	{
		error = GetLastError();

		if((error !=0) && (error != ERROR_SERVICE_NOT_ACTIVE))  // 1062
		{
			// 1062: Servicxex has not been started
			char buffer[256];
			sprintf(buffer, "Service could not be stopped: error code: %d", error);
			MessageBox(NULL, buffer, m_szServiceName, MB_OK);
			::CloseServiceHandle(hService);
			::CloseServiceHandle(hSCM);
			return FALSE;
		}

		SetLastError(0);
	}

    _delete = ::DeleteService(hService);
    ::CloseServiceHandle(hService);
    ::CloseServiceHandle(hSCM);

    if(!_delete)
	{
		char buffer[256];
		error = GetLastError();

		if( (error!= 0) && ( error != ERROR_SERVICE_MARKED_FOR_DELETE)) // 1072
		{
			sprintf(buffer, "Service could not be deleted: error code: %d", error);
			MessageBox(NULL, _T("Service could not be deleted"), m_szServiceName, MB_OK);
			return FALSE;
		}

		SetLastError(0);
	}

	return TRUE;
}


///////////////////////////////////////////////////////////////////////////////////////
// Logging functions
void CServiceModule::LogEvent(LPCTSTR pFormat, ...)
{
    TCHAR    chMsg[256];
    HANDLE  hEventSource;
    LPTSTR  lpszStrings[1];
    va_list pArg;
    va_start(pArg, pFormat);
    _vstprintf(chMsg, pFormat, pArg);
    va_end(pArg);

    lpszStrings[0] = chMsg;

    if (m_bService)
    {
        /* Get a handle to use with ReportEvent(). */
        hEventSource = RegisterEventSource(NULL, m_szServiceName);
        
		if (hEventSource != NULL)
        {
            /* Write to event log. */
            ReportEvent(hEventSource, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, (LPCTSTR*) &lpszStrings[0], NULL);
            DeregisterEventSource(hEventSource);
        }
    }
    else
    {
        // As we are not running as a service, just write the error to the console.
        _putts(chMsg);
    }
}


void CServiceModule::LogEvent( int signal, LPCTSTR pszFormat, ...)
{
    TCHAR    chMsg[256];
    HANDLE  hEventSource;
    LPTSTR  lpszStrings[1];
    va_list pArg;
    va_start(pArg, pszFormat);
    _vstprintf(chMsg, pszFormat, pArg);
    va_end(pArg);

    lpszStrings[0] = chMsg;

    if (m_bService)
    {
        /* Get a handle to use with ReportEvent(). */
        hEventSource = RegisterEventSource(NULL, m_szServiceName);
        
		if (hEventSource != NULL)
        {
            /* Write to event log. */
            ReportEvent(hEventSource, signal, 0, 0, NULL, 1, 0, (LPCTSTR*) &lpszStrings[0], NULL);
            DeregisterEventSource(hEventSource);
        }
    }
    else
    {
        // As we are not running as a service, just write the error to the console.
        _putts(chMsg);
    }
}


inline void CServiceModule::ServiceMain(DWORD /* dwArgc */, LPTSTR* /* lpszArgv */)
{
    // Register the control request handler
    m_status.dwCurrentState = SERVICE_START_PENDING;
    m_hServiceStatus = RegisterServiceCtrlHandler(m_szServiceName, _Handler);
   
	if (m_hServiceStatus == NULL)
    {
        LogEvent(_T("Handler not installed"));
        return;
    }
   
	SetServiceStatus(SERVICE_START_PENDING);
    m_status.dwWin32ExitCode = S_OK;
    m_status.dwCheckPoint = 0;
    m_status.dwWaitHint = 0;
    // When the Run function returns, the service has stopped.
    Run();
    SetServiceStatus(SERVICE_STOPPED);
    LogEvent(_T("Service stopped"));
}


inline void CServiceModule::Handler(DWORD dwOpcode)
{
    switch (dwOpcode)
    {
    case SERVICE_CONTROL_STOP:
        //SetServiceStatus(SERVICE_STOP_PENDING);
        //PostThreadMessage(dwThreadID, WM_QUIT, 0, 0);
		Stop();
        break;

    case SERVICE_CONTROL_PAUSE:
        break;

    case SERVICE_CONTROL_CONTINUE:
        break;

    case SERVICE_CONTROL_INTERROGATE:
        break;

    case SERVICE_CONTROL_SHUTDOWN:
        break;

    default:
        LogEvent(_T("Bad service request"));
    }
}


void CServiceModule::Stop( void)
{
    SetServiceStatus(SERVICE_STOP_PENDING);
    PostThreadMessage(dwThreadID, WM_QUIT, 0, 0);
	CloseLog();
}


/* 
DESC: Service startup and registration

  if not a service then calls Run - not the other way round
*/
void CServiceModule::Start()
{
    SERVICE_TABLE_ENTRY st[] =
    {
        { m_szServiceName, _ServiceMain },
        { NULL, NULL }
    };

    if (m_bService && !::StartServiceCtrlDispatcher(st))
    {
        m_bService = FALSE;
    }

/*
	Temporaily stripped out
  This all the code has to do: initialise and start a new watch thread
	if(!::InitHook())
	{
	}

	Watch4DepconLaunch();
*/
    if (m_bService == FALSE)
        Run();
}


void CServiceModule::OnStop( void)
{
	Log(1, "Onstop called");
	Term();
}


void CServiceModule::OnContinue( void)
{
	Log(1, "OnContinue called");
}


void CServiceModule::OnShutdown( void)
{
	Log(1, "OnShutdown called");
	Term();
}


void WINAPI CServiceModule::_ServiceMain(DWORD dwArgc, LPTSTR* lpszArgv)
{
    _Module.ServiceMain(dwArgc, lpszArgv);
}


void WINAPI CServiceModule::_Handler(DWORD dwOpcode)
{
    _Module.Handler(dwOpcode); 
}


void CServiceModule::SetServiceStatus(DWORD dwState)
{
    m_status.dwCurrentState = dwState;
    ::SetServiceStatus(m_hServiceStatus, &m_status);
}


void CServiceModule::Run()
{
    _Module.dwThreadID = GetCurrentThreadId();

    HRESULT hr = CoInitialize(NULL);
//  If you are running on NT 4.0 or higher you can use the following call
//  instead to make the EXE free threaded.
//  This means that calls come in on a random RPC thread
//  HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);

    _ASSERTE(SUCCEEDED(hr));

    // This provides a NULL DACL which will allow access to everyone.
    CSecurityDescriptor sd;
    sd.InitializeFromThreadToken();
    hr = CoInitializeSecurity(sd, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
    _ASSERTE(SUCCEEDED(hr));
    hr = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER, REGCLS_MULTIPLEUSE);
    _ASSERTE(SUCCEEDED(hr));

    LogEvent(_T("Service started"));
    
	if (m_bService)
        SetServiceStatus(SERVICE_RUNNING);

    MSG msg;
    while (GetMessage(&msg, 0, 0, 0))
        DispatchMessage(&msg);

    _Module.RevokeClassObjects();

    CoUninitialize();
}



void CServiceModule::StopService( void)
{
	SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
	SC_HANDLE hService = OpenService(  hSCM, m_szServiceName,  SERVICE_STOP | SERVICE_QUERY_STATUS | SERVICE_ENUMERATE_DEPENDENTS);  
 
    if (hService == NULL)
    { 
		char buffer[256];
        sprintf(buffer, "OpenService failed (%d)\n", GetLastError()); 
		::MessageBox( NULL, buffer, "", MB_OK);
        CloseServiceHandle(hSCM);
        return;
    }    

	StopService( hSCM, hService);
}


//
// Purpose: 
//   Stops the service.
//
// Parameters:
//   None
// 
// Return value:
//   None
//
VOID __stdcall CServiceModule::StopService( SC_HANDLE schSCManager, SC_HANDLE hService)
{
    //SERVICE_STATUS_PROCESS ssp;
    SERVICE_STATUS ss;
    DWORD dwStartTime = GetTickCount();
    //DWORD dwBytesNeeded;
    DWORD dwTimeout = 30000; // 30-second time-out
    DWORD dwWaitTime;
	char buffer[256];
	*buffer = 0;

    // Get a handle to the SCM database. 
 /*
    schSCManager = OpenSCManager( 
        NULL,                    // local computer
        NULL,                    // ServicesActive database 
        SC_MANAGER_ALL_ACCESS);  // full access rights 
 
    if (NULL == schSCManager) 
    {
        printf("OpenSCManager failed (%d)\n", GetLastError());
        return;
    }

    // Get a handle to the service.

    schService = OpenService( 
        schSCManager,         // SCM database 
        szSvcName,            // name of service 
        SERVICE_STOP | 
        SERVICE_QUERY_STATUS | 
        SERVICE_ENUMERATE_DEPENDENTS);  
 
    if (schService == NULL)
    { 
        printf("OpenService failed (%d)\n", GetLastError()); 
        CloseServiceHandle(schSCManager);
        return;
    }    
*/
    // Make sure the service is not already stopped.

/*    if ( !QueryServiceStatusEx( 
            hService, 
            SC_STATUS_PROCESS_INFO,
            (LPBYTE)&ssp, 
            sizeof(SERVICE_STATUS_PROCESS),
            &dwBytesNeeded ) )
			*/

	if(!QueryServiceStatus(hService, & ss))
    {
        sprintf(buffer, "QueryServiceStatusEx failed (%d)\n", GetLastError()); 
        goto stop_cleanup;
    }

    if ( ss.dwCurrentState == SERVICE_STOPPED )
    {
        //sprintf(buffer, "Service is already stopped.\n");
        goto stop_cleanup;
    }

    // If a stop is pending, wait for it.

    while ( ss.dwCurrentState == SERVICE_STOP_PENDING ) 
    {
        //printf("Service stop pending...\n");

        // Do not wait longer than the wait hint. A good interval is 
        // one-tenth of the wait hint but not less than 1 second  
        // and not more than 10 seconds. 
 
        dwWaitTime = ss.dwWaitHint / 10;

        if( dwWaitTime < 1000 )
            dwWaitTime = 1000;
        else if ( dwWaitTime > 10000 )
            dwWaitTime = 10000;

        Sleep( dwWaitTime );
		if(!QueryServiceStatus(hService, & ss))
        {
            sprintf(buffer, "QueryServiceStatusEx failed (%d)\n", GetLastError()); 
            goto stop_cleanup;
        }

        if ( ss.dwCurrentState == SERVICE_STOPPED )
        {
            printf("Service stopped successfully.\n");
            goto stop_cleanup;
        }

        if ( GetTickCount() - dwStartTime > dwTimeout )
        {
            printf("Service stop timed out.\n");
            goto stop_cleanup;
        }
    }

    // If the service is running, dependencies must be stopped first.

    StopDependentServices( schSCManager, hService);

    // Send a stop code to the service.

    if ( !ControlService( hService, SERVICE_CONTROL_STOP,&ss ) )
    {
        sprintf( buffer, "ControlService failed (%d)\n", GetLastError() );
        goto stop_cleanup;
    }

    // Wait for the service to stop.

    while ( ss.dwCurrentState != SERVICE_STOPPED ) 
    {
        Sleep( ss.dwWaitHint);

        if ( !QueryServiceStatus( hService, &ss) )
        {
            sprintf( buffer, "QueryServiceStatusEx failed (%d)\n", GetLastError() );
            goto stop_cleanup;
        }

        if ( ss.dwCurrentState == SERVICE_STOPPED )
            break;

        if ( GetTickCount() - dwStartTime > dwTimeout )
        {
            printf( "Wait timed out\n" );
            goto stop_cleanup;
        }
    }
    
	//printf("Service stopped successfully\n");

stop_cleanup:

	if(*buffer)
	{
		MessageBox(NULL, _T(buffer), m_szServiceName, MB_OK);
	}
	else
	{
		MessageBox(NULL, _T("Service stopped"), m_szServiceName, MB_OK);
	}

    //CloseServiceHandle(hService); 
    //CloseServiceHandle(schSCManager);
}


BOOL __stdcall CServiceModule::StopDependentServices( SC_HANDLE schSCManager, SC_HANDLE hService)
{
    DWORD i;
    DWORD dwBytesNeeded;
    DWORD dwCount;

    LPENUM_SERVICE_STATUS   lpDependencies = NULL;
    ENUM_SERVICE_STATUS     ess;
    SC_HANDLE               hDepService;
    SERVICE_STATUS			ss;

    DWORD dwStartTime = GetTickCount();
    DWORD dwTimeout = 30000; // 30-second time-out

    // Pass a zero-length buffer to get the required buffer size.
    if ( EnumDependentServices( hService, SERVICE_ACTIVE, lpDependencies, 0, &dwBytesNeeded, &dwCount ) ) 
    {
         // If the Enum call succeeds, then there are no dependent
         // services, so do nothing.
         return TRUE;
    } 
    else 
    {
        if ( GetLastError() != ERROR_MORE_DATA )
            return FALSE; // Unexpected error

        // Allocate a buffer for the dependencies.
        lpDependencies = (LPENUM_SERVICE_STATUS) HeapAlloc( 
            GetProcessHeap(), HEAP_ZERO_MEMORY, dwBytesNeeded );
  
        if ( !lpDependencies )
            return FALSE;

        __try {
            // Enumerate the dependencies.
            if ( !EnumDependentServices( hService, SERVICE_ACTIVE, 
                lpDependencies, dwBytesNeeded, &dwBytesNeeded,
                &dwCount ) )
            return FALSE;

            for ( i = 0; i < dwCount; i++ ) 
            {
                ess = *(lpDependencies + i);
                // Open the service.
                hDepService = OpenService( schSCManager, 
                   ess.lpServiceName, 
                   SERVICE_STOP | SERVICE_QUERY_STATUS );

                if ( !hDepService )
                   return FALSE;

                __try {
                    // Send a stop code.
                    if ( !ControlService( hDepService, SERVICE_CONTROL_STOP, &ss ) )
                    return FALSE;

                    // Wait for the service to stop.
                    while ( ss.dwCurrentState != SERVICE_STOPPED ) 
                    {
                        Sleep( ss.dwWaitHint );

                        if ( !QueryServiceStatus( hDepService, &ss) )
							return FALSE;

                        if ( ss.dwCurrentState == SERVICE_STOPPED )
                            break;

                        if ( GetTickCount() - dwStartTime > dwTimeout )
                            return FALSE;
                    }
                } 
                __finally 
                {
                    // Always release the service handle.
                    CloseServiceHandle( hDepService );
                }
            }
        } 
        __finally 
        {
            // Always free the enumeration buffer.
            HeapFree( GetProcessHeap(), 0, lpDependencies );
        }
    } 

    return TRUE;
}


bool CServiceModule::DeleteService()
{
	SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
	SC_HANDLE hService = OpenService(  hSCM, m_szServiceName,  DELETE |SERVICE_STOP | SERVICE_QUERY_STATUS | SERVICE_ENUMERATE_DEPENDENTS);  
 
    if (hService == NULL)
    { 
		char buffer[256];
        sprintf(buffer, "OpenService failed (%d)\n", GetLastError()); 
		::MessageBox( NULL, buffer, "", MB_OK);
        CloseServiceHandle(hSCM);
        return false;
    }   
	
	if(!::DeleteService( hService))
	{
		char buffer[256];
        sprintf(buffer, "DeleteService failed (%d)\n", GetLastError()); 
		::MessageBox( NULL, buffer, "", MB_OK);
        CloseServiceHandle(hSCM);
        CloseServiceHandle(hService);
        return false;
	}

	::MessageBox( NULL, "Service Deleted", "", MB_OK);
	return true;
}

Open in new window

Avatar of mastoo
mastoo
Flag of United States of America image

The service installs ok and shows up in your list of installed services?  If you start if from there you get a similar error?
Avatar of AndyAinscow
If it once started OK but now doesn't and you haven't changed anything - then what has changed on the server?
Avatar of 10Pints
10Pints

ASKER

Gentlemen:
many thanks for response.
right I've narrowed it down to:
inline void CServiceModule::Start()
{
    SERVICE_TABLE_ENTRY st[] =
    {
        { m_szServiceName, _ServiceMain },
        { NULL, NULL }
    };

    if (m_bService && !::StartServiceCtrlDispatcher(st))
    {
        m_bService = FALSE;
    }

    if (m_bService == FALSE)
      {
        Run();
      }
      else
      {
//            DebugBreak();
            //::InitHook();
            Dummy();
            //if(::InitHook())
            //{
                  // Start Depcon watch thread
                  //Watch4DepconLaunch();
            /*
            }
            else
            {
                  LogEvent(_T("Hook failed to initialise"));
            }
            */
      }
}


Even with a dummy call it fails.
the Dummy is the only function called that resides in the hook dll
it is simply:
BOOL Dummy()
{
      return TRUE;
}

Declared as:
BOOL HOOKDLL_API Dummy( void);

where the follwoing is defiend in a common header (between the Dll project and the service Project.
#ifdef HOOKDLL_EXPORTS
#define HOOKDLL_API __declspec(dllexport)
#else
#define HOOKDLL_API __declspec(dllimport)
#endif

In the usual maner.

the plan is for the service to make 1 call to initialise some stuff, then another call to a function that starts a thread to watch for the target exe to be launched.
When it is the thread will hook it and the Hook dlll injected.

I don't seem to be able to run the service from the Services Dialog
But I can register it in debug with the debugger, and it will setep into the Dll code.

Both the DLL and the exe reside in the same place:   D:\Data\Dev\Depcon\Code\Debug

Q: is the exe copied and placed else where when it is registered?
then the Dll would not be available ...

T

Avatar of 10Pints

ASKER

Got some more on this:
Tried LoadLibrary with the hook dll and it fails when I try to explicitly load when the Servic starts: (Full path provided to dll) with error 998: ERROR_NOACCESS  Invalid access to memory location.

It does however load in debug mode.
I am trying to do this from the service start routine, and may be I should delay it untill a little later, like after the win main routine ends? - Separate thread may be and a wait?
I presume that service start is called from win winmain. I read somewhere that therea mumber of restrictions on what you can do untill WinMain returns ...
any thoughts guys?
 
Avatar of 10Pints

ASKER

Got it:
Winows returns this also when ther has been an access violation.

This brings me to the real stumper: I want to use the service to monitor an application and support it: my client requires it to automatically populate certain fiields when the user clicks on nodes in the tree.  

I have this working fine from a separte window app, but when I run it as a service I get caught in the can't both raise a service with interact with desktop rights and under an account with sufficinet rights to hook the app.

I either get an error  87 launching the non Local system Service with  interact with desktop or

error 5 ( access denied) if I  launch it as a Local system one then call SetWindowsHookEx....

Help!!!!

I will raise a separate question with this, but if can help here then great ans please  take the points






I know people successfully write services that interact with the desktop(s), but I find it cleaner to write an exe that starts when they log on instead.  That way it runs as them so no special account is required, and it has no problem interacting with desktop apps the user runs.  You can either put the app in the start folder or put it in the Run registry key.
Avatar of 10Pints

ASKER

Ah thanks!
yes that would be easier.
What I think I should try then is to:
Put a start up entry for a hidden windows Monitor app in the reg (via installer)
This app will then periodiaclly poll for the existence of theclient app and hookit when it appears
It will then poll for the disappearance so it can then reset its state to watch for the app again when the window dissappears.

I will need to guarantee 1 instance of the monitor. (May be per instance of the client app  so my hooks dont get duplicated etc.)

mmm... Question:

Could I then have my service simply makesure my monitor app is running - using PSAPI metthods
and shellExec themontor should it be inadvertantly closed?

what do you reckon?
ASKER CERTIFIED SOLUTION
Avatar of mastoo
mastoo
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of 10Pints

ASKER

Yep and your latter point: thats exactly the reason, and I would have a quaranteed singleton instance for the service.

I am swinging the code over now to try this

ta

T
Avatar of 10Pints

ASKER

Right got the follwoing scenario in place:
Monitor monitor Service createed with not interact wi desktop, user creds: user/password
Service polls for monitor - works - but by using the the PsAPI EnumProcesses()
Launches Monitor if monitor is not running- works
But now the monitor is monitoring the wrong desktop session - i.e FindWindow will not detect the client app window.

If I install the service with interact wi desktop wi no user creds, the SetWindows hook fails: error 5  ACCESS_DENIED.

I can hook the client process I guess directly using EnumProcesses, but then my issue will be:
How do I detect the thread that launches the target window: ( I am only interested in one particular window which is always started on a new thread). Even then I still need to catch the WM_COMMAND messages and send windows messages.

Argh!!!!!!!!!!!!!!

I gues its back to the original approach - launch the hidden app automatically at startup and hope that it does not fail.
I could I suppose make cle client app's desktop short cut go to my monitor app directly, so that it is launched by the user when they think they are launching the client app, and this would then automatically launch the client app.

That sounds good. May be I need to supply a start up parameter so that when the monitor is automatically launched at log on then it does NOT immediatly launch depcon.

mmm that would work.  I just hate giving up on this service based appraoch - just hate it....
Avatar of 10Pints

ASKER

It seems to me that Windows security will not allow for the scenario of a service starting an app with full user rights eiter you get an error 87 launching the service with sufficent rights, or you launch the service as LOCAL SYSTEM but the hooks fail with error 5 ACCESS DENIED.

Please accept the points