G:/ScriptBasic/source/variations/httpd/service.c

Go to the documentation of this file.
00001 #ifdef WIN32
00002 // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
00003 // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
00004 // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
00005 // PARTICULAR PURPOSE.
00006 //
00007 // Copyright (C) 1993-1997  Microsoft Corporation.  All Rights Reserved.
00008 //
00009 //  MODULE:   service.c
00010 //
00011 //  PURPOSE:  Implements functions required by all services
00012 //            windows.
00013 //
00014 //  FUNCTIONS:
00015 //    main(int argc, char **argv);
00016 //    service_ctrl(DWORD dwCtrlCode);
00017 //    service_main(DWORD dwArgc, LPTSTR *lpszArgv);
00018 //    CmdInstallService();
00019 //    CmdRemoveService();
00020 //    CmdDebugService(int argc, char **argv);
00021 //    ControlHandler ( DWORD dwCtrlType );
00022 //    GetLastErrorText( LPTSTR lpszBuf, DWORD dwSize );
00023 //
00024 //  COMMENTS:
00025 //
00026 //  AUTHOR: Craig Link - Microsoft Developer Support
00027 //
00028 
00029 
00030 #include <windows.h>
00031 #include <stdio.h>
00032 #include <stdlib.h>
00033 #include <process.h>
00034 #include <tchar.h>
00035 
00036 #include "service.h"
00037 
00038 
00039 
00040 // internal variables
00041 SERVICE_STATUS          ssStatus;       // current status of the service
00042 SERVICE_STATUS_HANDLE   sshStatusHandle;
00043 DWORD                   dwErr = 0;
00044 BOOL                    bDebug = FALSE;
00045 TCHAR                   szErr[256];
00046 
00047 // internal function prototypes
00048 VOID WINAPI service_ctrl(DWORD dwCtrlCode);
00049 VOID WINAPI service_main(DWORD dwArgc, LPTSTR *lpszArgv);
00050 VOID CmdInstallService();
00051 VOID CmdRemoveService();
00052 VOID CmdDebugService(int argc, char **argv);
00053 BOOL WINAPI ControlHandler ( DWORD dwCtrlType );
00054 LPTSTR GetLastErrorText( LPTSTR lpszBuf, DWORD dwSize );
00055 
00056 
00057 
00058 //
00059 //  FUNCTION: service_main
00060 //
00061 //  PURPOSE: To perform actual initialization of the service
00062 //
00063 //  PARAMETERS:
00064 //    dwArgc   - number of command line arguments
00065 //    lpszArgv - array of command line arguments
00066 //
00067 //  RETURN VALUE:
00068 //    none
00069 //
00070 //  COMMENTS:
00071 //    This routine performs the service initialization and then calls
00072 //    the user defined ServiceStart() routine to perform majority
00073 //    of the work.
00074 //
00075 void WINAPI service_main(DWORD dwArgc, LPTSTR *lpszArgv)
00076 {
00077 
00078     // register our service control handler:
00079     //
00080     sshStatusHandle = RegisterServiceCtrlHandler( TEXT(SZSERVICENAME), service_ctrl);
00081 
00082     if (!sshStatusHandle)
00083         goto cleanup;
00084 
00085     // SERVICE_STATUS members that don't change in example
00086     //
00087     ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
00088     ssStatus.dwServiceSpecificExitCode = 0;
00089 
00090 
00091     // report the status to the service control manager.
00092     //
00093     if (!ReportStatusToSCMgr(
00094         SERVICE_START_PENDING, // service state
00095         NO_ERROR,              // exit code
00096         3000))                 // wait hint
00097         goto cleanup;
00098 
00099 
00100     ServiceStart( dwArgc, lpszArgv );
00101 
00102 cleanup:
00103 
00104     // try to report the stopped status to the service control manager.
00105     //
00106     if (sshStatusHandle)
00107         (VOID)ReportStatusToSCMgr(
00108                             SERVICE_STOPPED,
00109                             dwErr,
00110                             0);
00111 
00112     return;
00113 }
00114 
00115 
00116 
00117 //
00118 //  FUNCTION: service_ctrl
00119 //
00120 //  PURPOSE: This function is called by the SCM whenever
00121 //           ControlService() is called on this service.
00122 //
00123 //  PARAMETERS:
00124 //    dwCtrlCode - type of control requested
00125 //
00126 //  RETURN VALUE:
00127 //    none
00128 //
00129 //  COMMENTS:
00130 //
00131 VOID WINAPI service_ctrl(DWORD dwCtrlCode)
00132 {
00133     // Handle the requested control code.
00134     //
00135     switch(dwCtrlCode)
00136     {
00137         // Stop the service.
00138         //
00139         // SERVICE_STOP_PENDING should be reported before
00140         // setting the Stop Event - hServerStopEvent - in
00141         // ServiceStop().  This avoids a race condition
00142         // which may result in a 1053 - The Service did not respond...
00143         // error.
00144         case SERVICE_CONTROL_STOP:
00145             ReportStatusToSCMgr(SERVICE_STOP_PENDING, NO_ERROR, 0);
00146             ServiceStop();
00147             return;
00148 
00149         // Update the service status.
00150         //
00151         case SERVICE_CONTROL_INTERROGATE:
00152             break;
00153 
00154         // invalid control code
00155         //
00156         default:
00157             break;
00158 
00159     }
00160 
00161     ReportStatusToSCMgr(ssStatus.dwCurrentState, NO_ERROR, 0);
00162 }
00163 
00164 
00165 
00166 //
00167 //  FUNCTION: ReportStatusToSCMgr()
00168 //
00169 //  PURPOSE: Sets the current status of the service and
00170 //           reports it to the Service Control Manager
00171 //
00172 //  PARAMETERS:
00173 //    dwCurrentState - the state of the service
00174 //    dwWin32ExitCode - error code to report
00175 //    dwWaitHint - worst case estimate to next checkpoint
00176 //
00177 //  RETURN VALUE:
00178 //    TRUE  - success
00179 //    FALSE - failure
00180 //
00181 //  COMMENTS:
00182 //
00183 BOOL ReportStatusToSCMgr(DWORD dwCurrentState,
00184                          DWORD dwWin32ExitCode,
00185                          DWORD dwWaitHint)
00186 {
00187     static DWORD dwCheckPoint = 1;
00188     BOOL fResult = TRUE;
00189 
00190 
00191     if ( !bDebug ) // when debugging we don't report to the SCM
00192     {
00193         if (dwCurrentState == SERVICE_START_PENDING)
00194             ssStatus.dwControlsAccepted = 0;
00195         else
00196             ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
00197 
00198         ssStatus.dwCurrentState = dwCurrentState;
00199         ssStatus.dwWin32ExitCode = dwWin32ExitCode;
00200         ssStatus.dwWaitHint = dwWaitHint;
00201 
00202         if ( ( dwCurrentState == SERVICE_RUNNING ) ||
00203              ( dwCurrentState == SERVICE_STOPPED ) )
00204             ssStatus.dwCheckPoint = 0;
00205         else
00206             ssStatus.dwCheckPoint = dwCheckPoint++;
00207 
00208 
00209         // Report the status of the service to the service control manager.
00210         //
00211         if (!(fResult = SetServiceStatus( sshStatusHandle, &ssStatus))) {
00212             AddToMessageLog(TEXT("SetServiceStatus"));
00213         }
00214     }
00215     return fResult;
00216 }
00217 
00218 
00219 
00220 //
00221 //  FUNCTION: AddToMessageLog(LPTSTR lpszMsg)
00222 //
00223 //  PURPOSE: Allows any thread to log an error message
00224 //
00225 //  PARAMETERS:
00226 //    lpszMsg - text for message
00227 //
00228 //  RETURN VALUE:
00229 //    none
00230 //
00231 //  COMMENTS:
00232 //
00233 VOID AddToMessageLog(LPTSTR lpszMsg)
00234 {
00235     TCHAR   szMsg[256];
00236     HANDLE  hEventSource;
00237     LPTSTR  lpszStrings[2];
00238 
00239 
00240     if ( !bDebug )
00241     {
00242         dwErr = GetLastError();
00243 
00244         // Use event logging to log the error.
00245         //
00246         hEventSource = RegisterEventSource(NULL, TEXT(SZSERVICENAME));
00247 
00248         _stprintf(szMsg, TEXT("%s error: %d"), TEXT(SZSERVICENAME), dwErr);
00249         lpszStrings[0] = szMsg;
00250         lpszStrings[1] = lpszMsg;
00251 
00252         if (hEventSource != NULL) {
00253             ReportEvent(hEventSource, // handle of event source
00254                 EVENTLOG_ERROR_TYPE,  // event type
00255                 0,                    // event category
00256                 0,                    // event ID
00257                 NULL,                 // current user's SID
00258                 2,                    // strings in lpszStrings
00259                 0,                    // no bytes of raw data
00260                 lpszStrings,          // array of error strings
00261                 NULL);                // no raw data
00262 
00263             (VOID) DeregisterEventSource(hEventSource);
00264         }
00265     }
00266 }
00267 
00268 
00269 
00270 
00272 //
00273 //  The following code handles service installation and removal
00274 //
00275 
00276 
00277 //
00278 //  FUNCTION: CmdInstallService()
00279 //
00280 //  PURPOSE: Installs the service
00281 //
00282 //  PARAMETERS:
00283 //    none
00284 //
00285 //  RETURN VALUE:
00286 //    none
00287 //
00288 //  COMMENTS:
00289 //
00290 void CmdInstallService(){
00291   SC_HANDLE   schService;
00292   SC_HANDLE   schSCManager;
00293 
00294   TCHAR szPath[512];
00295 
00296   if( GetModuleFileName( NULL, szPath, 512 ) == 0 ){
00297     _tprintf(TEXT("Unable to install %s - %s\n"), TEXT(SZSERVICEDISPLAYNAME), GetLastErrorText(szErr, 256));
00298     return;
00299     }
00300 
00301   schSCManager = OpenSCManager(
00302                       NULL,                   // machine (NULL == local)
00303                       NULL,                   // database (NULL == default)
00304                       SC_MANAGER_ALL_ACCESS   // access required
00305                       );
00306   if( ! schSCManager ){
00307     _tprintf(TEXT("CreateService failed - %s\n"), GetLastErrorText(szErr, 256));
00308     return;
00309     }
00310   schService = CreateService(
00311       schSCManager,               // SCManager database
00312       TEXT(SZSERVICENAME),        // name of service
00313       TEXT(SZSERVICEDISPLAYNAME), // name to display
00314       SERVICE_ALL_ACCESS,         // desired access
00315       SERVICE_WIN32_OWN_PROCESS,  // service type
00316       SERVICE_DEMAND_START,       // start type
00317       SERVICE_ERROR_NORMAL,       // error control type
00318       szPath,                     // service's binary
00319       NULL,                       // no load ordering group
00320       NULL,                       // no tag identifier
00321       TEXT(SZDEPENDENCIES),       // dependencies
00322       NULL,                       // LocalSystem account
00323       NULL);                      // no password
00324 
00325     if( schService ){
00326       _tprintf(TEXT("%s installed.\n"), TEXT(SZSERVICEDISPLAYNAME) );
00327       CloseServiceHandle(schService);
00328       }
00329     CloseServiceHandle(schSCManager);
00330 }
00331 
00332 
00333 
00334 //
00335 //  FUNCTION: CmdRemoveService()
00336 //
00337 //  PURPOSE: Stops and removes the service
00338 //
00339 //  PARAMETERS:
00340 //    none
00341 //
00342 //  RETURN VALUE:
00343 //    none
00344 //
00345 //  COMMENTS:
00346 //
00347 void CmdRemoveService()
00348 {
00349     SC_HANDLE   schService;
00350     SC_HANDLE   schSCManager;
00351 
00352     schSCManager = OpenSCManager(
00353                         NULL,                   // machine (NULL == local)
00354                         NULL,                   // database (NULL == default)
00355                         SC_MANAGER_ALL_ACCESS   // access required
00356                         );
00357     if ( schSCManager )
00358     {
00359         schService = OpenService(schSCManager, TEXT(SZSERVICENAME), SERVICE_ALL_ACCESS);
00360 
00361         if (schService)
00362         {
00363             // try to stop the service
00364             if ( ControlService( schService, SERVICE_CONTROL_STOP, &ssStatus ) )
00365             {
00366                 _tprintf(TEXT("Stopping %s."), TEXT(SZSERVICEDISPLAYNAME));
00367                 Sleep( 1000 );
00368 
00369                 while( QueryServiceStatus( schService, &ssStatus ) )
00370                 {
00371                     if ( ssStatus.dwCurrentState == SERVICE_STOP_PENDING )
00372                     {
00373                         _tprintf(TEXT("."));
00374                         Sleep( 1000 );
00375                     }
00376                     else
00377                         break;
00378                 }
00379 
00380                 if ( ssStatus.dwCurrentState == SERVICE_STOPPED )
00381                     _tprintf(TEXT("\n%s stopped.\n"), TEXT(SZSERVICEDISPLAYNAME) );
00382                 else
00383                     _tprintf(TEXT("\n%s failed to stop.\n"), TEXT(SZSERVICEDISPLAYNAME) );
00384 
00385             }
00386 
00387             // now remove the service
00388             if( DeleteService(schService) )
00389                 _tprintf(TEXT("%s removed.\n"), TEXT(SZSERVICEDISPLAYNAME) );
00390             else
00391                 _tprintf(TEXT("DeleteService failed - %s\n"), GetLastErrorText(szErr,256));
00392 
00393 
00394             CloseServiceHandle(schService);
00395         }
00396         else
00397             _tprintf(TEXT("OpenService failed - %s\n"), GetLastErrorText(szErr,256));
00398 
00399         CloseServiceHandle(schSCManager);
00400     }
00401     else
00402         _tprintf(TEXT("OpenSCManager failed - %s\n"), GetLastErrorText(szErr,256));
00403 }
00404 
00405 
00406 
00407 
00409 //
00410 //  The following code is for running the service as a console app
00411 //
00412 
00413 
00414 //
00415 //  FUNCTION: CmdDebugService(int argc, char ** argv)
00416 //
00417 //  PURPOSE: Runs the service as a console application
00418 //
00419 //  PARAMETERS:
00420 //    argc - number of command line arguments
00421 //    argv - array of command line arguments
00422 //
00423 //  RETURN VALUE:
00424 //    none
00425 //
00426 //  COMMENTS:
00427 //
00428 void CmdDebugService(int argc, char ** argv)
00429 {
00430     DWORD dwArgc;
00431     LPTSTR *lpszArgv;
00432 
00433 #ifdef UNICODE
00434     lpszArgv = CommandLineToArgvW(GetCommandLineW(), &(dwArgc) );
00435 #else
00436     dwArgc   = (DWORD) argc;
00437     lpszArgv = argv;
00438 #endif
00439 
00440     _tprintf(TEXT("Debugging %s.\n"), TEXT(SZSERVICEDISPLAYNAME));
00441 
00442     SetConsoleCtrlHandler( ControlHandler, TRUE );
00443 
00444     ServiceStart( dwArgc, lpszArgv );
00445 }
00446 
00447 
00448 //
00449 //  FUNCTION: ControlHandler ( DWORD dwCtrlType )
00450 //
00451 //  PURPOSE: Handled console control events
00452 //
00453 //  PARAMETERS:
00454 //    dwCtrlType - type of control event
00455 //
00456 //  RETURN VALUE:
00457 //    True - handled
00458 //    False - unhandled
00459 //
00460 //  COMMENTS:
00461 //
00462 BOOL WINAPI ControlHandler ( DWORD dwCtrlType )
00463 {
00464     switch( dwCtrlType )
00465     {
00466         case CTRL_BREAK_EVENT:  // use Ctrl+C or Ctrl+Break to simulate
00467         case CTRL_C_EVENT:      // SERVICE_CONTROL_STOP in debug mode
00468             _tprintf(TEXT("Stopping %s.\n"), TEXT(SZSERVICEDISPLAYNAME));
00469             ServiceStop();
00470             return TRUE;
00471             break;
00472 
00473     }
00474     return FALSE;
00475 }
00476 
00477 //
00478 //  FUNCTION: GetLastErrorText
00479 //
00480 //  PURPOSE: copies error message text to string
00481 //
00482 //  PARAMETERS:
00483 //    lpszBuf - destination buffer
00484 //    dwSize - size of buffer
00485 //
00486 //  RETURN VALUE:
00487 //    destination buffer
00488 //
00489 //  COMMENTS:
00490 //
00491 LPTSTR GetLastErrorText( LPTSTR lpszBuf, DWORD dwSize )
00492 {
00493     DWORD dwRet;
00494     LPTSTR lpszTemp = NULL;
00495 
00496     dwRet = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_ARGUMENT_ARRAY,
00497                            NULL,
00498                            GetLastError(),
00499                            LANG_NEUTRAL,
00500                            (LPTSTR)&lpszTemp,
00501                            0,
00502                            NULL );
00503 
00504     // supplied buffer is not long enough
00505     if ( !dwRet || ( (long)dwSize < (long)dwRet+14 ) )
00506         lpszBuf[0] = TEXT('\0');
00507     else
00508     {
00509         lpszTemp[lstrlen(lpszTemp)-2] = TEXT('\0');  //remove cr and newline character
00510         _stprintf( lpszBuf, TEXT("%s (0x%x)"), lpszTemp, GetLastError() );
00511     }
00512 
00513     if ( lpszTemp )
00514         LocalFree((HLOCAL) lpszTemp );
00515 
00516     return lpszBuf;
00517 }
00518 #else
00519 #include <stdio.h>
00520 static dummy(){
00521   printf("hello\n");
00522   }
00523 #endif

Generated on Sun Mar 12 23:56:32 2006 for ScriptBasic by  doxygen 1.4.6-NO