枚举NT services

    技术2022-05-11  94

                                                    枚举NT services        闻怡洋·vchelp

      下面的文章提供了访问NT中所有Service的功能,每次列举Services时,函数会返回一个列表。 列表的内容依赖于你所使用的参数。 (我认为这是一种很巧妙的编程方法,它极大的减轻了数据和函数的冗余,利用一个STATIC函数来产生本身对象的列表或者是来产生对象)

      Class declaration:声明

      class TTrixServiceInfo {

      public:

       CString ServiceName;

       CString DisplayName;

       CString BinaryPath;

       DWORD ServiceType;

       DWORD StartType;

       DWORD ErrorControl;

       DWORD CurrentState;

      public:

       TTrixServiceInfo();

       TTrixServiceInfo& operator=(const TTrixServiceInfo& source);

       CString GetServiceType(void);

       CString GetStartType(void);

       CString GetErrorControl(void);

       CString GetCurrentState(void);

       static TTrixServiceInfo *EnumServices(DWORD serviceType,

       DWORD serviceState,DWORD *count);

      };

    Description:类的每一个实例都包含了SERVICE的各种信息,如果想得到SERVICE的列表,请调用TTrixServiceInfo::EnumServices(...)。

    参数ServiceType的取值可能是:SERVICE_WIN32 and SERVICE_DRIVER.

    参数ServiceState的取值可能是:SERVICE_ACTIVE and SERVICE_INACTIVE.

    EnumServices(...)将返回TTrixServiceInfo对象的列表,(如果出错返回NULL)。列表中对象的个数可以通过参数返回时得到。下面是具体的代码:

      TTrixServiceInfo *lpservice = NULL;

      DWORD count;

      lpservice =           TTrixServiceInfo::EnumServices(SERVICE_WIN32,SERVICE_ACTIVE|SERVICE_INACTIVE,&count/*得到个数*/);

      if (lpservice) {//如果正确

        for (DWORD index = 0; index < count; index ++) {

         printf("%d. %s, %s/n", index, lpservice[index].DisplayName,

         lpservice[index].GetCurrentState());

         }

        delete [] lpservice;

       }

      Source code:

      TTrixServiceInfo::TTrixServiceInfo()

      {

       ServiceName.Empty();

       DisplayName.Empty();

       BinaryPath.Empty();

       ServiceType = 0;

       StartType = 0;

       ErrorControl = 0;

       CurrentState = 0;

      }

      TTrixServiceInfo& TTrixServiceInfo::operator=(const TTrixServiceInfo& source)

      {

       ServiceName = source.ServiceName;

       DisplayName = source.DisplayName;

       BinaryPath = source.BinaryPath;

       ServiceType = source.ServiceType;

       StartType = source.StartType;

       ErrorControl = source.ErrorControl;

       CurrentState = source.CurrentState;

       return *this;

      }

      CString TTrixServiceInfo::GetServiceType(void)

      {

       // Winnt.h

       CString str = "UNKNOWN";

       if (ServiceType & SERVICE_WIN32) {

        if (ServiceType &

         SERVICE_WIN32_OWN_PROCESS)

         str = "WIN32_OWN_PROCESS";

        else if (ServiceType &

         SERVICE_WIN32_SHARE_PROCESS)

         str = "WIN32_SHARE_PROCESS";

        if (ServiceType &

          SERVICE_INTERACTIVE_PROCESS)

          str += "(INTERACTIVE_PROCESS)";

        }

         switch (ServiceType) {

          case SERVICE_KERNEL_DRIVER:

            str = "KERNEL_DRIVER"; break;

          case SERVICE_FILE_SYSTEM_DRIVER:

            str = "FILE_SYSTEM_DRIVER";

            break;

          };

        return str;

       }

      CString TTrixServiceInfo::GetStartType(void)

      {

       // Winnt.h

       TCHAR *types[] = {

       "BOOT_START", // 0

       "SYSTEM_START", // 1

       "AUTO_START", // 2

       "DEMAND_START", // 3

       "DISABLED" // 4

      };

      return CString(types[StartType]);

      }

      CString TTrixServiceInfo::GetErrorControl(void)

      {

       // Winnt.h

       TCHAR *types[] = {

       "ERROR_IGNORE", // 0

       "ERROR_NORMAL", // 1

       "ERROR_SEVERE", // 2

       "ERROR_CRITICAL" // 3

       };

      return CString(types[ErrorControl]);

      }

      CString TTrixServiceInfo::GetCurrentState(void)

      {

       // Winsvc.h

       TCHAR *types[] = {

       "UNKNOWN",

       "STOPPED", // 1

       "START_PENDING", // 2

       "STOP_PENDING", // 3

       "RUNNING", // 4

       "CONTINUE_PENDING", // 5

       "PAUSE_PENDING", // 6

       "PAUSED" // 7

       };

       return CString(types[CurrentState]);

      }

      // ServiceType = bit OR of SERVICE_WIN32, SERVICE_DRIVER

      // ServiceState = bit OR of SERVICE_ACTIVE, SERVICE_INACTIVE

      TTrixServiceInfo *TTrixServiceInfo::EnumServices(DWORD serviceType,DWORD

      serviceState,DWORD *count)

      {

       // Maybe check if serviceType and serviceState have at least one constant specified

       *count = 0;

       TTrixServiceInfo *info = NULL;

       SC_HANDLE scman = ::OpenSCManager(NULL,NULL,SC_MANAGER_ENUMERATE_SERVICE);

       if (scman) {

        ENUM_SERVICE_STATUS service, *lpservice;

        BOOL rc;

        DWORD bytesNeeded,servicesReturned,resumeHandle = 0;

        rc = ::EnumServicesStatus(scman,serviceType,serviceState,&service,sizeof(service),

           &bytesNeeded,&servicesReturned,&resumeHandle);

        if ((rc == FALSE) && (::GetLastError() == ERROR_MORE_DATA)) {

         DWORD bytes = bytesNeeded + sizeof(ENUM_SERVICE_STATUS);

         lpservice = new ENUM_SERVICE_STATUS [bytes];

              ::EnumServicesStatus(scman,serviceType,serviceState,lpservice,bytes,

              &bytesNeeded,&servicesReturned,&resumeHandle);

         *count = servicesReturned; // Not a chance that 0 services is returned

         info = new TTrixServiceInfo [servicesReturned];

      TCHAR Buffer[1024];

      // Should be enough for service info

      QUERY_SERVICE_CONFIG *lpqch = (QUERY_SERVICE_CONFIG*)Buffer;

      for (DWORD ndx = 0; ndx < servicesReturned; ndx++) {

        info[ndx].ServiceName = lpservice[ndx].lpServiceName;

        info[ndx].DisplayName = lpservice[ndx].lpDisplayName;

        info[ndx].ServiceType = lpservice[ndx].ServiceStatus.dwServiceType;

        info[ndx].CurrentState = lpservice[ndx].ServiceStatus.dwCurrentState;

        SC_HANDLE sh = ::OpenService(scman,lpservice[ndx].lpServiceName,SERVICE_QUERY_CONFIG);

        if (::QueryServiceConfig(sh,lpqch,sizeof(Buffer),&bytesNeeded)) {

         info[ndx].BinaryPath = lpqch->lpBinaryPathName;

         info[ndx].StartType = lpqch->dwStartType;

         info[ndx].ErrorControl = lpqch->dwErrorControl;

        }

        ::CloseServiceHandle(sh);

       }

       delete [] lpservice;

       }

       ::CloseServiceHandle(scman);

       }

       return info;

      }

     


    最新回复(0)