home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 January / Chip_2001-01_cd1.bin / tema / mysql / mysql-3.23.28g-win-source.exe / mysqlwatch / mysqlwatch.c next >
C/C++ Source or Header  |  1999-12-24  |  20KB  |  746 lines

  1. /****************************************************************************
  2.    MySqlWatch    - WinNT service program MySQL
  3.                  - Re-start MySql server in case of failure
  4. *****************************************************************************/
  5. #include <windows.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <process.h>
  9. #include <tchar.h>
  10.  
  11.  
  12. // name of the executable
  13. #define SZAPPNAME            "mysqlwatch"
  14. // internal name of the service
  15. #define SZSERVICENAME        "MySqlWatch"
  16. // displayed name of the service
  17. #define SZSERVICEDISPLAYNAME "MySqlWatch"
  18. // list of service dependencies - "dep1\0dep2\0\0"
  19. #define SZDEPENDENCIES       ""
  20.  
  21.  
  22.  
  23. VOID ServiceStart(DWORD dwArgc, LPTSTR *lpszArgv);
  24. VOID ServiceStop(void);
  25. BOOL ReportStatusToSCMgr(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint);
  26. void AddToMessageLog(LPTSTR lpszMsg);
  27.  
  28. // internal variables
  29. SERVICE_STATUS          ssStatus;       // current status of the service
  30. SERVICE_STATUS_HANDLE   sshStatusHandle;
  31. DWORD                   dwErr = 0;
  32. BOOL                    bDebug = FALSE;
  33. TCHAR                   szErr[256];
  34.  
  35. // internal function prototypes
  36. void WINAPI service_ctrl(DWORD dwCtrlCode);
  37. void WINAPI service_main(DWORD dwArgc, LPTSTR *lpszArgv);
  38. void CmdInstallService(void);
  39. void CmdRemoveService(void);
  40. void CmdDebugService(int argc, char **argv);
  41. BOOL WINAPI ControlHandler ( DWORD dwCtrlType );
  42. LPTSTR GetLastErrorText( LPTSTR lpszBuf, DWORD dwSize );
  43.  
  44. //
  45. //  FUNCTION: main
  46. //
  47. //  PURPOSE: entrypoint for service
  48. //
  49. //  PARAMETERS:
  50. //    argc - number of command line arguments
  51. //    argv - array of command line arguments
  52. //
  53. //  RETURN VALUE:
  54. //    none
  55. //
  56. //  COMMENTS:
  57. //    main() either performs the command line task, or
  58. //    call StartServiceCtrlDispatcher to register the
  59. //    main service thread.  When the this call returns,
  60. //    the service has stopped, so exit.
  61. //
  62. void main(int argc, char **argv)
  63. {
  64.     SERVICE_TABLE_ENTRY dispatchTable[] =
  65.     {
  66.         { TEXT(SZSERVICENAME), (LPSERVICE_MAIN_FUNCTION)service_main },
  67.         { NULL, NULL }
  68.     };
  69.  
  70.     if ( (argc > 1) &&
  71.          ((*argv[1] == '-') || (*argv[1] == '/')) )
  72.     {
  73.         if ( stricmp( "install", argv[1]+1 ) == 0 )
  74.         {
  75.             CmdInstallService();
  76.         }
  77.         else if ( stricmp( "remove", argv[1]+1 ) == 0 )
  78.         {
  79.             CmdRemoveService();
  80.         }
  81.         else if ( stricmp( "debug", argv[1]+1 ) == 0 )
  82.         {
  83.             bDebug = TRUE;
  84.             CmdDebugService(argc, argv);
  85.         }
  86.         else
  87.         {
  88.             goto dispatch;
  89.         }
  90.         exit(0);
  91.     }
  92.  
  93.     // if it doesn't match any of the above parameters
  94.     // the service control manager may be starting the service
  95.     // so we must call StartServiceCtrlDispatcher
  96.     dispatch:
  97.         // this is just to be friendly
  98.         printf( "%s -install          to install the service\n", SZAPPNAME );
  99.         printf( "%s -remove           to remove the service\n", SZAPPNAME );
  100.         printf( "%s -debug <params>   to run as a console app for debugging\n", SZAPPNAME );
  101.         printf( "\nStartServiceCtrlDispatcher being called.\n" );
  102.         printf( "This may take several seconds.  Please wait.\n" );
  103.  
  104.         if (!StartServiceCtrlDispatcher(dispatchTable))
  105.             AddToMessageLog(TEXT("StartServiceCtrlDispatcher failed."));
  106. }
  107.  
  108.  
  109.  
  110. //
  111. //  FUNCTION: service_main
  112. //
  113. //  PURPOSE: To perform actual initialization of the service
  114. //
  115. //  PARAMETERS:
  116. //    dwArgc   - number of command line arguments
  117. //    lpszArgv - array of command line arguments
  118. //
  119. //  RETURN VALUE:
  120. //    none
  121. //
  122. //  COMMENTS:
  123. //    This routine performs the service initialization and then calls
  124. //    the user defined ServiceStart() routine to perform majority
  125. //    of the work.
  126. //
  127. void WINAPI service_main(DWORD dwArgc, LPTSTR *lpszArgv)
  128. {
  129.  
  130.     // register our service control handler:
  131.     //
  132.     sshStatusHandle = RegisterServiceCtrlHandler( TEXT(SZSERVICENAME), service_ctrl);
  133.  
  134.     if (!sshStatusHandle)
  135.         goto cleanup;
  136.  
  137.     // SERVICE_STATUS members that don't change in example
  138.     //
  139.     ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
  140.     ssStatus.dwServiceSpecificExitCode = 0;
  141.  
  142.  
  143.     // report the status to the service control manager.
  144.     //
  145.     if (!ReportStatusToSCMgr(
  146.         SERVICE_START_PENDING, // service state
  147.         NO_ERROR,              // exit code
  148.         3000))                 // wait hint
  149.         goto cleanup;
  150.  
  151.  
  152.     ServiceStart( dwArgc, lpszArgv );
  153.  
  154. cleanup:
  155.  
  156.     // try to report the stopped status to the service control manager.
  157.     //
  158.     if (sshStatusHandle)
  159.         ReportStatusToSCMgr(
  160.                             SERVICE_STOPPED,
  161.                             dwErr,
  162.                             0);
  163.  
  164.     return;
  165. }
  166.  
  167.  
  168.  
  169. //
  170. //  FUNCTION: service_ctrl
  171. //
  172. //  PURPOSE: This function is called by the SCM whenever
  173. //           ControlService() is called on this service.
  174. //
  175. //  PARAMETERS:
  176. //    dwCtrlCode - type of control requested
  177. //
  178. //  RETURN VALUE:
  179. //    none
  180. //
  181. //  COMMENTS:
  182. //
  183. void WINAPI service_ctrl(DWORD dwCtrlCode)
  184. {
  185.     // Handle the requested control code.
  186.     //
  187.     switch(dwCtrlCode)
  188.     {
  189.         // Stop the service.
  190.         //
  191.         case SERVICE_CONTROL_STOP:
  192.             ssStatus.dwCurrentState = SERVICE_STOP_PENDING;
  193.             ServiceStop();
  194.             break;
  195.  
  196.         // Update the service status.
  197.         //
  198.         case SERVICE_CONTROL_INTERROGATE:
  199.             break;
  200.  
  201.         // invalid control code
  202.         //
  203.         default:
  204.             break;
  205.  
  206.     }
  207.  
  208.     ReportStatusToSCMgr(ssStatus.dwCurrentState, NO_ERROR, 0);
  209.  
  210. }
  211.  
  212.  
  213.  
  214. //
  215. //  FUNCTION: ReportStatusToSCMgr()
  216. //
  217. //  PURPOSE: Sets the current status of the service and
  218. //           reports it to the Service Control Manager
  219. //
  220. //  PARAMETERS:
  221. //    dwCurrentState - the state of the service
  222. //    dwWin32ExitCode - error code to report
  223. //    dwWaitHint - worst case estimate to next checkpoint
  224. //
  225. //  RETURN VALUE:
  226. //    TRUE  - success
  227. //    FALSE - failure
  228. //
  229. //  COMMENTS:
  230. //
  231. BOOL ReportStatusToSCMgr(DWORD dwCurrentState,
  232.                          DWORD dwWin32ExitCode,
  233.                          DWORD dwWaitHint)
  234. {
  235.     static DWORD dwCheckPoint = 1;
  236.     BOOL fResult = TRUE;
  237.  
  238.  
  239.     if ( !bDebug ) // when debugging we don't report to the SCM
  240.     {
  241.         if (dwCurrentState == SERVICE_START_PENDING)
  242.             ssStatus.dwControlsAccepted = 0;
  243.         else
  244.             ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
  245.  
  246.         ssStatus.dwCurrentState = dwCurrentState;
  247.         ssStatus.dwWin32ExitCode = dwWin32ExitCode;
  248.         ssStatus.dwWaitHint = dwWaitHint;
  249.  
  250.         if ( ( dwCurrentState == SERVICE_RUNNING ) ||
  251.              ( dwCurrentState == SERVICE_STOPPED ) )
  252.             ssStatus.dwCheckPoint = 0;
  253.         else
  254.             ssStatus.dwCheckPoint = dwCheckPoint++;
  255.  
  256.  
  257.         // Report the status of the service to the service control manager.
  258.         //
  259.         if (!(fResult = SetServiceStatus( sshStatusHandle, &ssStatus))) {
  260.             AddToMessageLog(TEXT("SetServiceStatus"));
  261.         }
  262.     }
  263.     return fResult;
  264. }
  265.  
  266.  
  267.  
  268. //
  269. //  FUNCTION: AddToMessageLog(LPTSTR lpszMsg)
  270. //
  271. //  PURPOSE: Allows any thread to log an error message
  272. //
  273. //  PARAMETERS:
  274. //    lpszMsg - text for message
  275. //
  276. //  RETURN VALUE:
  277. //    none
  278. //
  279. //  COMMENTS:
  280. //
  281. void AddToMessageLog(LPTSTR lpszMsg)
  282. {
  283.     TCHAR   szMsg[256];
  284.     HANDLE  hEventSource;
  285.     LPTSTR  lpszStrings[2];
  286.  
  287.  
  288.     if ( !bDebug )
  289.     {
  290.         dwErr = GetLastError();
  291.  
  292.         // Use event logging to log the error.
  293.         //
  294.         hEventSource = RegisterEventSource(NULL, TEXT(SZSERVICENAME));
  295.  
  296.         _stprintf(szMsg, TEXT("%s error: %d"), TEXT(SZSERVICENAME), dwErr);
  297.         lpszStrings[0] = szMsg;
  298.         lpszStrings[1] = lpszMsg;
  299.  
  300.         if (hEventSource != NULL) {
  301.             ReportEvent(hEventSource, // handle of event source
  302.                 EVENTLOG_ERROR_TYPE,  // event type
  303.                 0,                    // event category
  304.                 0,                    // event ID
  305.                 NULL,                 // current user's SID
  306.                 2,                    // strings in lpszStrings
  307.                 0,                    // no bytes of raw data
  308.                 lpszStrings,          // array of error strings
  309.                 NULL);                // no raw data
  310.  
  311.              DeregisterEventSource(hEventSource);
  312.         }
  313.     }
  314. }
  315.  
  316.  
  317.  
  318.  
  319. ///////////////////////////////////////////////////////////////////
  320. //
  321. //  The following code handles service installation and removal
  322. //
  323.  
  324.  
  325. //
  326. //  FUNCTION: CmdInstallService()
  327. //
  328. //  PURPOSE: Installs the service
  329. //
  330. //  PARAMETERS:
  331. //    none
  332. //
  333. //  RETURN VALUE:
  334. //    none
  335. //
  336. //  COMMENTS:
  337. //
  338. void CmdInstallService()
  339. {
  340.     SC_HANDLE   schService;
  341.     SC_HANDLE   schSCManager;
  342.  
  343.     TCHAR szPath[512];
  344.  
  345.     if ( GetModuleFileName( NULL, szPath, 512 ) == 0 )
  346.     {
  347.         _tprintf(TEXT("Unable to install %s - %s\n"), TEXT(SZSERVICEDISPLAYNAME), GetLastErrorText(szErr, 256));
  348.         return;
  349.     }
  350.  
  351.     schSCManager = OpenSCManager(
  352.                         NULL,                   // machine (NULL == local)
  353.                         NULL,                   // database (NULL == default)
  354.                         SC_MANAGER_ALL_ACCESS   // access required
  355.                         );
  356.     if ( schSCManager )
  357.     {
  358.         schService = CreateService(
  359.             schSCManager,               // SCManager database
  360.             TEXT(SZSERVICENAME),        // name of service
  361.             TEXT(SZSERVICEDISPLAYNAME), // name to display
  362.             SERVICE_ALL_ACCESS,         // desired access
  363.             SERVICE_WIN32_OWN_PROCESS,  // service type
  364.             SERVICE_DEMAND_START,       // start type
  365.             SERVICE_ERROR_NORMAL,       // error control type
  366.             szPath,                     // service's binary
  367.             NULL,                       // no load ordering group
  368.             NULL,                       // no tag identifier
  369.             TEXT(SZDEPENDENCIES),       // dependencies
  370.             NULL,                       // LocalSystem account
  371.             NULL);                      // no password
  372.  
  373.         if ( schService )
  374.         {
  375.             _tprintf(TEXT("%s installed.\n"), TEXT(SZSERVICEDISPLAYNAME) );
  376.             CloseServiceHandle(schService);
  377.         }
  378.         else
  379.         {
  380.             _tprintf(TEXT("CreateService failed - %s\n"), GetLastErrorText(szErr, 256));
  381.         }
  382.  
  383.         CloseServiceHandle(schSCManager);
  384.     }
  385.     else
  386.         _tprintf(TEXT("OpenSCManager failed - %s\n"), GetLastErrorText(szErr,256));
  387. }
  388.  
  389.  
  390.  
  391. //
  392. //  FUNCTION: CmdRemoveService()
  393. //
  394. //  PURPOSE: Stops and removes the service
  395. //
  396. //  PARAMETERS:
  397. //    none
  398. //
  399. //  RETURN VALUE:
  400. //    none
  401. //
  402. //  COMMENTS:
  403. //
  404. void CmdRemoveService()
  405. {
  406.     SC_HANDLE   schService;
  407.     SC_HANDLE   schSCManager;
  408.  
  409.     schSCManager = OpenSCManager(
  410.                         NULL,                   // machine (NULL == local)
  411.                         NULL,                   // database (NULL == default)
  412.                         SC_MANAGER_ALL_ACCESS   // access required
  413.                         );
  414.     if ( schSCManager )
  415.     {
  416.         schService = OpenService(schSCManager, TEXT(SZSERVICENAME), SERVICE_ALL_ACCESS);
  417.  
  418.         if (schService)
  419.         {
  420.             // try to stop the service
  421.             if ( ControlService( schService, SERVICE_CONTROL_STOP, &ssStatus ) )
  422.             {
  423.                 _tprintf(TEXT("Stopping %s."), TEXT(SZSERVICEDISPLAYNAME));
  424.                 Sleep( 1000 );
  425.  
  426.                 while( QueryServiceStatus( schService, &ssStatus ) )
  427.                 {
  428.                     if ( ssStatus.dwCurrentState == SERVICE_STOP_PENDING )
  429.                     {
  430.                         _tprintf(TEXT("."));
  431.                         Sleep( 1000 );
  432.                     }
  433.                     else
  434.                         break;
  435.                 }
  436.  
  437.                 if ( ssStatus.dwCurrentState == SERVICE_STOPPED )
  438.                     _tprintf(TEXT("\n%s stopped.\n"), TEXT(SZSERVICEDISPLAYNAME) );
  439.                 else
  440.                     _tprintf(TEXT("\n%s failed to stop.\n"), TEXT(SZSERVICEDISPLAYNAME) );
  441.  
  442.             }
  443.  
  444.             // now remove the service
  445.             if( DeleteService(schService) )
  446.                 _tprintf(TEXT("%s removed.\n"), TEXT(SZSERVICEDISPLAYNAME) );
  447.             else
  448.                 _tprintf(TEXT("DeleteService failed - %s\n"), GetLastErrorText(szErr,256));
  449.  
  450.  
  451.             CloseServiceHandle(schService);
  452.         }
  453.         else
  454.             _tprintf(TEXT("OpenService failed - %s\n"), GetLastErrorText(szErr,256));
  455.  
  456.         CloseServiceHandle(schSCManager);
  457.     }
  458.     else
  459.         _tprintf(TEXT("OpenSCManager failed - %s\n"), GetLastErrorText(szErr,256));
  460. }
  461.  
  462.  
  463.  
  464.  
  465.  
  466. //
  467. //  FUNCTION: CmdRestartService()
  468. //
  469. //  PURPOSE: Stops and removes the service
  470. //
  471. //  PARAMETERS:
  472. //    none
  473. //
  474. //  RETURN VALUE:
  475. //    none
  476. //
  477. //  COMMENTS:
  478. //
  479. void CmdRestartService(char *szServiceName)
  480. {
  481.     SC_HANDLE   schService;
  482.     SC_HANDLE   schSCManager;
  483.  
  484.     schSCManager = OpenSCManager(
  485.                         NULL,                   // machine (NULL == local)
  486.                         NULL,                   // database (NULL == default)
  487.                         SC_MANAGER_ALL_ACCESS   // access required
  488.                         );
  489.     if ( schSCManager )
  490.     {
  491.         schService = OpenService(schSCManager, TEXT(szServiceName), SERVICE_ALL_ACCESS);
  492.         if (schService)
  493.         {
  494.             if(! ControlService( schService, SERVICE_CONTROL_INTERROGATE, &ssStatus ) )
  495.             //if(QueryServiceStatus( schService, &ssStatus )==0)
  496.             {
  497.                 if(GetLastError()==ERROR_SERVICE_NOT_ACTIVE)
  498.                 {
  499.  
  500.                    //AddToMessageLog(TEXT("Start service..."));
  501.                    StartService( schService, 0,NULL);
  502.                 }
  503.                 else
  504.                 {  ;
  505.                    //AddToMessageLog(TEXT("QueryService..."));
  506.                    //AddToMessageLog(TEXT(GetLastErrorText(szErr,256)));
  507.                 }
  508.             }
  509.             CloseServiceHandle(schService);
  510.         }
  511.         else
  512.         {    _tprintf(TEXT("OpenService failed - %s\n"), GetLastErrorText(szErr,256));
  513.               AddToMessageLog(TEXT("OpenService..."));
  514.               AddToMessageLog(TEXT(GetLastErrorText(szErr,256)));
  515.  
  516.         }
  517.         CloseServiceHandle(schSCManager);
  518.     }
  519.     else
  520.     {    _tprintf(TEXT("OpenSCManager failed - %s\n"), GetLastErrorText(szErr,256));
  521.           AddToMessageLog(TEXT("OpenSCMManager.."));
  522.  
  523.     }
  524. }
  525.  
  526.  
  527.  
  528.  
  529. ///////////////////////////////////////////////////////////////////
  530. //
  531. //  The following code is for running the service as a console app
  532. //
  533.  
  534.  
  535. //
  536. //  FUNCTION: CmdDebugService(int argc, char ** argv)
  537. //
  538. //  PURPOSE: Runs the service as a console application
  539. //
  540. //  PARAMETERS:
  541. //    argc - number of command line arguments
  542. //    argv - array of command line arguments
  543. //
  544. //  RETURN VALUE:
  545. //    none
  546. //
  547. //  COMMENTS:
  548. //
  549. void CmdDebugService(int argc, char ** argv)
  550. {
  551.     DWORD dwArgc;
  552.     LPTSTR *lpszArgv;
  553.  
  554. #ifdef UNICODE
  555.     lpszArgv = CommandLineToArgvW(GetCommandLineW(), &(dwArgc) );
  556. #else
  557.     dwArgc   = (DWORD) argc;
  558.     lpszArgv = argv;
  559. #endif
  560.  
  561.     _tprintf(TEXT("Debugging %s.\n"), TEXT(SZSERVICEDISPLAYNAME));
  562.  
  563.     SetConsoleCtrlHandler( ControlHandler, TRUE );
  564.  
  565.     ServiceStart( dwArgc, lpszArgv );
  566. }
  567.  
  568.  
  569. //
  570. //  FUNCTION: ControlHandler ( DWORD dwCtrlType )
  571. //
  572. //  PURPOSE: Handled console control events
  573. //
  574. //  PARAMETERS:
  575. //    dwCtrlType - type of control event
  576. //
  577. //  RETURN VALUE:
  578. //    True - handled
  579. //    False - unhandled
  580. //
  581. //  COMMENTS:
  582. //
  583. BOOL WINAPI ControlHandler ( DWORD dwCtrlType )
  584. {
  585.     switch( dwCtrlType )
  586.     {
  587.         case CTRL_BREAK_EVENT:  // use Ctrl+C or Ctrl+Break to simulate
  588.         case CTRL_C_EVENT:      // SERVICE_CONTROL_STOP in debug mode
  589.             _tprintf(TEXT("Stopping %s.\n"), TEXT(SZSERVICEDISPLAYNAME));
  590.             ServiceStop();
  591.             return TRUE;
  592.             break;
  593.  
  594.     }
  595.     return FALSE;
  596. }
  597.  
  598. //
  599. //  FUNCTION: GetLastErrorText
  600. //
  601. //  PURPOSE: copies error message text to string
  602. //
  603. //  PARAMETERS:
  604. //    lpszBuf - destination buffer
  605. //    dwSize - size of buffer
  606. //
  607. //  RETURN VALUE:
  608. //    destination buffer
  609. //
  610. //  COMMENTS:
  611. //
  612. LPTSTR GetLastErrorText( LPTSTR lpszBuf, DWORD dwSize )
  613. {
  614.     DWORD dwRet;
  615.     LPTSTR lpszTemp = NULL;
  616.  
  617.     dwRet = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_ARGUMENT_ARRAY,
  618.                            NULL,
  619.                            GetLastError(),
  620.                            LANG_NEUTRAL,
  621.                            (LPTSTR)&lpszTemp,
  622.                            0,
  623.                            NULL );
  624.  
  625.     // supplied buffer is not long enough
  626.     if ( !dwRet || ( (long)dwSize < (long)dwRet+14 ) )
  627.         lpszBuf[0] = TEXT('\0');
  628.     else
  629.     {
  630.         lpszTemp[lstrlen(lpszTemp)-2] = TEXT('\0');  //remove cr and newline character
  631.         _stprintf( lpszBuf, TEXT("%s (0x%x)"), lpszTemp, GetLastError() );
  632.     }
  633.  
  634.     if ( lpszTemp )
  635.         LocalFree((HLOCAL) lpszTemp );
  636.  
  637.     return lpszBuf;
  638. }
  639.  
  640. //-------------------------------------------------
  641. // this event is signalled when the
  642. // service should end
  643. //-------------------------------------------------
  644. HANDLE  hServerStopEvent = NULL;
  645.  
  646.  
  647. //-------------------------------------------------
  648. //  FUNCTION: ServiceStart
  649. //
  650. //  PURPOSE: Actual code of the service
  651. //           that does the work.
  652. //-------------------------------------------------
  653. void ServiceStart (DWORD dwArgc, LPTSTR *lpszArgv)
  654. {
  655.     DWORD  dwWait,dwTimeout=1000*60*1;
  656.  
  657.     if (!ReportStatusToSCMgr(
  658.         SERVICE_START_PENDING, // service state
  659.         NO_ERROR,              // exit code
  660.         3000))                 // wait hint
  661.         goto cleanup;
  662.  
  663.     // create the event object. The control handler function signals
  664.     // this event when it receives the "stop" control code.
  665.     //
  666.     hServerStopEvent = CreateEvent(
  667.         NULL,    // no security attributes
  668.         TRUE,    // manual reset event
  669.         FALSE,   // not-signalled
  670.         NULL);   // no name
  671.  
  672.     if ( hServerStopEvent == NULL) goto cleanup;
  673.  
  674.  
  675.     // report the status to the service control manager.
  676.     //
  677.     if (!ReportStatusToSCMgr(
  678.         SERVICE_START_PENDING, // service state
  679.         NO_ERROR,              // exit code
  680.         3000))                 // wait hint
  681.         goto cleanup;
  682.  
  683.  
  684.  
  685.     // report the status to the service control manager.
  686.     //
  687.     if (!ReportStatusToSCMgr(
  688.         SERVICE_START_PENDING, // service state
  689.         NO_ERROR,              // exit code
  690.         3000))                 // wait hint
  691.         goto cleanup;
  692.  
  693.  
  694.  
  695.     // report the status to the service control manager.
  696.     //
  697.     if (!ReportStatusToSCMgr(
  698.         SERVICE_RUNNING,       // service state
  699.         NO_ERROR,              // exit code
  700.         0))                    // wait hint
  701.         goto cleanup;
  702.  
  703.     //
  704.     // End of initialization
  705.     // Service is now running, perform work until shutdown
  706.     //
  707.  
  708.     while ( 1 )
  709.     {
  710.  
  711.         dwWait = WaitForSingleObject(  hServerStopEvent, dwTimeout);
  712.         if(dwWait==WAIT_FAILED)
  713.         {
  714.            AddToMessageLog(TEXT("Error in WaitForSingleObject"));
  715.            break;
  716.         }
  717.         else if(dwWait==WAIT_TIMEOUT)
  718.         {
  719.             CmdRestartService("MySql");
  720.         }
  721.         else
  722.         {   break;  //shutdown
  723.         }
  724.  
  725.     }
  726.  
  727.   cleanup:
  728.  
  729.     if (hServerStopEvent)
  730.         CloseHandle(hServerStopEvent);
  731.  
  732. }
  733.  
  734.  
  735. //-------------------------------------------------
  736. //  FUNCTION: ServiceStop
  737. //
  738. //  PURPOSE: Stops the service
  739. //-------------------------------------------------
  740. void ServiceStop()
  741. {
  742.     if ( hServerStopEvent )
  743.         SetEvent(hServerStopEvent);
  744. }
  745. //-the end ----------------------------------------
  746.