(file) Return to service.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Server

  1 karl  1.4 //%2003////////////////////////////////////////////////////////////////////////
  2 tony  1.1 //
  3 karl  1.4 // Copyright (c) 2000, 2001, 2002  BMC Software, Hewlett-Packard Development
  4           // Company, L. P., IBM Corp., The Open Group, Tivoli Systems.
  5           // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L. P.;
  6           // IBM Corp.; EMC Corporation, The Open Group.
  7 tony  1.1 //
  8           // Permission is hereby granted, free of charge, to any person obtaining a copy
  9           // of this software and associated documentation files (the "Software"), to
 10           // deal in the Software without restriction, including without limitation the
 11           // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 12           // sell copies of the Software, and to permit persons to whom the Software is
 13           // furnished to do so, subject to the following conditions:
 14           // 
 15           // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
 16           // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
 17           // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
 18           // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 19           // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 20           // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 21           // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 22           // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 23           //
 24           //==============================================================================
 25           //
 26           // Author: Tony Fiorentino (fiorentino_tony@emc.com)
 27           //
 28 tony  1.1 //%/////////////////////////////////////////////////////////////////////////////
 29           #include <time.h>
 30           #include <stdio.h>
 31           #include <windows.h>
 32           #include <process.h>
 33           
 34           #include "service.h"
 35           
 36           //-------------------------------------------------------------------------
 37           // G L O B A L S
 38           //-------------------------------------------------------------------------
 39           int                    Service::g_argc                  = 0;
 40           char                 **Service::g_argv                  = NULL;
 41           char                  *Service::g_service_name          = NULL;
 42           char                  *Service::g_event_source          = NULL;
 43           DWORD                  Service::g_flags                 = 0;
 44           DWORD                  Service::g_current_state         = 0;
 45           SERVICE_STATUS_HANDLE  Service::g_service_status_handle = 0;
 46           SERVICE_MAIN_T         Service::g_service_main          = NULL;
 47           
 48           //-------------------------------------------------------------------------
 49 tony  1.1 // P U B L I C
 50           //-------------------------------------------------------------------------
 51           Service::Service(void)
 52           {
 53           }
 54           
 55           Service::Service(char *service_name)
 56           {
 57             g_service_name = service_name;
 58           }
 59           
 60           Service::Service(char *service_name, char *event_source)
 61           {
 62             g_event_source = event_source;
 63             g_service_name = service_name;
 64           }
 65           
 66           Service::~Service(void)
 67           {
 68           }
 69           
 70 tony  1.1 /*-------------------------------------------------------------------------*
 71            * Method: Install                                                         *
 72            *                                                                         *
 73            * Args:                                                                   *
 74            *   display_name                                                          *
 75            *     The service's display name (hopefully more descriptive, will show   *
 76            *     up in the Win32 Services MMC snapin as "Service Name").             *
 77            *                                                                         *
 78            *   exe_name:                                                             *
 79            *     The service's executable name (full path, please)                   *
 80            *                                                                         *
 81            *   flags:                                                                *
 82            *     Reserved.  Currently unused.                                        *
 83            *                                                                         *
 84            * Description:                                                            *
 85            *     This function creates the service.                                  *
 86            *                                                                         *
 87            * NOTE: If the process is successfully launched as a Win32 service, this  *
 88            *       function never returns, but calls exit() instead.                 *
 89            *-------------------------------------------------------------------------*/
 90           Service::ReturnCode
 91 tony  1.1 Service::Install(
 92             char  *display_name,
 93             char  *description,
 94             char  *exe_name)
 95           {
 96             ReturnCode status = SERVICE_RETURN_SUCCESS;
 97             SC_HANDLE sch;
 98           
 99             if (g_service_name == NULL || display_name == NULL || exe_name == NULL)
100               return SERVICE_ERROR_NOT_FOUND; // SERVICE_ERROR_NOT_FOUND
101             else if ((sch = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE)) == NULL)
102               status = get_error(GetLastError(), "open");
103             else
104               {
105                 SC_HANDLE service = CreateService( 
106                   sch,                       // SCManager database 
107                   g_service_name,            // name of service 
108                   display_name,              // service name to display 
109                   SERVICE_ALL_ACCESS,        // desired access 
110                   SERVICE_WIN32_OWN_PROCESS, // service type 
111                   SERVICE_DEMAND_START,      // start type 
112 tony  1.1         SERVICE_ERROR_NORMAL,      // error control type 
113                   exe_name,                  // service's binary 
114                   NULL,                      // no load ordering group 
115                   NULL,                      // no tag identifier 
116                   NULL,                      // no dependencies 
117                   NULL,                      // LocalSystem account 
118                   NULL);                     // no password 
119            
120                 if (service == NULL) 
121                   {
122                     status = get_error(GetLastError(), "create");
123                     return status;
124                   }
125                 else 
126                   {
127                     change_service_description(service, description);
128                     CloseServiceHandle(service);
129                   }
130             
131                 CloseServiceHandle(sch);
132               }
133 tony  1.1 
134             return status;
135           }
136           
137           /*-------------------------------------------------------------------------*
138            * Method: Remove                                                          *
139            *                                                                         *
140            * Description:                                                            *
141            *     Removes the service.                                                *
142            *-------------------------------------------------------------------------*/
143           Service::ReturnCode
144           Service::Remove(void)
145           {
146             ReturnCode status = SERVICE_RETURN_SUCCESS;
147             SC_HANDLE sch;
148           
149             if (g_service_name == NULL)
150               return SERVICE_ERROR_NOT_FOUND; /* SERVICE_ERROR_NOT_FOUND */
151             else if ((sch = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE)) == NULL)
152               status = get_error(GetLastError(), "open");
153             else
154 tony  1.1     {
155                 SC_HANDLE service = OpenService(sch, g_service_name, DELETE);
156            
157                 if (service == NULL) 
158                   {
159                     status = get_error(GetLastError(), "open");
160                   }
161                 else 
162                   {
163                     if (!DeleteService(service))
164                       {
165                         status = get_error(GetLastError(), "remove");
166                       }
167           
168                     CloseServiceHandle(service);
169                   }
170             
171                 CloseServiceHandle(sch);
172               }
173           
174             return status;
175 tony  1.1 }
176           
177           /*-------------------------------------------------------------------------*
178            * Method: Start                                                           *
179            *                                                                         *
180            * Args:                                                                   *
181            *   wait_time:                                                            *
182            *     The user supplied wait (~1 second per QueryServiceStatus() attempt) *
183            *                                                                         *
184            * Description:                                                            *
185            *     Attempt to start the service.                                       *
186            *-------------------------------------------------------------------------*/
187           Service::ReturnCode
188           Service::Start(int wait_time)
189           {
190             ReturnCode      status = SERVICE_RETURN_SUCCESS;
191             SERVICE_STATUS  service_status;
192             SC_HANDLE       sch;
193           
194             if (g_service_name == NULL)
195               return SERVICE_ERROR_NOT_FOUND; // SERVICE_ERROR_NOT_FOUND
196 tony  1.1   else if ((sch = OpenSCManager(NULL, NULL, GENERIC_READ)) == NULL)
197               status = get_error(GetLastError(), "open");
198             else
199               {
200                 SC_HANDLE service = OpenService(sch, g_service_name, SERVICE_START | SERVICE_QUERY_STATUS);
201            
202                 if (service == NULL) 
203                   status = get_error(GetLastError(), "open");
204                 else if (!StartService(service, 0, NULL))
205                   status = get_error(GetLastError(), "start");
206                 else 
207                   {
208                     int i, max = (wait_time > 0) ? wait_time : 5;
209           
210                     // Loop up to max times waiting for the service 
211                     // state to change to RUNNING
212           
213                     for (i = 0; i < max; i++)
214                       {
215                         if (!QueryServiceStatus(service, &service_status))
216                           {
217 tony  1.1                   status = get_error(GetLastError(), "query");
218                             return status; // QUERY_FAIL
219                           }
220           
221                         if (service_status.dwCurrentState == SERVICE_RUNNING)
222                           break;
223           
224                         Sleep(1 * CLOCKS_PER_SEC);
225                       }
226                     
227                     status = (i < max) ? SERVICE_RETURN_SUCCESS : SERVICE_ERROR_REQUEST_TIMEOUT;
228           
229                     CloseServiceHandle(service);
230                   }
231            
232                 CloseServiceHandle(sch); 
233               }
234           
235             return status;
236           } 
237           
238 tony  1.1 /*-------------------------------------------------------------------------*
239            * Method: Stop                                                            *
240            *                                                                         *
241            * Args:                                                                   *
242            *   wait_time:                                                            *
243            *     The user supplied wait (~1 second per QueryServiceStatus() attempt) *
244            *                                                                         *
245            * Description:                                                            *
246            *     Attempt to stop the service.                                        *
247            *-------------------------------------------------------------------------*/
248           Service::ReturnCode 
249           Service::Stop(int wait_time)
250           {
251             ReturnCode      status = SERVICE_RETURN_SUCCESS;
252             SERVICE_STATUS  service_status;
253             SC_HANDLE       sch;
254           
255             if (g_service_name == NULL)
256               return SERVICE_ERROR_NOT_FOUND; // SERVICE_ERROR_NOT_FOUND
257             else if ((sch = OpenSCManager(NULL, NULL, GENERIC_READ)) == NULL)
258               status = get_error(GetLastError(), "open");
259 tony  1.1  //   show_error("OpenSCMManager", "service", GetLastError());
260             else
261               {
262                 SC_HANDLE service = OpenService(sch, g_service_name, SERVICE_STOP | SERVICE_QUERY_STATUS);
263            
264                 if (service == NULL) 
265                   status = get_error(GetLastError(), "open");
266                 else if (!ControlService(service, SERVICE_CONTROL_STOP, &service_status))
267                   status = get_error(GetLastError(), "stop");
268                 else 
269                   {
270                     int i, max = (wait_time > 0) ? wait_time : 5;
271           
272                     // Loop up to max times waiting for the service 
273                     // state to change to STOPPED
274           
275                     for (i = 0; i < max; i++)
276                       {
277                         if (!QueryServiceStatus(service, &service_status))
278                           {
279                             status = get_error(GetLastError(), "query");
280 tony  1.1                   return status; // QUERY_FAIL
281                           }
282           
283                         if (service_status.dwCurrentState == SERVICE_STOPPED)
284                           break;
285           
286                         Sleep(1 * CLOCKS_PER_SEC);
287                       }
288                     
289                     status = (i < max) ? SERVICE_RETURN_SUCCESS : SERVICE_ERROR_REQUEST_TIMEOUT;
290           
291                     CloseServiceHandle(service);
292                   }
293            
294                 CloseServiceHandle(sch); 
295               }
296           
297             return status;
298           }
299           
300           /*-------------------------------------------------------------------------*
301 tony  1.1  * Method: Run                                                             *
302            *                                                                         *
303            * Args:                                                                   *
304            *   service_main:                                                         *
305            *     The user supplied service_main function (not to be confused with    *
306            *     real_service_main above)                                            *
307            *                                                                         *
308            *   flags:                                                                *
309            *     Reserved.  Currently unused.                                        *
310            *                                                                         *
311            * Description:                                                            *
312            *     This function interacts with the SCM to run the current process     *
313            *     as a Win32 service.                                                 *
314            *                                                                         *
315            * NOTE: If the process is successfully launched as a Win32 service, this  *
316            *       function never returns, but calls exit() instead.                 *
317            *-------------------------------------------------------------------------*/
318           
319           Service::ReturnCode 
320           Service::Run(SERVICE_MAIN_T service_main, DWORD flags)
321           {
322 tony  1.1   ReturnCode status = SERVICE_RETURN_SUCCESS;
323           
324             SERVICE_TABLE_ENTRY dispatchTable[] = 
325             { 
326               { g_service_name, real_service_main },
327               { NULL,         NULL              } 
328             };
329           
330             // Validate the arguments as best we can 
331           
332             if (g_service_name == NULL || service_main == NULL)
333               return SERVICE_ERROR_NOT_FOUND; // SERVICE_ERROR_NOT_FOUND
334           
335             // Save parameters in global variables 
336           
337             g_flags        = flags;
338             g_service_main = service_main;
339           
340             // Kick off the service 
341           
342             if (!StartServiceCtrlDispatcher(dispatchTable))
343 tony  1.1     {
344                 status = get_error(GetLastError(), "start");
345                 return status; // FAIL
346               }
347           
348 s.hills 1.2   // Don't call exit()
349               return status;
350 tony    1.1 }
351             
352             /*-------------------------------------------------------------------------*
353              * Method: GetState                                                        *
354              *                                                                         *
355              * Description:                                                            *
356              *     Returns the state of the service into "state".                      *
357              *-------------------------------------------------------------------------*/
358             Service::ReturnCode 
359             Service::GetState(State *state)
360             {
361               ReturnCode      status = SERVICE_RETURN_SUCCESS;
362               SERVICE_STATUS  service_status;
363               SC_HANDLE       sch;
364             
365               if (g_service_name == NULL)
366                 return SERVICE_ERROR_NOT_FOUND; // SERVICE_ERROR_NOT_FOUND
367               else if ((sch = OpenSCManager(NULL, NULL, GENERIC_READ)) == NULL)
368                 status = get_error(GetLastError(), "open");
369               else
370                 {
371 tony    1.1       SC_HANDLE service = OpenService(sch, g_service_name, SERVICE_QUERY_STATUS);
372              
373                   if (service == NULL) 
374                     status = get_error(GetLastError(), "open");
375                   else if (!QueryServiceStatus(service, &service_status))
376                     status = get_error(GetLastError(), "query");
377                   else
378                     {
379                       *state = get_state(service_status.dwCurrentState);
380                       CloseServiceHandle(service);
381                     }
382               
383                   CloseServiceHandle(sch);
384                 }
385             
386               return status;
387             }
388             
389             /*-------------------------------------------------------------------------*
390              * Method: LogEvent                                                        *
391              *                                                                         *
392 tony    1.1  * Args:                                                                   *
393              *   event_type:                                                           *
394              *     The Win32 event type. Valid event types are:                        *
395              *      EVENTLOG_SUCCESS          : Success event                          *
396              *      EVENTLOG_ERROR_TYPE       : Error event                            *
397              *      EVENTLOG_WARNING_TYPE     : Warning event                          *
398              *      EVENTLOG_INFORMATION_TYPE : Information event                      *
399              *      EVENTLOG_AUDIT_SUCCESS    : Success audit event                    *
400              *      EVENTLOG_AUDIT_FAILURE    : Failure audit event                    *
401              *                                                                         *
402              *   event_id:                                                             *
403              *     A fancy name for error code or error number.                        *
404              *                                                                         *
405              *   string:                                                               *
406              *     String to be logged or merged in with the error string in the       *
407              *     message DLL.                                                        *
408              *                                                                         *
409              * Description:                                                            *
410              *     This function provides a simple layer over the Win32 error logging  *
411              *     API's.                                                              *
412              *                                                                         *
413 tony    1.1  * Returns:                                                                *
414              *     true  if event was successfully logged                              *
415              *     false if the event could not be logged                              *
416              *-------------------------------------------------------------------------*/
417             bool
418             Service::LogEvent(WORD event_type, DWORD event_id, const char *string)
419             {
420               BOOL   status;
421               HANDLE h_event_source = RegisterEventSource(NULL, g_event_source);
422             
423               if (h_event_source == NULL)
424                 FALSE;
425             
426               status = ReportEvent (h_event_source, 
427                                     event_type, 
428                                     0, 
429                                     event_id, 
430                                     NULL, 
431                                     1, 
432                                     0, 
433                                     &string, 
434 tony    1.1                         NULL);
435             
436               DeregisterEventSource(h_event_source);
437             
438               return (status == TRUE) ? true : false;
439             }
440             
441             //-------------------------------------------------------------------------
442             // P R I V A T E
443             //-------------------------------------------------------------------------
444             /*-------------------------------------------------------------------------*
445              * Routine: real_service_main                                              *
446              *                                                                         *
447              * Args:                                                                   *
448              *   argc:                                                                 *
449              *     The number of arguments in the argv array                           *
450              *   argv:                                                                 *
451              *     An array of strings representing the command line arguments         *
452              *                                                                         *
453              * Description:                                                            *
454              *     This function is the real service main (as opposed to the user      *
455 tony    1.1  *     supplied service main, which is called service_main).               *
456              *                                                                         *
457              * Returns:                                                                *
458              *     nothing                                                             *
459              *-------------------------------------------------------------------------*/
460             void __stdcall
461             Service::real_service_main(DWORD argc, LPTSTR *argv)
462             {
463               // Let the SCM know we're alive and kicking
464             
465               report_status(SERVICE_START_PENDING, NO_ERROR, 0, 5000);
466             
467               // If the command line arguments include the string "-debug" then
468               // invoke the debugger
469             
470               if (check_args_for_string("-debug"))
471                 DebugBreak();
472             
473               // Save copy of argc and argc in global variables
474             
475               g_argc = argc;
476 tony    1.1   g_argv = argv;
477             
478               // Start service actions
479             
480               g_service_status_handle = RegisterServiceCtrlHandler (g_service_name, 
481                                                                     service_control_handler);
482             
483               if (g_service_status_handle == 0)
484                 {
485                   show_error("register", "Service Control Handler", GetLastError());
486                   report_status(SERVICE_STOPPED, NO_ERROR, 0, 5000);
487                   return;
488                 }
489             
490               // Change our state to RUNNING, then invoke the user supplied
491               // service_main function. After the user's service_main exits,
492               // change the service state to STOPPED.
493             
494               report_status(SERVICE_RUNNING, NO_ERROR, 0, 5000);
495               g_service_main(STARTUP_FLAG, argc, argv);
496               report_status(SERVICE_STOPPED, NO_ERROR, 0, 5000);
497 tony    1.1 
498               return;
499             }
500             
501             /*-------------------------------------------------------------------------*
502              * Routine: check_args_for_string                                          *
503              *                                                                         *
504              * Args:                                                                   *
505              *   string:                                                               *
506              *     The string to match.                                                *
507              *                                                                         *
508              * Description:                                                            *
509              *     This function iterates through the command line arguments searching *
510              *     for the string specified by the string parameter.                   *
511              *                                                                         *
512              * Returns:                                                                *
513              *     true  if the string was found                                       *
514              *     false if the string was not found                                   *
515              *-------------------------------------------------------------------------*/
516             bool
517             Service::check_args_for_string(char *string)
518 tony    1.1 {
519               int i;
520             
521               for (i = 1; i < g_argc; i++)
522                 {
523                   if (strcmp(g_argv[i], string) == 0)
524                     return true;
525                 }
526             
527               return false;
528             }
529             
530             /*-------------------------------------------------------------------------*
531              * Method: service_control_handler                                         *
532              *                                                                         *
533              * Args:                                                                   *
534              *   control:                                                              *
535              *     The control sent from the SCM telling us what action to take:       *
536              *     start, stop, pause, continue, etc.                                  *
537              *                                                                         *
538              * Description:                                                            *
539 tony    1.1  *     This function handles control messages sent from the SCM. Currently *
540              *     the only message that is handled differently is the STOP message,   *
541              *     which invokes the user's service main function passing to it the    *
542              *     SHUTDOWN_FLAG. The user is then responsible to perform all shutdown *
543              *     related tasks.                                                      *
544              *                                                                         *
545              * Returns:                                                                *
546              *     Nothing                                                             *
547              *-------------------------------------------------------------------------*/
548             
549             void WINAPI
550             Service::service_control_handler(DWORD control)
551             {
552               /* Currently, only the stop contol requires special handling */
553             
554               if (control == SERVICE_CONTROL_STOP)
555                 {
556                   report_status(SERVICE_STOP_PENDING, NO_ERROR, 0, 5000);
557                   g_service_main(SHUTDOWN_FLAG, g_argc, g_argv);
558                   return;
559                 }
560 tony    1.1 
561               /* For every other control, just send back our current state */
562             
563               report_status(g_current_state, NO_ERROR, 0, 5000);
564             }
565             
566             /*-------------------------------------------------------------------------*
567              * Method: report_status                                                   *
568              *                                                                         *
569              * Args:                                                                   *
570              *   current_state:                                                        *
571              *     The service's new state. May be any valid Win32 service state.      *
572              *                                                                         *
573              *   exit_code:                                                            *
574              *     This must be a Win32 exit code. If the server is exiting due to     *
575              *     an error returned from the Win32 API, then this is the place to     *
576              *     report the error status. Most of the time, this will be NO_ERROR.   *
577              *                                                                         *
578              *   check_point:                                                          *
579              *     An integer value that should start at zero and increment as each    *
580              *     discrete step within a phase is completed. For example, if startup  *
581 tony    1.1  *     consists of 3 steps, then the startup will issue its first check-   *
582              *     point of zero, then increment up through and including 2 as each    *
583              *     step is finished.                                                   *
584              *                                                                         *
585              *   wait_hint:                                                            *
586              *     Tells the SCM how long to expect to wait for the next status        *
587              *     update.                                                             *
588              *                                                                         *
589              * Description:                                                            *
590              *     This function provides an even higher level of abstraction over     *
591              *     the Win32 event logging API's.                                      *
592              *                                                                         *
593              * Returns:                                                                *
594              *     true  if the status was successfully reported                       *
595              *     false if the status could not be reported                           *
596              *-------------------------------------------------------------------------*/
597             bool
598             Service::report_status(
599               DWORD current_state, 
600               DWORD exit_code, 
601               DWORD check_point, 
602 tony    1.1   DWORD wait_hint)
603             {
604               SERVICE_STATUS current_status = 
605               {
606                 SERVICE_WIN32,
607                 current_state,
608                 SERVICE_CONTROL_INTERROGATE,
609                 exit_code,
610                 0,
611                 check_point,
612                 wait_hint
613               };
614             
615               /* Wait until we're started before we accept a stop control */
616             
617               if (current_state == SERVICE_RUNNING)
618                 current_status.dwControlsAccepted += SERVICE_ACCEPT_STOP;
619             
620               /* Save new state */
621             
622               g_current_state = current_state;
623 tony    1.1   
624               return (SetServiceStatus(g_service_status_handle, &current_status) == TRUE) ? true : false;
625             }
626             
627             /*-------------------------------------------------------------------------*
628              * Method: change_service_description                                      *
629              *                                                                         *
630              * Args:                                                                   *
631              *   service:                                                              *
632              *     Handle to the service                                               *
633              *                                                                         *
634              *   description:                                                          *
635              *     The service's description                                           *
636              *                                                                         *
637              * Description:                                                            *
638              *     This function sets the description for the service. The description *
639              *     text shows up in the Services mmc snapin. The description is added  *
640              *     as a benefit to users, but does not affect the service's operation. *
641              *     Therefore, if this function should fail for any reason, there is    *
642              *     no need to stop. That's why this function has no return value.      *
643              *                                                                         *
644 tony    1.1  * Returns:                                                                *
645              *     Nothing                                                             *
646              *                                                                         *
647              * Notes:                                                                  *
648              *     This function uses the ChangeServiceConfig2() API function which    *
649              *     first appeared in Windows2000. Therefore, this code checks the      *
650              *     OS version, before calling ChangeServiceConfig2().                  *
651              *-------------------------------------------------------------------------*/
652             void 
653             Service::change_service_description(SC_HANDLE service, char *description)
654             {
655               OSVERSIONINFO osvi;
656             
657               /* 
658                *  Test for Windows 2000 or greater
659                */ 
660               
661               osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
662             
663               if (GetVersionEx(&osvi) != 0                      && 
664                   osvi.dwPlatformId    == VER_PLATFORM_WIN32_NT && 
665 tony    1.1       osvi.dwMajorVersion  >= 5)
666                 {
667                   typedef BOOL (WINAPI *CHANGE_SERVICE_CONFIG2_T)(SC_HANDLE, DWORD, LPVOID);
668             
669                   HINSTANCE hdll = LoadLibrary("advapi32.dll");
670             
671                   if (hdll != NULL)
672                     {
673                       SERVICE_DESCRIPTION      sd;
674                       CHANGE_SERVICE_CONFIG2_T csc;
675             
676                       csc = (CHANGE_SERVICE_CONFIG2_T) GetProcAddress(hdll, "ChangeServiceConfig2A");
677             
678                       if (csc)
679                         {
680                           sd.lpDescription = description;
681                           csc(service, SERVICE_CONFIG_DESCRIPTION, &sd);
682                         }
683             
684                       FreeLibrary(hdll);
685                     }
686 tony    1.1     }
687             }
688             
689             /*-------------------------------------------------------------------------*
690              * Method: show_error                                                      *
691              *                                                                         *
692              * Args:                                                                   *
693              *   action:                                                               *
694              *     A single verb decribing the action going on when the error          *
695              *     occurred. For example, "opening", "creating", etc.                  *
696              *                                                                         *
697              *   object:                                                               *
698              *     Description of the object on which was action occurred. Examples    *
699              *     are "file", "service", etc.                                         *
700              *                                                                         *
701              *   hr:                                                                   *
702              *     The error status. Can be an hresult, or Win32 error status.         *
703              *                                                                         *
704              * Description:                                                            *
705              *     This function provides an even higher level of abstraction over     *
706              *     the Win32 event logging API's.                                      *
707 tony    1.1  *                                                                         *
708              * Returns:                                                                *
709              *     true  if event was successfully logged                              *
710              *     false if the event could not be logged                              *
711              *-------------------------------------------------------------------------*/
712             bool
713             Service::show_error(const char *action, const char *object, DWORD hr)
714             {
715               char console_title[_MAX_PATH] = {0};
716               char  txt[_MAX_PATH]          = "";
717               char  msg[_MAX_PATH]          = "";
718               DWORD nchars;
719             
720               nchars = FormatMessage(
721                 FORMAT_MESSAGE_FROM_SYSTEM,
722                 NULL,
723                 hr,
724                 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
725                 msg,
726                 sizeof(msg),
727                 NULL);
728 tony    1.1 
729               if (nchars == 0) 
730                 sprintf(msg, "Unknown error code - %%X%x", hr);
731               else if (nchars > 1)
732                 {
733                   if (msg[nchars - 1] == '\n') msg[nchars - 1] = '\0';
734                   if (msg[nchars - 2] == '\r') msg[nchars - 2] = '\0';
735                 }
736             
737               sprintf(txt, "Failed to %s %s %s. Reason: %s", action, object, g_service_name, msg);
738             
739               // Running from a console window
740               // send courtesy message txt to stderr
741               if (GetConsoleTitle(console_title, _MAX_PATH) > 0)
742                 {
743 s.hills 1.3       PEGASUS_STD(cerr) << txt << PEGASUS_STD(endl);
744 tony    1.1     }
745             
746               return LogEvent(EVENTLOG_ERROR_TYPE, 1, txt);
747             }
748             
749             Service::State
750             Service::get_state(DWORD scm_state)
751             {
752               return (State)scm_state;
753             }
754             
755             Service::ReturnCode 
756             Service::get_error(DWORD error_status, const char *action)
757             {
758               switch (error_status)
759                 {
760                 /*
761                   // INFO: Could add cases to suppress error message.
762                   case ERROR_SERVICE_DOES_NOT_EXIST:
763                   case ERROR_SERVICE_CANNOT_ACCEPT_CTRL:
764                     break;
765 tony    1.1     */
766                   case SERVICE_RETURN_SUCCESS:
767                     break;
768             
769                   default:
770                     show_error(action, "service", error_status); 
771                     break;
772                 }
773               return (ReturnCode)error_status;
774             }
775             

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2