~ubuntu-branches/ubuntu/precise/mysql-5.1/precise

« back to all changes in this revision

Viewing changes to sql/nt_servc.cc

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Tretkowski
  • Date: 2010-03-17 14:56:02 UTC
  • Revision ID: james.westby@ubuntu.com-20100317145602-x7e30l1b2sb5s6w6
Tags: upstream-5.1.45
ImportĀ upstreamĀ versionĀ 5.1.45

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
  @file
 
3
 
 
4
  @brief
 
5
  Windows NT Service class library.
 
6
 
 
7
  Copyright Abandoned 1998 Irena Pancirov - Irnet Snc
 
8
  This file is public domain and comes with NO WARRANTY of any kind
 
9
*/
 
10
#include <windows.h>
 
11
#include <process.h>
 
12
#include <stdio.h>
 
13
#include "nt_servc.h"
 
14
 
 
15
 
 
16
static NTService *pService;
 
17
 
 
18
/* ------------------------------------------------------------------------
 
19
 
 
20
 -------------------------------------------------------------------------- */
 
21
NTService::NTService()
 
22
{
 
23
 
 
24
    bOsNT            = FALSE;
 
25
    //service variables
 
26
    ServiceName      = NULL;
 
27
    hExitEvent       = 0;
 
28
    bPause           = FALSE;
 
29
    bRunning         = FALSE;
 
30
    hThreadHandle    = 0;
 
31
    fpServiceThread  = NULL;
 
32
 
 
33
    //time-out variables
 
34
    nStartTimeOut    = 15000;
 
35
    nStopTimeOut     = 86400000;
 
36
    nPauseTimeOut    = 5000;
 
37
    nResumeTimeOut   = 5000;
 
38
 
 
39
    //install variables
 
40
    dwDesiredAccess  = SERVICE_ALL_ACCESS;
 
41
    dwServiceType    = SERVICE_WIN32_OWN_PROCESS;
 
42
    dwStartType      = SERVICE_AUTO_START;
 
43
    dwErrorControl   = SERVICE_ERROR_NORMAL;
 
44
    szLoadOrderGroup = NULL;
 
45
    lpdwTagID        = NULL;
 
46
    szDependencies   = NULL;
 
47
 
 
48
    my_argc          = 0;
 
49
    my_argv          = NULL;
 
50
    hShutdownEvent   = 0;
 
51
    nError           = 0;
 
52
    dwState          = 0;
 
53
}
 
54
 
 
55
/* ------------------------------------------------------------------------
 
56
 
 
57
 -------------------------------------------------------------------------- */
 
58
NTService::~NTService()
 
59
{
 
60
  if (ServiceName != NULL) delete[] ServiceName;
 
61
}
 
62
/* ------------------------------------------------------------------------
 
63
 
 
64
 -------------------------------------------------------------------------- */
 
65
 
 
66
BOOL NTService::GetOS()
 
67
{
 
68
  bOsNT = FALSE;
 
69
  memset(&osVer, 0, sizeof(OSVERSIONINFO));
 
70
  osVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
 
71
  if (GetVersionEx(&osVer))
 
72
  {
 
73
    if (osVer.dwPlatformId == VER_PLATFORM_WIN32_NT)
 
74
      bOsNT = TRUE;
 
75
  }
 
76
  return bOsNT;
 
77
}
 
78
 
 
79
 
 
80
/**
 
81
  Registers the main service thread with the service manager.
 
82
 
 
83
  @param ServiceThread  pointer to the main programs entry function
 
84
                        when the service is started
 
85
*/
 
86
 
 
87
 
 
88
long NTService::Init(LPCSTR szInternName,void *ServiceThread)
 
89
{
 
90
 
 
91
  pService = this;
 
92
 
 
93
  fpServiceThread = (THREAD_FC)ServiceThread;
 
94
  ServiceName = new char[lstrlen(szInternName)+1];
 
95
  lstrcpy(ServiceName,szInternName);
 
96
 
 
97
  SERVICE_TABLE_ENTRY stb[] =
 
98
  {
 
99
    { (char *)szInternName,(LPSERVICE_MAIN_FUNCTION) ServiceMain} ,
 
100
    { NULL, NULL }
 
101
  };
 
102
 
 
103
  return StartServiceCtrlDispatcher(stb); //register with the Service Manager
 
104
}
 
105
 
 
106
 
 
107
/**
 
108
  Installs the service with Service manager.
 
109
 
 
110
  nError values:
 
111
  - 0  success
 
112
  - 1  Can't open the Service manager
 
113
  - 2  Failed to create service.
 
114
*/
 
115
 
 
116
 
 
117
BOOL NTService::Install(int startType, LPCSTR szInternName,
 
118
                        LPCSTR szDisplayName,
 
119
                        LPCSTR szFullPath, LPCSTR szAccountName,
 
120
                        LPCSTR szPassword)
 
121
{
 
122
  BOOL ret_val=FALSE;
 
123
  SC_HANDLE newService, scm;
 
124
 
 
125
  if (!SeekStatus(szInternName,1))
 
126
   return FALSE;
 
127
 
 
128
  char szFilePath[_MAX_PATH];
 
129
  GetModuleFileName(NULL, szFilePath, sizeof(szFilePath));
 
130
 
 
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
 
135
  {
 
136
    if (!(newService=
 
137
          CreateService(scm,
 
138
                        szInternName,
 
139
                        szDisplayName,
 
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");
 
153
     else
 
154
     {
 
155
       printf("Service successfully installed.\n");
 
156
       CloseServiceHandle(newService);
 
157
       ret_val=TRUE;                            // Everything went ok
 
158
     }
 
159
     CloseServiceHandle(scm);
 
160
  }
 
161
  return ret_val;
 
162
}
 
163
 
 
164
 
 
165
/**
 
166
  Removes  the service.
 
167
 
 
168
  nError values:
 
169
  - 0  success
 
170
  - 1  Can't open the Service manager
 
171
  - 2  Failed to locate service
 
172
  - 3  Failed to delete service.
 
173
*/
 
174
 
 
175
 
 
176
BOOL NTService::Remove(LPCSTR szInternName)
 
177
{
 
178
  BOOL ret_value=FALSE;
 
179
  SC_HANDLE service, scm;
 
180
 
 
181
  if (!SeekStatus(szInternName,0))
 
182
   return FALSE;
 
183
 
 
184
  nError=0;
 
185
 
 
186
  // open a connection to the SCM
 
187
  if (!(scm = OpenSCManager(0, 0,SC_MANAGER_CREATE_SERVICE)))
 
188
  {
 
189
    printf("Failed to remove the service (Couldn't open the SCM)\n");
 
190
  }
 
191
  else
 
192
  {
 
193
    if ((service = OpenService(scm,szInternName, DELETE)))
 
194
    {
 
195
      if (!DeleteService(service))
 
196
        printf("Failed to remove the service\n");
 
197
      else
 
198
      {
 
199
        printf("Service successfully removed.\n");
 
200
        ret_value=TRUE;                         // everything went ok
 
201
      }
 
202
      CloseServiceHandle(service);
 
203
    }
 
204
    else
 
205
      printf("Failed to remove the service (Couldn't open the service)\n");
 
206
    CloseServiceHandle(scm);
 
207
  }
 
208
  return ret_value;
 
209
}
 
210
 
 
211
/**
 
212
  this function should be called before the app. exits to stop
 
213
  the service
 
214
*/
 
215
void NTService::Stop(void)
 
216
{
 
217
  SetStatus(SERVICE_STOP_PENDING,NO_ERROR, 0, 1, 60000);
 
218
  StopService();
 
219
  SetStatus(SERVICE_STOPPED, NO_ERROR, 0, 1, 1000);
 
220
}
 
221
 
 
222
/**
 
223
  This is the function that is called from the
 
224
  service manager to start the service.
 
225
*/
 
226
 
 
227
 
 
228
void NTService::ServiceMain(DWORD argc, LPTSTR *argv)
 
229
{
 
230
 
 
231
  // registration function
 
232
  if (!(pService->hServiceStatusHandle =
 
233
        RegisterServiceCtrlHandler(pService->ServiceName,
 
234
                                   (LPHANDLER_FUNCTION)
 
235
                                   NTService::ServiceCtrlHandler)))
 
236
    goto error;
 
237
 
 
238
  // notify SCM of progress
 
239
  if (!pService->SetStatus(SERVICE_START_PENDING,NO_ERROR, 0, 1, 8000))
 
240
    goto error;
 
241
 
 
242
  // create the exit event
 
243
  if (!(pService->hExitEvent = CreateEvent (0, TRUE, FALSE,0)))
 
244
    goto error;
 
245
 
 
246
  if (!pService->SetStatus(SERVICE_START_PENDING,NO_ERROR, 0, 3,
 
247
                           pService->nStartTimeOut))
 
248
    goto error;
 
249
 
 
250
  // save start arguments
 
251
  pService->my_argc=argc;
 
252
  pService->my_argv=argv;
 
253
 
 
254
  // start the service
 
255
  if (!pService->StartService())
 
256
    goto error;
 
257
 
 
258
  // wait for exit event
 
259
  WaitForSingleObject (pService->hExitEvent, INFINITE);
 
260
 
 
261
  // wait for thread to exit
 
262
  if (WaitForSingleObject (pService->hThreadHandle, INFINITE) == WAIT_TIMEOUT)
 
263
   CloseHandle(pService->hThreadHandle);
 
264
 
 
265
  pService->Exit(0);
 
266
  return;
 
267
 
 
268
error:
 
269
  pService->Exit(GetLastError());
 
270
  return;
 
271
}
 
272
 
 
273
 
 
274
 
 
275
void NTService::SetRunning()
 
276
{
 
277
  if (pService)
 
278
    pService->SetStatus(SERVICE_RUNNING,NO_ERROR, 0, 0, 0);
 
279
}
 
280
 
 
281
 
 
282
/* ------------------------------------------------------------------------
 
283
   StartService() - starts the application thread
 
284
 -------------------------------------------------------------------------- */
 
285
 
 
286
BOOL NTService::StartService()
 
287
{
 
288
  // Start the real service's thread (application)
 
289
  if (!(hThreadHandle = (HANDLE) _beginthread((THREAD_FC)fpServiceThread,0,
 
290
                                              (void *) this)))
 
291
    return FALSE;
 
292
  bRunning = TRUE;
 
293
  return TRUE;
 
294
}
 
295
/* ------------------------------------------------------------------------
 
296
 
 
297
 -------------------------------------------------------------------------- */
 
298
void NTService::StopService()
 
299
{
 
300
  bRunning=FALSE;
 
301
 
 
302
  // Set the event for application
 
303
  if (hShutdownEvent)
 
304
     SetEvent(hShutdownEvent);
 
305
 
 
306
  // Set the event for ServiceMain
 
307
  SetEvent(hExitEvent);
 
308
}
 
309
/* ------------------------------------------------------------------------
 
310
 
 
311
 -------------------------------------------------------------------------- */
 
312
void NTService::PauseService()
 
313
{
 
314
  bPause = TRUE;
 
315
  SuspendThread(hThreadHandle);
 
316
}
 
317
/* ------------------------------------------------------------------------
 
318
 
 
319
 -------------------------------------------------------------------------- */
 
320
void NTService::ResumeService()
 
321
{
 
322
  bPause=FALSE;
 
323
  ResumeThread(hThreadHandle);
 
324
}
 
325
/* ------------------------------------------------------------------------
 
326
 
 
327
 -------------------------------------------------------------------------- */
 
328
BOOL NTService::SetStatus (DWORD dwCurrentState,DWORD dwWin32ExitCode,
 
329
                           DWORD dwServiceSpecificExitCode, DWORD dwCheckPoint,
 
330
                           DWORD dwWaitHint)
 
331
{
 
332
  BOOL bRet;
 
333
  SERVICE_STATUS serviceStatus;
 
334
 
 
335
  dwState=dwCurrentState;
 
336
 
 
337
  serviceStatus.dwServiceType   = SERVICE_WIN32_OWN_PROCESS;
 
338
  serviceStatus.dwCurrentState = dwCurrentState;
 
339
 
 
340
  if (dwCurrentState == SERVICE_START_PENDING)
 
341
    serviceStatus.dwControlsAccepted = 0;       //don't accept control events
 
342
  else
 
343
    serviceStatus.dwControlsAccepted =    (SERVICE_ACCEPT_STOP |
 
344
                                           SERVICE_ACCEPT_PAUSE_CONTINUE |
 
345
                                           SERVICE_ACCEPT_SHUTDOWN);
 
346
 
 
347
  // if a specific exit code is defined,set up the win32 exit code properly
 
348
  if (dwServiceSpecificExitCode == 0)
 
349
    serviceStatus.dwWin32ExitCode = dwWin32ExitCode;
 
350
  else
 
351
    serviceStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
 
352
 
 
353
  serviceStatus.dwServiceSpecificExitCode = dwServiceSpecificExitCode;
 
354
 
 
355
  serviceStatus.dwCheckPoint = dwCheckPoint;
 
356
  serviceStatus.dwWaitHint   = dwWaitHint;
 
357
 
 
358
  // Pass the status to the Service Manager
 
359
  if (!(bRet=SetServiceStatus (hServiceStatusHandle, &serviceStatus)))
 
360
    StopService();
 
361
 
 
362
  return bRet;
 
363
}
 
364
/* ------------------------------------------------------------------------
 
365
 
 
366
 -------------------------------------------------------------------------- */
 
367
void NTService::ServiceCtrlHandler(DWORD ctrlCode)
 
368
{
 
369
  DWORD  dwState;
 
370
 
 
371
  if (!pService)
 
372
    return;
 
373
 
 
374
  dwState=pService->dwState;  // get current state
 
375
 
 
376
  switch(ctrlCode) {
 
377
 
 
378
#ifdef NOT_USED  /* do we need this ? */
 
379
  case SERVICE_CONTROL_PAUSE:
 
380
    if (pService->bRunning && ! pService->bPause)
 
381
    {
 
382
      dwState = SERVICE_PAUSED;
 
383
      pService->SetStatus(SERVICE_PAUSE_PENDING,NO_ERROR, 0, 1,
 
384
                          pService->nPauseTimeOut);
 
385
      pService->PauseService();
 
386
    }
 
387
    break;
 
388
 
 
389
  case SERVICE_CONTROL_CONTINUE:
 
390
    if (pService->bRunning && pService->bPause)
 
391
    {
 
392
      dwState = SERVICE_RUNNING;
 
393
      pService->SetStatus(SERVICE_CONTINUE_PENDING,NO_ERROR, 0, 1,
 
394
                          pService->nResumeTimeOut);
 
395
      pService->ResumeService();
 
396
    }
 
397
    break;
 
398
#endif
 
399
 
 
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();
 
406
    break;
 
407
 
 
408
  default:
 
409
    pService->SetStatus(dwState, NO_ERROR,0, 0, 0);
 
410
    break;
 
411
  }
 
412
  //pService->SetStatus(dwState, NO_ERROR,0, 0, 0);
 
413
}
 
414
 
 
415
/* ------------------------------------------------------------------------
 
416
 
 
417
 -------------------------------------------------------------------------- */
 
418
 
 
419
void NTService::Exit(DWORD error)
 
420
{
 
421
  if (hExitEvent)
 
422
    CloseHandle(hExitEvent);
 
423
 
 
424
  // Send a message to the scm to tell that we stop
 
425
  if (hServiceStatusHandle)
 
426
    SetStatus(SERVICE_STOPPED, error,0, 0, 0);
 
427
 
 
428
  // If the thread has started kill it ???
 
429
  // if (hThreadHandle) CloseHandle(hThreadHandle);
 
430
 
 
431
}
 
432
 
 
433
/* ------------------------------------------------------------------------
 
434
 
 
435
 -------------------------------------------------------------------------- */
 
436
 
 
437
BOOL NTService::SeekStatus(LPCSTR szInternName, int OperationType)
 
438
{
 
439
  BOOL ret_value=FALSE;
 
440
  SC_HANDLE service, scm;
 
441
 
 
442
  // open a connection to the SCM
 
443
  if (!(scm = OpenSCManager(0, 0,SC_MANAGER_CREATE_SERVICE)))
 
444
  {
 
445
    DWORD ret_error=GetLastError();
 
446
    if (ret_error == ERROR_ACCESS_DENIED)
 
447
    {
 
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");
 
451
    }
 
452
    else
 
453
     printf("There is a problem for to open the Service Control Manager!\n");
 
454
  }
 
455
  else
 
456
  {
 
457
    if (OperationType == 1)
 
458
    {
 
459
      /* an install operation */
 
460
      if ((service = OpenService(scm,szInternName, SERVICE_ALL_ACCESS )))
 
461
      {
 
462
        LPQUERY_SERVICE_CONFIG ConfigBuf;
 
463
        DWORD dwSize;
 
464
 
 
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);
 
472
      }
 
473
      else
 
474
        ret_value=TRUE;
 
475
    }
 
476
    else
 
477
    {
 
478
      /* a remove operation */
 
479
      if (!(service = OpenService(scm,szInternName, SERVICE_ALL_ACCESS )))
 
480
        printf("The service doesn't exist!\n");
 
481
      else
 
482
      {
 
483
        SERVICE_STATUS ss;
 
484
 
 
485
        memset(&ss, 0, sizeof(ss));
 
486
        if (QueryServiceStatus(service,&ss))
 
487
        {
 
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)
 
492
            printf("\
 
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");
 
496
          else
 
497
            ret_value= TRUE;
 
498
        }
 
499
        CloseServiceHandle(service);
 
500
      }
 
501
    }
 
502
    CloseServiceHandle(scm);
 
503
  }
 
504
 
 
505
  return ret_value;
 
506
}
 
507
/* ------------------------------------------------------------------------
 
508
 -------------------------------------------------------------------------- */
 
509
BOOL NTService::IsService(LPCSTR ServiceName)
 
510
{
 
511
  BOOL ret_value=FALSE;
 
512
  SC_HANDLE service, scm;
 
513
  
 
514
  if ((scm= OpenSCManager(0, 0,SC_MANAGER_ENUMERATE_SERVICE)))
 
515
  {
 
516
    if ((service = OpenService(scm,ServiceName, SERVICE_QUERY_STATUS)))
 
517
    {
 
518
      ret_value=TRUE;
 
519
      CloseServiceHandle(service);
 
520
    }
 
521
    CloseServiceHandle(scm);
 
522
  }
 
523
  return ret_value;
 
524
}
 
525
/* ------------------------------------------------------------------------
 
526
 -------------------------------------------------------------------------- */
 
527
BOOL NTService::got_service_option(char **argv, char *service_option)
 
528
{
 
529
  char *option;
 
530
  for (option= argv[1]; *option; option++)
 
531
    if (!strcmp(option, service_option))
 
532
      return TRUE;
 
533
  return FALSE;
 
534
}
 
535
/* ------------------------------------------------------------------------
 
536
 -------------------------------------------------------------------------- */
 
537
BOOL NTService::is_super_user()
 
538
{
 
539
  HANDLE hAccessToken;
 
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;
 
545
  UINT x;
 
546
  BOOL ret_value=FALSE;
 
547
 
 
548
  if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE,&hAccessToken ))
 
549
  {
 
550
   if (GetLastError() != ERROR_NO_TOKEN)
 
551
     return FALSE;
 
552
 
 
553
   if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hAccessToken))
 
554
     return FALSE;
 
555
  }
 
556
 
 
557
  ret_value= GetTokenInformation(hAccessToken,TokenGroups,InfoBuffer,
 
558
                                 1024, &dwInfoBufferSize);
 
559
 
 
560
  CloseHandle(hAccessToken);
 
561
 
 
562
  if (!ret_value )
 
563
    return FALSE;
 
564
 
 
565
  if (!AllocateAndInitializeSid(&siaNtAuthority, 2,
 
566
                                SECURITY_BUILTIN_DOMAIN_RID,
 
567
                                DOMAIN_ALIAS_RID_ADMINS,
 
568
                                0, 0, 0, 0, 0, 0,
 
569
                                &psidAdministrators))
 
570
    return FALSE;
 
571
 
 
572
  ret_value = FALSE;
 
573
 
 
574
  for (x=0;x<ptgGroups->GroupCount;x++)
 
575
  {
 
576
   if ( EqualSid(psidAdministrators, ptgGroups->Groups[x].Sid) )
 
577
   {
 
578
    ret_value = TRUE;
 
579
    break;
 
580
   }
 
581
 
 
582
  }
 
583
  FreeSid(psidAdministrators);
 
584
  return ret_value;
 
585
}