Fix a buffer overflow. Thanks to Christoph for spotting this.
[reactos.git] / reactos / subsys / system / servman / query.c
1 /*
2 * PROJECT: ReactOS Services
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: subsys/system/servman/query.c
5 * PURPOSE: Query service information
6 * COPYRIGHT: Copyright 2005 Ged Murphy <gedmurphy@gmail.com>
7 *
8 */
9
10 #include "servman.h"
11
12 extern HINSTANCE hInstance;
13 extern HWND hListView;
14 extern HWND hStatus;
15
16 /* Stores the service array */
17 ENUM_SERVICE_STATUS_PROCESS *pServiceStatus = NULL;
18
19
20 /* free service array */
21 VOID FreeMemory(VOID)
22 {
23 HeapFree(GetProcessHeap(), 0, pServiceStatus);
24 }
25
26
27 BOOL
28 RefreshServiceList(VOID)
29 {
30 LVITEM item;
31 TCHAR szNumServices[32];
32 TCHAR szStatus[128];
33 DWORD NumServices = 0;
34 DWORD Index;
35
36 NumServices = GetServiceList();
37
38 if (NumServices)
39 {
40 HICON hiconItem; /* icon for list-view items */
41 HIMAGELIST hSmall; /* image list for other views */
42 TCHAR buf[256];
43
44 /* Create the icon image lists */
45 hSmall = ImageList_Create(GetSystemMetrics(SM_CXSMICON),
46 GetSystemMetrics(SM_CYSMICON), ILC_MASK, 1, 1);
47
48 /* Add an icon to each image list */
49 hiconItem = LoadImage(hInstance, MAKEINTRESOURCE(IDI_SM_ICON), IMAGE_ICON, 16, 16, 0);
50 ImageList_AddIcon(hSmall, hiconItem);
51
52 ListView_SetImageList(hListView, hSmall, LVSIL_SMALL);
53
54 /* set the number of services in the status bar */
55 LoadString(hInstance, IDS_SERVICES_NUM_SERVICES, szNumServices, 32);
56 _stprintf(buf, szNumServices, NumServices);
57 SendMessage(hStatus, SB_SETTEXT, 0, (LPARAM)buf);
58
59
60 for (Index = 0; Index < NumServices; Index++)
61 {
62 HKEY hKey = NULL;
63 LPTSTR Description = NULL;
64 LONG ret;
65 LPTSTR LogOnAs = NULL;
66 DWORD StartUp = 0;
67 DWORD dwValueSize;
68
69 /* open the registry key for the service */
70 _stprintf(buf, _T("System\\CurrentControlSet\\Services\\%s"),
71 pServiceStatus[Index].lpServiceName);
72
73 if( RegOpenKeyEx(HKEY_LOCAL_MACHINE,
74 buf,
75 0,
76 KEY_READ,
77 &hKey) != ERROR_SUCCESS)
78 {
79 GetError();
80 return FALSE;
81 }
82
83
84 /* set the display name */
85
86 ZeroMemory(&item, sizeof(LV_ITEM));
87 item.mask = LVIF_TEXT;
88 item.pszText = pServiceStatus[Index].lpDisplayName;
89 item.iItem = ListView_GetItemCount(hListView);
90 item.iItem = ListView_InsertItem(hListView, &item);
91
92
93
94 /* set the description */
95 dwValueSize = 0;
96 ret = RegQueryValueEx(hKey,
97 _T("Description"),
98 NULL,
99 NULL,
100 NULL,
101 &dwValueSize);
102 if (ret != ERROR_SUCCESS && ret != ERROR_FILE_NOT_FOUND)
103 {
104 RegCloseKey(hKey);
105 return FALSE;
106 }
107
108 if (ret != ERROR_FILE_NOT_FOUND)
109 {
110 Description = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwValueSize);
111 if (Description == NULL)
112 {
113 RegCloseKey(hKey);
114 return FALSE;
115 }
116 if(RegQueryValueEx(hKey,
117 _T("Description"),
118 NULL,
119 NULL,
120 (LPBYTE)Description,
121 &dwValueSize))
122 {
123 HeapFree(GetProcessHeap(), 0, Description);
124 RegCloseKey(hKey);
125 return FALSE;
126 }
127
128 item.pszText = Description;
129 item.iSubItem = 1;
130 SendMessage(hListView, LVM_SETITEMTEXT, item.iItem, (LPARAM) &item);
131
132 HeapFree(GetProcessHeap(), 0, Description);
133 }
134 else
135 {
136 item.pszText = '\0';
137 item.iSubItem = 1;
138 SendMessage(hListView, LVM_SETITEMTEXT, item.iItem, (LPARAM) &item);
139 }
140
141
142 /* set the status */
143
144 if (pServiceStatus[Index].ServiceStatusProcess.dwCurrentState == SERVICE_RUNNING)
145 {
146 LoadString(hInstance, IDS_SERVICES_STATUS_RUNNING, szStatus, 128);
147 item.pszText = szStatus;
148 item.iSubItem = 2;
149 SendMessage(hListView, LVM_SETITEMTEXT, item.iItem, (LPARAM) &item);
150 }
151 else
152 {
153 item.pszText = '\0';
154 item.iSubItem = 2;
155 SendMessage(hListView, LVM_SETITEMTEXT, item.iItem, (LPARAM) &item);
156 }
157
158 /* set the startup type */
159
160 dwValueSize = sizeof(DWORD);
161 if (RegQueryValueEx(hKey,
162 _T("Start"),
163 NULL,
164 NULL,
165 (LPBYTE)&StartUp,
166 &dwValueSize))
167 {
168 RegCloseKey(hKey);
169 return FALSE;
170 }
171
172 if (StartUp == 0x02)
173 {
174 LoadString(hInstance, IDS_SERVICES_AUTO, szStatus, 128);
175 item.pszText = szStatus;
176 item.iSubItem = 3;
177 SendMessage(hListView, LVM_SETITEMTEXT, item.iItem, (LPARAM) &item);
178 }
179 else if (StartUp == 0x03)
180 {
181 LoadString(hInstance, IDS_SERVICES_MAN, szStatus, 128);
182 item.pszText = szStatus;
183 item.iSubItem = 3;
184 SendMessage(hListView, LVM_SETITEMTEXT, item.iItem, (LPARAM) &item);
185 }
186 else if (StartUp == 0x04)
187 {
188 LoadString(hInstance, IDS_SERVICES_DIS, szStatus, 128);
189 item.pszText = szStatus;
190 item.iSubItem = 3;
191 SendMessage(hListView, LVM_SETITEMTEXT, item.iItem, (LPARAM) &item);
192 }
193
194
195
196 /* set Log On As */
197
198 dwValueSize = 0;
199 if (RegQueryValueEx(hKey,
200 _T("ObjectName"),
201 NULL,
202 NULL,
203 NULL,
204 &dwValueSize))
205 {
206 RegCloseKey(hKey);
207 return FALSE;
208 }
209
210 LogOnAs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwValueSize);
211 if (LogOnAs == NULL)
212 {
213 RegCloseKey(hKey);
214 return FALSE;
215 }
216 if(RegQueryValueEx(hKey,
217 _T("ObjectName"),
218 NULL,
219 NULL,
220 (LPBYTE)LogOnAs,
221 &dwValueSize))
222 {
223 HeapFree(GetProcessHeap(), 0, LogOnAs);
224 RegCloseKey(hKey);
225 return FALSE;
226 }
227
228 item.pszText = LogOnAs;
229 item.iSubItem = 4;
230 SendMessage(hListView, LVM_SETITEMTEXT, item.iItem, (LPARAM) &item);
231
232 HeapFree(GetProcessHeap(), 0, LogOnAs);
233
234 RegCloseKey(hKey);
235
236 }
237 }
238
239 return TRUE;
240 }
241
242
243
244
245 DWORD
246 GetServiceList(VOID)
247 {
248 SC_HANDLE ScHandle;
249
250 DWORD BytesNeeded = 0;
251 DWORD ResumeHandle = 0;
252 DWORD NumServices = 0;
253
254 ScHandle = OpenSCManager(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
255 if (ScHandle != INVALID_HANDLE_VALUE)
256 {
257 if (EnumServicesStatusEx(ScHandle,
258 SC_ENUM_PROCESS_INFO,
259 SERVICE_WIN32,
260 SERVICE_STATE_ALL,
261 (LPBYTE)pServiceStatus,
262 0, &BytesNeeded,
263 &NumServices,
264 &ResumeHandle,
265 0) == 0)
266 {
267 /* Call function again if required size was returned */
268 if (GetLastError() == ERROR_MORE_DATA)
269 {
270 /* reserve memory for service info array */
271 pServiceStatus = (ENUM_SERVICE_STATUS_PROCESS *) HeapAlloc(GetProcessHeap(), 0, BytesNeeded);
272 if (pServiceStatus == NULL)
273 return FALSE;
274
275 /* fill array with service info */
276 if (EnumServicesStatusEx(ScHandle,
277 SC_ENUM_PROCESS_INFO,
278 SERVICE_WIN32,
279 SERVICE_STATE_ALL,
280 (LPBYTE)pServiceStatus,
281 BytesNeeded,
282 &BytesNeeded,
283 &NumServices,
284 &ResumeHandle,
285 0) == 0)
286 {
287 HeapFree(GetProcessHeap(), 0, pServiceStatus);
288 return FALSE;
289 }
290 }
291 else /* exit on failure */
292 {
293 return FALSE;
294 }
295 }
296 }
297
298 CloseServiceHandle(ScHandle);
299
300 return NumServices;
301 }
302
303
304
305
306
307
308
309
310
311
312
313 /*
314 //WORD wCodePage;
315 //WORD wLangID;
316 //SC_HANDLE hService;
317 //DWORD dwHandle, dwLen;
318 //UINT BufLen;
319 //TCHAR* lpData;
320 //TCHAR* lpBuffer;
321 //TCHAR szStrFileInfo[80];
322 //TCHAR FileName[MAX_PATH];
323 //LPVOID pvData;
324
325 //LPSERVICE_FAILURE_ACTIONS pServiceFailureActions = NULL;
326 //LPQUERY_SERVICE_CONFIG pServiceConfig = NULL;
327
328 BytesNeeded = 0;
329 hService = OpenService(ScHandle,
330 pServiceStatus[Index].lpServiceName,
331 SC_MANAGER_CONNECT);
332 if (hService != INVALID_HANDLE_VALUE)
333 {
334 / * check if service is required by the system* /
335 if (!QueryServiceConfig2(hService,
336 SERVICE_CONFIG_FAILURE_ACTIONS,
337 (LPBYTE)pServiceFailureActions,
338 0,
339 &BytesNeeded))
340 {
341 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
342 {
343 pServiceFailureActions = (LPSERVICE_FAILURE_ACTIONS)
344 HeapAlloc(GetProcessHeap(), 0, BytesNeeded);
345 if (pServiceFailureActions == NULL)
346 return FALSE;
347
348 if (!QueryServiceConfig2(hService,
349 SERVICE_CONFIG_FAILURE_ACTIONS,
350 (LPBYTE)pServiceFailureActions,
351 BytesNeeded,
352 &BytesNeeded))
353 {
354 HeapFree(GetProcessHeap(), 0, pServiceFailureActions);
355 return FALSE;
356 }
357 }
358 else / * exit on failure * /
359 {
360 return FALSE;
361 }
362 }
363 if (pServiceFailureActions->cActions)
364 {
365 if (pServiceFailureActions->lpsaActions[0].Type == SC_ACTION_REBOOT)
366 {
367 LoadString(hInstance, IDS_SERVICES_YES, szStatus, 128);
368 item.pszText = szStatus;
369 item.iSubItem = 1;
370 SendMessage(hListView, LVM_SETITEMTEXT, item.iItem, (LPARAM) &item);
371 }
372 }
373
374 if (pServiceFailureActions != NULL)
375 {
376 HeapFree(GetProcessHeap(), 0, pServiceFailureActions);
377 pServiceFailureActions = NULL;
378 }
379
380 / * get vendor of service binary * /
381 BytesNeeded = 0;
382 if (!QueryServiceConfig(hService, pServiceConfig, 0, &BytesNeeded))
383 {
384 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
385 {
386 pServiceConfig = (LPQUERY_SERVICE_CONFIG)
387 HeapAlloc(GetProcessHeap(), 0, BytesNeeded);
388 if (pServiceConfig == NULL)
389 return FALSE;
390
391 if (!QueryServiceConfig(hService,
392 pServiceConfig,
393 BytesNeeded,
394 &BytesNeeded))
395 {
396 HeapFree(GetProcessHeap(), 0, pServiceConfig);
397 return FALSE;
398 }
399 }
400 else / * exit on failure * /
401 {
402 return FALSE;
403 }
404 }
405
406 memset(&FileName, 0, MAX_PATH);
407 if (_tcscspn(pServiceConfig->lpBinaryPathName, _T("\"")))
408 {
409 _tcsncpy(FileName, pServiceConfig->lpBinaryPathName,
410 _tcscspn(pServiceConfig->lpBinaryPathName, _T(" ")) );
411 }
412 else
413 {
414 _tcscpy(FileName, pServiceConfig->lpBinaryPathName);
415 }
416
417 HeapFree(GetProcessHeap(), 0, pServiceConfig);
418 pServiceConfig = NULL;
419
420 dwLen = GetFileVersionInfoSize(FileName, &dwHandle);
421 if (dwLen)
422 {
423 lpData = (TCHAR*) HeapAlloc(GetProcessHeap(), 0, dwLen);
424 if (lpData == NULL)
425 return FALSE;
426
427 if (!GetFileVersionInfo (FileName, dwHandle, dwLen, lpData)) {
428 HeapFree(GetProcessHeap(), 0, lpData);
429 return FALSE;
430 }
431
432 if (VerQueryValue(lpData, _T("\\VarFileInfo\\Translation"), &pvData, (PUINT) &BufLen))
433 {
434 wCodePage = LOWORD(*(DWORD*) pvData);
435 wLangID = HIWORD(*(DWORD*) pvData);
436 wsprintf(szStrFileInfo, _T("StringFileInfo\\%04X%04X\\CompanyName"), wCodePage, wLangID);
437 }
438
439 if (VerQueryValue (lpData, szStrFileInfo, (LPVOID) &lpBuffer, (PUINT) &BufLen)) {
440 item.pszText = lpBuffer;
441 item.iSubItem = 2;
442 SendMessage(hListView, LVM_SETITEMTEXT, item.iItem, (LPARAM) &item);
443 }
444 HeapFree(GetProcessHeap(), 0, lpData);
445 }
446 else
447 {
448 LoadString(hInstance, IDS_SERVICES_UNKNOWN, szStatus, 128);
449 item.pszText = szStatus;
450 item.iSubItem = 2;
451 SendMessage(hListView, LVM_SETITEMTEXT, item.iItem, (LPARAM) &item);
452 }
453 CloseServiceHandle(hService);
454 }
455 */