[NTDLL]
[reactos.git] / base / applications / mscutils / servman / start.c
1 /*
2 * PROJECT: ReactOS Services
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: base/applications/mscutils/servman/start.c
5 * PURPOSE: Start a service
6 * COPYRIGHT: Copyright 2005-2010 Ged Murphy <gedmurphy@reactos.org>
7 *
8 */
9
10 #include "precomp.h"
11
12 static BOOL
13 DoStartService(PMAIN_WND_INFO Info,
14 HWND hProgress)
15 {
16 SC_HANDLE hSCManager;
17 SC_HANDLE hService;
18 SERVICE_STATUS_PROCESS ServiceStatus;
19 DWORD BytesNeeded = 0;
20 DWORD dwStartTickCount;
21 DWORD dwOldCheckPoint;
22 DWORD dwWaitTime;
23 DWORD dwMaxWait;
24 BOOL bRet = FALSE;
25
26 hSCManager = OpenSCManager(NULL,
27 NULL,
28 SC_MANAGER_CONNECT);
29 if (hSCManager)
30 {
31 hService = OpenService(hSCManager,
32 Info->pCurrentService->lpServiceName,
33 SERVICE_START | SERVICE_QUERY_STATUS);
34 if (hService)
35 {
36 if (hProgress)
37 {
38 /* Increment the progress bar */
39 IncrementProgressBar(hProgress, DEFAULT_STEP);
40 }
41
42 /* Start the service */
43 bRet = StartService(hService,
44 0,
45 NULL);
46 if (!bRet && GetLastError() == ERROR_SERVICE_ALREADY_RUNNING)
47 {
48 /* If it's already running, just return TRUE */
49 bRet = TRUE;
50 }
51 else if (bRet)
52 {
53 bRet = FALSE;
54
55 /* Get the service status to check if it's running */
56 if (QueryServiceStatusEx(hService,
57 SC_STATUS_PROCESS_INFO,
58 (LPBYTE)&ServiceStatus,
59 sizeof(SERVICE_STATUS_PROCESS),
60 &BytesNeeded))
61 {
62 /* We don't want to wait for more than 30 seconds */
63 dwMaxWait = 30000;
64 dwStartTickCount = GetTickCount();
65
66 /* Loop until it's running */
67 while (ServiceStatus.dwCurrentState != SERVICE_RUNNING)
68 {
69 dwOldCheckPoint = ServiceStatus.dwCheckPoint;
70 dwWaitTime = ServiceStatus.dwWaitHint / 10;
71
72 /* Get the latest status info */
73 if (!QueryServiceStatusEx(hService,
74 SC_STATUS_PROCESS_INFO,
75 (LPBYTE)&ServiceStatus,
76 sizeof(SERVICE_STATUS_PROCESS),
77 &BytesNeeded))
78 {
79 /* Something went wrong... */
80 break;
81 }
82
83 /* Is the service making progress? */
84 if (ServiceStatus.dwCheckPoint > dwOldCheckPoint)
85 {
86 /* It is, get the latest tickcount to reset the max wait time */
87 dwStartTickCount = GetTickCount();
88 dwOldCheckPoint = ServiceStatus.dwCheckPoint;
89 IncrementProgressBar(hProgress, DEFAULT_STEP);
90 }
91 else
92 {
93 /* It's not, make sure we haven't exceeded our wait time */
94 if (GetTickCount() >= dwStartTickCount + dwMaxWait)
95 {
96 /* We have, give up */
97 break;
98 }
99 }
100
101 /* Adjust the wait hint times */
102 if (dwWaitTime < 200)
103 dwWaitTime = 200;
104 else if (dwWaitTime > 10000)
105 dwWaitTime = 10000;
106
107 /* Wait before trying again */
108 Sleep(dwWaitTime);
109 }
110 }
111
112 if (ServiceStatus.dwCurrentState == SERVICE_RUNNING)
113 {
114 bRet = TRUE;
115 }
116 }
117
118 CloseServiceHandle(hService);
119 }
120
121 CloseServiceHandle(hSCManager);
122 }
123
124 return bRet;
125 }
126
127 BOOL
128 DoStart(PMAIN_WND_INFO Info)
129 {
130 HWND hProgress;
131 BOOL bRet = FALSE;
132
133 /* Create a progress window to track the progress of the stopping service */
134 hProgress = CreateProgressDialog(Info->hMainWnd,
135 IDS_PROGRESS_INFO_START);
136 if (hProgress)
137 {
138 /* Set the service name and reset the progress bag */
139 InitializeProgressDialog(hProgress, Info->pCurrentService->lpServiceName);
140
141 /* Start the requested service */
142 bRet = DoStartService(Info, hProgress);
143
144 /* Complete and destroy the progress bar */
145 DestroyProgressDialog(hProgress, bRet);
146 }
147
148 return bRet;
149 }
150