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.

448 lines
13 KiB

  1. // --------------------------------------------------------------------------
  2. // Module Name: ServerAPI.cpp
  3. //
  4. // Copyright (c) 1999-2000, Microsoft Corporation
  5. //
  6. // An abstract base class containing virtual functions that allow the basic
  7. // port functionality code to be reused to create another server. These
  8. // virtual functions create other objects with pure virtual functions which
  9. // the basic port functionality code invokes thru the v-table.
  10. //
  11. // History: 1999-11-07 vtan created
  12. // 2000-08-25 vtan moved from Neptune to Whistler
  13. // --------------------------------------------------------------------------
  14. #include "StandardHeader.h"
  15. #include "ServerAPI.h"
  16. #include <lpcgeneric.h>
  17. #include "APIConnection.h"
  18. #include "StatusCode.h"
  19. #include "TokenInformation.h"
  20. // --------------------------------------------------------------------------
  21. // CServerAPI::CServerAPI
  22. //
  23. // Arguments: <none>
  24. //
  25. // Returns: <none>
  26. //
  27. // Purpose: Constructor for the abstract base class.
  28. //
  29. // History: 1999-11-07 vtan created
  30. // 2000-08-25 vtan moved from Neptune to Whistler
  31. // --------------------------------------------------------------------------
  32. CServerAPI::CServerAPI (void)
  33. {
  34. }
  35. // --------------------------------------------------------------------------
  36. // CServerAPI::~CServerAPI
  37. //
  38. // Arguments: <none>
  39. //
  40. // Returns: <none>
  41. //
  42. // Purpose: Constructor for the abstract base class.
  43. //
  44. // History: 1999-11-07 vtan created
  45. // 2000-08-25 vtan moved from Neptune to Whistler
  46. // --------------------------------------------------------------------------
  47. CServerAPI::~CServerAPI (void)
  48. {
  49. }
  50. // --------------------------------------------------------------------------
  51. // CServerAPI::Start
  52. //
  53. // Arguments:
  54. //
  55. // Returns: NTSTATUS
  56. //
  57. // Purpose: Uses the service control manager to start the service.
  58. //
  59. // History: 2000-10-13 vtan created
  60. // 2000-11-28 vtan rewrote for Win32 services
  61. // --------------------------------------------------------------------------
  62. NTSTATUS CServerAPI::Start (void)
  63. {
  64. NTSTATUS status;
  65. SC_HANDLE hSCManager;
  66. hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
  67. if (hSCManager != NULL)
  68. {
  69. SC_HANDLE hSCService;
  70. hSCService = OpenService(hSCManager, GetServiceName(), SERVICE_START);
  71. if (hSCService != NULL)
  72. {
  73. if (StartService(hSCService, 0, NULL) != FALSE)
  74. {
  75. status = STATUS_SUCCESS;
  76. }
  77. else
  78. {
  79. status = CStatusCode::StatusCodeOfLastError();
  80. }
  81. TBOOL(CloseServiceHandle(hSCService));
  82. }
  83. else
  84. {
  85. status = CStatusCode::StatusCodeOfLastError();
  86. }
  87. TBOOL(CloseServiceHandle(hSCManager));
  88. }
  89. else
  90. {
  91. status = CStatusCode::StatusCodeOfLastError();
  92. }
  93. return(status);
  94. }
  95. // --------------------------------------------------------------------------
  96. // CServerAPI::Stop
  97. //
  98. // Arguments: <none>
  99. //
  100. // Returns: NTSTATUS
  101. //
  102. // Purpose: Use the service control manager to stop the service.
  103. //
  104. // History: 2000-10-17 vtan created
  105. // 2000-11-28 vtan rewrote for Win32 services
  106. // --------------------------------------------------------------------------
  107. NTSTATUS CServerAPI::Stop (void)
  108. {
  109. NTSTATUS status;
  110. HANDLE hPort;
  111. // First try connecting to the server and asking it to stop. This is
  112. // cleanest method.
  113. status = Connect(&hPort);
  114. if (NT_SUCCESS(status))
  115. {
  116. NTSTATUS status;
  117. API_GENERIC apiRequest;
  118. CPortMessage portMessageIn, portMessageOut;
  119. apiRequest.ulAPINumber = API_GENERIC_STOPSERVER;
  120. portMessageIn.SetData(&apiRequest, sizeof(apiRequest));
  121. status = NtRequestWaitReplyPort(hPort,
  122. portMessageIn.GetPortMessage(),
  123. portMessageOut.GetPortMessage());
  124. if (NT_SUCCESS(status))
  125. {
  126. status = reinterpret_cast<const API_GENERIC*>(portMessageOut.GetData())->status;
  127. }
  128. TBOOL(CloseHandle(hPort));
  129. }
  130. return(status);
  131. }
  132. // --------------------------------------------------------------------------
  133. // CServerAPI::IsRunning
  134. //
  135. // Arguments: <none>
  136. //
  137. // Returns: bool
  138. //
  139. // Purpose: Use the service control manager to query whether the service
  140. // is running.
  141. //
  142. // History: 2000-11-29 vtan created
  143. // --------------------------------------------------------------------------
  144. bool CServerAPI::IsRunning (void)
  145. {
  146. bool fRunning;
  147. SC_HANDLE hSCManager;
  148. fRunning = false;
  149. hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
  150. if (hSCManager != NULL)
  151. {
  152. SC_HANDLE hSCService;
  153. hSCService = OpenService(hSCManager, GetServiceName(), SERVICE_QUERY_STATUS);
  154. if (hSCService != NULL)
  155. {
  156. SERVICE_STATUS serviceStatus;
  157. if (QueryServiceStatus(hSCService, &serviceStatus) != FALSE)
  158. {
  159. fRunning = (serviceStatus.dwCurrentState == SERVICE_RUNNING);
  160. }
  161. TBOOL(CloseServiceHandle(hSCService));
  162. }
  163. TBOOL(CloseServiceHandle(hSCManager));
  164. }
  165. return(fRunning);
  166. }
  167. // --------------------------------------------------------------------------
  168. // CServerAPI::IsAutoStart
  169. //
  170. // Arguments: <none>
  171. //
  172. // Returns: bool
  173. //
  174. // Purpose: Use the service contorl manager to find out if the service
  175. // is configured to be an automatically started service.
  176. //
  177. // History: 2000-11-30 vtan created
  178. // --------------------------------------------------------------------------
  179. bool CServerAPI::IsAutoStart (void)
  180. {
  181. bool fAutoStart;
  182. SC_HANDLE hSCManager;
  183. fAutoStart = false;
  184. hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
  185. if (hSCManager != NULL)
  186. {
  187. SC_HANDLE hSCService;
  188. hSCService = OpenService(hSCManager, GetServiceName(), SERVICE_QUERY_CONFIG);
  189. if (hSCService != NULL)
  190. {
  191. DWORD dwBytesNeeded;
  192. QUERY_SERVICE_CONFIG *pServiceConfig;
  193. (BOOL)QueryServiceConfig(hSCService, NULL, 0, &dwBytesNeeded);
  194. pServiceConfig = static_cast<QUERY_SERVICE_CONFIG*>(LocalAlloc(LMEM_FIXED, dwBytesNeeded));
  195. if (pServiceConfig != NULL)
  196. {
  197. if (QueryServiceConfig(hSCService, pServiceConfig, dwBytesNeeded, &dwBytesNeeded) != FALSE)
  198. {
  199. fAutoStart = (pServiceConfig->dwStartType == SERVICE_AUTO_START);
  200. }
  201. (HLOCAL)LocalFree(pServiceConfig);
  202. }
  203. TBOOL(CloseServiceHandle(hSCService));
  204. }
  205. TBOOL(CloseServiceHandle(hSCManager));
  206. }
  207. return(fAutoStart);
  208. }
  209. // --------------------------------------------------------------------------
  210. // CServerAPI::Wait
  211. //
  212. // Arguments: <none>
  213. //
  214. // Returns: NTSTATUS
  215. //
  216. // Purpose: Waits for the service control manager to return the state that
  217. // the service is running. This does not check that the service
  218. // is auto start or not. You can only call this function if the
  219. // service is auto start or you demand started the service.
  220. // Otherwise the function will timeout.
  221. //
  222. // History: 2000-11-28 vtan created
  223. // --------------------------------------------------------------------------
  224. NTSTATUS CServerAPI::Wait (DWORD dwTimeout)
  225. {
  226. NTSTATUS status;
  227. SC_HANDLE hSCManager;
  228. hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
  229. if (hSCManager != NULL)
  230. {
  231. SC_HANDLE hSCService;
  232. hSCService = OpenService(hSCManager, GetServiceName(), SERVICE_QUERY_STATUS);
  233. if (hSCService != NULL)
  234. {
  235. SERVICE_STATUS serviceStatus;
  236. if (QueryServiceStatus(hSCService, &serviceStatus) != FALSE)
  237. {
  238. status = STATUS_SUCCESS;
  239. if (serviceStatus.dwCurrentState != SERVICE_RUNNING)
  240. {
  241. bool fTimedOut;
  242. DWORD dwTickStart;
  243. dwTickStart = GetTickCount();
  244. fTimedOut = ((GetTickCount() - dwTickStart) >= dwTimeout);
  245. while (NT_SUCCESS(status) &&
  246. !fTimedOut &&
  247. (serviceStatus.dwCurrentState != SERVICE_RUNNING) &&
  248. (serviceStatus.dwCurrentState != SERVICE_STOP_PENDING))
  249. {
  250. Sleep(50);
  251. if (QueryServiceStatus(hSCService, &serviceStatus) != FALSE)
  252. {
  253. fTimedOut = ((GetTickCount() - dwTickStart) >= dwTimeout);
  254. }
  255. else
  256. {
  257. status = CStatusCode::StatusCodeOfLastError();
  258. }
  259. }
  260. if (serviceStatus.dwCurrentState == SERVICE_RUNNING)
  261. {
  262. status = STATUS_SUCCESS;
  263. }
  264. else if (fTimedOut)
  265. {
  266. status = STATUS_TIMEOUT;
  267. }
  268. else
  269. {
  270. status = STATUS_UNSUCCESSFUL;
  271. }
  272. #ifdef DBG
  273. char sz[256];
  274. wsprintfA(sz, "Waited %d ticks for theme service", GetTickCount() - dwTickStart);
  275. INFORMATIONMSG(sz);
  276. #endif /* DBG */
  277. }
  278. }
  279. else
  280. {
  281. status = CStatusCode::StatusCodeOfLastError();
  282. }
  283. TBOOL(CloseServiceHandle(hSCService));
  284. }
  285. else
  286. {
  287. status = CStatusCode::StatusCodeOfLastError();
  288. }
  289. TBOOL(CloseServiceHandle(hSCManager));
  290. }
  291. else
  292. {
  293. status = CStatusCode::StatusCodeOfLastError();
  294. }
  295. return(status);
  296. }
  297. // --------------------------------------------------------------------------
  298. // CServerAPI::StaticInitialize
  299. //
  300. // Arguments: <none>
  301. //
  302. // Returns: NTSTATUS
  303. //
  304. // Purpose: Initializes static member variables for this class. Must be
  305. // called by subclasses of this class.
  306. //
  307. // History: 2000-10-13 vtan created
  308. // --------------------------------------------------------------------------
  309. NTSTATUS CServerAPI::StaticInitialize (void)
  310. {
  311. #ifdef DBG
  312. TSTATUS(CDebug::StaticInitialize());
  313. #endif
  314. return(STATUS_SUCCESS);
  315. }
  316. // --------------------------------------------------------------------------
  317. // CServerAPI::StaticTerminate
  318. //
  319. // Arguments: <none>
  320. //
  321. // Returns: NTSTATUS
  322. //
  323. // Purpose: Releases static resources used by this class.
  324. //
  325. // History: 2000-10-13 vtan created
  326. // --------------------------------------------------------------------------
  327. NTSTATUS CServerAPI::StaticTerminate (void)
  328. {
  329. #ifdef DBG
  330. TSTATUS(CDebug::StaticTerminate());
  331. #endif
  332. return(STATUS_SUCCESS);
  333. }
  334. // --------------------------------------------------------------------------
  335. // CServerAPI::IsClientTheSystem
  336. //
  337. // Arguments: portMessage = CPortMessage from the client.
  338. //
  339. // Returns: bool
  340. //
  341. // Purpose: Determines whether the client in the port message is the local
  342. // system account.
  343. //
  344. // History: 1999-12-13 vtan created
  345. // 2000-08-25 vtan moved from Neptune to Whistler
  346. // --------------------------------------------------------------------------
  347. bool CServerAPI::IsClientTheSystem (const CPortMessage& portMessage)
  348. {
  349. bool fResult;
  350. HANDLE hToken;
  351. if (NT_SUCCESS(portMessage.OpenClientToken(hToken)))
  352. {
  353. CTokenInformation tokenInformation(hToken);
  354. fResult = tokenInformation.IsUserTheSystem();
  355. ReleaseHandle(hToken);
  356. }
  357. else
  358. {
  359. fResult = false;
  360. }
  361. return(fResult);
  362. }
  363. // --------------------------------------------------------------------------
  364. // CServerAPI::IsClientAnAdministrator
  365. //
  366. // Arguments: portMessage = CPortMessage from the client.
  367. //
  368. // Returns: bool
  369. //
  370. // Purpose: Determines whether the client in the port message is an
  371. // administrator.
  372. //
  373. // History: 1999-11-07 vtan created
  374. // 2000-08-25 vtan moved from Neptune to Whistler
  375. // --------------------------------------------------------------------------
  376. bool CServerAPI::IsClientAnAdministrator (const CPortMessage& portMessage)
  377. {
  378. bool fResult;
  379. HANDLE hToken;
  380. if (NT_SUCCESS(portMessage.OpenClientToken(hToken)))
  381. {
  382. CTokenInformation tokenInformation(hToken);
  383. fResult = tokenInformation.IsUserAnAdministrator();
  384. ReleaseHandle(hToken);
  385. }
  386. else
  387. {
  388. fResult = false;
  389. }
  390. return(fResult);
  391. }