5
Windows NT Service class library.
7
Copyright Abandoned 1998 Irena Pancirov - Irnet Snc
8
This file is public domain and comes with NO WARRANTY of any kind
16
static NTService *pService;
18
/* ------------------------------------------------------------------------
20
-------------------------------------------------------------------------- */
21
NTService::NTService()
31
fpServiceThread = NULL;
34
nStartTimeOut = 15000;
35
nStopTimeOut = 86400000;
37
nResumeTimeOut = 5000;
40
dwDesiredAccess = SERVICE_ALL_ACCESS;
41
dwServiceType = SERVICE_WIN32_OWN_PROCESS;
42
dwStartType = SERVICE_AUTO_START;
43
dwErrorControl = SERVICE_ERROR_NORMAL;
44
szLoadOrderGroup = NULL;
46
szDependencies = NULL;
55
/* ------------------------------------------------------------------------
57
-------------------------------------------------------------------------- */
58
NTService::~NTService()
60
if (ServiceName != NULL) delete[] ServiceName;
62
/* ------------------------------------------------------------------------
64
-------------------------------------------------------------------------- */
66
BOOL NTService::GetOS()
69
memset(&osVer, 0, sizeof(OSVERSIONINFO));
70
osVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
71
if (GetVersionEx(&osVer))
73
if (osVer.dwPlatformId == VER_PLATFORM_WIN32_NT)
81
Registers the main service thread with the service manager.
83
@param ServiceThread pointer to the main programs entry function
84
when the service is started
88
long NTService::Init(LPCSTR szInternName,void *ServiceThread)
93
fpServiceThread = (THREAD_FC)ServiceThread;
94
ServiceName = new char[lstrlen(szInternName)+1];
95
lstrcpy(ServiceName,szInternName);
97
SERVICE_TABLE_ENTRY stb[] =
99
{ (char *)szInternName,(LPSERVICE_MAIN_FUNCTION) ServiceMain} ,
103
return StartServiceCtrlDispatcher(stb); //register with the Service Manager
108
Installs the service with Service manager.
112
- 1 Can't open the Service manager
113
- 2 Failed to create service.
117
BOOL NTService::Install(int startType, LPCSTR szInternName,
118
LPCSTR szDisplayName,
119
LPCSTR szFullPath, LPCSTR szAccountName,
123
SC_HANDLE newService, scm;
125
if (!SeekStatus(szInternName,1))
128
char szFilePath[_MAX_PATH];
129
GetModuleFileName(NULL, szFilePath, sizeof(szFilePath));
131
// open a connection to the SCM
132
if (!(scm = OpenSCManager(0, 0,SC_MANAGER_CREATE_SERVICE)))
133
printf("Failed to install the service (Couldn't open the SCM)\n");
134
else // Install the new service
140
dwDesiredAccess,//default: SERVICE_ALL_ACCESS
141
dwServiceType, //default: SERVICE_WIN32_OWN_PROCESS
142
//default: SERVICE_AUTOSTART
143
(startType == 1 ? SERVICE_AUTO_START :
144
SERVICE_DEMAND_START),
145
dwErrorControl, //default: SERVICE_ERROR_NORMAL
146
szFullPath, //exec full path
147
szLoadOrderGroup, //default: NULL
148
lpdwTagID, //default: NULL
149
szDependencies, //default: NULL
150
szAccountName, //default: NULL
151
szPassword))) //default: NULL
152
printf("Failed to install the service (Couldn't create service)\n");
155
printf("Service successfully installed.\n");
156
CloseServiceHandle(newService);
157
ret_val=TRUE; // Everything went ok
159
CloseServiceHandle(scm);
170
- 1 Can't open the Service manager
171
- 2 Failed to locate service
172
- 3 Failed to delete service.
176
BOOL NTService::Remove(LPCSTR szInternName)
178
BOOL ret_value=FALSE;
179
SC_HANDLE service, scm;
181
if (!SeekStatus(szInternName,0))
186
// open a connection to the SCM
187
if (!(scm = OpenSCManager(0, 0,SC_MANAGER_CREATE_SERVICE)))
189
printf("Failed to remove the service (Couldn't open the SCM)\n");
193
if ((service = OpenService(scm,szInternName, DELETE)))
195
if (!DeleteService(service))
196
printf("Failed to remove the service\n");
199
printf("Service successfully removed.\n");
200
ret_value=TRUE; // everything went ok
202
CloseServiceHandle(service);
205
printf("Failed to remove the service (Couldn't open the service)\n");
206
CloseServiceHandle(scm);
212
this function should be called before the app. exits to stop
215
void NTService::Stop(void)
217
SetStatus(SERVICE_STOP_PENDING,NO_ERROR, 0, 1, 60000);
219
SetStatus(SERVICE_STOPPED, NO_ERROR, 0, 1, 1000);
223
This is the function that is called from the
224
service manager to start the service.
228
void NTService::ServiceMain(DWORD argc, LPTSTR *argv)
231
// registration function
232
if (!(pService->hServiceStatusHandle =
233
RegisterServiceCtrlHandler(pService->ServiceName,
235
NTService::ServiceCtrlHandler)))
238
// notify SCM of progress
239
if (!pService->SetStatus(SERVICE_START_PENDING,NO_ERROR, 0, 1, 8000))
242
// create the exit event
243
if (!(pService->hExitEvent = CreateEvent (0, TRUE, FALSE,0)))
246
if (!pService->SetStatus(SERVICE_START_PENDING,NO_ERROR, 0, 3,
247
pService->nStartTimeOut))
250
// save start arguments
251
pService->my_argc=argc;
252
pService->my_argv=argv;
255
if (!pService->StartService())
258
// wait for exit event
259
WaitForSingleObject (pService->hExitEvent, INFINITE);
261
// wait for thread to exit
262
if (WaitForSingleObject (pService->hThreadHandle, INFINITE) == WAIT_TIMEOUT)
263
CloseHandle(pService->hThreadHandle);
269
pService->Exit(GetLastError());
275
void NTService::SetRunning()
278
pService->SetStatus(SERVICE_RUNNING,NO_ERROR, 0, 0, 0);
282
/* ------------------------------------------------------------------------
283
StartService() - starts the application thread
284
-------------------------------------------------------------------------- */
286
BOOL NTService::StartService()
288
// Start the real service's thread (application)
289
if (!(hThreadHandle = (HANDLE) _beginthread((THREAD_FC)fpServiceThread,0,
295
/* ------------------------------------------------------------------------
297
-------------------------------------------------------------------------- */
298
void NTService::StopService()
302
// Set the event for application
304
SetEvent(hShutdownEvent);
306
// Set the event for ServiceMain
307
SetEvent(hExitEvent);
309
/* ------------------------------------------------------------------------
311
-------------------------------------------------------------------------- */
312
void NTService::PauseService()
315
SuspendThread(hThreadHandle);
317
/* ------------------------------------------------------------------------
319
-------------------------------------------------------------------------- */
320
void NTService::ResumeService()
323
ResumeThread(hThreadHandle);
325
/* ------------------------------------------------------------------------
327
-------------------------------------------------------------------------- */
328
BOOL NTService::SetStatus (DWORD dwCurrentState,DWORD dwWin32ExitCode,
329
DWORD dwServiceSpecificExitCode, DWORD dwCheckPoint,
333
SERVICE_STATUS serviceStatus;
335
dwState=dwCurrentState;
337
serviceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
338
serviceStatus.dwCurrentState = dwCurrentState;
340
if (dwCurrentState == SERVICE_START_PENDING)
341
serviceStatus.dwControlsAccepted = 0; //don't accept control events
343
serviceStatus.dwControlsAccepted = (SERVICE_ACCEPT_STOP |
344
SERVICE_ACCEPT_PAUSE_CONTINUE |
345
SERVICE_ACCEPT_SHUTDOWN);
347
// if a specific exit code is defined,set up the win32 exit code properly
348
if (dwServiceSpecificExitCode == 0)
349
serviceStatus.dwWin32ExitCode = dwWin32ExitCode;
351
serviceStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
353
serviceStatus.dwServiceSpecificExitCode = dwServiceSpecificExitCode;
355
serviceStatus.dwCheckPoint = dwCheckPoint;
356
serviceStatus.dwWaitHint = dwWaitHint;
358
// Pass the status to the Service Manager
359
if (!(bRet=SetServiceStatus (hServiceStatusHandle, &serviceStatus)))
364
/* ------------------------------------------------------------------------
366
-------------------------------------------------------------------------- */
367
void NTService::ServiceCtrlHandler(DWORD ctrlCode)
374
dwState=pService->dwState; // get current state
378
#ifdef NOT_USED /* do we need this ? */
379
case SERVICE_CONTROL_PAUSE:
380
if (pService->bRunning && ! pService->bPause)
382
dwState = SERVICE_PAUSED;
383
pService->SetStatus(SERVICE_PAUSE_PENDING,NO_ERROR, 0, 1,
384
pService->nPauseTimeOut);
385
pService->PauseService();
389
case SERVICE_CONTROL_CONTINUE:
390
if (pService->bRunning && pService->bPause)
392
dwState = SERVICE_RUNNING;
393
pService->SetStatus(SERVICE_CONTINUE_PENDING,NO_ERROR, 0, 1,
394
pService->nResumeTimeOut);
395
pService->ResumeService();
400
case SERVICE_CONTROL_SHUTDOWN:
401
case SERVICE_CONTROL_STOP:
402
dwState = SERVICE_STOP_PENDING;
403
pService->SetStatus(SERVICE_STOP_PENDING,NO_ERROR, 0, 1,
404
pService->nStopTimeOut);
405
pService->StopService();
409
pService->SetStatus(dwState, NO_ERROR,0, 0, 0);
412
//pService->SetStatus(dwState, NO_ERROR,0, 0, 0);
415
/* ------------------------------------------------------------------------
417
-------------------------------------------------------------------------- */
419
void NTService::Exit(DWORD error)
422
CloseHandle(hExitEvent);
424
// Send a message to the scm to tell that we stop
425
if (hServiceStatusHandle)
426
SetStatus(SERVICE_STOPPED, error,0, 0, 0);
428
// If the thread has started kill it ???
429
// if (hThreadHandle) CloseHandle(hThreadHandle);
433
/* ------------------------------------------------------------------------
435
-------------------------------------------------------------------------- */
437
BOOL NTService::SeekStatus(LPCSTR szInternName, int OperationType)
439
BOOL ret_value=FALSE;
440
SC_HANDLE service, scm;
442
// open a connection to the SCM
443
if (!(scm = OpenSCManager(0, 0,SC_MANAGER_CREATE_SERVICE)))
445
DWORD ret_error=GetLastError();
446
if (ret_error == ERROR_ACCESS_DENIED)
448
printf("Install/Remove of the Service Denied!\n");
449
if (!is_super_user())
450
printf("That operation should be made by an user with Administrator privileges!\n");
453
printf("There is a problem for to open the Service Control Manager!\n");
457
if (OperationType == 1)
459
/* an install operation */
460
if ((service = OpenService(scm,szInternName, SERVICE_ALL_ACCESS )))
462
LPQUERY_SERVICE_CONFIG ConfigBuf;
465
ConfigBuf = (LPQUERY_SERVICE_CONFIG) LocalAlloc(LPTR, 4096);
466
printf("The service already exists!\n");
467
if (QueryServiceConfig(service,ConfigBuf,4096,&dwSize))
468
printf("The current server installed: %s\n",
469
ConfigBuf->lpBinaryPathName);
470
LocalFree(ConfigBuf);
471
CloseServiceHandle(service);
478
/* a remove operation */
479
if (!(service = OpenService(scm,szInternName, SERVICE_ALL_ACCESS )))
480
printf("The service doesn't exist!\n");
485
memset(&ss, 0, sizeof(ss));
486
if (QueryServiceStatus(service,&ss))
488
DWORD dwState = ss.dwCurrentState;
489
if (dwState == SERVICE_RUNNING)
490
printf("Failed to remove the service because the service is running\nStop the service and try again\n");
491
else if (dwState == SERVICE_STOP_PENDING)
493
Failed to remove the service because the service is in stop pending state!\n\
494
Wait 30 seconds and try again.\n\
495
If this condition persist, reboot the machine and try again\n");
499
CloseServiceHandle(service);
502
CloseServiceHandle(scm);
507
/* ------------------------------------------------------------------------
508
-------------------------------------------------------------------------- */
509
BOOL NTService::IsService(LPCSTR ServiceName)
511
BOOL ret_value=FALSE;
512
SC_HANDLE service, scm;
514
if ((scm= OpenSCManager(0, 0,SC_MANAGER_ENUMERATE_SERVICE)))
516
if ((service = OpenService(scm,ServiceName, SERVICE_QUERY_STATUS)))
519
CloseServiceHandle(service);
521
CloseServiceHandle(scm);
525
/* ------------------------------------------------------------------------
526
-------------------------------------------------------------------------- */
527
BOOL NTService::got_service_option(char **argv, char *service_option)
530
for (option= argv[1]; *option; option++)
531
if (!strcmp(option, service_option))
535
/* ------------------------------------------------------------------------
536
-------------------------------------------------------------------------- */
537
BOOL NTService::is_super_user()
540
UCHAR InfoBuffer[1024];
541
PTOKEN_GROUPS ptgGroups=(PTOKEN_GROUPS)InfoBuffer;
542
DWORD dwInfoBufferSize;
543
PSID psidAdministrators;
544
SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY;
546
BOOL ret_value=FALSE;
548
if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE,&hAccessToken ))
550
if (GetLastError() != ERROR_NO_TOKEN)
553
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hAccessToken))
557
ret_value= GetTokenInformation(hAccessToken,TokenGroups,InfoBuffer,
558
1024, &dwInfoBufferSize);
560
CloseHandle(hAccessToken);
565
if (!AllocateAndInitializeSid(&siaNtAuthority, 2,
566
SECURITY_BUILTIN_DOMAIN_RID,
567
DOMAIN_ALIAS_RID_ADMINS,
569
&psidAdministrators))
574
for (x=0;x<ptgGroups->GroupCount;x++)
576
if ( EqualSid(psidAdministrators, ptgGroups->Groups[x].Sid) )
583
FreeSid(psidAdministrators);