ReactOS 0.4.15-dev-8100-g1887773
service.c File Reference
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <process.h>
#include <tchar.h>
#include "service.h"
Include dependency graph for service.c:

Go to the source code of this file.

Functions

VOID WINAPI service_ctrl (DWORD dwCtrlCode)
 
VOID WINAPI service_main (DWORD dwArgc, LPTSTR *lpszArgv)
 
VOID CmdInstallService ()
 
VOID CmdRemoveService ()
 
VOID CmdDebugService (int argc, char **argv)
 
BOOL WINAPI ControlHandler (DWORD dwCtrlType)
 
LPTSTR GetLastErrorText (LPTSTR lpszBuf, DWORD dwSize)
 
void __cdecl main (int argc, char **argv)
 
BOOL ReportStatusToSCMgr (DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint)
 
VOID AddToMessageLog (LPTSTR lpszMsg)
 

Variables

SERVICE_STATUS ssStatus
 
SERVICE_STATUS_HANDLE sshStatusHandle
 
DWORD dwErr = 0
 
BOOL bDebug = FALSE
 
TCHAR szErr [256]
 

Function Documentation

◆ AddToMessageLog()

VOID AddToMessageLog ( LPTSTR  lpszMsg)

Definition at line 289 of file service.c.

290{
291 TCHAR szMsg [(sizeof(SZSERVICENAME) / sizeof(TCHAR)) + 100 ];
292 HANDLE hEventSource;
293 LPTSTR lpszStrings[2];
294
295 if ( !bDebug )
296 {
298
299 // Use event logging to log the error.
300 //
301 hEventSource = RegisterEventSource(NULL, TEXT(SZSERVICENAME));
302
303#ifndef __REACTOS__
304 _stprintf_s(szMsg,(sizeof(SZSERVICENAME) / sizeof(TCHAR)) + 100, TEXT("%s error: %d"), TEXT(SZSERVICENAME), dwErr);
305#else
306 _sntprintf(szMsg,(sizeof(SZSERVICENAME) / sizeof(TCHAR)) + 100, TEXT("%s error: %d"), TEXT(SZSERVICENAME), dwErr);
307#endif
308 lpszStrings[0] = szMsg;
309 lpszStrings[1] = lpszMsg;
310
311 if (hEventSource != NULL)
312 {
313 ReportEvent(hEventSource, // handle of event source
314 EVENTLOG_ERROR_TYPE, // event type
315 0, // event category
316 0, // event ID
317 NULL, // current user's SID
318 2, // strings in lpszStrings
319 0, // no bytes of raw data
320 lpszStrings, // array of error strings
321 NULL); // no raw data
322
323 (VOID) DeregisterEventSource(hEventSource);
324 }
325 }
326}
#define VOID
Definition: acefi.h:82
BOOL bDebug
Definition: service.c:37
DWORD dwErr
Definition: service.c:36
#define NULL
Definition: types.h:112
BOOL WINAPI DeregisterEventSource(IN HANDLE hEventLog)
Definition: eventlog.c:473
#define TEXT(s)
Definition: k32.h:26
#define SZSERVICENAME
Definition: service.h:67
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define ReportEvent
Definition: winbase.h:3899
#define RegisterEventSource
Definition: winbase.h:3894
#define EVENTLOG_ERROR_TYPE
Definition: winnt_old.h:2834
char TCHAR
Definition: xmlstorage.h:189
#define _sntprintf
Definition: xmlstorage.h:201
CHAR * LPTSTR
Definition: xmlstorage.h:192

Referenced by main(), and ReportStatusToSCMgr().

◆ CmdDebugService()

void CmdDebugService ( int  argc,
char **  argv 
)

Definition at line 497 of file service.c.

498{
499 DWORD dwArgc;
500 LPTSTR *lpszArgv;
501
502#ifdef UNICODE
503 lpszArgv = CommandLineToArgvW(GetCommandLineW(), &(dwArgc) );
504 if (NULL == lpszArgv)
505 {
506 // CommandLineToArvW failed!!
507 _tprintf(TEXT("CmdDebugService CommandLineToArgvW returned NULL\n"));
508 return;
509 }
510#else
511 dwArgc = (DWORD) argc;
512 lpszArgv = argv;
513#endif
514
515 _tprintf(TEXT("Debugging %s.\n"), TEXT(SZSERVICEDISPLAYNAME));
516
518
519 ServiceStart( dwArgc, lpszArgv );
520
521#ifdef UNICODE
522// Must free memory allocated for arguments
523
524 GlobalFree(lpszArgv);
525#endif // UNICODE
526
527}
static int argc
Definition: ServiceArgs.c:12
BOOL WINAPI ControlHandler(DWORD dwCtrlType)
Definition: service.c:544
#define TRUE
Definition: types.h:120
BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine, BOOL Add)
Definition: console.c:2109
LPWSTR WINAPI GetCommandLineW(VOID)
Definition: proc.c:2013
unsigned long DWORD
Definition: ntddk_ex.h:95
HGLOBAL NTAPI GlobalFree(HGLOBAL hMem)
Definition: heapmem.c:611
#define _tprintf
Definition: tchar.h:506
#define argv
Definition: mplay32.c:18
VOID ServiceStart(DWORD argc, LPTSTR *argv)
Definition: nfs41_daemon.c:381
#define DWORD
Definition: nt_native.h:44
#define SZSERVICEDISPLAYNAME
Definition: service.h:69
LPWSTR *WINAPI CommandLineToArgvW(LPCWSTR lpCmdline, int *numargs)
Definition: shell32_main.c:80

Referenced by main().

◆ CmdInstallService()

void CmdInstallService ( )

Definition at line 350 of file service.c.

351{
352 SC_HANDLE schService;
353 SC_HANDLE schSCManager;
354
355 TCHAR szPath[512];
356
357 if ( GetModuleFileName( NULL, szPath, 512 ) == 0 )
358 {
359 _tprintf(TEXT("Unable to install %s - %s\n"), TEXT(SZSERVICEDISPLAYNAME), GetLastErrorText(szErr, 256));
360 return;
361 }
362
363 schSCManager = OpenSCManager(
364 NULL, // machine (NULL == local)
365 NULL, // database (NULL == default)
367 );
368 if ( schSCManager )
369 {
370 schService = CreateService(
371 schSCManager, // SCManager database
372 TEXT(SZSERVICENAME), // name of service
373 TEXT(SZSERVICEDISPLAYNAME), // name to display
374 SERVICE_QUERY_STATUS, // desired access
375 SERVICE_WIN32_OWN_PROCESS, // service type
376 SERVICE_AUTO_START, // start type
377 SERVICE_ERROR_NORMAL, // error control type
378 szPath, // service's binary
379 NULL, // no load ordering group
380 NULL, // no tag identifier
381 TEXT(SZDEPENDENCIES), // dependencies
382 NULL, // LocalSystem account
383 NULL); // no password
384
385 if ( schService )
386 {
387 _tprintf(TEXT("%s installed.\n"), TEXT(SZSERVICEDISPLAYNAME) );
388 CloseServiceHandle(schService);
389 }
390 else
391 {
392 _tprintf(TEXT("CreateService failed - %s\n"), GetLastErrorText(szErr, 256));
393 }
394
395 CloseServiceHandle(schSCManager);
396 }
397 else
398 _tprintf(TEXT("OpenSCManager failed - %s\n"), GetLastErrorText(szErr,256));
399}
TCHAR szErr[256]
Definition: service.c:38
LPTSTR GetLastErrorText(LPTSTR lpszBuf, DWORD dwSize)
Definition: service.c:573
LPCWSTR szPath
Definition: env.c:37
BOOL WINAPI CloseServiceHandle(SC_HANDLE hSCObject)
Definition: scm.c:580
#define SZDEPENDENCIES
Definition: service.h:71
#define GetModuleFileName
Definition: winbase.h:3831
#define SERVICE_QUERY_STATUS
Definition: winsvc.h:55
#define OpenSCManager
Definition: winsvc.h:575
#define CreateService
Definition: winsvc.h:569
#define SC_MANAGER_CREATE_SERVICE
Definition: winsvc.h:15
#define SC_MANAGER_CONNECT
Definition: winsvc.h:14
#define SERVICE_AUTO_START
Definition: cmtypes.h:977
#define SERVICE_WIN32_OWN_PROCESS
Definition: cmtypes.h:962
#define SERVICE_ERROR_NORMAL
Definition: cmtypes.h:982

Referenced by main().

◆ CmdRemoveService()

void CmdRemoveService ( )

Definition at line 416 of file service.c.

417{
418 SC_HANDLE schService;
419 SC_HANDLE schSCManager;
420
421 schSCManager = OpenSCManager(
422 NULL, // machine (NULL == local)
423 NULL, // database (NULL == default)
424 SC_MANAGER_CONNECT // access required
425 );
426 if ( schSCManager )
427 {
428 schService = OpenService(schSCManager, TEXT(SZSERVICENAME), DELETE | SERVICE_STOP | SERVICE_QUERY_STATUS);
429
430 if (schService)
431 {
432 // try to stop the service
433 if ( ControlService( schService, SERVICE_CONTROL_STOP, &ssStatus ) )
434 {
435 _tprintf(TEXT("Stopping %s."), TEXT(SZSERVICEDISPLAYNAME));
436 Sleep( 1000 );
437
438 while ( QueryServiceStatus( schService, &ssStatus ) )
439 {
441 {
442 _tprintf(TEXT("."));
443 Sleep( 1000 );
444 }
445 else
446 break;
447 }
448
450 _tprintf(TEXT("\n%s stopped.\n"), TEXT(SZSERVICEDISPLAYNAME) );
451 else
452 _tprintf(TEXT("\n%s failed to stop.\n"), TEXT(SZSERVICEDISPLAYNAME) );
453
454 }
455
456 // now remove the service
457 if ( DeleteService(schService) )
458 _tprintf(TEXT("%s removed.\n"), TEXT(SZSERVICEDISPLAYNAME) );
459 else
460 _tprintf(TEXT("DeleteService failed - %s\n"), GetLastErrorText(szErr,256));
461
462
463 CloseServiceHandle(schService);
464 }
465 else
466 _tprintf(TEXT("OpenService failed - %s\n"), GetLastErrorText(szErr,256));
467
468 CloseServiceHandle(schSCManager);
469 }
470 else
471 _tprintf(TEXT("OpenSCManager failed - %s\n"), GetLastErrorText(szErr,256));
472}
SERVICE_STATUS ssStatus
Definition: service.c:34
#define DELETE
Definition: nt_native.h:57
BOOL WINAPI QueryServiceStatus(SC_HANDLE hService, LPSERVICE_STATUS lpServiceStatus)
Definition: scm.c:2845
BOOL WINAPI DeleteService(SC_HANDLE hService)
Definition: scm.c:921
BOOL WINAPI ControlService(SC_HANDLE hService, DWORD dwControl, LPSERVICE_STATUS lpServiceStatus)
Definition: scm.c:622
DWORD dwCurrentState
Definition: winsvc.h:100
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:790
#define SERVICE_STOPPED
Definition: winsvc.h:21
#define SERVICE_STOP_PENDING
Definition: winsvc.h:23
#define SERVICE_STOP
Definition: winsvc.h:58
#define SERVICE_CONTROL_STOP
Definition: winsvc.h:36
#define OpenService
Definition: winsvc.h:576

Referenced by main().

◆ ControlHandler()

BOOL WINAPI ControlHandler ( DWORD  dwCtrlType)

Definition at line 544 of file service.c.

545{
546 switch ( dwCtrlType )
547 {
548 case CTRL_BREAK_EVENT: // use Ctrl+C or Ctrl+Break to simulate
549 case CTRL_C_EVENT: // SERVICE_CONTROL_STOP in debug mode
550 _tprintf(TEXT("Stopping %s.\n"), TEXT(SZSERVICEDISPLAYNAME));
551 ServiceStop();
552 return TRUE;
553 break;
554
555 }
556 return FALSE;
557}
#define FALSE
Definition: types.h:117
VOID ServiceStop()
Definition: nfs41_daemon.c:156
#define CTRL_C_EVENT
Definition: wincon.h:68
#define CTRL_BREAK_EVENT
Definition: wincon.h:69

Referenced by CmdDebugService().

◆ GetLastErrorText()

LPTSTR GetLastErrorText ( LPTSTR  lpszBuf,
DWORD  dwSize 
)

Definition at line 573 of file service.c.

574{
575 DWORD dwRet;
576 LPTSTR lpszTemp = NULL;
577
579 NULL,
580 GetLastError(),
582 (LPTSTR)&lpszTemp,
583 0,
584 NULL );
585
586 // supplied buffer is not long enough
587 if ( !dwRet || ( (long)dwSize < (long)dwRet+14 ) )
588 lpszBuf[0] = TEXT('\0');
589 else
590 {
591 if (NULL != lpszTemp)
592 {
593 lpszTemp[lstrlen(lpszTemp)-2] = TEXT('\0'); //remove cr and newline character
594#ifndef __REACTOS__
595 _stprintf_s( lpszBuf, dwSize, TEXT("%s (0x%x)"), lpszTemp, GetLastError() );
596#else
597 _sntprintf( lpszBuf, dwSize, TEXT("%s (0x%x)"), lpszTemp, GetLastError() );
598#endif
599 }
600 }
601
602 if ( NULL != lpszTemp )
603 LocalFree((HLOCAL) lpszTemp );
604
605 return lpszBuf;
606}
HLOCAL NTAPI LocalFree(HLOCAL hMem)
Definition: heapmem.c:1594
PSDBQUERYRESULT_VISTA PVOID DWORD * dwSize
Definition: env.c:56
#define LANG_NEUTRAL
Definition: nls.h:22
#define FormatMessage
Definition: winbase.h:3795
#define FORMAT_MESSAGE_FROM_SYSTEM
Definition: winbase.h:423
#define FORMAT_MESSAGE_ALLOCATE_BUFFER
Definition: winbase.h:419
#define FORMAT_MESSAGE_ARGUMENT_ARRAY
Definition: winbase.h:424
#define lstrlen
Definition: winbase.h:3876

Referenced by CmdInstallService(), and CmdRemoveService().

◆ main()

void __cdecl main ( int argc  ,
char **  argv 
)

Definition at line 67 of file service.c.

68{
69 SERVICE_TABLE_ENTRY dispatchTable[] =
70 {
72 { NULL, NULL}
73 };
74
75 if ( (argc > 1) &&
76 ((*argv[1] == '-') || (*argv[1] == '/')) )
77 {
78 if ( _stricmp( "install", argv[1]+1 ) == 0 )
79 {
81 }
82 else if ( _stricmp( "remove", argv[1]+1 ) == 0 )
83 {
85 }
86 else if ( _stricmp( "debug", argv[1]+1 ) == 0 )
87 {
88 bDebug = TRUE;
90 }
91 else
92 {
93 goto dispatch;
94 }
95 exit(0);
96 }
97
98 // if it doesn't match any of the above parameters
99 // the service control manager may be starting the service
100 // so we must call StartServiceCtrlDispatcher
101 dispatch:
102 // this is just to be friendly
103 printf( "%s -install to install the service\n", SZAPPNAME );
104 printf( "%s -remove to remove the service\n", SZAPPNAME );
105 printf( "%s -debug <params> to run as a console app for debugging\n", SZAPPNAME );
106 printf( "\nStartServiceCtrlDispatcher being called.\n" );
107 printf( "This may take several seconds. Please wait.\n" );
108
109 if (!StartServiceCtrlDispatcher(dispatchTable))
110 AddToMessageLog(TEXT("StartServiceCtrlDispatcher failed."));
111}
void dispatch(HANDLE hStopEvent)
Definition: dispatch.c:70
VOID WINAPI service_main(DWORD dwArgc, LPTSTR *lpszArgv)
Definition: service.c:132
VOID CmdInstallService()
Definition: service.c:350
VOID AddToMessageLog(LPTSTR lpszMsg)
Definition: service.c:289
VOID CmdDebugService(int argc, char **argv)
Definition: service.c:497
VOID CmdRemoveService()
Definition: service.c:416
#define _stricmp
Definition: cat.c:22
#define printf
Definition: freeldr.h:97
#define exit(n)
Definition: config.h:202
#define SZAPPNAME
Definition: service.h:65
#define StartServiceCtrlDispatcher
Definition: winsvc.h:586
LPSERVICE_MAIN_FUNCTIONA LPSERVICE_MAIN_FUNCTION
Definition: winsvc.h:553

◆ ReportStatusToSCMgr()

BOOL ReportStatusToSCMgr ( DWORD  dwCurrentState,
DWORD  dwWin32ExitCode,
DWORD  dwWaitHint 
)

Definition at line 240 of file service.c.

243{
244 static DWORD dwCheckPoint = 1;
245 BOOL fResult = TRUE;
246
247
248 if ( !bDebug ) // when debugging we don't report to the SCM
249 {
250 if (dwCurrentState == SERVICE_START_PENDING)
252 else
254
255 ssStatus.dwCurrentState = dwCurrentState;
256 ssStatus.dwWin32ExitCode = dwWin32ExitCode;
257 ssStatus.dwWaitHint = dwWaitHint;
258
259 if ( ( dwCurrentState == SERVICE_RUNNING ) ||
260 ( dwCurrentState == SERVICE_STOPPED ) )
262 else
263 ssStatus.dwCheckPoint = dwCheckPoint++;
264
265
266 // Report the status of the service to the service control manager.
268 if (!fResult)
269 AddToMessageLog(TEXT("SetServiceStatus"));
270 }
271 return fResult;
272}
SERVICE_STATUS_HANDLE sshStatusHandle
Definition: service.c:35
unsigned int BOOL
Definition: ntddk_ex.h:94
BOOL WINAPI SetServiceStatus(SERVICE_STATUS_HANDLE hServiceStatus, LPSERVICE_STATUS lpServiceStatus)
Definition: sctrl.c:997
DWORD dwWin32ExitCode
Definition: winsvc.h:102
DWORD dwControlsAccepted
Definition: winsvc.h:101
DWORD dwWaitHint
Definition: winsvc.h:105
DWORD dwCheckPoint
Definition: winsvc.h:104
#define SERVICE_ACCEPT_STOP
Definition: winsvc.h:28
#define SERVICE_START_PENDING
Definition: winsvc.h:22
#define SERVICE_RUNNING
Definition: winsvc.h:24

Referenced by open_log_files(), service_ctrl(), service_main(), and ServiceStart().

◆ service_ctrl()

VOID WINAPI service_ctrl ( DWORD  dwCtrlCode)

Definition at line 187 of file service.c.

188{
189 // Handle the requested control code.
190 //
191
192 switch (dwCtrlCode)
193 {
194 // Stop the service.
195 //
196 // SERVICE_STOP_PENDING should be reported before
197 // setting the Stop Event - hServerStopEvent - in
198 // ServiceStop(). This avoids a race condition
199 // which may result in a 1053 - The Service did not respond...
200 // error.
203 ServiceStop();
204 return;
205
206 // Update the service status.
207 //
209 break;
210
211 // invalid control code
212 //
213 default:
214 break;
215
216 }
217
219}
BOOL ReportStatusToSCMgr(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint)
Definition: service.c:240
#define NO_ERROR
Definition: dderror.h:5
#define SERVICE_CONTROL_INTERROGATE
Definition: winsvc.h:39

Referenced by service_main().

◆ service_main()

void WINAPI service_main ( DWORD  dwArgc,
LPTSTR lpszArgv 
)

Definition at line 132 of file service.c.

133{
134
135 // register our service control handler:
136 //
138
139 if (!sshStatusHandle)
140 goto cleanup;
141
142 // SERVICE_STATUS members that don't change in example
143 //
146
147
148 // report the status to the service control manager.
149 //
151 SERVICE_START_PENDING, // service state
152 NO_ERROR, // exit code
153 3000)) // wait hint
154 goto cleanup;
155
156 ServiceStart( dwArgc, lpszArgv );
157
158 cleanup:
159
160 // try to report the stopped status to the service control manager.
161 //
162 if (sshStatusHandle)
165 dwErr,
166 0);
167
168 return;
169}
VOID WINAPI service_ctrl(DWORD dwCtrlCode)
Definition: service.c:187
static void cleanup(void)
Definition: main.c:1335
DWORD dwServiceType
Definition: winsvc.h:99
DWORD dwServiceSpecificExitCode
Definition: winsvc.h:103
#define RegisterServiceCtrlHandler
Definition: winsvc.h:583

Referenced by main(), run_service(), and START_TEST().

Variable Documentation

◆ bDebug

◆ dwErr

◆ sshStatusHandle

SERVICE_STATUS_HANDLE sshStatusHandle

Definition at line 35 of file service.c.

Referenced by ReportStatusToSCMgr(), and service_main().

◆ ssStatus

◆ szErr

TCHAR szErr[256]

Definition at line 38 of file service.c.

Referenced by CmdInstallService(), CmdRemoveService(), DoTestEntry(), and MUIGetString().