Leaked source code of windows server 2003
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.

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