Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

ServiceManager.h

Go to the documentation of this file.
00001 /*  ServiceManager.h - Service Control API wrapper
00002     Copyright (C) 2001-2004 Mark Weaver
00003     Written by Mark Weaver <mark@npsl.co.uk>
00004 
00005     Part of the Open-Win32 library.
00006     This library is free software; you can redistribute it and/or
00007     modify it under the terms of the GNU Library General Public
00008     License as published by the Free Software Foundation; either
00009     version 2 of the License, or (at your option) any later version.
00010 
00011     This library is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014     Library General Public License for more details.
00015 
00016     You should have received a copy of the GNU Library General Public
00017     License along with this library; if not, write to the
00018     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00019     Boston, MA  02111-1307, USA.
00020 */
00021 
00026 #ifndef OW32_ServiceManager_h
00027 #define OW32_ServiceManager_h
00028 
00029 #include <OW32/XSC_HANDLE.h>
00030 #include <OW32/auto_buf.h>
00031 
00032 namespace OW32
00033 {
00034 class OW32_LIB_EXPORT CEnumDependentServices;
00035 
00037 class OW32_LIB_EXPORT CSCService
00038 {
00039 private:
00040     XSC_HANDLE m_hService;
00041 
00042 public:
00044     CSCService(SC_HANDLE hService) :
00045         m_hService(hService)
00046     {
00047     }
00048 
00050     ~CSCService()
00051     {
00052         // obscure, CloseServiceHandle sets last error to ERROR_IO_PENDING
00053         DWORD dwLastError = ::GetLastError();
00054         m_hService.Close();
00055         ::SetLastError(dwLastError);
00056     }
00057 
00059     SC_HANDLE GetHandle() const { return m_hService; }
00060 
00066     BOOL Control(DWORD dwControl, LPSERVICE_STATUS lpServiceStatus) 
00067     {
00068         return ::ControlService(m_hService, dwControl, lpServiceStatus);
00069     }
00070 
00076     BOOL Start(DWORD dwNumServiceArgs = 0, LPCTSTR* lpServiceArgVectors = NULL)
00077     {
00078         return ::StartService(m_hService, dwNumServiceArgs, lpServiceArgVectors);
00079     }
00080 
00085     BOOL Stop(LPSERVICE_STATUS lpServiceStatus)
00086     {
00087         return ::ControlService(m_hService, SERVICE_CONTROL_STOP, lpServiceStatus);
00088     }
00089 
00094     BOOL Delete()
00095     {
00096         return ::DeleteService(m_hService);
00097     }
00098 
00103     BOOL QueryStatus(LPSERVICE_STATUS lpServiceStatus) { return ::QueryServiceStatus(m_hService, lpServiceStatus); }
00104 
00109     inline CEnumDependentServices* EnumDependentServices(DWORD dwServiceState = SERVICE_STATE_ALL);
00110 
00112     operator SC_HANDLE() { return m_hService; }
00113 };
00114 
00115 #ifdef _MSC_VER
00116 #pragma warning(disable: 4251)
00117 #endif
00118 
00120 class OW32_LIB_EXPORT CEnumDependentServices
00121 {
00122 public:
00127     CEnumDependentServices(CSCService& parent, DWORD dwServiceState) :
00128         m_parent(parent),
00129         m_dwServiceState(dwServiceState),
00130         m_dwCount(0),
00131         m_dwPos(0),
00132         m_bGot(false)
00133     {
00134         m_buf.reserve(sizeof(ENUM_SERVICE_STATUS) + 256*2); // space for at least one entry
00135     }
00136 
00141     BOOL Next(ENUM_SERVICE_STATUS** ppEntry)
00142     {
00143         if (!m_bGot) 
00144         {
00145             for (int i = 0; i < 2; i++) {
00146                 DWORD cbBytesNeeded;
00147                 if (!EnumDependentServices(m_parent, m_dwServiceState, (ENUM_SERVICE_STATUS*)m_buf.str(),
00148                     (DWORD)m_buf.capacity(), &cbBytesNeeded, &m_dwCount)) {
00149                     if (i > 0 || GetLastError() != ERROR_MORE_DATA)
00150                         return FALSE;
00151                 }
00152                 m_buf.reserve(cbBytesNeeded);
00153             }
00154             m_bGot = true;
00155         }
00156 
00157         if (m_dwPos >= m_dwCount) {
00158             SetLastError(ERROR_NO_MORE_ITEMS);
00159             return FALSE;
00160         }
00161 
00162         *ppEntry = &((ENUM_SERVICE_STATUS*)m_buf.str())[m_dwPos++];
00163         return TRUE;
00164     }
00165 
00166 private:
00167     CEnumDependentServices(const CEnumDependentServices &other);
00168     CEnumDependentServices& operator=(const CEnumDependentServices &other);
00169 
00170     CSCService      &m_parent;
00171     DWORD           m_dwServiceState;
00172     DWORD           m_dwPos, m_dwCount;
00173     auto_byte_buf   m_buf;
00174     bool            m_bGot;
00175 };
00176 
00177 #ifdef _MSC_VER
00178 #pragma warning(default: 4251)
00179 #endif
00180 
00181 inline CEnumDependentServices* CSCService::EnumDependentServices(DWORD dwServiceState)
00182 {
00183     return new CEnumDependentServices(*this, dwServiceState);
00184 }
00185 
00186 class OW32_LIB_EXPORT CEnumServicesStatus;
00187 
00189 class OW32_LIB_EXPORT CSCManager
00190 {
00191 private:
00192     XSC_HANDLE m_SCManager;
00193 
00194 public:
00199     BOOL Open(DWORD dwDesiredAccess = SC_MANAGER_ALL_ACCESS, LPCTSTR lpszMachineName = NULL)
00200     {
00201         m_SCManager = ::OpenSCManager(lpszMachineName, SERVICES_ACTIVE_DATABASE, dwDesiredAccess);
00202         return m_SCManager != NULL;
00203     }
00204 
00206     void Close()
00207     {
00208         m_SCManager.Close();
00209     }
00210 
00212     ~CSCManager()
00213     {
00214         // obscure, CloseServiceHandle sets last error to ERROR_IO_PENDING
00215         DWORD dwLastError = ::GetLastError();
00216         m_SCManager.Close();
00217         ::SetLastError(dwLastError);
00218     }
00219 
00221     SC_HANDLE GetHandle() const { return m_SCManager; }
00222 
00228     inline CEnumServicesStatus* EnumServicesStatus(DWORD dwServiceType=SERVICE_WIN32, DWORD dwServiceState=SERVICE_STATE_ALL);
00229 
00245     CSCService* CreateService(
00246         LPCTSTR lpServiceName,                            // net stop name
00247         LPCTSTR lpPath,                                   // module path
00248         LPCTSTR lpServiceDescription = NULL,              // friendly name
00249         DWORD dwDesiredAccess = STANDARD_RIGHTS_REQUIRED, // delete/control/interrogate/etc
00250         DWORD dwServiceType = SERVICE_WIN32_OWN_PROCESS,  // own process/shared/drivers
00251         DWORD dwStartType = SERVICE_AUTO_START,           // auto start flag
00252         DWORD dwErrorControl = SERVICE_ERROR_NORMAL,      // error handling mode
00253         LPCTSTR lpLoadOrderGroup = NULL,                  // load order group
00254         LPDWORD lpLoadOrderTag = NULL,                    // load order tag
00255         LPCTSTR lpDependencies = NULL,                    // array of dependency names
00256         LPCTSTR lpAccountName = NULL,                     // local system
00257         LPCTSTR lpPassword = NULL)                        // (NULL is OK for local system)
00258     {
00259         SC_HANDLE hService = 
00260             ::CreateService(m_SCManager, lpServiceName, lpServiceDescription, dwDesiredAccess,
00261                             dwServiceType, dwStartType, dwErrorControl, lpPath,
00262                             lpLoadOrderGroup, lpLoadOrderTag, lpDependencies, lpAccountName, lpPassword);
00263         if (hService==NULL)
00264             return NULL;
00265         return new CSCService(hService);
00266     }
00267 
00273     CSCService* OpenService(LPCTSTR lpServiceName, DWORD dwDesiredAccess = SERVICE_ALL_ACCESS)
00274     {
00275         SC_HANDLE hService = ::OpenService(m_SCManager, lpServiceName, dwDesiredAccess);
00276         if (hService==NULL)
00277             return NULL;
00278         return new CSCService(hService);
00279     }
00280 };
00281 
00283 class OW32_LIB_EXPORT CEnumServicesStatus
00284 {
00285 public:
00291     inline CEnumServicesStatus(CSCManager& parent, DWORD dwServiceType, DWORD dwServiceState);
00292 
00297     inline DWORD Next(ENUM_SERVICE_STATUS** ppEntry); // returns ERROR_NO_MORE_DATA if finished; ERROR_SUCCESS if OK
00298 
00299 private:
00300     CEnumServicesStatus(const CEnumServicesStatus &other);
00301     CEnumServicesStatus& operator=(const CEnumServicesStatus &other);
00302 
00303     CSCManager          &m_Parent;
00304     DWORD               m_CurrentPos,m_BufferCount;
00305     DWORD               m_dwServiceType,m_dwServiceState,m_dwResumeHandle;
00306     bool                m_bMoreToCome;
00307     ENUM_SERVICE_STATUS m_StatusBuffer[1024 / sizeof(ENUM_SERVICE_STATUS)];
00308 };
00309 
00310 inline CEnumServicesStatus* CSCManager::EnumServicesStatus(DWORD dwServiceType, DWORD dwServiceState)
00311 {
00312     return new CEnumServicesStatus(*this, dwServiceType, dwServiceState);
00313 }
00314 
00315 inline CEnumServicesStatus::CEnumServicesStatus(CSCManager& parent, DWORD dwServiceType, DWORD dwServiceState) :
00316     m_Parent(parent),
00317     m_CurrentPos(0),
00318     m_BufferCount(0),
00319     m_dwServiceType(dwServiceType),
00320     m_dwServiceState(dwServiceState),
00321     m_dwResumeHandle(0),
00322     m_bMoreToCome(true)
00323 {
00324 }
00325 
00326 inline DWORD CEnumServicesStatus::Next(ENUM_SERVICE_STATUS** ppEntry)
00327 {
00328     // use current buffer & advance counter
00329     if (m_CurrentPos < m_BufferCount) {
00330         *ppEntry = &m_StatusBuffer[m_CurrentPos++];
00331         return ERROR_SUCCESS;
00332     }
00333     
00334     // otherwise, fetch more data
00335     if (m_bMoreToCome) {
00336         DWORD dwBytesNeeded;
00337         if (!EnumServicesStatus(m_Parent.GetHandle(), m_dwServiceType, m_dwServiceState, m_StatusBuffer, 
00338                                 sizeof(m_StatusBuffer), &dwBytesNeeded, &m_BufferCount, &m_dwResumeHandle))
00339         {
00340             DWORD dwError=GetLastError();
00341             if (dwError!=ERROR_MORE_DATA)
00342                 return dwError;
00343         } else
00344             m_bMoreToCome = false; // all data fetched
00345     } else {
00346         return 1; // TODO: hack!
00347     }
00348 
00349     // return the data & reset the buffer pointer
00350     m_CurrentPos=0;
00351     *ppEntry = &m_StatusBuffer[m_CurrentPos++];
00352     return ERROR_SUCCESS;
00353 }
00354 
00355 }
00356 
00357 #endif // OW32_ServiceManager_h

Generated on Sun Jun 5 01:29:18 2005 for OW32 by  doxygen 1.3.9.1