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.

404 lines
11 KiB

  1. /*
  2. File service.c
  3. Handles requests to deal with the remote access service as neccessary for
  4. the dialup-server ui.
  5. Paul Mayfield, 11/3/97
  6. */
  7. #include "rassrv.h"
  8. // Data used for the dialup server
  9. typedef struct _SERVICE_DATA {
  10. HANDLE hSC;
  11. HANDLE hService;
  12. SERVICE_STATUS Status;
  13. } SERVICE_DATA;
  14. // This is the string that holds the name of the remote access service
  15. static WCHAR pszRemoteAccess[] = L"remoteaccess";
  16. static WCHAR pszRasman[] = L"rasman";
  17. static WCHAR pszServer[] = L"lanmanserver";
  18. // Opens a named dialup service object
  19. //
  20. DWORD
  21. DialupOpenNamedService(
  22. IN WCHAR* pszService,
  23. OUT HANDLE * phDialup)
  24. {
  25. SERVICE_DATA * pServData;
  26. BOOL bOk = FALSE;
  27. DWORD dwErr = NO_ERROR;
  28. // Validate parameters
  29. if (!phDialup)
  30. {
  31. return ERROR_INVALID_PARAMETER;
  32. }
  33. // Create the data structure
  34. if ((pServData = RassrvAlloc(sizeof(SERVICE_DATA), TRUE)) == NULL)
  35. {
  36. return ERROR_NOT_ENOUGH_MEMORY;
  37. }
  38. do
  39. {
  40. // Open the service manager
  41. pServData->hSC = OpenSCManager(
  42. NULL,
  43. SERVICES_ACTIVE_DATABASE,
  44. GENERIC_EXECUTE);
  45. if (! pServData->hSC)
  46. {
  47. dwErr = GetLastError();
  48. break;
  49. }
  50. // Open the dialup service
  51. pServData->hService = OpenServiceW(
  52. pServData->hSC,
  53. pszService,
  54. SERVICE_START |
  55. SERVICE_STOP |
  56. SERVICE_CHANGE_CONFIG |
  57. SERVICE_QUERY_STATUS);
  58. if (! pServData->hService)
  59. {
  60. dwErr = GetLastError();
  61. break;
  62. }
  63. // Assign the handle
  64. *phDialup = (HANDLE)pServData;
  65. bOk = TRUE;
  66. } while (FALSE);
  67. // Cleanup
  68. {
  69. if (! bOk)
  70. {
  71. if (pServData->hService)
  72. {
  73. CloseServiceHandle(pServData->hService);
  74. }
  75. if (pServData->hSC)
  76. {
  77. CloseServiceHandle(pServData->hSC);
  78. }
  79. RassrvFree(pServData);
  80. *phDialup = NULL;
  81. }
  82. }
  83. return NO_ERROR;
  84. }
  85. // Opens a reference to the server service object
  86. DWORD SvcOpenServer(HANDLE * phDialup) {
  87. return DialupOpenNamedService(pszServer, phDialup);
  88. }
  89. // Opens a reference to the rasman service object
  90. DWORD SvcOpenRasman(HANDLE * phDialup) {
  91. return DialupOpenNamedService(pszRasman, phDialup);
  92. }
  93. // Creates/destroys instances of the dialup server service object
  94. DWORD SvcOpenRemoteAccess(HANDLE * phDialup) {
  95. return DialupOpenNamedService(pszRemoteAccess, phDialup);
  96. }
  97. // Close up the references to the dialup service object
  98. DWORD SvcClose(HANDLE hDialup) {
  99. SERVICE_DATA * pServData = (SERVICE_DATA *)hDialup;
  100. if (! pServData)
  101. return ERROR_INVALID_PARAMETER;
  102. if (pServData->hService)
  103. CloseServiceHandle(pServData->hService);
  104. if (pServData->hSC)
  105. CloseServiceHandle(pServData->hSC);
  106. RassrvFree(pServData);
  107. return NO_ERROR;
  108. }
  109. // Gets the status of a dialup server service object.
  110. DWORD SvcIsStarted (HANDLE hDialup, PBOOL pbStarted) {
  111. SERVICE_DATA * pServData = (SERVICE_DATA *)hDialup;
  112. BOOL bOk;
  113. // Verify parameters
  114. if (!pServData || !pbStarted)
  115. return ERROR_INVALID_PARAMETER;
  116. // Get the status
  117. bOk = QueryServiceStatus (pServData->hService, &pServData->Status);
  118. if (! bOk)
  119. return GetLastError();
  120. // Return the status
  121. *pbStarted = (BOOL)(pServData->Status.dwCurrentState == SERVICE_RUNNING);
  122. return NO_ERROR;
  123. }
  124. // Gets the status of a dialup server service object.
  125. DWORD SvcIsStopped (HANDLE hDialup, PBOOL pbStopped) {
  126. SERVICE_DATA * pServData = (SERVICE_DATA *)hDialup;
  127. BOOL bOk;
  128. // Verify parameters
  129. if (!pServData || !pbStopped)
  130. return ERROR_INVALID_PARAMETER;
  131. // Get the status
  132. bOk = QueryServiceStatus (pServData->hService, &pServData->Status);
  133. if (! bOk)
  134. return GetLastError();
  135. // Return the status
  136. *pbStopped = (BOOL)(pServData->Status.dwCurrentState == SERVICE_STOPPED);
  137. return NO_ERROR;
  138. }
  139. // Gets the status of a dialup server service object.
  140. DWORD SvcIsPaused (HANDLE hDialup, PBOOL pbPaused) {
  141. SERVICE_DATA * pServData = (SERVICE_DATA *)hDialup;
  142. BOOL bOk;
  143. // Verify parameters
  144. if (!pServData || !pbPaused)
  145. return ERROR_INVALID_PARAMETER;
  146. // Get the status
  147. bOk = QueryServiceStatus (pServData->hService, &pServData->Status);
  148. if (! bOk)
  149. return GetLastError();
  150. // Return the status
  151. *pbPaused = (BOOL)(pServData->Status.dwCurrentState == SERVICE_PAUSED);
  152. return NO_ERROR;
  153. }
  154. //
  155. // Returns whether the given state is a pending state
  156. //
  157. BOOL DialupIsPendingState (DWORD dwState) {
  158. return (BOOL) ((dwState == SERVICE_START_PENDING) ||
  159. (dwState == SERVICE_STOP_PENDING) ||
  160. (dwState == SERVICE_CONTINUE_PENDING) ||
  161. (dwState == SERVICE_PAUSE_PENDING)
  162. );
  163. }
  164. // Gets the status of a dialup server service object.
  165. DWORD SvcIsPending (HANDLE hDialup, PBOOL pbPending) {
  166. SERVICE_DATA * pServData = (SERVICE_DATA *)hDialup;
  167. BOOL bOk;
  168. // Verify parameters
  169. if (!pServData || !pbPending)
  170. return ERROR_INVALID_PARAMETER;
  171. // Get the status
  172. bOk = QueryServiceStatus (pServData->hService, &pServData->Status);
  173. if (! bOk)
  174. return GetLastError();
  175. // Return the status
  176. *pbPending = DialupIsPendingState (pServData->Status.dwCurrentState);
  177. return NO_ERROR;
  178. }
  179. // Start and stop the service. Both functions block until the service
  180. // completes startup/stop or until dwTimeout (in seconds) expires.
  181. DWORD SvcStart(HANDLE hDialup, DWORD dwTimeout) {
  182. SERVICE_DATA * pServData = (SERVICE_DATA *)hDialup;
  183. DWORD dwErr, dwState;
  184. BOOL bStarted, bOk;
  185. // See if we're already started
  186. if ((dwErr = SvcIsStarted(hDialup, &bStarted)) != NO_ERROR)
  187. return dwErr;
  188. if (bStarted)
  189. return NO_ERROR;
  190. // Put the service in a state that so that
  191. // it is trying to start. (continue if paused,
  192. // start if stopped)
  193. dwState = pServData->Status.dwCurrentState;
  194. switch (dwState) {
  195. case SERVICE_STOPPED:
  196. bOk = StartService(pServData->hService, 0, NULL);
  197. if (! bOk)
  198. return GetLastError();
  199. break;
  200. case SERVICE_PAUSED:
  201. bOk = ControlService(pServData->hService,
  202. SERVICE_CONTROL_CONTINUE,
  203. &(pServData->Status));
  204. if (! bOk)
  205. return GetLastError();
  206. break;
  207. }
  208. // Wait for the service to change states or for the timeout to
  209. // expire.
  210. while (dwTimeout != 0) {
  211. // Wait for something to happen
  212. Sleep(1000);
  213. dwTimeout--;
  214. // Get the status of the service
  215. bOk = QueryServiceStatus (pServData->hService,
  216. &(pServData->Status));
  217. if (! bOk)
  218. return GetLastError();
  219. // See if the state changed
  220. if (dwState != pServData->Status.dwCurrentState) {
  221. // If the service changed to a pending state, continue
  222. if (DialupIsPendingState (pServData->Status.dwCurrentState))
  223. dwState = pServData->Status.dwCurrentState;
  224. // Otherwise, we're either stopped or running
  225. else
  226. break;
  227. }
  228. }
  229. // Return a timeout error if appropriate
  230. if (dwTimeout == 0)
  231. return ERROR_TIMEOUT;
  232. // If the service is now running, then everything
  233. if (pServData->Status.dwCurrentState == SERVICE_RUNNING)
  234. return NO_ERROR;
  235. // Otherwise, return the fact that we were'nt able to
  236. // get to a running state
  237. if (pServData->Status.dwWin32ExitCode != NO_ERROR)
  238. return pServData->Status.dwWin32ExitCode;
  239. return ERROR_CAN_NOT_COMPLETE;
  240. }
  241. // Stops the service.
  242. DWORD SvcStop(HANDLE hDialup, DWORD dwTimeout) {
  243. SERVICE_DATA * pServData = (SERVICE_DATA *)hDialup;
  244. DWORD dwErr, dwState;
  245. BOOL bStopped, bOk;
  246. // See if we're already stopped
  247. if ((dwErr = SvcIsStopped(hDialup, &bStopped)) != NO_ERROR)
  248. return dwErr;
  249. if (bStopped)
  250. return NO_ERROR;
  251. // Stop the service
  252. dwState = pServData->Status.dwCurrentState;
  253. bOk = ControlService(pServData->hService, SERVICE_CONTROL_STOP, &pServData->Status);
  254. if (! bOk)
  255. return GetLastError();
  256. // Wait for the service to change states or for the timeout to
  257. // expire.
  258. while (dwTimeout != 0) {
  259. // Wait for something to happen
  260. Sleep(1000);
  261. dwTimeout--;
  262. // Get the status of the service
  263. bOk = QueryServiceStatus (pServData->hService,
  264. &(pServData->Status));
  265. if (! bOk)
  266. return GetLastError();
  267. // See if the state changed
  268. if (dwState != pServData->Status.dwCurrentState) {
  269. // If the service changed to a pending state, continue
  270. if (DialupIsPendingState (pServData->Status.dwCurrentState))
  271. dwState = pServData->Status.dwCurrentState;
  272. // Otherwise, we're either stopped or running
  273. else
  274. break;
  275. }
  276. }
  277. // Report a timeout
  278. if (dwTimeout == 0)
  279. return ERROR_TIMEOUT;
  280. // If the service is now stopped, then everything is great
  281. if (pServData->Status.dwCurrentState == SERVICE_STOPPED)
  282. return NO_ERROR;
  283. // Otherwise report that we're unable to stop the service
  284. return ERROR_CAN_NOT_COMPLETE;
  285. }
  286. // Marks the dialup service as autostart
  287. DWORD SvcMarkAutoStart(HANDLE hDialup) {
  288. SERVICE_DATA * pServData = (SERVICE_DATA *)hDialup;
  289. BOOL bOk;
  290. // Validate the parameters
  291. if (! pServData)
  292. return ERROR_INVALID_PARAMETER;
  293. // Stop the service
  294. bOk = ChangeServiceConfig(pServData->hService,
  295. SERVICE_NO_CHANGE,
  296. SERVICE_AUTO_START,
  297. SERVICE_NO_CHANGE,
  298. NULL,
  299. NULL,
  300. NULL,
  301. NULL,
  302. NULL,
  303. NULL,
  304. NULL);
  305. if (! bOk)
  306. return GetLastError();
  307. return NO_ERROR;
  308. }
  309. // Marks the service as disabled.
  310. DWORD SvcMarkDisabled(HANDLE hDialup) {
  311. SERVICE_DATA * pServData = (SERVICE_DATA *)hDialup;
  312. BOOL bOk;
  313. // Validate the parameters
  314. if (! pServData)
  315. return ERROR_INVALID_PARAMETER;
  316. // Stop the service
  317. bOk = ChangeServiceConfig(pServData->hService,
  318. SERVICE_NO_CHANGE,
  319. SERVICE_DISABLED,
  320. SERVICE_NO_CHANGE,
  321. NULL,
  322. NULL,
  323. NULL,
  324. NULL,
  325. NULL,
  326. NULL,
  327. NULL);
  328. if (! bOk)
  329. return GetLastError();
  330. return NO_ERROR;
  331. }