📄 service.cpp
字号:
// 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-1995 Microsoft Corporation. All Rights Reserved.//// MODULE: service.c//// PURPOSE: Implements functions required by all services// windows.//// FUNCTIONS:// main(int argc, char **argv);// service_ctrl(DWORD dwCtrlCode);// service_main(DWORD dwArgc, LPTSTR *lpszArgv);// CmdInstallService();// CmdRemoveService(BOOL bErrorOnNotInstalled);// CmdDebugService(int argc, char **argv);// ControlHandler ( DWORD dwCtrlType );// GetLastErrorText( LPTSTR lpszBuf, DWORD dwSize );//// COMMENTS://// AUTHOR: Craig Link - Microsoft Developer Support//#include <winsock2.h>#include <windows.h>#include <stdio.h>#include <stdlib.h>#include <tchar.h>#include "privileges.h"#include "service.h"#include <ntsecapi.h>#include "mpdimpl.h"// global variablesBOOL bDebug = FALSE;bool interact = false;bool bSetupRestart = true;// internal variablesstatic SERVICE_STATUS ssStatus; // current status of the servicestatic SERVICE_STATUS_HANDLE sshStatusHandle;static DWORD dwErr = 0;static TCHAR szErr[256];// internal function prototypesVOID WINAPI service_ctrl(DWORD dwCtrlCode);VOID WINAPI service_main(DWORD dwArgc, LPTSTR *lpszArgv);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.//void main(int argc, char **argv){ SERVICE_TABLE_ENTRY dispatchTable[] = { { TEXT(SZSERVICENAME), (LPSERVICE_MAIN_FUNCTION)service_main }, { NULL, NULL } }; parseCommandLine(&argc, &argv); // if it doesn't match any of the above parameters // the service control manager may be starting the service // so we must call StartServiceCtrlDispatcher printf( "\nStartServiceCtrlDispatcher being called.\n" ); printf( "This may take several seconds. Please wait.\n" ); fflush(stdout); if (!StartServiceCtrlDispatcher(dispatchTable)) AddErrorToMessageLog(TEXT("StartServiceCtrlDispatcher failed."));}//// 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. // case SERVICE_CONTROL_STOP: ssStatus.dwCurrentState = SERVICE_STOP_PENDING; ServiceStop(); break; // 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))) { AddErrorToMessageLog(TEXT("SetServiceStatus")); } } return fResult;}//// FUNCTION: AddErrorToMessageLog(LPTSTR lpszMsg)//// PURPOSE: Allows any thread to log an error message//// PARAMETERS:// lpszMsg - text for message//// RETURN VALUE:// none//// COMMENTS://VOID AddErrorToMessageLog(LPTSTR lpszMsg){ TCHAR szMsg[256]; HANDLE hEventSource; LPTSTR lpszStrings[2]; if ( !bDebug ) { dwErr = GetLastError(); // Use event logging to log the error. // hEventSource = RegisterEventSource(NULL, TEXT(SZSERVICENAME)); _stprintf(szMsg, TEXT("%s error: %d"), TEXT(SZSERVICENAME), dwErr); lpszStrings[0] = szMsg; lpszStrings[1] = lpszMsg; if (hEventSource != NULL) { ReportEvent(hEventSource, // handle of event source EVENTLOG_ERROR_TYPE, // event type 0, // event category 0, // event ID NULL, // current user's SID 2, // strings in lpszStrings 0, // no bytes of raw data (LPCTSTR*)lpszStrings,// array of error strings NULL); // no raw data (VOID) DeregisterEventSource(hEventSource); } }}//// FUNCTION: AddInfoToMessageLog(LPTSTR lpszMsg)//// PURPOSE: Allows any thread to log an info message//// PARAMETERS:// lpszMsg - text for message//// RETURN VALUE:// none//// COMMENTS://VOID AddInfoToMessageLog(LPTSTR lpszMsg){ HANDLE hEventSource; LPTSTR lpszStrings[1]; if ( !bDebug ) { printf("adding to message log\n");fflush(stdout); // Use event logging to log the message. // hEventSource = RegisterEventSource(NULL, TEXT(SZSERVICENAME)); lpszStrings[0] = lpszMsg; if (hEventSource != NULL) { ReportEvent(hEventSource, // handle of event source EVENTLOG_INFORMATION_TYPE, // event type 0, // event category 0, // event ID NULL, // current user's SID 1, // strings in lpszStrings 0, // no bytes of raw data (LPCTSTR*)lpszStrings,// array of error strings NULL); // no raw data (VOID) DeregisterEventSource(hEventSource); } }}//// FUNCTION: Setup_Service_restart( SC_HANDLE schService )//// PURPOSE: Setup the service to automatically restart if it has been down for 5 minutes//// PARAMETERS:// schService - service handle//// RETURN VALUE:// BOOL//// COMMENTS:// code provided by Bradley, Peter C. (MIS/CFD) [bradlepc@pweh.com]//static BOOL Setup_Service_restart( SC_HANDLE schService ){ SC_ACTION actionList[3]; SERVICE_FAILURE_ACTIONS schActionOptions; HMODULE hModule; BOOL ( WINAPI * ChangeServiceConfig2_fn)(SC_HANDLE hService, DWORD dwInfoLevel, LPVOID lpInfo); hModule = GetModuleHandle("Advapi32"); if (hModule == NULL) return FALSE; ChangeServiceConfig2_fn = (BOOL ( WINAPI *)(SC_HANDLE, DWORD, LPVOID))GetProcAddress(hModule, "ChangeServiceConfig2A"); if (ChangeServiceConfig2_fn == NULL) return FALSE; // The actions in this array are performed in order each time the service fails // within the specified reset period. // This array attempts to restart mpd twice and then allow it to stay dead. actionList[0].Type = SC_ACTION_RESTART; actionList[0].Delay = 0; actionList[1].Type = SC_ACTION_RESTART; actionList[1].Delay = 0; actionList[2].Type = SC_ACTION_NONE; actionList[2].Delay = 0; schActionOptions.dwResetPeriod = (DWORD) 300; /* 5 minute reset */ schActionOptions.lpRebootMsg = NULL; schActionOptions.lpCommand = NULL; schActionOptions.cActions = (DWORD) (sizeof actionList / sizeof actionList[0]); schActionOptions.lpsaActions = actionList; return ChangeServiceConfig2_fn(schService, SERVICE_CONFIG_FAILURE_ACTIONS, &schActionOptions);}/////////////////////////////////////////////////////////////////////// The following code handles service installation and removal////// FUNCTION: CmdInstallService()//// PURPOSE: Installs the service//// PARAMETERS:// none//// RETURN VALUE:// none//// COMMENTS://void CmdInstallService(LPTSTR account, LPTSTR password, bool bMPDUserCapable /* = false */){ SC_HANDLE schService; SC_HANDLE schSCManager; TCHAR szPath[1024]; if ( GetModuleFileName( NULL, szPath, 1024 ) == 0 ) { _tprintf(TEXT("Unable to install %s.\n%s\n"), TEXT(SZSERVICEDISPLAYNAME), GetLastErrorText(szErr, 256)); fflush(stdout); return; } if (account == NULL) password = NULL; else { DWORD result; if (password == NULL) { _tprintf(TEXT("No password provided for mpd user %s\n"), account);fflush(stdout); return; } result = SetAccountRights(account, SE_SERVICE_LOGON_NAME); if (result != ERROR_SUCCESS) { SetLastError(result); _tprintf(TEXT("Unable to grant the necessary privileges to %s.\nInstallation failed. Error: %s.\n"), account, GetLastErrorText(szErr, 256)); fflush(stdout); return; } /* result = SetAccountRights(account, SE_INTERACTIVE_LOGON_NAME); if (result != ERROR_SUCCESS) { SetLastError(result);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -