summaryrefslogtreecommitdiffstats
path: root/sql/nt_servc.cc
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 18:07:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 18:07:14 +0000
commita175314c3e5827eb193872241446f2f8f5c9d33c (patch)
treecd3d60ca99ae00829c52a6ca79150a5b6e62528b /sql/nt_servc.cc
parentInitial commit. (diff)
downloadmariadb-10.5-a175314c3e5827eb193872241446f2f8f5c9d33c.tar.xz
mariadb-10.5-a175314c3e5827eb193872241446f2f8f5c9d33c.zip
Adding upstream version 1:10.5.12.upstream/1%10.5.12upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--sql/nt_servc.cc555
1 files changed, 555 insertions, 0 deletions
diff --git a/sql/nt_servc.cc b/sql/nt_servc.cc
new file mode 100644
index 00000000..9c754763
--- /dev/null
+++ b/sql/nt_servc.cc
@@ -0,0 +1,555 @@
+/**
+ @file
+
+ @brief
+ 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 <stdio.h>
+#include <stdlib.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 = 86400000;
+ 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;
+}
+/* ------------------------------------------------------------------------
+
+ -------------------------------------------------------------------------- */
+
+
+/**
+ Registers the main service thread with the service manager.
+
+ @param ServiceThread pointer to the main programs entry function
+ when the service is started
+*/
+
+
+long NTService::Init(LPCSTR szInternName, THREAD_FC ServiceThread)
+{
+
+ pService = this;
+
+ fpServiceThread = ServiceThread;
+ ServiceName = new char[lstrlen(szInternName)+1];
+ lstrcpy(ServiceName,szInternName);
+
+ SERVICE_TABLE_ENTRY stb[] =
+ {
+ { (char *)szInternName, ServiceMain} ,
+ { NULL, NULL }
+ };
+
+ return StartServiceCtrlDispatcher(stb); //register with the Service Manager
+}
+
+
+/**
+ 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(int startType, LPCSTR szInternName,
+ LPCSTR szDisplayName,
+ LPCSTR szFullPath, LPCSTR szAccountName,
+ LPCSTR szPassword)
+{
+ BOOL ret_val=FALSE;
+ SC_HANDLE newService, scm;
+
+ if (!SeekStatus(szInternName,1))
+ return FALSE;
+
+ char szFilePath[_MAX_PATH];
+ GetModuleFileName(NULL, szFilePath, sizeof(szFilePath));
+
+ // open a connection to the SCM
+ if (!(scm = OpenSCManager(0, 0,SC_MANAGER_CREATE_SERVICE)))
+ printf("Failed to install the service (Couldn't open the SCM)\n");
+ else // Install the new service
+ {
+ if (!(newService=
+ CreateService(scm,
+ szInternName,
+ szDisplayName,
+ dwDesiredAccess,//default: SERVICE_ALL_ACCESS
+ dwServiceType, //default: SERVICE_WIN32_OWN_PROCESS
+ //default: SERVICE_AUTOSTART
+ (startType == 1 ? SERVICE_AUTO_START :
+ SERVICE_DEMAND_START),
+ dwErrorControl, //default: SERVICE_ERROR_NORMAL
+ szFullPath, //exec full path
+ szLoadOrderGroup, //default: NULL
+ lpdwTagID, //default: NULL
+ szDependencies, //default: NULL
+ szAccountName, //default: NULL
+ szPassword))) //default: NULL
+ printf("Failed to install the service (Couldn't create service)\n");
+ else
+ {
+ printf("Service successfully installed.\n");
+ CloseServiceHandle(newService);
+ ret_val=TRUE; // Everything went ok
+ }
+ CloseServiceHandle(scm);
+ }
+ return ret_val;
+}
+
+
+/**
+ 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)
+{
+ BOOL ret_value=FALSE;
+ SC_HANDLE service, scm;
+
+ if (!SeekStatus(szInternName,0))
+ return FALSE;
+
+ nError=0;
+
+ // open a connection to the SCM
+ if (!(scm = OpenSCManager(0, 0,SC_MANAGER_CREATE_SERVICE)))
+ {
+ printf("Failed to remove the service (Couldn't open the SCM)\n");
+ }
+ else
+ {
+ if ((service = OpenService(scm,szInternName, DELETE)))
+ {
+ if (!DeleteService(service))
+ printf("Failed to remove the service\n");
+ else
+ {
+ printf("Service successfully removed.\n");
+ ret_value=TRUE; // everything went ok
+ }
+ CloseServiceHandle(service);
+ }
+ else
+ printf("Failed to remove the service (Couldn't open the service)\n");
+ CloseServiceHandle(scm);
+ }
+ return ret_value;
+}
+
+/**
+ 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);
+}
+
+/**
+ This is the function that is called from the
+ service manager to start the service.
+*/
+
+
+void NTService::ServiceMain(DWORD argc, LPTSTR *argv)
+{
+
+ // registration function
+ if (!(pService->hServiceStatusHandle =
+ RegisterServiceCtrlHandler(pService->ServiceName,
+ NTService::ServiceCtrlHandler)))
+ goto error;
+
+ // notify SCM of progress
+ if (!pService->SetStatus(SERVICE_START_PENDING,NO_ERROR, 0, 1, 8000))
+ goto error;
+
+ // create the exit event
+ if (!(pService->hExitEvent = CreateEvent (0, TRUE, FALSE,0)))
+ goto error;
+
+ if (!pService->SetStatus(SERVICE_START_PENDING,NO_ERROR, 0, 3,
+ pService->nStartTimeOut))
+ goto error;
+
+ // save start arguments
+ pService->my_argc=argc;
+ pService->my_argv=argv;
+
+ // start the service
+ if (!pService->StartService())
+ goto error;
+
+ // wait for exit event
+ WaitForSingleObject (pService->hExitEvent, INFINITE);
+
+ // wait for thread to exit
+ if (WaitForSingleObject (pService->hThreadHandle, INFINITE) == WAIT_TIMEOUT)
+ CloseHandle(pService->hThreadHandle);
+
+ pService->Exit(0);
+ return;
+
+error:
+ pService->Exit(GetLastError());
+ return;
+}
+
+
+
+void NTService::SetRunning()
+{
+ if (pService)
+ pService->SetStatus(SERVICE_RUNNING, NO_ERROR, 0, 0, 0);
+}
+
+void NTService::SetSlowStarting(unsigned long timeout)
+{
+ if (pService)
+ pService->SetStatus(SERVICE_START_PENDING,NO_ERROR, 0, 0, timeout);
+}
+
+
+/* ------------------------------------------------------------------------
+ StartService() - starts the application thread
+ -------------------------------------------------------------------------- */
+
+BOOL NTService::StartService()
+{
+ // Start the real service's thread (application)
+ if (!(hThreadHandle = (HANDLE) _beginthread(fpServiceThread,0,
+ (void *) this)))
+ 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 control 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
+ if (!(bRet=SetServiceStatus (hServiceStatusHandle, &serviceStatus)))
+ StopService();
+
+ return bRet;
+}
+/* ------------------------------------------------------------------------
+
+ -------------------------------------------------------------------------- */
+void NTService::ServiceCtrlHandler(DWORD ctrlCode)
+{
+ DWORD dwState;
+
+ if (!pService)
+ return;
+
+ dwState=pService->dwState; // get current state
+
+ switch(ctrlCode) {
+ 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);
+
+}
+
+/* ------------------------------------------------------------------------
+
+ -------------------------------------------------------------------------- */
+
+BOOL NTService::SeekStatus(LPCSTR szInternName, int OperationType)
+{
+ BOOL ret_value=FALSE;
+ SC_HANDLE service, scm;
+
+ // open a connection to the SCM
+ if (!(scm = OpenSCManager(0, 0,SC_MANAGER_CREATE_SERVICE)))
+ {
+ DWORD ret_error=GetLastError();
+ if (ret_error == ERROR_ACCESS_DENIED)
+ {
+ printf("Install/Remove of the Service Denied!\n");
+ if (!is_super_user())
+ printf("That operation should be made by an user with Administrator privileges!\n");
+ }
+ else
+ printf("There is a problem for to open the Service Control Manager!\n");
+ }
+ else
+ {
+ if (OperationType == 1)
+ {
+ /* an install operation */
+ if ((service = OpenService(scm,szInternName, SERVICE_ALL_ACCESS )))
+ {
+ LPQUERY_SERVICE_CONFIG ConfigBuf;
+ DWORD dwSize;
+
+ ConfigBuf = (LPQUERY_SERVICE_CONFIG) LocalAlloc(LPTR, 4096);
+ printf("The service already exists!\n");
+ if (QueryServiceConfig(service,ConfigBuf,4096,&dwSize))
+ printf("The current server installed: %s\n",
+ ConfigBuf->lpBinaryPathName);
+ LocalFree(ConfigBuf);
+ CloseServiceHandle(service);
+ }
+ else
+ ret_value=TRUE;
+ }
+ else
+ {
+ /* a remove operation */
+ if (!(service = OpenService(scm,szInternName, SERVICE_ALL_ACCESS )))
+ printf("The service doesn't exist!\n");
+ else
+ {
+ SERVICE_STATUS ss;
+
+ memset(&ss, 0, sizeof(ss));
+ if (QueryServiceStatus(service,&ss))
+ {
+ DWORD dwState = ss.dwCurrentState;
+ if (dwState == SERVICE_RUNNING)
+ printf("Failed to remove the service because the service is running\nStop the service and try again\n");
+ else if (dwState == SERVICE_STOP_PENDING)
+ printf("\
+Failed to remove the service because the service is in stop pending state!\n\
+Wait 30 seconds and try again.\n\
+If this condition persist, reboot the machine and try again\n");
+ else
+ ret_value= TRUE;
+ }
+ CloseServiceHandle(service);
+ }
+ }
+ CloseServiceHandle(scm);
+ }
+
+ return ret_value;
+}
+/* ------------------------------------------------------------------------
+ -------------------------------------------------------------------------- */
+BOOL NTService::IsService(LPCSTR ServiceName)
+{
+ BOOL ret_value=FALSE;
+ SC_HANDLE service, scm;
+
+ if ((scm= OpenSCManager(0, 0,SC_MANAGER_ENUMERATE_SERVICE)))
+ {
+ if ((service = OpenService(scm,ServiceName, SERVICE_QUERY_STATUS)))
+ {
+ ret_value=TRUE;
+ CloseServiceHandle(service);
+ }
+ CloseServiceHandle(scm);
+ }
+ return ret_value;
+}
+/* ------------------------------------------------------------------------
+ -------------------------------------------------------------------------- */
+BOOL NTService::got_service_option(char **argv, const char *service_option)
+{
+ char *option;
+ for (option= argv[1]; *option; option++)
+ if (!strcmp(option, service_option))
+ return TRUE;
+ return FALSE;
+}
+/* ------------------------------------------------------------------------
+ -------------------------------------------------------------------------- */
+BOOL NTService::is_super_user()
+{
+ HANDLE hAccessToken;
+ UCHAR InfoBuffer[1024];
+ PTOKEN_GROUPS ptgGroups=(PTOKEN_GROUPS)InfoBuffer;
+ DWORD dwInfoBufferSize;
+ PSID psidAdministrators;
+ SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY;
+ UINT x;
+ BOOL ret_value=FALSE;
+
+ if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE,&hAccessToken ))
+ {
+ if (GetLastError() != ERROR_NO_TOKEN)
+ return FALSE;
+
+ if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hAccessToken))
+ return FALSE;
+ }
+
+ ret_value= GetTokenInformation(hAccessToken,TokenGroups,InfoBuffer,
+ 1024, &dwInfoBufferSize);
+
+ CloseHandle(hAccessToken);
+
+ if (!ret_value )
+ return FALSE;
+
+ if (!AllocateAndInitializeSid(&siaNtAuthority, 2,
+ SECURITY_BUILTIN_DOMAIN_RID,
+ DOMAIN_ALIAS_RID_ADMINS,
+ 0, 0, 0, 0, 0, 0,
+ &psidAdministrators))
+ return FALSE;
+
+ ret_value = FALSE;
+
+ for (x=0;x<ptgGroups->GroupCount;x++)
+ {
+ if ( EqualSid(psidAdministrators, ptgGroups->Groups[x].Sid) )
+ {
+ ret_value = TRUE;
+ break;
+ }
+
+ }
+ FreeSid(psidAdministrators);
+ return ret_value;
+}