[MSCONFIG]
[reactos.git] / reactos / base / applications / msconfig / srvpage.c
1 /*
2 * PROJECT: ReactOS Applications
3 * LICENSE: LGPL - See COPYING in the top level directory
4 * FILE: base/applications/srvpage.c
5 * PURPOSE: Services page message handler
6 * COPYRIGHT: Copyright 2005-2006 Christoph von Wittich <Christoph@ApiViewer.de>
7 *
8 */
9
10 #include "precomp.h"
11
12 #include <winsvc.h>
13 #include <winver.h>
14
15 HWND hServicesPage;
16 HWND hServicesListCtrl;
17 HWND hServicesDialog;
18
19 void GetServices ( void );
20
21 INT_PTR CALLBACK
22 ServicesPageWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
23 {
24 LV_COLUMN column;
25 TCHAR szTemp[256];
26 DWORD dwStyle;
27
28 UNREFERENCED_PARAMETER(lParam);
29 UNREFERENCED_PARAMETER(wParam);
30
31 switch (message) {
32 case WM_INITDIALOG:
33
34 hServicesListCtrl = GetDlgItem(hDlg, IDC_SERVICES_LIST);
35 hServicesDialog = hDlg;
36
37 dwStyle = (DWORD) SendMessage(hServicesListCtrl, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
38 dwStyle = dwStyle | LVS_EX_FULLROWSELECT | LVS_EX_CHECKBOXES;
39 SendMessage(hServicesListCtrl, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, dwStyle);
40
41 SetWindowPos(hDlg, NULL, 10, 32, 0, 0, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSIZE | SWP_NOZORDER);
42
43 // Initialize the application page's controls
44 column.mask = LVCF_TEXT | LVCF_WIDTH;
45
46 LoadString(hInst, IDS_SERVICES_COLUMN_SERVICE, szTemp, 256);
47 column.pszText = szTemp;
48 column.cx = 200;
49 (void)ListView_InsertColumn(hServicesListCtrl, 0, &column);
50
51 column.mask = LVCF_TEXT | LVCF_WIDTH;
52 LoadString(hInst, IDS_SERVICES_COLUMN_REQ, szTemp, 256);
53 column.pszText = szTemp;
54 column.cx = 70;
55 (void)ListView_InsertColumn(hServicesListCtrl, 1, &column);
56
57 column.mask = LVCF_TEXT | LVCF_WIDTH;
58 LoadString(hInst, IDS_SERVICES_COLUMN_VENDOR, szTemp, 256);
59 column.pszText = szTemp;
60 column.cx = 200;
61 (void)ListView_InsertColumn(hServicesListCtrl, 2, &column);
62
63 column.mask = LVCF_TEXT | LVCF_WIDTH;
64 LoadString(hInst, IDS_SERVICES_COLUMN_STATUS, szTemp, 256);
65 column.pszText = szTemp;
66 column.cx = 70;
67 (void)ListView_InsertColumn(hServicesListCtrl, 3, &column);
68
69 GetServices();
70 return TRUE;
71 }
72
73 return 0;
74 }
75
76 void
77 GetServices ( void )
78 {
79 LV_ITEM item;
80 WORD wCodePage;
81 WORD wLangID;
82 SC_HANDLE ScHandle;
83 SC_HANDLE hService;
84 DWORD BytesNeeded = 0;
85 DWORD ResumeHandle = 0;
86 DWORD NumServices = 0;
87 DWORD dwHandle, dwLen;
88 size_t Index;
89 UINT BufLen;
90 TCHAR szStatus[128];
91 TCHAR* lpData;
92 TCHAR* lpBuffer;
93 TCHAR szStrFileInfo[80];
94 TCHAR FileName[MAX_PATH];
95 LPVOID pvData;
96
97 LPSERVICE_FAILURE_ACTIONS pServiceFailureActions = NULL;
98 LPQUERY_SERVICE_CONFIG pServiceConfig = NULL;
99 ENUM_SERVICE_STATUS_PROCESS *pServiceStatus = NULL;
100
101 ScHandle = OpenSCManager(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
102 if (ScHandle != NULL)
103 {
104 if (EnumServicesStatusEx(ScHandle, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, SERVICE_STATE_ALL, (LPBYTE)pServiceStatus, 0, &BytesNeeded, &NumServices, &ResumeHandle, 0) == 0)
105 {
106 /* Call function again if required size was returned */
107 if (GetLastError() == ERROR_MORE_DATA)
108 {
109 /* reserve memory for service info array */
110 pServiceStatus = HeapAlloc(GetProcessHeap(), 0, BytesNeeded);
111 if (!pServiceStatus)
112 {
113 CloseServiceHandle(ScHandle);
114 return;
115 }
116
117 /* fill array with service info */
118 if (EnumServicesStatusEx(ScHandle, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, SERVICE_STATE_ALL, (LPBYTE)pServiceStatus, BytesNeeded, &BytesNeeded, &NumServices, &ResumeHandle, 0) == 0)
119 {
120 HeapFree(GetProcessHeap(), 0, pServiceStatus);
121 CloseServiceHandle(ScHandle);
122 return;
123 }
124 }
125 else /* exit on failure */
126 {
127 CloseServiceHandle(ScHandle);
128 return;
129 }
130 }
131
132 if (NumServices)
133 {
134 if (!pServiceStatus)
135 {
136 CloseServiceHandle(ScHandle);
137 return;
138 }
139
140 for (Index = 0; Index < NumServices; Index++)
141 {
142 memset(&item, 0, sizeof(LV_ITEM));
143 item.mask = LVIF_TEXT;
144 item.iImage = 0;
145 item.pszText = pServiceStatus[Index].lpDisplayName;
146 item.iItem = ListView_GetItemCount(hServicesListCtrl);
147 item.lParam = 0;
148 item.iItem = ListView_InsertItem(hServicesListCtrl, &item);
149
150 if (pServiceStatus[Index].ServiceStatusProcess.dwCurrentState == SERVICE_RUNNING)
151 {
152 ListView_SetCheckState(hServicesListCtrl, item.iItem, TRUE);
153 }
154
155 BytesNeeded = 0;
156 hService = OpenService(ScHandle, pServiceStatus[Index].lpServiceName, SC_MANAGER_CONNECT);
157 if (hService != NULL)
158 {
159 /* check if service is required by the system*/
160 if (!QueryServiceConfig2(hService, SERVICE_CONFIG_FAILURE_ACTIONS, (LPBYTE)NULL, 0, &BytesNeeded))
161 {
162 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
163 {
164 pServiceFailureActions = HeapAlloc(GetProcessHeap(), 0, BytesNeeded);
165 if (pServiceFailureActions == NULL)
166 {
167 HeapFree(GetProcessHeap(), 0, pServiceStatus);
168 CloseServiceHandle(hService);
169 CloseServiceHandle(ScHandle);
170 return;
171 }
172
173 if (!QueryServiceConfig2(hService, SERVICE_CONFIG_FAILURE_ACTIONS, (LPBYTE)pServiceFailureActions, BytesNeeded, &BytesNeeded))
174 {
175 HeapFree(GetProcessHeap(), 0, pServiceFailureActions);
176 HeapFree(GetProcessHeap(), 0, pServiceStatus);
177 CloseServiceHandle(hService);
178 CloseServiceHandle(ScHandle);
179 return;
180 }
181 }
182 else /* exit on failure */
183 {
184 HeapFree(GetProcessHeap(), 0, pServiceStatus);
185 CloseServiceHandle(hService);
186 CloseServiceHandle(ScHandle);
187 return;
188 }
189 }
190 if (pServiceFailureActions->cActions)
191 {
192 if (pServiceFailureActions->lpsaActions[0].Type == SC_ACTION_REBOOT)
193 {
194 LoadString(hInst, IDS_SERVICES_YES, szStatus, 128);
195 item.pszText = szStatus;
196 item.iSubItem = 1;
197 SendMessage(hServicesListCtrl, LVM_SETITEMTEXT, item.iItem, (LPARAM) &item);
198 }
199 }
200
201 if (pServiceFailureActions != NULL)
202 {
203 HeapFree(GetProcessHeap(), 0, pServiceFailureActions);
204 pServiceFailureActions = NULL;
205 }
206
207 /* get vendor of service binary */
208 BytesNeeded = 0;
209 if (!QueryServiceConfig(hService, NULL, 0, &BytesNeeded))
210 {
211 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
212 {
213 pServiceConfig = HeapAlloc(GetProcessHeap(), 0, BytesNeeded);
214 if (pServiceConfig == NULL)
215 {
216 HeapFree(GetProcessHeap(), 0, pServiceStatus);
217 CloseServiceHandle(hService);
218 CloseServiceHandle(ScHandle);
219 return;
220 }
221 if (!QueryServiceConfig(hService, pServiceConfig, BytesNeeded, &BytesNeeded))
222 {
223 HeapFree(GetProcessHeap(), 0, pServiceConfig);
224 HeapFree(GetProcessHeap(), 0, pServiceStatus);
225 CloseServiceHandle(hService);
226 CloseServiceHandle(ScHandle);
227 return;
228 }
229 }
230 else /* exit on failure */
231 {
232 HeapFree(GetProcessHeap(), 0, pServiceStatus);
233 CloseServiceHandle(hService);
234 CloseServiceHandle(ScHandle);
235 return;
236 }
237 }
238
239 memset(&FileName, 0, MAX_PATH);
240 if (_tcscspn(pServiceConfig->lpBinaryPathName, _T("\"")))
241 {
242 _tcsncpy(FileName, pServiceConfig->lpBinaryPathName, _tcscspn(pServiceConfig->lpBinaryPathName, _T(" ")) );
243 }
244 else
245 {
246 _tcscpy(FileName, pServiceConfig->lpBinaryPathName);
247 }
248
249 HeapFree(GetProcessHeap(), 0, pServiceConfig);
250 pServiceConfig = NULL;
251
252 dwLen = GetFileVersionInfoSize(FileName, &dwHandle);
253 if (dwLen)
254 {
255 lpData = HeapAlloc(GetProcessHeap(), 0, dwLen);
256 if (lpData == NULL)
257 {
258 HeapFree(GetProcessHeap(), 0, pServiceStatus);
259 CloseServiceHandle(hService);
260 CloseServiceHandle(ScHandle);
261 return;
262 }
263 if (!GetFileVersionInfo (FileName, dwHandle, dwLen, lpData))
264 {
265 HeapFree(GetProcessHeap(), 0, lpData);
266 HeapFree(GetProcessHeap(), 0, pServiceStatus);
267 CloseServiceHandle(hService);
268 CloseServiceHandle(ScHandle);
269 return;
270 }
271
272 if (VerQueryValue(lpData, _T("\\VarFileInfo\\Translation"), &pvData, (PUINT) &BufLen))
273 {
274 wCodePage = LOWORD(*(DWORD*) pvData);
275 wLangID = HIWORD(*(DWORD*) pvData);
276 wsprintf(szStrFileInfo, _T("StringFileInfo\\%04X%04X\\CompanyName"), wCodePage, wLangID);
277 }
278
279 if (VerQueryValue (lpData, szStrFileInfo, (void**) &lpBuffer, (PUINT) &BufLen))
280 {
281 item.pszText = lpBuffer;
282 item.iSubItem = 2;
283 SendMessage(hServicesListCtrl, LVM_SETITEMTEXT, item.iItem, (LPARAM) &item);
284 }
285 HeapFree(GetProcessHeap(), 0, lpData);
286 }
287 else
288 {
289 LoadString(hInst, IDS_SERVICES_UNKNOWN, szStatus, 128);
290 item.pszText = szStatus;
291 item.iSubItem = 2;
292 SendMessage(hServicesListCtrl, LVM_SETITEMTEXT, item.iItem, (LPARAM) &item);
293 }
294 CloseServiceHandle(hService);
295 }
296
297 LoadString(hInst, ((pServiceStatus[Index].ServiceStatusProcess.dwCurrentState == SERVICE_STOPPED) ? IDS_SERVICES_STATUS_STOPPED : IDS_SERVICES_STATUS_RUNNING), szStatus, 128);
298 item.pszText = szStatus;
299 item.iSubItem = 3;
300 SendMessage(hServicesListCtrl, LVM_SETITEMTEXT, item.iItem, (LPARAM) &item);
301
302 }
303 }
304
305 HeapFree(GetProcessHeap(), 0, pServiceStatus);
306 CloseServiceHandle(ScHandle);
307 }
308
309 }