nt_servc.cpp
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:16k
源码类别:

MySQL数据库

开发平台:

Visual C++

  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 <stdio.h>
  9. #include "nt_servc.h"
  10. static NTService *pService;
  11. /* ------------------------------------------------------------------------
  12.  -------------------------------------------------------------------------- */
  13. NTService::NTService()
  14. {
  15.     bOsNT      = FALSE;
  16.     //service variables
  17.     ServiceName      = NULL;
  18.     hExitEvent      = 0;
  19.     bPause      = FALSE;
  20.     bRunning      = FALSE;
  21.     hThreadHandle    = 0;
  22.     fpServiceThread  = NULL;
  23.     //time-out variables
  24.     nStartTimeOut    = 15000;
  25.     nStopTimeOut     = 86400000;
  26.     nPauseTimeOut    = 5000;
  27.     nResumeTimeOut   = 5000;
  28.     //install variables
  29.     dwDesiredAccess  = SERVICE_ALL_ACCESS;
  30.     dwServiceType    = SERVICE_WIN32_OWN_PROCESS;
  31.     dwStartType      = SERVICE_AUTO_START;
  32.     dwErrorControl   = SERVICE_ERROR_NORMAL;
  33.     szLoadOrderGroup = NULL;
  34.     lpdwTagID      = NULL;
  35.     szDependencies   = NULL;
  36.     my_argc      = 0;
  37.     my_argv      = NULL;
  38.     hShutdownEvent   = 0;
  39.     nError      = 0;
  40.     dwState      = 0;
  41. }
  42. /* ------------------------------------------------------------------------
  43.  -------------------------------------------------------------------------- */
  44. NTService::~NTService()
  45. {
  46.   if (ServiceName != NULL) delete[] ServiceName;
  47. }
  48. /* ------------------------------------------------------------------------
  49.  -------------------------------------------------------------------------- */
  50. BOOL NTService::GetOS()
  51. {
  52.   bOsNT = FALSE;
  53.   memset(&osVer, 0, sizeof(OSVERSIONINFO));
  54.   osVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  55.   if (GetVersionEx(&osVer))
  56.   {
  57.     if (osVer.dwPlatformId == VER_PLATFORM_WIN32_NT)
  58.       bOsNT = TRUE;
  59.   }
  60.   return bOsNT;
  61. }
  62. /* ------------------------------------------------------------------------
  63.  Init()  Registers the main service thread with the service manager
  64.     ServiceThread - pointer to the main programs entry function
  65.     when the service is started
  66.  -------------------------------------------------------------------------- */
  67. long NTService::Init(LPCSTR szInternName,void *ServiceThread)
  68. {
  69.   pService = this;
  70.   fpServiceThread = (THREAD_FC)ServiceThread;
  71.   ServiceName = new char[lstrlen(szInternName)+1];
  72.   lstrcpy(ServiceName,szInternName);
  73.   SERVICE_TABLE_ENTRY stb[] =
  74.   {
  75.     { (char *)szInternName,(LPSERVICE_MAIN_FUNCTION) ServiceMain} ,
  76.     { NULL, NULL }
  77.   };
  78.   return StartServiceCtrlDispatcher(stb); //register with the Service Manager
  79. }
  80. /* ------------------------------------------------------------------------
  81.   Install() - Installs the service with Service manager
  82.   nError values:
  83. 0  success
  84. 1  Can't open the Service manager
  85. 2  Failed to create service
  86.  -------------------------------------------------------------------------- */
  87. BOOL NTService::Install(int startType, LPCSTR szInternName,
  88. LPCSTR szDisplayName,
  89. LPCSTR szFullPath, LPCSTR szAccountName,
  90. LPCSTR szPassword)
  91. {
  92.   BOOL ret_val=FALSE;
  93.   SC_HANDLE newService, scm;
  94.   if (!SeekStatus(szInternName,1))
  95.    return FALSE;
  96.   char szFilePath[_MAX_PATH];
  97.   GetModuleFileName(NULL, szFilePath, sizeof(szFilePath));
  98.   // open a connection to the SCM
  99.   if (!(scm = OpenSCManager(0, 0,SC_MANAGER_CREATE_SERVICE)))
  100.     printf("Failed to install the service (Couldn't open the SCM)n");
  101.   else  // Install the new service
  102.   {
  103.     if (!(newService=
  104.   CreateService(scm,
  105. szInternName,
  106. szDisplayName,
  107. dwDesiredAccess,//default: SERVICE_ALL_ACCESS
  108. dwServiceType, //default: SERVICE_WIN32_OWN_PROCESS
  109.      //default: SERVICE_AUTOSTART
  110. (startType == 1 ? SERVICE_AUTO_START :
  111.  SERVICE_DEMAND_START),
  112. dwErrorControl, //default: SERVICE_ERROR_NORMAL
  113. szFullPath, //exec full path
  114. szLoadOrderGroup, //default: NULL
  115. lpdwTagID, //default: NULL
  116. szDependencies, //default: NULL
  117. szAccountName, //default: NULL
  118. szPassword))) //default: NULL
  119.       printf("Failed to install the service (Couldn't create service)n");
  120.      else
  121.      {
  122.        printf("Service successfully installed.n");
  123.        CloseServiceHandle(newService);
  124.        ret_val=TRUE; // Everything went ok
  125.      }
  126.      CloseServiceHandle(scm);
  127.   }
  128.   return ret_val;
  129. }
  130. /* ------------------------------------------------------------------------
  131.   Remove() - Removes  the service
  132.   nError values:
  133. 0  success
  134. 1  Can't open the Service manager
  135. 2  Failed to locate service
  136. 3  Failed to delete service
  137.  -------------------------------------------------------------------------- */
  138. BOOL NTService::Remove(LPCSTR szInternName)
  139. {
  140.   BOOL ret_value=FALSE;
  141.   SC_HANDLE service, scm;
  142.   if (!SeekStatus(szInternName,0))
  143.    return FALSE;
  144.   nError=0;
  145.   // open a connection to the SCM
  146.   if (!(scm = OpenSCManager(0, 0,SC_MANAGER_CREATE_SERVICE)))
  147.   {
  148.     printf("Failed to remove the service (Couldn't open the SCM)n");
  149.   }
  150.   else
  151.   {
  152.     if ((service = OpenService(scm,szInternName, DELETE)))
  153.     {
  154.       if (!DeleteService(service))
  155.         printf("Failed to remove the servicen");
  156.       else
  157.       {
  158.         printf("Service successfully removed.n");
  159. ret_value=TRUE; // everything went ok
  160.       }
  161.       CloseServiceHandle(service);
  162.     }
  163.     else
  164.       printf("Failed to remove the service (Couldn't open the service)n");
  165.     CloseServiceHandle(scm);
  166.   }
  167.   return ret_value;
  168. }
  169. /* ------------------------------------------------------------------------
  170.    Stop() - this function should be called before the app. exits to stop
  171.     the service
  172.  -------------------------------------------------------------------------- */
  173. void NTService::Stop(void)
  174. {
  175.   SetStatus(SERVICE_STOP_PENDING,NO_ERROR, 0, 1, 60000);
  176.   StopService();
  177.   SetStatus(SERVICE_STOPPED, NO_ERROR, 0, 1, 1000);
  178. }
  179. /* ------------------------------------------------------------------------
  180.   ServiceMain() - This is the function that is called from the
  181.   service manager to start the service
  182.  -------------------------------------------------------------------------- */
  183. void NTService::ServiceMain(DWORD argc, LPTSTR *argv)
  184. {
  185.   // registration function
  186.   if (!(pService->hServiceStatusHandle =
  187. RegisterServiceCtrlHandler(pService->ServiceName,
  188.    (LPHANDLER_FUNCTION)
  189.    NTService::ServiceCtrlHandler)))
  190.     goto error;
  191.   // notify SCM of progress
  192.   if (!pService->SetStatus(SERVICE_START_PENDING,NO_ERROR, 0, 1, 8000))
  193.     goto error;
  194.   // create the exit event
  195.   if (!(pService->hExitEvent = CreateEvent (0, TRUE, FALSE,0)))
  196.     goto error;
  197.   if (!pService->SetStatus(SERVICE_START_PENDING,NO_ERROR, 0, 3,
  198.    pService->nStartTimeOut))
  199.     goto error;
  200.   // save start arguments
  201.   pService->my_argc=argc;
  202.   pService->my_argv=argv;
  203.   // start the service
  204.   if (!pService->StartService())
  205.     goto error;
  206.   // Check that the service is now running.
  207.   if (!pService->SetStatus(SERVICE_RUNNING,NO_ERROR, 0, 0, 0))
  208.     goto error;
  209.   // wait for exit event
  210.   WaitForSingleObject (pService->hExitEvent, INFINITE);
  211.   // wait for thread to exit
  212.   if (WaitForSingleObject (pService->hThreadHandle, INFINITE) == WAIT_TIMEOUT)
  213.    CloseHandle(pService->hThreadHandle);
  214.   pService->Exit(0);
  215.   return;
  216. error:
  217.   pService->Exit(GetLastError());
  218.   return;
  219. }
  220. /* ------------------------------------------------------------------------
  221.    StartService() - starts the appliaction thread
  222.  -------------------------------------------------------------------------- */
  223. BOOL NTService::StartService()
  224. {
  225.   // Start the real service's thread (application)
  226.   if (!(hThreadHandle = (HANDLE) _beginthread((THREAD_FC)fpServiceThread,0,
  227.       (void *) this)))
  228.     return FALSE;
  229.   bRunning = TRUE;
  230.   return TRUE;
  231. }
  232. /* ------------------------------------------------------------------------
  233.  -------------------------------------------------------------------------- */
  234. void NTService::StopService()
  235. {
  236.   bRunning=FALSE;
  237.   // Set the event for application
  238.   if (hShutdownEvent)
  239.      SetEvent(hShutdownEvent);
  240.   // Set the event for ServiceMain
  241.   SetEvent(hExitEvent);
  242. }
  243. /* ------------------------------------------------------------------------
  244.  -------------------------------------------------------------------------- */
  245. void NTService::PauseService()
  246. {
  247.   bPause = TRUE;
  248.   SuspendThread(hThreadHandle);
  249. }
  250. /* ------------------------------------------------------------------------
  251.  -------------------------------------------------------------------------- */
  252. void NTService::ResumeService()
  253. {
  254.   bPause=FALSE;
  255.   ResumeThread(hThreadHandle);
  256. }
  257. /* ------------------------------------------------------------------------
  258.  -------------------------------------------------------------------------- */
  259. BOOL NTService::SetStatus (DWORD dwCurrentState,DWORD dwWin32ExitCode,
  260.    DWORD dwServiceSpecificExitCode, DWORD dwCheckPoint,
  261.    DWORD dwWaitHint)
  262. {
  263.   BOOL bRet;
  264.   SERVICE_STATUS serviceStatus;
  265.   dwState=dwCurrentState;
  266.   serviceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
  267.   serviceStatus.dwCurrentState = dwCurrentState;
  268.   if (dwCurrentState == SERVICE_START_PENDING)
  269.     serviceStatus.dwControlsAccepted = 0; //don't accept control events
  270.   else
  271.     serviceStatus.dwControlsAccepted =    (SERVICE_ACCEPT_STOP |
  272.    SERVICE_ACCEPT_PAUSE_CONTINUE |
  273.    SERVICE_ACCEPT_SHUTDOWN);
  274.   // if a specific exit code is defined,set up the win32 exit code properly
  275.   if (dwServiceSpecificExitCode == 0)
  276.     serviceStatus.dwWin32ExitCode = dwWin32ExitCode;
  277.   else
  278.     serviceStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
  279.   serviceStatus.dwServiceSpecificExitCode = dwServiceSpecificExitCode;
  280.   serviceStatus.dwCheckPoint = dwCheckPoint;
  281.   serviceStatus.dwWaitHint   = dwWaitHint;
  282.   // Pass the status to the Service Manager
  283.   if (!(bRet=SetServiceStatus (hServiceStatusHandle, &serviceStatus)))
  284.     StopService();
  285.   return bRet;
  286. }
  287. /* ------------------------------------------------------------------------
  288.  -------------------------------------------------------------------------- */
  289. void NTService::ServiceCtrlHandler(DWORD ctrlCode)
  290. {
  291.   DWORD  dwState;
  292.   if (!pService)
  293.     return;
  294.   dwState=pService->dwState;  // get current state
  295.   switch(ctrlCode) {
  296. #ifdef NOT_USED  /* do we need this ? */
  297.   case SERVICE_CONTROL_PAUSE:
  298.     if (pService->bRunning && ! pService->bPause)
  299.     {
  300.       dwState = SERVICE_PAUSED;
  301.       pService->SetStatus(SERVICE_PAUSE_PENDING,NO_ERROR, 0, 1,
  302.   pService->nPauseTimeOut);
  303.       pService->PauseService();
  304.     }
  305.     break;
  306.   case SERVICE_CONTROL_CONTINUE:
  307.     if (pService->bRunning && pService->bPause)
  308.     {
  309.       dwState = SERVICE_RUNNING;
  310.       pService->SetStatus(SERVICE_CONTINUE_PENDING,NO_ERROR, 0, 1,
  311.   pService->nResumeTimeOut);
  312.       pService->ResumeService();
  313.     }
  314.     break;
  315. #endif
  316.   case SERVICE_CONTROL_SHUTDOWN:
  317.   case SERVICE_CONTROL_STOP:
  318.     dwState = SERVICE_STOP_PENDING;
  319.     pService->SetStatus(SERVICE_STOP_PENDING,NO_ERROR, 0, 1,
  320. pService->nStopTimeOut);
  321.     pService->StopService();
  322.     break;
  323.   default:
  324.     pService->SetStatus(dwState, NO_ERROR,0, 0, 0);
  325.     break;
  326.   }
  327.   //pService->SetStatus(dwState, NO_ERROR,0, 0, 0);
  328. }
  329. /* ------------------------------------------------------------------------
  330.  -------------------------------------------------------------------------- */
  331. void NTService::Exit(DWORD error)
  332. {
  333.   if (hExitEvent)
  334.     CloseHandle(hExitEvent);
  335.   // Send a message to the scm to tell that we stop
  336.   if (hServiceStatusHandle)
  337.     SetStatus(SERVICE_STOPPED, error,0, 0, 0);
  338.   // If the thread has started kill it ???
  339.   // if (hThreadHandle) CloseHandle(hThreadHandle);
  340. }
  341. /* ------------------------------------------------------------------------
  342.  -------------------------------------------------------------------------- */
  343. BOOL NTService::SeekStatus(LPCSTR szInternName, int OperationType)
  344. {
  345.   BOOL ret_value=FALSE;
  346.   SC_HANDLE service, scm;
  347.   // open a connection to the SCM
  348.   if (!(scm = OpenSCManager(0, 0,SC_MANAGER_CREATE_SERVICE)))
  349.   {
  350.     DWORD ret_error=GetLastError();
  351.     if (ret_error == ERROR_ACCESS_DENIED)
  352.     {
  353.      printf("Install/Remove of the Service Denied!n");
  354.      if (!is_super_user())
  355.       printf("That operation should be made by an user with Administrator privileges!n");
  356.     }
  357.     else
  358.      printf("There is a problem for to open the Service Control Manager!n");
  359.   }
  360.   else
  361.   {
  362.     if (OperationType == 1)
  363.     {
  364.       /* an install operation */
  365.       if ((service = OpenService(scm,szInternName, SERVICE_ALL_ACCESS )))
  366.       {
  367. LPQUERY_SERVICE_CONFIG ConfigBuf;
  368. DWORD dwSize;
  369. ConfigBuf = (LPQUERY_SERVICE_CONFIG) LocalAlloc(LPTR, 4096);
  370. printf("The service already exists!n");
  371. if (QueryServiceConfig(service,ConfigBuf,4096,&dwSize))
  372.   printf("The current server installed: %sn",
  373.  ConfigBuf->lpBinaryPathName);
  374. LocalFree(ConfigBuf);
  375. CloseServiceHandle(service);
  376.       }
  377.       else
  378. ret_value=TRUE;
  379.     }
  380.     else
  381.     {
  382.       /* a remove operation */
  383.       if (!(service = OpenService(scm,szInternName, SERVICE_ALL_ACCESS )))
  384. printf("The service doesn't exist!n");
  385.       else
  386.       {
  387. SERVICE_STATUS ss;
  388. memset(&ss, 0, sizeof(ss));
  389. if (QueryServiceStatus(service,&ss))
  390. {
  391.   DWORD dwState = ss.dwCurrentState;
  392.   if (dwState == SERVICE_RUNNING)
  393.     printf("Failed to remove the service because the service is runningnStop the service and try againn");
  394.   else if (dwState == SERVICE_STOP_PENDING)
  395.     printf("
  396. Failed to remove the service because the service is in stop pending state!n
  397. Wait 30 seconds and try again.n
  398. If this condition persist, reboot the machine and try againn");
  399.   else
  400.     ret_value= TRUE;
  401. }
  402. CloseServiceHandle(service);
  403.       }
  404.     }
  405.     CloseServiceHandle(scm);
  406.   }
  407.   return ret_value;
  408. }
  409. /* ------------------------------------------------------------------------
  410.  -------------------------------------------------------------------------- */
  411. BOOL NTService::IsService(LPCSTR ServiceName)
  412. {
  413.   BOOL ret_value=FALSE;
  414.   SC_HANDLE service, scm;
  415.   
  416.   if ((scm= OpenSCManager(0, 0,SC_MANAGER_ENUMERATE_SERVICE)))
  417.   {
  418.     if ((service = OpenService(scm,ServiceName, SERVICE_QUERY_STATUS)))
  419.     {
  420.       ret_value=TRUE;
  421.       CloseServiceHandle(service);
  422.     }
  423.     CloseServiceHandle(scm);
  424.   }
  425.   return ret_value;
  426. }
  427. /* ------------------------------------------------------------------------
  428.  -------------------------------------------------------------------------- */
  429. BOOL NTService::got_service_option(char **argv, char *service_option)
  430. {
  431.   char *option;
  432.   for (option= argv[1]; *option; option++)
  433.     if (!strcmp(option, service_option))
  434.       return TRUE;
  435.   return FALSE;
  436. }
  437. /* ------------------------------------------------------------------------
  438.  -------------------------------------------------------------------------- */
  439. BOOL NTService::is_super_user()
  440. {
  441.   HANDLE hAccessToken;
  442.   UCHAR InfoBuffer[1024];
  443.   PTOKEN_GROUPS ptgGroups=(PTOKEN_GROUPS)InfoBuffer;
  444.   DWORD dwInfoBufferSize;
  445.   PSID psidAdministrators;
  446.   SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY;
  447.   UINT x;
  448.   BOOL ret_value=FALSE;
  449.  
  450.   if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE,&hAccessToken ))
  451.   {
  452.    if (GetLastError() != ERROR_NO_TOKEN)
  453.      return FALSE;
  454.  
  455.    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hAccessToken))
  456.      return FALSE;
  457.   }
  458.  
  459.   ret_value= GetTokenInformation(hAccessToken,TokenGroups,InfoBuffer,
  460.                                  1024, &dwInfoBufferSize);
  461.   CloseHandle(hAccessToken);
  462.  
  463.   if (!ret_value )
  464.     return FALSE;
  465.  
  466.   if (!AllocateAndInitializeSid(&siaNtAuthority, 2,
  467. SECURITY_BUILTIN_DOMAIN_RID,
  468. DOMAIN_ALIAS_RID_ADMINS,
  469. 0, 0, 0, 0, 0, 0,
  470. &psidAdministrators))
  471.     return FALSE;
  472.   ret_value = FALSE;
  473.  
  474.   for (x=0;x<ptgGroups->GroupCount;x++)
  475.   {
  476.    if ( EqualSid(psidAdministrators, ptgGroups->Groups[x].Sid) )
  477.    {
  478.     ret_value = TRUE;
  479.     break;
  480.    }
  481.  
  482.   }
  483.   FreeSid(psidAdministrators);
  484.   return ret_value;
  485. }