diff options
Diffstat (limited to 'service-win32/service.c')
-rw-r--r-- | service-win32/service.c | 695 |
1 files changed, 0 insertions, 695 deletions
diff --git a/service-win32/service.c b/service-win32/service.c deleted file mode 100644 index 91b5821..0000000 --- a/service-win32/service.c +++ /dev/null @@ -1,695 +0,0 @@ -/*--------------------------------------------------------------------------- -THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF -ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A -PARTICULAR PURPOSE. - -Copyright (C) 1993 - 2000. Microsoft Corporation. All rights reserved. - -MODULE: service.c - -PURPOSE: Implements functions required by all Windows NT services - -FUNCTIONS: - main(int argc, char **argv); - service_ctrl(DWORD dwCtrlCode); - service_main(DWORD dwArgc, LPTSTR *lpszArgv); - CmdInstallService(); - CmdRemoveService(); - CmdStartService(); - CmdDebugService(int argc, char **argv); - ControlHandler ( DWORD dwCtrlType ); - GetLastErrorText( LPTSTR lpszBuf, DWORD dwSize ); - ----------------------------------------------------------------------------*/ - -#include <windows.h> -#include <stdio.h> -#include <stdlib.h> -#include <process.h> -#include <tchar.h> - -#include "service.h" - -// internal variables -SERVICE_STATUS ssStatus; // current status of the service -SERVICE_STATUS_HANDLE sshStatusHandle; -DWORD dwErr = 0; -BOOL bDebug = FALSE; -TCHAR szErr[256]; - -// internal function prototypes -VOID WINAPI service_ctrl(DWORD dwCtrlCode); -VOID WINAPI service_main(DWORD dwArgc, LPTSTR *lpszArgv); -int CmdInstallService(); -int CmdRemoveService(); -int CmdStartService(); -VOID CmdDebugService(int argc, char **argv); -BOOL WINAPI ControlHandler ( DWORD dwCtrlType ); -LPTSTR GetLastErrorText( LPTSTR lpszBuf, DWORD dwSize ); - -// -// FUNCTION: main -// -// PURPOSE: entrypoint for service -// -// PARAMETERS: -// argc - number of command line arguments -// argv - array of command line arguments -// -// RETURN VALUE: -// none -// -// COMMENTS: -// main() either performs the command line task, or -// call StartServiceCtrlDispatcher to register the -// main service thread. When the this call returns, -// the service has stopped, so exit. -// -int __cdecl main(int argc, char **argv) -{ - SERVICE_TABLE_ENTRY dispatchTable[] = - { - { TEXT(SZSERVICENAME), (LPSERVICE_MAIN_FUNCTION)service_main}, - { NULL, NULL} - }; - - if ( (argc > 1) && - ((*argv[1] == '-') || (*argv[1] == '/')) ) - { - if ( _stricmp( "install", argv[1]+1 ) == 0 ) - { - return CmdInstallService(); - } - else if ( _stricmp( "remove", argv[1]+1 ) == 0 ) - { - return CmdRemoveService(); - } - else if ( _stricmp( "start", argv[1]+1 ) == 0) - { - return CmdStartService(); - } - else if ( _stricmp( "debug", argv[1]+1 ) == 0 ) - { - bDebug = TRUE; - CmdDebugService(argc, argv); - } - else - { - goto dispatch; - } - return 0; - } - - // if it doesn't match any of the above parameters - // the service control manager may be starting the service - // so we must call StartServiceCtrlDispatcher - dispatch: - // this is just to be friendly - printf( "%s -install to install the service\n", SZAPPNAME ); - printf( "%s -start to start the service\n", SZAPPNAME ); - printf( "%s -remove to remove the service\n", SZAPPNAME ); - printf( "%s -debug <params> to run as a console app for debugging\n", SZAPPNAME ); - printf( "\nStartServiceCtrlDispatcher being called.\n" ); - printf( "This may take several seconds. Please wait.\n" ); - - if (!StartServiceCtrlDispatcher(dispatchTable)) - AddToMessageLog(MSG_FLAGS_ERROR, TEXT("StartServiceCtrlDispatcher failed.")); - - return 0; -} - - - -// -// FUNCTION: service_main -// -// PURPOSE: To perform actual initialization of the service -// -// PARAMETERS: -// dwArgc - number of command line arguments -// lpszArgv - array of command line arguments -// -// RETURN VALUE: -// none -// -// COMMENTS: -// This routine performs the service initialization and then calls -// the user defined ServiceStart() routine to perform majority -// of the work. -// -void WINAPI service_main(DWORD dwArgc, LPTSTR *lpszArgv) -{ - - // register our service control handler: - // - sshStatusHandle = RegisterServiceCtrlHandler( TEXT(SZSERVICENAME), service_ctrl); - - if (!sshStatusHandle) - goto cleanup; - - // SERVICE_STATUS members that don't change in example - // - ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; - ssStatus.dwServiceSpecificExitCode = 0; - - - // report the status to the service control manager. - // - if (!ReportStatusToSCMgr( - SERVICE_START_PENDING, // service state - NO_ERROR, // exit code - 3000)) // wait hint - goto cleanup; - - - ServiceStart( dwArgc, lpszArgv ); - - cleanup: - - // try to report the stopped status to the service control manager. - // - if (sshStatusHandle) - (VOID)ReportStatusToSCMgr( - SERVICE_STOPPED, - dwErr, - 0); - - return; -} - - - -// -// FUNCTION: service_ctrl -// -// PURPOSE: This function is called by the SCM whenever -// ControlService() is called on this service. -// -// PARAMETERS: -// dwCtrlCode - type of control requested -// -// RETURN VALUE: -// none -// -// COMMENTS: -// -VOID WINAPI service_ctrl(DWORD dwCtrlCode) -{ - // Handle the requested control code. - // - switch (dwCtrlCode) - { - // Stop the service. - // - // SERVICE_STOP_PENDING should be reported before - // setting the Stop Event - hServerStopEvent - in - // ServiceStop(). This avoids a race condition - // which may result in a 1053 - The Service did not respond... - // error. - case SERVICE_CONTROL_STOP: - ReportStatusToSCMgr(SERVICE_STOP_PENDING, NO_ERROR, 0); - ServiceStop(); - return; - - // Update the service status. - // - case SERVICE_CONTROL_INTERROGATE: - break; - - // invalid control code - // - default: - break; - - } - - ReportStatusToSCMgr(ssStatus.dwCurrentState, NO_ERROR, 0); -} - - - -// -// FUNCTION: ReportStatusToSCMgr() -// -// PURPOSE: Sets the current status of the service and -// reports it to the Service Control Manager -// -// PARAMETERS: -// dwCurrentState - the state of the service -// dwWin32ExitCode - error code to report -// dwWaitHint - worst case estimate to next checkpoint -// -// RETURN VALUE: -// TRUE - success -// FALSE - failure -// -// COMMENTS: -// -BOOL ReportStatusToSCMgr(DWORD dwCurrentState, - DWORD dwWin32ExitCode, - DWORD dwWaitHint) -{ - static DWORD dwCheckPoint = 1; - BOOL fResult = TRUE; - - - if ( !bDebug ) // when debugging we don't report to the SCM - { - if (dwCurrentState == SERVICE_START_PENDING) - ssStatus.dwControlsAccepted = 0; - else - ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP; - - ssStatus.dwCurrentState = dwCurrentState; - ssStatus.dwWin32ExitCode = dwWin32ExitCode; - ssStatus.dwWaitHint = dwWaitHint; - - if ( ( dwCurrentState == SERVICE_RUNNING ) || - ( dwCurrentState == SERVICE_STOPPED ) ) - ssStatus.dwCheckPoint = 0; - else - ssStatus.dwCheckPoint = dwCheckPoint++; - - - // Report the status of the service to the service control manager. - // - if (!(fResult = SetServiceStatus( sshStatusHandle, &ssStatus))) - { - AddToMessageLog(MSG_FLAGS_ERROR, TEXT("SetServiceStatus")); - } - } - return fResult; -} - - - -// -// FUNCTION: AddToMessageLog(LPTSTR lpszMsg) -// -// PURPOSE: Allows any thread to log an error message -// -// PARAMETERS: -// lpszMsg - text for message -// -// RETURN VALUE: -// none -// -// COMMENTS: -// -void AddToMessageLog(DWORD flags, LPTSTR lpszMsg) -{ - TCHAR szMsg [(sizeof(SZSERVICENAME) / sizeof(TCHAR)) + 100 ]; - HANDLE hEventSource; - LPCSTR lpszStrings[2]; - - if ( !bDebug ) - { - if (flags & MSG_FLAGS_SYS_CODE) - dwErr = GetLastError(); - else - dwErr = 0; - - // Use event logging to log the error. - // - hEventSource = RegisterEventSource(NULL, TEXT(SZSERVICENAME)); - - _stprintf(szMsg, TEXT("%s error: %d"), TEXT(SZSERVICENAME), (int)dwErr); - lpszStrings[0] = szMsg; - lpszStrings[1] = lpszMsg; - - if (hEventSource != NULL) - { - ReportEvent(hEventSource, // handle of event source - // event type - (flags & MSG_FLAGS_ERROR) - ? EVENTLOG_ERROR_TYPE : EVENTLOG_INFORMATION_TYPE, - 0, // event category - 0, // event ID - NULL, // current user's SID - 2, // strings in lpszStrings - 0, // no bytes of raw data - lpszStrings, // array of error strings - NULL); // no raw data - - (VOID) DeregisterEventSource(hEventSource); - } - } -} - -void ResetError (void) -{ - dwErr = 0; -} - -/////////////////////////////////////////////////////////////////// -// -// The following code handles service installation and removal -// - - -// -// FUNCTION: CmdInstallService() -// -// PURPOSE: Installs the service -// -// PARAMETERS: -// none -// -// RETURN VALUE: -// 0 if success -// -// COMMENTS: -// -int CmdInstallService() -{ - SC_HANDLE schService; - SC_HANDLE schSCManager; - - TCHAR szPath[512]; - - int ret = 0; - - if ( GetModuleFileName( NULL, szPath+1, 510 ) == 0 ) - { - _tprintf(TEXT("Unable to install %s - %s\n"), TEXT(SZSERVICEDISPLAYNAME), GetLastErrorText(szErr, 256)); - return 1; - } - szPath[0] = '\"'; - strcat(szPath, "\""); - - schSCManager = OpenSCManager( - NULL, // machine (NULL == local) - NULL, // database (NULL == default) - SC_MANAGER_CONNECT | SC_MANAGER_CREATE_SERVICE // access required - ); - if ( schSCManager ) - { - schService = CreateService( - schSCManager, // SCManager database - TEXT(SZSERVICENAME), // name of service - TEXT(SZSERVICEDISPLAYNAME), // name to display - SERVICE_QUERY_STATUS, // desired access - SERVICE_WIN32_OWN_PROCESS, // service type - SERVICE_DEMAND_START, // start type -- alternative: SERVICE_AUTO_START - SERVICE_ERROR_NORMAL, // error control type - szPath, // service's binary - NULL, // no load ordering group - NULL, // no tag identifier - TEXT(SZDEPENDENCIES), // dependencies - NULL, // LocalSystem account - NULL); // no password - - if ( schService ) - { - _tprintf(TEXT("%s installed.\n"), TEXT(SZSERVICEDISPLAYNAME) ); - CloseServiceHandle(schService); - } - else - { - _tprintf(TEXT("CreateService failed - %s\n"), GetLastErrorText(szErr, 256)); - ret = 1; - } - - CloseServiceHandle(schSCManager); - } - else - { - _tprintf(TEXT("OpenSCManager failed - %s\n"), GetLastErrorText(szErr,256)); - ret = 1; - } - return ret; -} - -// -// FUNCTION: CmdStartService() -// -// PURPOSE: Start the service -// -// PARAMETERS: -// none -// -// RETURN VALUE: -// 0 if success -// -// COMMENTS: - -int CmdStartService() -{ - int ret = 0; - - SC_HANDLE schSCManager; - SC_HANDLE schService; - - - // Open a handle to the SC Manager database. - schSCManager = OpenSCManager( - NULL, // local machine - NULL, // ServicesActive database - SC_MANAGER_ALL_ACCESS); // full access rights - - if (NULL == schSCManager) { - _tprintf(TEXT("OpenSCManager failed - %s\n"), GetLastErrorText(szErr,256)); - ret = 1; - } - - schService = OpenService( - schSCManager, // SCM database - SZSERVICENAME, // service name - SERVICE_ALL_ACCESS); - - if (schService == NULL) { - _tprintf(TEXT("OpenService failed - %s\n"), GetLastErrorText(szErr,256)); - ret = 1; - } - - if (!StartService( - schService, // handle to service - 0, // number of arguments - NULL) ) // no arguments - { - _tprintf(TEXT("StartService failed - %s\n"), GetLastErrorText(szErr,256)); - ret = 1; - } - else - { - _tprintf(TEXT("Service Started\n")); - ret = 0; - } - CloseServiceHandle(schService); - CloseServiceHandle(schSCManager); - return ret; -} - -// -// FUNCTION: CmdRemoveService() -// -// PURPOSE: Stops and removes the service -// -// PARAMETERS: -// none -// -// RETURN VALUE: -// 0 if success -// -// COMMENTS: -// -int CmdRemoveService() -{ - SC_HANDLE schService; - SC_HANDLE schSCManager; - - int ret = 0; - - schSCManager = OpenSCManager( - NULL, // machine (NULL == local) - NULL, // database (NULL == default) - SC_MANAGER_CONNECT // access required - ); - if ( schSCManager ) - { - schService = OpenService(schSCManager, TEXT(SZSERVICENAME), DELETE | SERVICE_STOP | SERVICE_QUERY_STATUS); - - if (schService) - { - // try to stop the service - if ( ControlService( schService, SERVICE_CONTROL_STOP, &ssStatus ) ) - { - _tprintf(TEXT("Stopping %s."), TEXT(SZSERVICEDISPLAYNAME)); - Sleep( 1000 ); - - while ( QueryServiceStatus( schService, &ssStatus ) ) - { - if ( ssStatus.dwCurrentState == SERVICE_STOP_PENDING ) - { - _tprintf(TEXT(".")); - Sleep( 1000 ); - } - else - break; - } - - if ( ssStatus.dwCurrentState == SERVICE_STOPPED ) - _tprintf(TEXT("\n%s stopped.\n"), TEXT(SZSERVICEDISPLAYNAME) ); - else - { - _tprintf(TEXT("\n%s failed to stop.\n"), TEXT(SZSERVICEDISPLAYNAME) ); - ret = 1; - } - - } - - // now remove the service - if ( DeleteService(schService) ) - _tprintf(TEXT("%s removed.\n"), TEXT(SZSERVICEDISPLAYNAME) ); - else - { - _tprintf(TEXT("DeleteService failed - %s\n"), GetLastErrorText(szErr,256)); - ret = 1; - } - - - CloseServiceHandle(schService); - } - else - { - _tprintf(TEXT("OpenService failed - %s\n"), GetLastErrorText(szErr,256)); - ret = 1; - } - - CloseServiceHandle(schSCManager); - } - else - { - _tprintf(TEXT("OpenSCManager failed - %s\n"), GetLastErrorText(szErr,256)); - ret = 1; - } - return ret; -} - - - - -/////////////////////////////////////////////////////////////////// -// -// The following code is for running the service as a console app -// - - -// -// FUNCTION: CmdDebugService(int argc, char ** argv) -// -// PURPOSE: Runs the service as a console application -// -// PARAMETERS: -// argc - number of command line arguments -// argv - array of command line arguments -// -// RETURN VALUE: -// none -// -// COMMENTS: -// -void CmdDebugService(int argc, char ** argv) -{ - DWORD dwArgc; - LPTSTR *lpszArgv; - -#ifdef UNICODE - lpszArgv = CommandLineToArgvW(GetCommandLineW(), &(dwArgc) ); - if (NULL == lpszArgv) - { - // CommandLineToArvW failed!! - _tprintf(TEXT("CmdDebugService CommandLineToArgvW returned NULL\n")); - return; - } -#else - dwArgc = (DWORD) argc; - lpszArgv = argv; -#endif - - _tprintf(TEXT("Debugging %s.\n"), TEXT(SZSERVICEDISPLAYNAME)); - - SetConsoleCtrlHandler( ControlHandler, TRUE ); - - ServiceStart( dwArgc, lpszArgv ); - -#ifdef UNICODE -// Must free memory allocated for arguments - - GlobalFree(lpszArgv); -#endif // UNICODE - -} - - -// -// FUNCTION: ControlHandler ( DWORD dwCtrlType ) -// -// PURPOSE: Handled console control events -// -// PARAMETERS: -// dwCtrlType - type of control event -// -// RETURN VALUE: -// True - handled -// False - unhandled -// -// COMMENTS: -// -BOOL WINAPI ControlHandler ( DWORD dwCtrlType ) -{ - switch ( dwCtrlType ) - { - case CTRL_BREAK_EVENT: // use Ctrl+C or Ctrl+Break to simulate - case CTRL_C_EVENT: // SERVICE_CONTROL_STOP in debug mode - _tprintf(TEXT("Stopping %s.\n"), TEXT(SZSERVICEDISPLAYNAME)); - ServiceStop(); - return TRUE; - break; - - } - return FALSE; -} - -// -// FUNCTION: GetLastErrorText -// -// PURPOSE: copies error message text to string -// -// PARAMETERS: -// lpszBuf - destination buffer -// dwSize - size of buffer -// -// RETURN VALUE: -// destination buffer -// -// COMMENTS: -// -LPTSTR GetLastErrorText( LPTSTR lpszBuf, DWORD dwSize ) -{ - DWORD dwRet; - LPTSTR lpszTemp = NULL; - - dwRet = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_ARGUMENT_ARRAY, - NULL, - GetLastError(), - LANG_NEUTRAL, - (LPTSTR)&lpszTemp, - 0, - NULL ); - - // supplied buffer is not long enough - if ( !dwRet || ( (long)dwSize < (long)dwRet+14 ) ) - lpszBuf[0] = TEXT('\0'); - else - { - lpszTemp[lstrlen(lpszTemp)-2] = TEXT('\0'); //remove cr and newline character - _stprintf( lpszBuf, TEXT("%s (0x%x)"), lpszTemp, (int)GetLastError() ); - } - - if ( lpszTemp ) - LocalFree((HLOCAL) lpszTemp ); - - return lpszBuf; -} |