home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 January / Chip_2001-01_cd1.bin / tema / mysql / mysql-3.23.28g-win-source.exe / sql / nt_servc.cpp < prev    next >
C/C++ Source or Header  |  2000-08-31  |  11KB  |  401 lines

  1. /* ------------------------------------------------------------------------
  2.    Windows NT Service class library
  3.    Copyright Abandoned 1998 Irena Pancirov - Irnet Snc
  4.    This file is public domain and comes with NO WARRANTY of any kind
  5.  -------------------------------------------------------------------------- */
  6. #include <windows.h>
  7. #include <process.h>
  8. #include "nt_servc.h"
  9.  
  10.  
  11. static NTService *pService;
  12.  
  13. /* ------------------------------------------------------------------------
  14.  
  15.  -------------------------------------------------------------------------- */
  16. NTService::NTService()
  17. {
  18.  
  19.     bOsNT         = FALSE;
  20.     //service variables
  21.     ServiceName      = NULL;
  22.     hExitEvent         = 0;
  23.     bPause         = FALSE;
  24.     bRunning         = FALSE;
  25.     hThreadHandle    = 0;
  26.     fpServiceThread  = NULL;
  27.  
  28.     //time-out variables
  29.     nStartTimeOut    = 15000;
  30.     nStopTimeOut     = 15000;
  31.     nPauseTimeOut    = 5000;
  32.     nResumeTimeOut   = 5000;
  33.  
  34.     //install variables
  35.     dwDesiredAccess  = SERVICE_ALL_ACCESS;
  36.     dwServiceType    = SERVICE_WIN32_OWN_PROCESS;
  37.     dwStartType      = SERVICE_AUTO_START;
  38.     dwErrorControl   = SERVICE_ERROR_NORMAL;
  39.     szLoadOrderGroup = NULL;
  40.     lpdwTagID         = NULL;
  41.     szDependencies   = NULL;
  42.  
  43.     my_argc         = 0;
  44.     my_argv         = NULL;
  45.     hShutdownEvent   = 0;
  46.     nError         = 0;
  47.     dwState         = 0;
  48. }
  49.  
  50. /* ------------------------------------------------------------------------
  51.  
  52.  -------------------------------------------------------------------------- */
  53. NTService::~NTService()
  54. {
  55.   if(ServiceName != NULL) delete[] ServiceName;
  56. }
  57. /* ------------------------------------------------------------------------
  58.  
  59.  -------------------------------------------------------------------------- */
  60. BOOL NTService::GetOS()
  61. {
  62.   bOsNT = FALSE;
  63.   memset(&osVer, 0, sizeof(OSVERSIONINFO));
  64.   osVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  65.   if (GetVersionEx(&osVer))
  66.   {
  67.     if (osVer.dwPlatformId == VER_PLATFORM_WIN32_NT)
  68.       bOsNT = TRUE;
  69.   }
  70.   return bOsNT;
  71. }
  72.  
  73. /* ------------------------------------------------------------------------
  74.  Init()  Registers the main service thread with the service manager
  75.  
  76.     ServiceThread - pointer to the main programs entry function
  77.             when the service is started
  78.  -------------------------------------------------------------------------- */
  79. long NTService::Init(LPCSTR szInternName,void *ServiceThread)
  80. {
  81.  
  82.   pService = this;
  83.  
  84.   fpServiceThread = (THREAD_FC)ServiceThread;
  85.   ServiceName = new char[lstrlen(szInternName)+1];
  86.   lstrcpy(ServiceName,szInternName);
  87.  
  88.   SERVICE_TABLE_ENTRY stb[] =
  89.   {
  90.     { (char *)szInternName,(LPSERVICE_MAIN_FUNCTION) ServiceMain} ,
  91.     { NULL, NULL }
  92.   };
  93.  
  94.   return StartServiceCtrlDispatcher(stb); //register with the Service Manager
  95. }
  96. /* ------------------------------------------------------------------------
  97.   Install() - Installs the service with Service manager
  98.   nError values:
  99.     0  success
  100.     1  Can't open the Service manager
  101.     2  Failed to create service
  102.  -------------------------------------------------------------------------- */
  103. BOOL NTService::Install(LPCSTR szInternName,LPCSTR szDisplayName,
  104.                LPCSTR szFullPath, LPCSTR szAccountName,LPCSTR szPassword)
  105. {
  106.   SC_HANDLE newService, scm;
  107.  
  108.   nError=0;
  109.  
  110.   // open a connection to the SCM
  111.   scm = OpenSCManager(0, 0,SC_MANAGER_CREATE_SERVICE);
  112.   if(scm)  // Install the new service
  113.   {  newService = CreateService(
  114.     scm,
  115.     szInternName,
  116.     szDisplayName,
  117.     dwDesiredAccess,    //default: SERVICE_ALL_ACCESS
  118.     dwServiceType,        //default: SERVICE_WIN32_OWN_PROCESS
  119.     dwStartType,        //default: SERVICE_AUTOSTART
  120.     dwErrorControl,        //default: SERVICE_ERROR_NORMAL
  121.     szFullPath,        //exec full path
  122.     szLoadOrderGroup,    //default: NULL
  123.     lpdwTagID,        //default: NULL
  124.     szDependencies,        //default: NULL
  125.     szAccountName,        //default: NULL
  126.     szPassword);        //default: NULL
  127.  
  128.      if (newService) CloseServiceHandle(newService);  // clean up
  129.      else         nError=2;
  130.  
  131.      // clean up
  132.      CloseServiceHandle(scm);
  133.   }
  134.   else nError=1;
  135.  
  136.   return (!nError);
  137. }
  138. /* ------------------------------------------------------------------------
  139.   Remove() - Removes  the service
  140.   nError values:
  141.     0  success
  142.     1  Can't open the Service manager
  143.     2  Failed to locate service
  144.     3  Failed to delete service
  145.  -------------------------------------------------------------------------- */
  146. BOOL NTService::Remove(LPCSTR szInternName)
  147. {
  148.  
  149.   SC_HANDLE service, scm;
  150.  
  151.   nError=0;
  152.  
  153.   // open a connection to the SCM
  154.   scm = OpenSCManager(0, 0,SC_MANAGER_CREATE_SERVICE);
  155.  
  156.   if (scm)
  157.   {
  158.     //open the service
  159.     service = OpenService(scm,szInternName, DELETE );
  160.     if(service)
  161.     {
  162.       if(!DeleteService(service)) nError=3;
  163.       CloseServiceHandle(service);
  164.     }
  165.     else
  166.     {
  167.      //MessageBox(NULL,"Can't find the service","Remove Error",MB_OK|MB_ICONHAND);
  168.        nError=2;
  169.     }
  170.     CloseServiceHandle(scm);
  171.   }
  172.   else nError=1;
  173.  
  174.   return (!nError);
  175. }
  176.  
  177. /* ------------------------------------------------------------------------
  178.    Stop() - this function should be called before the app. exits to stop
  179.         the service
  180.  -------------------------------------------------------------------------- */
  181. void NTService::Stop(void)
  182. {
  183.   SetStatus(SERVICE_STOP_PENDING,NO_ERROR, 0, 1, 60000);
  184.   StopService();
  185.   SetStatus(SERVICE_STOPPED, NO_ERROR, 0, 1, 1000);
  186. }
  187.  
  188. /* ------------------------------------------------------------------------
  189.   ServiceMain() - This is the function that is called from the
  190.           service manager to start the service
  191.  -------------------------------------------------------------------------- */
  192. void NTService::ServiceMain(DWORD argc, LPTSTR *argv)
  193. {
  194.  
  195.   // registration function
  196.   pService->hServiceStatusHandle =
  197.        RegisterServiceCtrlHandler(pService->ServiceName,
  198.                (LPHANDLER_FUNCTION )NTService::ServiceCtrlHandler);
  199.  
  200.   if(!pService->hServiceStatusHandle)
  201.   {
  202.       pService->Exit(GetLastError());
  203.       return;
  204.   }
  205.  
  206.   // notify SCM of progress
  207.   if(!pService->SetStatus(SERVICE_START_PENDING,NO_ERROR, 0, 1, 8000))
  208.   {
  209.       pService->Exit(GetLastError());
  210.       return;
  211.   }
  212.  
  213.   // create the exit event
  214.   pService->hExitEvent = CreateEvent (0, TRUE, FALSE,0);
  215.   if(!pService->hExitEvent)
  216.   {
  217.       pService->Exit(GetLastError());
  218.       return;
  219.   }
  220.  
  221.   if(!pService->SetStatus(SERVICE_START_PENDING,NO_ERROR, 0, 3, pService->nStartTimeOut))
  222.   {
  223.       pService->Exit(GetLastError());
  224.       return;
  225.   }
  226.  
  227.   // save start arguments
  228.   pService->my_argc=argc;
  229.   pService->my_argv=argv;
  230.  
  231.   // start the service
  232.   if(!pService->StartService())
  233.   {
  234.       pService->Exit(GetLastError());
  235.       return;
  236.   }
  237.  
  238.   // the service is now running.
  239.   if(!pService->SetStatus(SERVICE_RUNNING,NO_ERROR, 0, 0, 0))
  240.   {
  241.       pService->Exit(GetLastError());
  242.       return;
  243.   }
  244.  
  245.   // wait for exit event
  246.   WaitForSingleObject (pService->hExitEvent, INFINITE);
  247.  
  248.   // wait for thread to exit
  249.   WaitForSingleObject (pService->hThreadHandle, 30000);
  250.  
  251.   pService->Exit(0);
  252. }
  253.  
  254. /* ------------------------------------------------------------------------
  255.    StartService() - starts the appliaction thread
  256.  -------------------------------------------------------------------------- */
  257. BOOL NTService::StartService()
  258. {
  259.  
  260.   // Start the real service's thread (application)
  261.   hThreadHandle = (HANDLE) _beginthread((THREAD_FC)fpServiceThread,0,(void *)this);
  262.  
  263.   if (hThreadHandle==0) return FALSE;
  264.  
  265.   bRunning = TRUE;
  266.   return TRUE;
  267. }
  268. /* ------------------------------------------------------------------------
  269.  
  270.  -------------------------------------------------------------------------- */
  271. void NTService::StopService()
  272. {
  273.   bRunning=FALSE;
  274.  
  275.   // Set the event for application
  276.   if(hShutdownEvent)
  277.      SetEvent(hShutdownEvent);
  278.  
  279.   // Set the event for ServiceMain
  280.   SetEvent(hExitEvent);
  281. }
  282. /* ------------------------------------------------------------------------
  283.  
  284.  -------------------------------------------------------------------------- */
  285. void NTService::PauseService()
  286. {
  287.     bPause = TRUE;
  288.     SuspendThread(hThreadHandle);
  289. }
  290. /* ------------------------------------------------------------------------
  291.  
  292.  -------------------------------------------------------------------------- */
  293. void NTService::ResumeService()
  294. {
  295.     bPause=FALSE;
  296.     ResumeThread(hThreadHandle);
  297. }
  298. /* ------------------------------------------------------------------------
  299.  
  300.  -------------------------------------------------------------------------- */
  301. BOOL NTService::SetStatus (DWORD dwCurrentState,DWORD dwWin32ExitCode,
  302.         DWORD dwServiceSpecificExitCode,DWORD dwCheckPoint,DWORD dwWaitHint)
  303. {
  304.   BOOL bRet;
  305.   SERVICE_STATUS serviceStatus;
  306.  
  307.    dwState=dwCurrentState;
  308.  
  309.    serviceStatus.dwServiceType    = SERVICE_WIN32_OWN_PROCESS;
  310.    serviceStatus.dwCurrentState = dwCurrentState;
  311.  
  312.    if (dwCurrentState == SERVICE_START_PENDING)
  313.     serviceStatus.dwControlsAccepted = 0;    //don't accept conrol events
  314.    else
  315.     serviceStatus.dwControlsAccepted =    SERVICE_ACCEPT_STOP |
  316.         SERVICE_ACCEPT_PAUSE_CONTINUE | SERVICE_ACCEPT_SHUTDOWN;
  317.  
  318.    // if a specific exit code is defined,set up the win32 exit code properly
  319.    if (dwServiceSpecificExitCode == 0)
  320.        serviceStatus.dwWin32ExitCode = dwWin32ExitCode;
  321.    else
  322.        serviceStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
  323.  
  324.    serviceStatus.dwServiceSpecificExitCode = dwServiceSpecificExitCode;
  325.  
  326.    serviceStatus.dwCheckPoint = dwCheckPoint;
  327.    serviceStatus.dwWaitHint   = dwWaitHint;
  328.  
  329.    // Pass the status to the Service Manager
  330.    bRet=SetServiceStatus (hServiceStatusHandle, &serviceStatus);
  331.  
  332.    if(!bRet) StopService();
  333.  
  334.    return bRet;
  335. }
  336. /* ------------------------------------------------------------------------
  337.  
  338.  -------------------------------------------------------------------------- */
  339. void NTService::ServiceCtrlHandler(DWORD ctrlCode)
  340. {
  341.  
  342.   DWORD  dwState = 0;
  343.  
  344.   if(!pService) return;
  345.  
  346.   dwState=pService->dwState;  // get current state
  347.  
  348.   switch(ctrlCode)
  349.   {
  350.  
  351.    /*********** do we need this ? *******************************
  352.     case SERVICE_CONTROL_PAUSE:
  353.      if (pService->bRunning && ! pService->bPause)
  354.      {
  355.          dwState = SERVICE_PAUSED;
  356.          pService->SetStatus(SERVICE_PAUSE_PENDING,NO_ERROR, 0, 1, pService->nPauseTimeOut);
  357.          pService->PauseService();
  358.      }
  359.      break;
  360.  
  361.    case SERVICE_CONTROL_CONTINUE:
  362.     if (pService->bRunning && pService->bPause)
  363.     {
  364.         dwState = SERVICE_RUNNING;
  365.         pService->SetStatus(SERVICE_CONTINUE_PENDING,NO_ERROR, 0, 1, pService->nResumeTimeOut);
  366.         pService->ResumeService();
  367.     }
  368.     break;
  369.    ****************************************************************/
  370.  
  371.     case SERVICE_CONTROL_SHUTDOWN:
  372.     case SERVICE_CONTROL_STOP:
  373.      dwState = SERVICE_STOP_PENDING;
  374.      pService->SetStatus(SERVICE_STOP_PENDING,NO_ERROR, 0, 1, pService->nStopTimeOut);
  375.      pService->StopService();
  376.      break;
  377.  
  378.    default:
  379.     pService->SetStatus(dwState, NO_ERROR,0, 0, 0);
  380.     break;
  381.   }
  382.   //pService->SetStatus(dwState, NO_ERROR,0, 0, 0);
  383. }
  384. /* ------------------------------------------------------------------------
  385.  
  386.  -------------------------------------------------------------------------- */
  387. void NTService::Exit(DWORD error)
  388. {
  389.   if (hExitEvent) CloseHandle(hExitEvent);
  390.  
  391.   // Send a message to the scm to tell that we stop
  392.   if (hServiceStatusHandle)
  393.       SetStatus(SERVICE_STOPPED, error,0, 0, 0);
  394.  
  395.   // If the thread has started kill it ???
  396.   // if (hThreadHandle) CloseHandle(hThreadHandle);
  397.  
  398. }
  399.  
  400. /* ------------------------- the end -------------------------------------- */
  401.