diff options
author | bk@work.mysql.com <> | 2000-07-31 21:29:14 +0200 |
---|---|---|
committer | bk@work.mysql.com <> | 2000-07-31 21:29:14 +0200 |
commit | f4c589ff6c653d1d2a09c26e46ead3c8a15655d8 (patch) | |
tree | d253a359142dfc1ed247d5d4365d86972ea31109 /sql/nt_servc.cc | |
parent | 7eec25e393727b16bb916b50d82b0aa3084e065c (diff) | |
download | mariadb-git-f4c589ff6c653d1d2a09c26e46ead3c8a15655d8.tar.gz |
Import changeset
Diffstat (limited to 'sql/nt_servc.cc')
-rw-r--r-- | sql/nt_servc.cc | 400 |
1 files changed, 400 insertions, 0 deletions
diff --git a/sql/nt_servc.cc b/sql/nt_servc.cc new file mode 100644 index 00000000000..5884300fe95 --- /dev/null +++ b/sql/nt_servc.cc @@ -0,0 +1,400 @@ +/* ------------------------------------------------------------------------ + Windows NT Service class library + Copyright Abandoned 1998 Irena Pancirov - Irnet Snc + This file is public domain and comes with NO WARRANTY of any kind + -------------------------------------------------------------------------- */ +#include <windows.h> +#include <process.h> +#include "nt_servc.h" + + +static NTService *pService; + +/* ------------------------------------------------------------------------ + + -------------------------------------------------------------------------- */ +NTService::NTService() +{ + + bOsNT = FALSE; + //service variables + ServiceName = NULL; + hExitEvent = 0; + bPause = FALSE; + bRunning = FALSE; + hThreadHandle = 0; + fpServiceThread = NULL; + + //time-out variables + nStartTimeOut = 15000; + nStopTimeOut = 15000; + nPauseTimeOut = 5000; + nResumeTimeOut = 5000; + + //install variables + dwDesiredAccess = SERVICE_ALL_ACCESS; + dwServiceType = SERVICE_WIN32_OWN_PROCESS; + dwStartType = SERVICE_AUTO_START; + dwErrorControl = SERVICE_ERROR_NORMAL; + szLoadOrderGroup = NULL; + lpdwTagID = NULL; + szDependencies = NULL; + + my_argc = 0; + my_argv = NULL; + hShutdownEvent = 0; + nError = 0; + dwState = 0; +} + +/* ------------------------------------------------------------------------ + + -------------------------------------------------------------------------- */ +NTService::~NTService() +{ + if(ServiceName != NULL) delete[] ServiceName; +} +/* ------------------------------------------------------------------------ + + -------------------------------------------------------------------------- */ +BOOL NTService::GetOS() +{ + bOsNT = FALSE; + memset(&osVer, 0, sizeof(OSVERSIONINFO)); + osVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + if (GetVersionEx(&osVer)) + { + if (osVer.dwPlatformId == VER_PLATFORM_WIN32_NT) + bOsNT = TRUE; + } + return bOsNT; +} + +/* ------------------------------------------------------------------------ + Init() Registers the main service thread with the service manager + + ServiceThread - pointer to the main programs entry function + when the service is started + -------------------------------------------------------------------------- */ +long NTService::Init(LPCSTR szInternName,void *ServiceThread) +{ + + pService = this; + + fpServiceThread = (THREAD_FC)ServiceThread; + ServiceName = new char[lstrlen(szInternName)+1]; + lstrcpy(ServiceName,szInternName); + + SERVICE_TABLE_ENTRY stb[] = + { + { (char *)szInternName,(LPSERVICE_MAIN_FUNCTION) ServiceMain} , + { NULL, NULL } + }; + + return StartServiceCtrlDispatcher(stb); //register with the Service Manager +} +/* ------------------------------------------------------------------------ + Install() - Installs the service with Service manager + nError values: + 0 success + 1 Can't open the Service manager + 2 Failed to create service + -------------------------------------------------------------------------- */ +BOOL NTService::Install(LPCSTR szInternName,LPCSTR szDisplayName, + LPCSTR szFullPath, LPCSTR szAccountName,LPCSTR szPassword) +{ + SC_HANDLE newService, scm; + + nError=0; + + // open a connection to the SCM + scm = OpenSCManager(0, 0,SC_MANAGER_CREATE_SERVICE); + if(scm) // Install the new service + { newService = CreateService( + scm, + szInternName, + szDisplayName, + dwDesiredAccess, //default: SERVICE_ALL_ACCESS + dwServiceType, //default: SERVICE_WIN32_OWN_PROCESS + dwStartType, //default: SERVICE_AUTOSTART + dwErrorControl, //default: SERVICE_ERROR_NORMAL + szFullPath, //exec full path + szLoadOrderGroup, //default: NULL + lpdwTagID, //default: NULL + szDependencies, //default: NULL + szAccountName, //default: NULL + szPassword); //default: NULL + + if (newService) CloseServiceHandle(newService); // clean up + else nError=2; + + // clean up + CloseServiceHandle(scm); + } + else nError=1; + + return (!nError); +} +/* ------------------------------------------------------------------------ + Remove() - Removes the service + nError values: + 0 success + 1 Can't open the Service manager + 2 Failed to locate service + 3 Failed to delete service + -------------------------------------------------------------------------- */ +BOOL NTService::Remove(LPCSTR szInternName) +{ + + SC_HANDLE service, scm; + + nError=0; + + // open a connection to the SCM + scm = OpenSCManager(0, 0,SC_MANAGER_CREATE_SERVICE); + + if (scm) + { + //open the service + service = OpenService(scm,szInternName, DELETE ); + if(service) + { + if(!DeleteService(service)) nError=3; + CloseServiceHandle(service); + } + else + { + //MessageBox(NULL,"Can't find the service","Remove Error",MB_OK|MB_ICONHAND); + nError=2; + } + CloseServiceHandle(scm); + } + else nError=1; + + return (!nError); +} + +/* ------------------------------------------------------------------------ + Stop() - this function should be called before the app. exits to stop + the service + -------------------------------------------------------------------------- */ +void NTService::Stop(void) +{ + SetStatus(SERVICE_STOP_PENDING,NO_ERROR, 0, 1, 60000); + StopService(); + SetStatus(SERVICE_STOPPED, NO_ERROR, 0, 1, 1000); +} + +/* ------------------------------------------------------------------------ + ServiceMain() - This is the function that is called from the + service manager to start the service + -------------------------------------------------------------------------- */ +void NTService::ServiceMain(DWORD argc, LPTSTR *argv) +{ + + // registration function + pService->hServiceStatusHandle = + RegisterServiceCtrlHandler(pService->ServiceName, + (LPHANDLER_FUNCTION )NTService::ServiceCtrlHandler); + + if(!pService->hServiceStatusHandle) + { + pService->Exit(GetLastError()); + return; + } + + // notify SCM of progress + if(!pService->SetStatus(SERVICE_START_PENDING,NO_ERROR, 0, 1, 8000)) + { + pService->Exit(GetLastError()); + return; + } + + // create the exit event + pService->hExitEvent = CreateEvent (0, TRUE, FALSE,0); + if(!pService->hExitEvent) + { + pService->Exit(GetLastError()); + return; + } + + if(!pService->SetStatus(SERVICE_START_PENDING,NO_ERROR, 0, 3, pService->nStartTimeOut)) + { + pService->Exit(GetLastError()); + return; + } + + // save start arguments + pService->my_argc=argc; + pService->my_argv=argv; + + // start the service + if(!pService->StartService()) + { + pService->Exit(GetLastError()); + return; + } + + // the service is now running. + if(!pService->SetStatus(SERVICE_RUNNING,NO_ERROR, 0, 0, 0)) + { + pService->Exit(GetLastError()); + return; + } + + // wait for exit event + WaitForSingleObject (pService->hExitEvent, INFINITE); + + // wait for thread to exit + WaitForSingleObject (pService->hThreadHandle, 30000); + + pService->Exit(0); +} + +/* ------------------------------------------------------------------------ + StartService() - starts the appliaction thread + -------------------------------------------------------------------------- */ +BOOL NTService::StartService() +{ + + // Start the real service's thread (application) + hThreadHandle = (HANDLE) _beginthread((THREAD_FC)fpServiceThread,0,(void *)this); + + if (hThreadHandle==0) return FALSE; + + bRunning = TRUE; + return TRUE; +} +/* ------------------------------------------------------------------------ + + -------------------------------------------------------------------------- */ +void NTService::StopService() +{ + bRunning=FALSE; + + // Set the event for application + if(hShutdownEvent) + SetEvent(hShutdownEvent); + + // Set the event for ServiceMain + SetEvent(hExitEvent); +} +/* ------------------------------------------------------------------------ + + -------------------------------------------------------------------------- */ +void NTService::PauseService() +{ + bPause = TRUE; + SuspendThread(hThreadHandle); +} +/* ------------------------------------------------------------------------ + + -------------------------------------------------------------------------- */ +void NTService::ResumeService() +{ + bPause=FALSE; + ResumeThread(hThreadHandle); +} +/* ------------------------------------------------------------------------ + + -------------------------------------------------------------------------- */ +BOOL NTService::SetStatus (DWORD dwCurrentState,DWORD dwWin32ExitCode, + DWORD dwServiceSpecificExitCode,DWORD dwCheckPoint,DWORD dwWaitHint) +{ + BOOL bRet; + SERVICE_STATUS serviceStatus; + + dwState=dwCurrentState; + + serviceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; + serviceStatus.dwCurrentState = dwCurrentState; + + if (dwCurrentState == SERVICE_START_PENDING) + serviceStatus.dwControlsAccepted = 0; //don't accept conrol events + else + serviceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | + SERVICE_ACCEPT_PAUSE_CONTINUE | SERVICE_ACCEPT_SHUTDOWN; + + // if a specific exit code is defined,set up the win32 exit code properly + if (dwServiceSpecificExitCode == 0) + serviceStatus.dwWin32ExitCode = dwWin32ExitCode; + else + serviceStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR; + + serviceStatus.dwServiceSpecificExitCode = dwServiceSpecificExitCode; + + serviceStatus.dwCheckPoint = dwCheckPoint; + serviceStatus.dwWaitHint = dwWaitHint; + + // Pass the status to the Service Manager + bRet=SetServiceStatus (hServiceStatusHandle, &serviceStatus); + + if(!bRet) StopService(); + + return bRet; +} +/* ------------------------------------------------------------------------ + + -------------------------------------------------------------------------- */ +void NTService::ServiceCtrlHandler(DWORD ctrlCode) +{ + + DWORD dwState = 0; + + if(!pService) return; + + dwState=pService->dwState; // get current state + + switch(ctrlCode) + { + + /*********** do we need this ? ******************************* + case SERVICE_CONTROL_PAUSE: + if (pService->bRunning && ! pService->bPause) + { + dwState = SERVICE_PAUSED; + pService->SetStatus(SERVICE_PAUSE_PENDING,NO_ERROR, 0, 1, pService->nPauseTimeOut); + pService->PauseService(); + } + break; + + case SERVICE_CONTROL_CONTINUE: + if (pService->bRunning && pService->bPause) + { + dwState = SERVICE_RUNNING; + pService->SetStatus(SERVICE_CONTINUE_PENDING,NO_ERROR, 0, 1, pService->nResumeTimeOut); + pService->ResumeService(); + } + break; + ****************************************************************/ + + case SERVICE_CONTROL_SHUTDOWN: + case SERVICE_CONTROL_STOP: + dwState = SERVICE_STOP_PENDING; + pService->SetStatus(SERVICE_STOP_PENDING,NO_ERROR, 0, 1, pService->nStopTimeOut); + pService->StopService(); + break; + + default: + pService->SetStatus(dwState, NO_ERROR,0, 0, 0); + break; + } + //pService->SetStatus(dwState, NO_ERROR,0, 0, 0); +} +/* ------------------------------------------------------------------------ + + -------------------------------------------------------------------------- */ +void NTService::Exit(DWORD error) +{ + if (hExitEvent) CloseHandle(hExitEvent); + + // Send a message to the scm to tell that we stop + if (hServiceStatusHandle) + SetStatus(SERVICE_STOPPED, error,0, 0, 0); + + // If the thread has started kill it ??? + // if (hThreadHandle) CloseHandle(hThreadHandle); + +} + +/* ------------------------- the end -------------------------------------- */ |