Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

394 lines
11 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997 - 1998
  5. //
  6. // File: C S E R V I C E . H
  7. //
  8. // Contents: This file contains CService and CServiceManager, wrapper
  9. // classes to the Win32 Service APIs.
  10. //
  11. // Notes: Note that not all functionallity is currently extended through
  12. // these classes.
  13. // Note that most functionality is inline in this file. What is
  14. // not inline is in cservice.cpp
  15. //
  16. // Author: mikemi 6 Mar 1997
  17. //
  18. //----------------------------------------------------------------------------
  19. #ifndef _CSERVICE_H_
  20. #define _CSERVICE_H_
  21. //#include "debugx.h"
  22. //#include "ncbase.h"
  23. //-------------------------------------------------------------------
  24. //
  25. //
  26. //-------------------------------------------------------------------
  27. size_t CchMsz(const TCHAR * msz);
  28. class CService
  29. {
  30. friend class CServiceManager;
  31. public:
  32. CService()
  33. {
  34. _schandle = NULL;
  35. };
  36. ~CService()
  37. {
  38. Close();
  39. };
  40. VOID Close()
  41. {
  42. BOOL frt;
  43. if (_schandle)
  44. {
  45. frt = ::CloseServiceHandle( _schandle );
  46. AssertSz(frt, "CloseServiceHandle failed!");
  47. _schandle = NULL;
  48. }
  49. }
  50. HRESULT HrDelete()
  51. {
  52. Assert(_schandle != NULL );
  53. if (::DeleteService( _schandle ))
  54. return S_OK;
  55. else
  56. return HRESULT_FROM_WIN32(GetLastError());
  57. }
  58. HRESULT HrStart( DWORD cNumServiceArgs = 0,
  59. LPCTSTR* papServiceArgs = NULL)
  60. {
  61. Assert(_schandle != NULL );
  62. if (::StartService( _schandle, cNumServiceArgs, papServiceArgs ))
  63. return S_OK;
  64. else
  65. return HRESULT_FROM_WIN32(GetLastError());
  66. }
  67. HRESULT HrControl( DWORD dwControl )
  68. {
  69. SERVICE_STATUS sStatus;
  70. Assert(_schandle != NULL );
  71. AssertSz((dwControl != SERVICE_CONTROL_INTERROGATE),
  72. "CService::HrControl does not support the SERVICE_CONTROL_INTERROGATE flag");
  73. if ( ::ControlService( _schandle, dwControl, &sStatus ))
  74. return S_OK;
  75. else
  76. return HRESULT_FROM_WIN32(GetLastError());
  77. }
  78. HRESULT HrMoveOutOfState( DWORD dwState );
  79. HRESULT HrQueryState( DWORD* pdwState );
  80. HRESULT HrQueryStartType( DWORD* pdwStartType );
  81. HRESULT HrSetStartType( DWORD dwStartType )
  82. {
  83. Assert(_schandle != NULL );
  84. if (::ChangeServiceConfig( _schandle,
  85. SERVICE_NO_CHANGE,
  86. dwStartType,
  87. SERVICE_NO_CHANGE,
  88. NULL,
  89. NULL,
  90. NULL,
  91. NULL,
  92. NULL,
  93. NULL,
  94. NULL))
  95. return S_OK;
  96. else
  97. return HRESULT_FROM_WIN32(GetLastError());
  98. }
  99. HRESULT HrQueryDependencies(OUT LPTSTR * pmszDependencyList);
  100. HRESULT HrSetDependencies(IN LPCTSTR mszDependencyList)
  101. {
  102. Assert(_schandle != NULL );
  103. if (::ChangeServiceConfig( _schandle,
  104. SERVICE_NO_CHANGE, // ServiceType
  105. SERVICE_NO_CHANGE, // StartType
  106. SERVICE_NO_CHANGE, // ErrorControl
  107. NULL, // BinaryPathName
  108. NULL, // LoadOredrGroup
  109. NULL, // TagId
  110. mszDependencyList, // Dependencies
  111. NULL, // ServiceStartName
  112. NULL, // Password
  113. NULL)) // DisplayName
  114. return S_OK;
  115. else
  116. return HRESULT_FROM_WIN32(GetLastError());
  117. }
  118. HRESULT HrSetDisplayName(IN LPCTSTR mszDisplayName)
  119. {
  120. Assert(_schandle != NULL );
  121. if (::ChangeServiceConfig( _schandle,
  122. SERVICE_NO_CHANGE, // ServiceType
  123. SERVICE_NO_CHANGE, // StartType
  124. SERVICE_NO_CHANGE, // ErrorControl
  125. NULL, // BinaryPathName
  126. NULL, // LoadOredrGroup
  127. NULL, // TagId
  128. NULL, // Dependencies
  129. NULL, // ServiceStartName
  130. NULL, // Password
  131. mszDisplayName)) // DisplayName
  132. {
  133. return S_OK;
  134. }
  135. else
  136. {
  137. return HRESULT_FROM_WIN32(GetLastError());
  138. }
  139. }
  140. HRESULT HrSetServiceObjectSecurity(
  141. SECURITY_INFORMATION dwSecurityInformation,
  142. PSECURITY_DESCRIPTOR lpSecurityDescriptor)
  143. {
  144. Assert(_schandle != NULL );
  145. if (::SetServiceObjectSecurity( _schandle,
  146. dwSecurityInformation, lpSecurityDescriptor))
  147. {
  148. return S_OK;
  149. }
  150. else
  151. {
  152. return HRESULT_FROM_WIN32(GetLastError());
  153. }
  154. }
  155. private:
  156. SC_HANDLE _schandle;
  157. };
  158. //-------------------------------------------------------------------
  159. //
  160. //
  161. //-------------------------------------------------------------------
  162. class CServiceManager
  163. {
  164. public:
  165. CServiceManager()
  166. {
  167. _schandle = NULL;
  168. _sclock = NULL;
  169. };
  170. ~CServiceManager()
  171. {
  172. if (_sclock)
  173. {
  174. Unlock();
  175. }
  176. if (_schandle)
  177. {
  178. Close();
  179. }
  180. };
  181. HRESULT HrOpen( DWORD dwDesiredAccess = SC_MANAGER_ALL_ACCESS,
  182. LPCTSTR pszMachineName = NULL,
  183. LPCTSTR pszDatabaseName = NULL )
  184. {
  185. if (_schandle != NULL)
  186. {
  187. Close();
  188. }
  189. _schandle = ::OpenSCManager( pszMachineName,
  190. pszDatabaseName,
  191. dwDesiredAccess );
  192. if ( _schandle != NULL )
  193. return S_OK;
  194. else
  195. return HRESULT_FROM_WIN32(GetLastError());
  196. }
  197. VOID Close()
  198. {
  199. BOOL frt;
  200. Assert(_schandle != NULL );
  201. frt = ::CloseServiceHandle( _schandle );
  202. _schandle = NULL;
  203. AssertSz(frt, "CloseServiceHandle failed!");
  204. }
  205. HRESULT HrLock()
  206. {
  207. INT cRetries = 3;
  208. static const INT c_secWait = 30;
  209. static const INT c_msecWait = (c_secWait / (cRetries - 1)) * 1000;
  210. Assert(_schandle != NULL );
  211. Assert(_sclock == NULL );
  212. while (cRetries--)
  213. {
  214. _sclock = ::LockServiceDatabase( _schandle );
  215. if (_sclock != NULL)
  216. return S_OK;
  217. else
  218. {
  219. if (GetLastError() != ERROR_SERVICE_DATABASE_LOCKED ||
  220. !cRetries)
  221. {
  222. return HRESULT_FROM_WIN32(GetLastError());
  223. }
  224. Trace1("SCM is locked, waiting for %d seconds before retrying...", c_msecWait / 1000);
  225. // wait for a bit to see if the database unlocks in that
  226. Sleep(c_msecWait);
  227. }
  228. }
  229. AssertSz(FALSE, "HrLock error");
  230. return S_OK;
  231. }
  232. VOID Unlock()
  233. {
  234. BOOL frt;
  235. Assert(_schandle != NULL );
  236. Assert(_sclock != NULL );
  237. frt = ::UnlockServiceDatabase( _sclock );
  238. _sclock = NULL;
  239. AssertSz(frt, "UnlockServiceDatabase failed!");
  240. }
  241. HRESULT HrQueryLocked(BOOL *pfLocked);
  242. HRESULT HrOpenService( CService* pcsService,
  243. LPCTSTR pszServiceName,
  244. DWORD dwDesiredAccess = SERVICE_ALL_ACCESS )
  245. {
  246. // make sure the service is not in use
  247. if (pcsService->_schandle != NULL)
  248. {
  249. pcsService->Close();
  250. }
  251. pcsService->_schandle = ::OpenService( _schandle, pszServiceName, dwDesiredAccess );
  252. if ( pcsService->_schandle != NULL )
  253. return S_OK;
  254. else
  255. {
  256. DWORD dw=GetLastError();
  257. return HRESULT_FROM_WIN32(dw);
  258. }
  259. }
  260. HRESULT HrCreateService( CService* pcsService,
  261. LPCTSTR pszServiceName,
  262. LPCTSTR pszDisplayName,
  263. DWORD dwServiceType,
  264. DWORD dwStartType,
  265. DWORD dwErrorControl,
  266. LPCTSTR pszBinaryPathName,
  267. LPCTSTR pslzDependencies = NULL,
  268. LPCTSTR pszLoadOrderGroup = NULL,
  269. PDWORD pdwTagId = NULL,
  270. DWORD dwDesiredAccess = SERVICE_ALL_ACCESS,
  271. LPCTSTR pszServiceStartName = NULL,
  272. LPCTSTR pszPassword = NULL )
  273. {
  274. // make sure the service is not in use
  275. if (pcsService->_schandle != NULL)
  276. {
  277. pcsService->Close();
  278. }
  279. pcsService->_schandle = ::CreateService( _schandle,
  280. pszServiceName,
  281. pszDisplayName,
  282. dwDesiredAccess,
  283. dwServiceType,
  284. dwStartType,
  285. dwErrorControl,
  286. pszBinaryPathName,
  287. pszLoadOrderGroup,
  288. pdwTagId,
  289. pslzDependencies,
  290. pszServiceStartName,
  291. pszPassword );
  292. if ( pcsService->_schandle != NULL )
  293. return S_OK;
  294. else
  295. return HRESULT_FROM_WIN32(GetLastError());
  296. }
  297. enum SERVICE_START_CRITERIA
  298. {
  299. SERVICE_NO_CRITERIA, // Start the service regardless
  300. SERVICE_ONLY_AUTO_START // Only start the service if it is of type
  301. // Auto-Start
  302. };
  303. HRESULT HrStartService(LPCTSTR szService)
  304. {
  305. return (HrStartServiceHelper(szService, SERVICE_NO_CRITERIA));
  306. }
  307. HRESULT HrStartAutoStartService(LPCTSTR szService)
  308. {
  309. return (HrStartServiceHelper(szService, SERVICE_ONLY_AUTO_START));
  310. }
  311. HRESULT HrStartServiceHelper(LPCTSTR szService,
  312. SERVICE_START_CRITERIA eCriteria);
  313. HRESULT HrStopService(LPCTSTR szService);
  314. enum DEPENDENCY_ADDREMOVE
  315. {
  316. DEPENDENCY_ADD,
  317. DEPENDENCY_REMOVE
  318. };
  319. HRESULT HrAddServiceDependency(LPCTSTR szServiceName, LPCTSTR szDependency)
  320. {
  321. return HrAddRemoveServiceDependency(szServiceName,
  322. szDependency,
  323. DEPENDENCY_ADD);
  324. }
  325. HRESULT HrRemoveServiceDependency(LPCTSTR szServiceName, LPCTSTR szDependency)
  326. {
  327. return HrAddRemoveServiceDependency(szServiceName,
  328. szDependency,
  329. DEPENDENCY_REMOVE);
  330. }
  331. HRESULT HrAddRemoveServiceDependency(LPCTSTR szServiceName,
  332. LPCTSTR szDependency,
  333. DEPENDENCY_ADDREMOVE enumFlag);
  334. private:
  335. SC_HANDLE _schandle;
  336. SC_LOCK _sclock;
  337. };
  338. #endif // _CSERVICE_H_