#include "stdafx.h" #include "WinService.h" using namespace WZPUBLIC; WinService::WinService() : m_handleServiceEvent( 0 ) { } WinService::~WinService() { if( m_handleServiceEvent != 0 ) ::CloseHandle( m_handleServiceEvent ); } void WinService::AddEventLog( char* sourceName, EventLogType type, char* format, ... ) { char buffer[1024] = {0, }; va_list args; va_start( args, format ); wvsprintf( buffer, format, args ); va_end( args ); void* handleEventSource = ::RegisterEventSource( 0, sourceName ); if( handleEventSource != 0 ) { LPCTSTR temp = buffer; ::ReportEvent( handleEventSource, (WORD)type, 0, 0, 0, 1, 0, &temp, 0 ); ::DeregisterEventSource( handleEventSource ); } } bool WinService::UploadService(char* serviceName, char* displayName, char* binaryPath, char* serviceLogin, char* password, bool autoStart) { return UploadService(serviceName, displayName, binaryPath, serviceLogin, password, NULL, autoStart); } /** 2006.08.10 add by guiun ¼­ºñ½º Á¾¼Ó¼ºÀ» °¡Áú ¼ö ÀÖ´Â ¼­ºñ½º µî·Ï Ãß°¡ */ bool WinService::UploadService(char* serviceName, char* displayName, char* binaryPath, char* serviceLogin, char* password, char* dependency, bool /*autoStart*/ ) { SC_HANDLE handleManager = ::OpenSCManager( 0, 0, SC_MANAGER_ALL_ACCESS ); if( handleManager == 0 ) { return false; } //DWORD dwStartType = (autoStart==true) ? SERVICE_AUTO_START : SERVICE_DEMAND_START; SC_HANDLE handleService = ::CreateService(handleManager, serviceName, displayName, SERVICE_ALL_ACCESS, SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, binaryPath, NULL, NULL, dependency, serviceLogin, password); if( handleService == 0 ) { ::CloseServiceHandle( handleManager ); return false; } ::CloseServiceHandle( handleService ); ::CloseServiceHandle( handleManager ); return true; } bool WinService::RemoveService( char* serviceName ) { SC_HANDLE handleManager = ::OpenSCManager( 0, 0, SC_MANAGER_CREATE_SERVICE ); if( handleManager == 0 ) { return false; } SC_HANDLE handleService = ::OpenService( handleManager, serviceName, DELETE ); if( handleService == 0 ) { ::CloseServiceHandle( handleManager ); return false; } ::DeleteService( handleService ); ::CloseServiceHandle( handleService ); ::CloseServiceHandle( handleManager ); return true; } bool WinService::StartDispatcher( char* serviceName, FN_StartCallback fnStart, FN_StopCallback fnStop, FN_UpdateCallback fnUpdate ) { SERVICE_TABLE_ENTRY dispatch[] = { { m_serviceName, ServiceLoop }, { 0, 0 } }; ::strcpy_s( m_serviceName, serviceName ); m_serviceStartFunc = fnStart; m_serviceStopFunc = fnStop; m_serviceUpdateFunc = fnUpdate; if( ::StartServiceCtrlDispatcher( dispatch ) == 0 ) { return false; } return true; } void WinService::BreakOutDispatcher() { m_statusEvent = SERVICE_CONTROL_STOP; ::SetEvent( m_handleServiceEvent ); } bool WinService::ChangeServiceInfo( char* netMachine, char* serviceName, char* account, char* password, DWORD startType ) { SC_HANDLE handleService = ::OpenSCManager( netMachine, 0, GENERIC_ALL ); if( handleService == 0 ) { return false; } SC_HANDLE handleServerConnect = ::OpenService( handleService, serviceName, SERVICE_CHANGE_CONFIG ); if( handleServerConnect == 0 ) { ::CloseServiceHandle( handleService ); return false; } BOOL ret = ::ChangeServiceConfig( handleServerConnect, SERVICE_WIN32_OWN_PROCESS, startType, SERVICE_ALL_ACCESS, 0, 0, 0, 0, account, password, 0 ); return ( ret == TRUE ); } DWORD WinService::QueryService( char* netMachine, char* serviceName, QUERY_SERVICE_CONFIG* config, DWORD bufSize ) { SC_HANDLE handleService = ::OpenSCManager( netMachine, 0, GENERIC_READ ); if( handleService == 0 ) return ::GetLastError(); // ÇØ´ç ¼­ºñ½ºÀÇ Á¤º¸¸¦ ¾ò¾î¿Â´Ù. if( config != 0 ) { DWORD configBytes = 0; SC_HANDLE handleConfig = ::OpenService( handleService, serviceName, SERVICE_QUERY_CONFIG ); ::QueryServiceConfig( handleConfig, config, bufSize, &configBytes ); ::CloseServiceHandle( handleConfig ); } // ÇØ´ç ¼­ºñ½ºÀÇ »óŸ¦ ¾ò¾î¿Â´Ù. SC_HANDLE handleServerConnect = ::OpenService( handleService, serviceName, SERVICE_INTERROGATE ); if( handleServerConnect == 0 ) { ::CloseServiceHandle( handleService ); return ::GetLastError(); } do { ::ControlService( handleServerConnect, SERVICE_CONTROL_INTERROGATE, &m_ssQueryControl ); } while( m_ssQueryControl.dwCurrentState != SERVICE_STOPPED && m_ssQueryControl.dwCurrentState != SERVICE_RUNNING && m_ssQueryControl.dwCurrentState != SERVICE_PAUSED && m_ssQueryControl.dwCurrentState != 1 && handleServerConnect != 0 ); switch( m_ssQueryControl.dwCurrentState ) { case SERVICE_STOPPED: case SERVICE_RUNNING: case SERVICE_PAUSED: break; default: m_ssQueryControl.dwCurrentState = 0; break; } ::CloseServiceHandle( handleServerConnect ); ::CloseServiceHandle( handleService ); return m_ssQueryControl.dwCurrentState; } DWORD WinService::StartService( char* netMachine, char* serviceName ) { DWORD dwErrorCode = ERROR_SUCCESS; SC_HANDLE handleService = ::OpenSCManager( netMachine, 0, SC_MANAGER_CONNECT ); if( handleService == 0 ){ dwErrorCode = ::GetLastError(); return dwErrorCode; } SC_HANDLE handleServerConnect = ::OpenService( handleService, serviceName, SERVICE_START | SERVICE_QUERY_STATUS ); if( handleServerConnect == 0 ) { ::CloseServiceHandle( handleService ); dwErrorCode = ::GetLastError(); return dwErrorCode; } if(::StartService( handleServerConnect, 0, 0 ) == TRUE ) { ::Sleep( m_ssQueryControl.dwWaitHint ); ::QueryServiceStatus( handleServerConnect, &m_ssQueryControl ); } ::CloseServiceHandle( handleServerConnect ); ::CloseServiceHandle( handleService ); return m_ssQueryControl.dwCurrentState; } DWORD WinService::StopService( char* netMachine, char* serviceName ) { SC_HANDLE handleService = ::OpenSCManager( netMachine, 0, SC_MANAGER_CONNECT ); if( handleService == 0 ) return ::GetLastError(); SC_HANDLE handleServerConnect = ::OpenService( handleService, serviceName, GENERIC_EXECUTE ); if( handleServerConnect == 0 ) { ::CloseServiceHandle( handleService ); return ::GetLastError(); } ::ControlService( handleServerConnect, SERVICE_CONTROL_STOP, &m_ssQueryControl ); ::CloseServiceHandle( handleServerConnect ); ::CloseServiceHandle( handleService ); return m_ssQueryControl.dwCurrentState; } bool WinService::ConnectNet( char* account, char* password, char* netMachine ) { char temp[128] = {0, }; NETRESOURCE netInfo; memset( &netInfo, 0, sizeof( netInfo ) ); StringCchPrintf( temp, 128, "\\\\%s", netMachine ); netInfo.dwType = RESOURCETYPE_ANY; netInfo.lpLocalName = 0; netInfo.lpRemoteName = temp; netInfo.lpProvider = 0; return ( ::WNetAddConnection2( &netInfo, password, account, CONNECT_UPDATE_PROFILE | CONNECT_INTERACTIVE) == NO_ERROR ); } bool WinService::CancelNet( char* netMachine ) { char temp[128] = {0, }; StringCchPrintf( temp, 128, "\\\\%s", netMachine ); return ( ::WNetCancelConnection2( temp, 0, 0 ) == NO_ERROR ); } void __stdcall WinService::ServiceHandler( DWORD status ) { _instance(WinService)->m_statusEvent = status; ::SetEvent( _instance(WinService)->m_handleServiceEvent ); } void __stdcall WinService::ServiceLoop( DWORD /*argc*/, char** /*argv*/ ) { bool loop = true; DWORD serviceState = SERVICE_RUNNING; if( _instance(WinService)->OnServiceStart() == false ) { _instance(WinService)->OnServiceStop(); return; } while( loop ) { if( _instance(WinService)->IsServiceUpdate() ) { // sun network library if( !_instance(WinService)->OnServiceUpdate() ) { serviceState = SERVICE_STOP_PENDING; loop = false; continue; } } else { // rnd network library if ( WAIT_TIMEOUT == ::WaitForSingleObject( _instance(WinService)->m_handleServiceEvent, 60000 ) ) { continue; } } switch( _instance(WinService)->m_statusEvent ) { case SERVICE_CONTROL_STOP : serviceState = SERVICE_STOP_PENDING; loop = false; break; case SERVICE_CONTROL_CONTINUE : serviceState = SERVICE_RUNNING; break; case SERVICE_CONTROL_PAUSE : serviceState = SERVICE_PAUSED; break; case SERVICE_CONTROL_SHUTDOWN : serviceState = SERVICE_STOP_PENDING; loop = false; break; case SERVICE_CONTROL_INTERROGATE : break; default : break; } } _instance(WinService)->OnServiceStop(); } bool WinService::OnServiceStart() { SERVICE_STATUS ss; m_handleServiceEvent = ::CreateEvent( 0, 0, 0, 0 ); m_handleServiceStatus = ::RegisterServiceCtrlHandler( m_serviceName, ServiceHandler ); ss.dwServiceType = SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS; ss.dwCurrentState = SERVICE_START_PENDING; ss.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN; ss.dwWin32ExitCode = NO_ERROR; ss.dwServiceSpecificExitCode = 0; ss.dwCheckPoint = 1; ss.dwWaitHint = 1000; ::SetServiceStatus( m_handleServiceStatus, &ss ); if( m_serviceStartFunc != 0 && ( *m_serviceStartFunc )() == false ) { return false; } ss.dwCurrentState = SERVICE_RUNNING; ss.dwCheckPoint = 0; ss.dwWaitHint = 0; ::SetServiceStatus( m_handleServiceStatus, &ss ); return true; } bool WinService::OnServiceUpdate() { if( m_serviceUpdateFunc != 0 ) return ( *m_serviceUpdateFunc )(); return true; } bool WinService::IsServiceUpdate() { if( m_serviceUpdateFunc ) return true; return false; } void WinService::OnServiceStop() { SERVICE_STATUS ss; ss.dwServiceType = SERVICE_WIN32_OWN_PROCESS; ss.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN; ss.dwWin32ExitCode = NO_ERROR; ss.dwServiceSpecificExitCode = 0; ss.dwCurrentState = SERVICE_STOP_PENDING; ss.dwCheckPoint = 1; ss.dwWaitHint = 5000; ::SetServiceStatus( m_handleServiceStatus, &ss ); if( m_serviceStopFunc != 0 ) ( *m_serviceStopFunc )(); ss.dwCurrentState = SERVICE_STOPPED; ss.dwCheckPoint = 0; ss.dwWaitHint = 0; ::SetServiceStatus( m_handleServiceStatus, &ss ); if( m_handleServiceEvent == INVALID_HANDLE_VALUE ) { ::CloseHandle( m_handleServiceEvent ); m_handleServiceEvent = INVALID_HANDLE_VALUE; } } bool WinService::LocalSystemShutdown( LPTSTR msg, DWORD timeout, BOOL bReboot ) { HANDLE handleToken; if( ::OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &handleToken ) == FALSE ) return FALSE; // Get the LUID for shutdown privilege. TOKEN_PRIVILEGES tkp; LookupPrivilegeValue( 0, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid ); tkp.PrivilegeCount = 1; tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; // Get shutdown privilege for this process. ::AdjustTokenPrivileges( handleToken, FALSE, &tkp, 0, ( PTOKEN_PRIVILEGES )0, 0 ); // Cannot test the return value of AdjustTokenPrivileges. if( ::GetLastError() != ERROR_SUCCESS ) { return false; } // Display the shutdown dialog box and start the countdown. BOOL result = ::InitiateSystemShutdown( 0, // shut down local computer msg, // message for user timeout, // time-out period FALSE, // ask user to close apps bReboot); // reboot after shutdown if( result == FALSE ) { return false; } // Disable shutdown privilege. if( msg != 0 ) { tkp.Privileges[0].Attributes = 0; AdjustTokenPrivileges( handleToken, FALSE, &tkp, 0, ( PTOKEN_PRIVILEGES ) 0, 0 ); } return true; }