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