ntservice.cpp

来自「Socketlib: 一个轻量级的C++ 封装Socket C API 网络编程」· C++ 代码 · 共 1,176 行 · 第 1/3 页

CPP
1,176
字号
/////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 1998 Telic Software International B.V.
//
// Module Name:
//
//    NTService.h
//
//Notes:
//	   DO NOT EDIT THIS FILE BY HAND!
//
//    This file is GENERATED by the MC tool from the NTServiceEventLogMsg.mc file.
//
//////////////////////////////////////////////////////////////////////////

#include <stdio.h>
#include <tchar.h>
#include <crtdbg.h>

#include <io.h>			//!! TCW MOD
#include <fcntl.h>		//!! TCW MOD

#include "NTService.h"
#include "NTServiceEventLogMsg.h"

#ifndef RSP_SIMPLE_SERVICE
	#define RSP_SIMPLE_SERVICE 1
#endif
#ifndef RSP_UNREGISTER_SERVICE
	#define RSP_UNREGISTER_SERVICE 0
#endif

namespace SL
{

BOOL CNTService::m_bInstance = FALSE;
static CNTService * gpTheService = 0;			// the one and only instance
CNTService * AfxGetService() 
{ 
	return gpTheService; 
}

static LPCTSTR gszAppRegKey = TEXT("SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\");
static LPCTSTR gszWin95ServKey = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\RunServices");	//!! TCW MOD
//static LPCTSTR gszWin95ServKey=TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Run");	//!! TCW MOD

/////////////////////////////////////////////////////////////////////////////
// class CNTService -- construction/destruction

CNTService :: CNTService( LPCTSTR lpServiceName, LPCTSTR lpDisplayName )
	: m_lpServiceName(lpServiceName)
	, m_lpDisplayName(lpDisplayName ? lpDisplayName : lpServiceName)
	, m_dwCheckPoint(0)
	, m_dwErr(0)
	, m_bDebug(FALSE)
	, m_sshStatusHandle(0)
	, m_dwControlsAccepted(SERVICE_ACCEPT_STOP|SERVICE_ACCEPT_PAUSE_CONTINUE)
	, m_pUserSID(0)
	, m_fConsoleReady(FALSE)
	// parameters to the "CreateService()" function:
	, m_dwDesiredAccess(SERVICE_ALL_ACCESS)
	, m_dwServiceType(SERVICE_WIN32_OWN_PROCESS)
	, m_dwStartType(SERVICE_AUTO_START)
	, m_dwErrorControl(SERVICE_ERROR_NORMAL)
	, m_pszLoadOrderGroup(0)
	, m_dwTagID(0)
	, m_pszDependencies(0)
	, m_pszStartName(0)
	, m_pszPassword(0)
{
	_ASSERTE( ! m_bInstance );

	OSVERSIONINFO vi;
	vi.dwOSVersionInfoSize=sizeof(vi);  // init this.
	GetVersionEx(&vi);      //lint !e534
	m_bWinNT = (vi.dwPlatformId == VER_PLATFORM_WIN32_NT);

	m_bInstance = TRUE;
	gpTheService = this;
	
	// SERVICE_STATUS members that rarely change
	m_ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
	m_ssStatus.dwServiceSpecificExitCode = 0;

	if ( m_bWinNT ) 
	{
		/////////////////////////////////////////////////////////////////////////
		// Providing a SID (security identifier) was contributed by Victor
		// Vogelpoel (VictorV@Telic.nl).
		// The code from Victor was slightly modified.

		// Get security information of current user
		BYTE	security_identifier_buffer[ 4096 ];
		DWORD	dwSizeSecurityIdBuffer = sizeof( security_identifier_buffer );
		PSID	user_security_identifier = NULL;

		TCHAR sUserName[ 256 ];
		DWORD dwSizeUserName  =  255;

		TCHAR sDomainName[ 256 ];
		DWORD dwSizeDomainName = 255;

		SID_NAME_USE sidTypeSecurityId;

		::ZeroMemory( sUserName, sizeof( sUserName ) );
		::ZeroMemory( sDomainName, sizeof( sDomainName ) );
		::ZeroMemory( security_identifier_buffer, dwSizeSecurityIdBuffer );

		::GetUserName( sUserName, &dwSizeUserName );

		if( ::LookupAccountName(
					0,
					sUserName,
					&security_identifier_buffer,
					&dwSizeSecurityIdBuffer,
					sDomainName,
					&dwSizeDomainName,
					&sidTypeSecurityId
				)) {
			if( ::IsValidSid( PSID(security_identifier_buffer) ) ) {
				DWORD dwSidLen = ::GetLengthSid(PSID(security_identifier_buffer));
				m_pUserSID = PSID(new BYTE [dwSidLen]);
				::CopySid(dwSidLen, m_pUserSID, security_identifier_buffer);
				_ASSERTE(::EqualSid(m_pUserSID, security_identifier_buffer));
			}
		}
	}
	/////////////////////////////////////////////////////////////////////////
}


CNTService :: ~CNTService() {
	_ASSERTE( m_bInstance );
	delete [] LPBYTE(m_pUserSID);
	m_bInstance = FALSE;
	gpTheService = 0;
}



/////////////////////////////////////////////////////////////////////////////
// class CNTService -- overridables

#define NEXT_ARG ((((*Argv)[2])==TEXT('\0'))?(--Argc,*++Argv):(*Argv)+2)


BOOL CNTService :: RegisterService( int argc, TCHAR ** argv) {
	BOOL (CNTService::* fnc)() = &CNTService::StartDispatcher;
    DWORD Argc;
    LPTSTR * Argv;

#ifdef UNICODE
    Argv = CommandLineToArgvW(GetCommandLineW(), &Argc );
#else
    Argc = (DWORD) argc;
    Argv = argv;
#endif


    while( ++Argv, --Argc ) {
		if( Argv[0][0] == TEXT('-') ) {
			switch( Argv[0][1] ) {
				case TEXT('i'):	// install the service
					fnc = &CNTService::InstallService;
					break;
				case TEXT('l'):	// login-account (only useful with -i)
					m_pszStartName = NEXT_ARG;
					break;
				case TEXT('p'):	// password (only useful with -i)
					m_pszPassword = NEXT_ARG;
					break;
				case TEXT('u'):	// uninstall the service
					fnc = &CNTService::RemoveService;
					break;
				case TEXT('s'):	// start the service
					fnc = &CNTService::StartupService;
					break;
				case TEXT('e'):	// end the service
					fnc = &CNTService::EndService;
					break;
				case TEXT('d'):	// debug the service
				case TEXT('f'):	//!! TCW MOD faceless non-service (Win95) mode
					#ifdef UNICODE
						::GlobalFree(HGLOBAL)Argv);
					#endif

					m_bDebug = TRUE;
					// pass original parameters to DebugService()
					return DebugService(argc, argv,(Argv[0][1]==TEXT('f'))); //!! TCW MOD faceless non-service (Win95) mode
			}
		}
	}

#ifdef UNICODE
	::GlobalFree(HGLOBAL)Argv);
#endif

	//!! TCW MOD START - if Win95, run as faceless app.
	if(fnc == &CNTService::InstallService)
	{
		(this->*fnc)();
		if( OsIsWin95() ) 
		{
			// act as if -f was passed anyways.
			m_bDebug = TRUE;
			return DebugService(argc, argv, TRUE);
		}
		else
		{
			return this->StartupService();
		}
	}

	
	if( fnc == &CNTService::StartDispatcher && OsIsWin95() ) 
	{
		// act as if -f was passed anyways.
		m_bDebug = TRUE;
		return DebugService(argc, argv, TRUE);
	}
	//!! TCW MOD END - if Win95, run as faceless app.

	return (this->*fnc)();
}


BOOL CNTService :: StartDispatcher() {
    // Default implementation creates a single threaded service.
	// Override this method and provide more table entries for
	// a multithreaded service (one entry for each thread).
	SERVICE_TABLE_ENTRY dispatchTable[] =
    {
        { LPTSTR(m_lpServiceName), (LPSERVICE_MAIN_FUNCTION)ServiceMain },
        { 0, 0 }
    };

	BOOL bRet = StartServiceCtrlDispatcher(dispatchTable);
	if( ! bRet ) {
		TCHAR szBuf[256];
        AddToMessageLog(GetLastErrorText(szBuf,255));
	}

	return bRet;
}


BOOL CNTService :: InstallService()
{
	BOOL bRet = FALSE;
  
	TCHAR szPath[1024];
	static LPCTSTR gszWin95ServKey=TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\RunServices");	//!! TCW MOD

	if( GetModuleFileName( 0, szPath, 1023 ) == 0 ) {
		TCHAR szErr[256];
		_tprintf(TEXT("Unable to install %s - %s\n"), m_lpDisplayName, GetLastErrorText(szErr, 256));
		return FALSE;
	}



	if ( OsIsWin95() ) 
	{	//!! TCW MOD - code added to install as Win95 service
		// Create a key for that application and insert values for
		// "EventMessageFile" and "TypesSupported"
		HKEY hKey = 0;
		LONG lRet = ERROR_SUCCESS;
		if( ::RegCreateKey(HKEY_LOCAL_MACHINE, gszWin95ServKey , &hKey) == ERROR_SUCCESS ) {
			lRet =	::RegSetValueEx(
						hKey,				// handle of key to set value for
						m_lpServiceName,	// address of value to set (NAME OF SERVICE)
						0,					// reserved
						REG_SZ,		// flag for value type
						(CONST BYTE*)szPath,// address of value data
						_tcslen(szPath) + 1	// size of value data
					);
			::RegCloseKey(hKey);
			bRet=TRUE;
		}
	} 
	else 
	{
		// Real NT services go here.
		SC_HANDLE schSCManager =	OpenSCManager(
										0,						// machine (NULL == local)
										0,						// database (NULL == default)
										SC_MANAGER_ALL_ACCESS	// access required
									);
		if( schSCManager ) {
			SC_HANDLE schService =	CreateService(
										schSCManager,
										m_lpServiceName,
										m_lpDisplayName,
										m_dwDesiredAccess,
										m_dwServiceType,
										m_dwStartType,
										m_dwErrorControl,
										szPath,
										m_pszLoadOrderGroup,
										((m_dwServiceType == SERVICE_KERNEL_DRIVER ||
										  m_dwServiceType == SERVICE_FILE_SYSTEM_DRIVER) &&
										 (m_dwStartType == SERVICE_BOOT_START ||
										  m_dwStartType == SERVICE_SYSTEM_START)) ?
											&m_dwTagID : 0,
										m_pszDependencies,
										m_pszStartName,
										m_pszPassword
									);

			if( schService ) 
			{
				CloseServiceHandle(schService);
				bRet = TRUE;
			} 
			else 
			{
				TCHAR szErr[256];
				GetLastErrorText(szErr, 256);
				//AfxMessageBox(szErr, MB_ICONSTOP);
			}

			CloseServiceHandle(schSCManager);
		 } else {
			TCHAR szErr[256];
			_tprintf(TEXT("OpenSCManager failed - %s\n"), GetLastErrorText(szErr,256));
		}

		if( bRet ) {
			// installation succeeded. Now register the message file
			RegisterApplicationLog(
				szPath,		// the path to the application itself
				EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE // supported types
			);

			AddToMessageLog(TEXT("Service installed"),EVENTLOG_INFORMATION_TYPE);
		}
	}	//!! TCW MOD

	return bRet;
}


BOOL CNTService :: RemoveService() 
{
	BOOL bRet = FALSE;

	SetupConsole();	//!! TCW MOD - have to show the console here for the
					// diagnostic or error reason: orignal class assumed
					// that we were using _main for entry (a console app).
					// This particular usage is a Windows app (no console),
					// so we need to create it. Using SetupConsole with _main
					// is ok - does nothing, since you only get one console.


	if( OsIsWin95() ) {	//!! TCW MOD - code added to install as Win95 service
		HKEY hKey = 0;
		LONG lRet = ERROR_SUCCESS;
		if( ::RegCreateKey(HKEY_LOCAL_MACHINE, gszWin95ServKey , &hKey) == ERROR_SUCCESS ) {
			lRet = ::RegDeleteValue(hKey, m_lpServiceName);
			::RegCloseKey(hKey);
			bRet=TRUE;
		}
	} else {
		// Real NT services go here.
		SC_HANDLE schSCManager = OpenSCManager(
									0,						// machine (NULL == local)
									0,						// database (NULL == default)
									SC_MANAGER_ALL_ACCESS	// access required
								);
		if( schSCManager ) {
			SC_HANDLE schService =	OpenService(
										schSCManager,
										m_lpServiceName,
										SERVICE_ALL_ACCESS
									);

			if( schService ) {
				// try to stop the service
				if( ControlService(schService, SERVICE_CONTROL_STOP, &m_ssStatus) ) {
					_tprintf(TEXT("Stopping %s."), m_lpDisplayName);
					Sleep(1000);

					while( QueryServiceStatus(schService, &m_ssStatus) ) {
						if( m_ssStatus.dwCurrentState == SERVICE_STOP_PENDING ) {
							_tprintf(TEXT("."));
							Sleep( 1000 );
						} else
							break;
					}

					if( m_ssStatus.dwCurrentState == SERVICE_STOPPED )
						_tprintf(TEXT("\n%s stopped.\n"), m_lpDisplayName);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?