Initial commit
This commit is contained in:
@@ -0,0 +1,466 @@
|
||||
/*******************************************************************************
|
||||
*
|
||||
* 模 块 名:DBService 文件名:DBService.c
|
||||
* 相关文件:DBService.h
|
||||
* 提交日期:2012.2.1 作 者:Alex
|
||||
* 版 本:0.1
|
||||
* 模块描述:
|
||||
* 本模块提供了Service程序的框架
|
||||
* main(int argc, char **argv);
|
||||
* service_ctrl(DWORD dwCtrlCode);
|
||||
* service_main(DWORD dwArgc, LPTSTR *lpszArgv);
|
||||
* CmdInstallService();
|
||||
* CmdRemoveService();
|
||||
* CmdDebugService(int argc, char **argv);
|
||||
* ControlHandler ( DWORD dwCtrlType );
|
||||
* GetLastErrorText( LPTSTR lpszBuf, DWORD dwSize );
|
||||
* 修改记录:
|
||||
* 日 期 版本 修改人 修改内容
|
||||
*
|
||||
*
|
||||
*******************************************************************************/
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <process.h>
|
||||
#include <tchar.h>
|
||||
|
||||
#define _DBSERVICE_C
|
||||
#include "DBService.h"
|
||||
#undef _DBSERVICE_C
|
||||
|
||||
// internal variables
|
||||
SERVICE_STATUS ssStatus; // current status of the service
|
||||
SERVICE_STATUS_HANDLE sshStatusHandle;
|
||||
DWORD dwErr = 0;
|
||||
TCHAR szErr[256];
|
||||
char SZDEPENDENCIES[10] = "";
|
||||
|
||||
// internal function prototypes
|
||||
VOID WINAPI service_ctrl(DWORD dwCtrlCode);
|
||||
VOID WINAPI ServiceMain(DWORD dwArgc, LPTSTR *lpszArgv);
|
||||
VOID CmdInstallService();
|
||||
VOID CmdRemoveService();
|
||||
VOID CmdDebugService(int argc, char **argv);
|
||||
BOOL WINAPI ControlHandler ( DWORD dwCtrlType );
|
||||
// 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 _CRTAPI1 main(int argc, char **argv)
|
||||
int __cdecl _tmain(int argc, TCHAR *argv[])
|
||||
{
|
||||
SERVICE_TABLE_ENTRY dispatchTable[] = {
|
||||
{ TEXT(SZSERVICENAME), (LPSERVICE_MAIN_FUNCTION)ServiceMain },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
if ( (argc > 1) &&((*argv[1] == '-') || (*argv[1] == '/')) ){
|
||||
int cmd = 0;
|
||||
|
||||
if ( _stricmp( "install", argv[1]+1 ) == 0 ){
|
||||
if( argc>2 ){
|
||||
strcpy( SZDEPENDENCIES, argv[2] );
|
||||
}
|
||||
|
||||
cmd = 1;
|
||||
}
|
||||
else if ( _stricmp( "remove", argv[1]+1 ) == 0 ){
|
||||
cmd = 2;
|
||||
}
|
||||
else if ( _stricmp( "debug", argv[1]+1 ) == 0 ){
|
||||
g_eDebug = 4;
|
||||
|
||||
if( argc>2 ){
|
||||
if ( _stricmp( "f", argv[2] ) == 0 ){
|
||||
g_eDebug = 1;
|
||||
}
|
||||
else if ( _stricmp( "n", argv[2] ) == 0 ){
|
||||
g_eDebug = 2;
|
||||
}
|
||||
else if ( _stricmp( "s", argv[2] ) == 0 ){
|
||||
g_eDebug = 3;
|
||||
}
|
||||
}
|
||||
|
||||
cmd = 3;
|
||||
}
|
||||
else if( _stricmp( "check", argv[1]+1 ) == 0 && argc>2 ){
|
||||
g_iChkStyle = atoi(argv[2]);
|
||||
|
||||
if( g_iChkStyle>0 ){
|
||||
g_eDebug = 3;
|
||||
cmd = 3;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if( cmd==1 ){
|
||||
CmdInstallService();
|
||||
}
|
||||
else if( cmd==2 ){
|
||||
CmdRemoveService();
|
||||
}
|
||||
else if( cmd==3 ){
|
||||
CmdDebugService(argc, argv);
|
||||
}
|
||||
else{
|
||||
// this is just to be friendly
|
||||
printf( "%s -install <params> to install 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( "%s -check <index> to run as a console app for check style\n", SZAPPNAME );
|
||||
printf( "\nStartServiceCtrlDispatcher being called.\n" );
|
||||
printf( "This may take several seconds. Please wait.\n" );
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
if (!StartServiceCtrlDispatcher(dispatchTable))
|
||||
AddToMessageLog(TEXT("StartServiceCtrlDispatcher failed."));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// This routine performs the service initialization and then calls
|
||||
// the user defined ServiceStart() routine to perform majority
|
||||
// of the work.
|
||||
//
|
||||
void WINAPI ServiceMain(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);
|
||||
printf( "%s stopped the service\n", SZAPPNAME );
|
||||
|
||||
// getchar();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//This function is called by the SCM whenever
|
||||
//ControlService() is called on this service.
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//Sets the current status of the service and
|
||||
//reports it to the Service Control Manager
|
||||
BOOL ReportStatusToSCMgr(DWORD dwCurrentState,
|
||||
DWORD dwWin32ExitCode,
|
||||
DWORD dwWaitHint)
|
||||
{
|
||||
static DWORD dwCheckPoint = 1;
|
||||
BOOL fResult = TRUE;
|
||||
|
||||
if( g_eDebug==0 ){
|
||||
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(TEXT("SetServiceStatus"));
|
||||
}
|
||||
}
|
||||
|
||||
return fResult;
|
||||
}
|
||||
|
||||
//Allows any thread to log an error message
|
||||
VOID AddToMessageLog(LPTSTR lpszMsg)
|
||||
{
|
||||
TCHAR szMsg[256];
|
||||
HANDLE hEventSource;
|
||||
LPCTSTR lpszStrings[2];
|
||||
|
||||
// if ( g_eDebug<0 ){
|
||||
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
|
||||
lpszStrings, // array of error strings
|
||||
NULL); // no raw data
|
||||
|
||||
(VOID) DeregisterEventSource(hEventSource);
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//Installs the service
|
||||
void CmdInstallService()
|
||||
{
|
||||
SC_HANDLE schService;
|
||||
SC_HANDLE schSCManager;
|
||||
|
||||
TCHAR szPath[512];
|
||||
DWORD dwBytesNeeded;
|
||||
|
||||
if ( GetModuleFileName( NULL, szPath, 512 ) == 0 ){
|
||||
_tprintf(TEXT("Unable to install %s - %s\n"), TEXT(SZSERVICEDISPLAYNAME), GetLastErrorText(szErr, 256));
|
||||
return;
|
||||
}
|
||||
|
||||
schSCManager = OpenSCManager(
|
||||
NULL, // machine (NULL == local)
|
||||
NULL, // database (NULL == default)
|
||||
SC_MANAGER_ALL_ACCESS // access required
|
||||
);
|
||||
|
||||
if ( schSCManager ){
|
||||
schService = CreateService(
|
||||
schSCManager, // SCManager database
|
||||
TEXT(SZSERVICENAME), // name of service
|
||||
TEXT(SZSERVICEDISPLAYNAME), // name to display
|
||||
SERVICE_ALL_ACCESS, // desired access
|
||||
SERVICE_WIN32_OWN_PROCESS, // service type
|
||||
SERVICE_AUTO_START, // start type
|
||||
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) );
|
||||
|
||||
if( !StartService(schService, 0, NULL) ){
|
||||
printf("StartService failed (%d)\n", GetLastError());
|
||||
CloseServiceHandle(schService);
|
||||
CloseServiceHandle(schSCManager);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!QueryServiceStatusEx(
|
||||
schService, // handle to service
|
||||
SC_STATUS_PROCESS_INFO, // info level
|
||||
(LPBYTE) &ssStatus, // address of structure
|
||||
sizeof(SERVICE_STATUS_PROCESS), // size of structure
|
||||
&dwBytesNeeded ) ) // if buffer too small
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CloseServiceHandle(schService);
|
||||
}
|
||||
else{
|
||||
_tprintf(TEXT("CreateService failed - %s\n"), GetLastErrorText(szErr, 256));
|
||||
}
|
||||
|
||||
CloseServiceHandle(schSCManager);
|
||||
}
|
||||
else
|
||||
_tprintf(TEXT("OpenSCManager failed - %s\n"), GetLastErrorText(szErr,256));
|
||||
}
|
||||
|
||||
// PURPOSE: Stops and removes the service
|
||||
void CmdRemoveService()
|
||||
{
|
||||
SC_HANDLE schService;
|
||||
SC_HANDLE schSCManager;
|
||||
|
||||
schSCManager = OpenSCManager(
|
||||
NULL, // machine (NULL == local)
|
||||
NULL, // database (NULL == default)
|
||||
SC_MANAGER_ALL_ACCESS // access required
|
||||
);
|
||||
|
||||
if ( schSCManager ){
|
||||
schService = OpenService(schSCManager, TEXT(SZSERVICENAME), SERVICE_ALL_ACCESS);
|
||||
|
||||
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) );
|
||||
|
||||
}
|
||||
|
||||
// now remove the service
|
||||
if( DeleteService(schService) )
|
||||
_tprintf(TEXT("%s removed.\n"), TEXT(SZSERVICEDISPLAYNAME) );
|
||||
else
|
||||
_tprintf(TEXT("DeleteService failed - %s\n"), GetLastErrorText(szErr,256));
|
||||
|
||||
CloseServiceHandle(schService);
|
||||
}
|
||||
else
|
||||
_tprintf(TEXT("OpenService failed - %s\n"), GetLastErrorText(szErr,256));
|
||||
|
||||
CloseServiceHandle(schSCManager);
|
||||
}
|
||||
else
|
||||
_tprintf(TEXT("OpenSCManager failed - %s\n"), GetLastErrorText(szErr,256));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//Runs the service as a console application
|
||||
void CmdDebugService(int argc, char ** argv)
|
||||
{
|
||||
DWORD dwArgc;
|
||||
LPTSTR *lpszArgv;
|
||||
|
||||
#ifdef UNICODE
|
||||
lpszArgv = CommandLineToArgvW(GetCommandLineW(), &(dwArgc) );
|
||||
#else
|
||||
dwArgc = (DWORD) argc;
|
||||
lpszArgv = argv;
|
||||
#endif
|
||||
|
||||
_tprintf(TEXT("Debugging %s.\n"), TEXT(SZSERVICEDISPLAYNAME));
|
||||
_tprintf(TEXT("Press Ctl+C to stop %s...\n"), TEXT(SZSERVICEDISPLAYNAME));
|
||||
SetConsoleCtrlHandler( ControlHandler, TRUE );
|
||||
|
||||
ServiceStart( dwArgc, lpszArgv );
|
||||
}
|
||||
|
||||
//Handled console control events
|
||||
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;
|
||||
}
|
||||
|
||||
//copies error message text to string
|
||||
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, GetLastError() );
|
||||
}
|
||||
|
||||
if ( lpszTemp )
|
||||
LocalFree((HLOCAL) lpszTemp );
|
||||
|
||||
return lpszBuf;
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user