1 /* 2 * PROJECT: ReactOS Services 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: base/applications/sc/query.c 5 * PURPOSE: queries service info 6 * COPYRIGHT: Copyright 2005 - 2006 Ged Murphy <gedmurphy@gmail.com> 7 * Copyright 2018 Eric Kohl <eric.kohl@reactos.org> 8 */ 9 10 #include "sc.h" 11 12 LPSERVICE_STATUS_PROCESS 13 QueryService(LPCTSTR ServiceName) 14 { 15 SC_HANDLE hSCManager = NULL; 16 LPSERVICE_STATUS_PROCESS pServiceInfo = NULL; 17 SC_HANDLE hSc = NULL; 18 DWORD BufSiz = 0; 19 DWORD BytesNeeded = 0; 20 DWORD Ret; 21 22 hSCManager = OpenSCManager(NULL, 23 NULL, 24 SC_MANAGER_CONNECT); 25 if (hSCManager == NULL) 26 { 27 ReportLastError(); 28 return NULL; 29 } 30 31 hSc = OpenService(hSCManager, 32 ServiceName, 33 SERVICE_QUERY_STATUS); 34 if (hSc == NULL) 35 goto fail; 36 37 Ret = QueryServiceStatusEx(hSc, 38 SC_STATUS_PROCESS_INFO, 39 NULL, 40 BufSiz, 41 &BytesNeeded); 42 if ((Ret != 0) || (GetLastError() != ERROR_INSUFFICIENT_BUFFER)) 43 goto fail; 44 45 pServiceInfo = (LPSERVICE_STATUS_PROCESS)HeapAlloc(GetProcessHeap(), 46 0, 47 BytesNeeded); 48 if (pServiceInfo == NULL) 49 goto fail; 50 51 if (!QueryServiceStatusEx(hSc, 52 SC_STATUS_PROCESS_INFO, 53 (LPBYTE)pServiceInfo, 54 BytesNeeded, 55 &BytesNeeded)) 56 { 57 goto fail; 58 } 59 60 CloseServiceHandle(hSc); 61 CloseServiceHandle(hSCManager); 62 return pServiceInfo; 63 64 fail: 65 ReportLastError(); 66 if (pServiceInfo) HeapFree(GetProcessHeap(), 0, pServiceInfo); 67 if (hSc) CloseServiceHandle(hSc); 68 if (hSCManager) CloseServiceHandle(hSCManager); 69 return NULL; 70 } 71 72 73 static 74 DWORD 75 EnumServices(ENUM_SERVICE_STATUS_PROCESS **pServiceStatus, 76 DWORD dwServiceType, 77 DWORD dwServiceState, 78 DWORD dwBufferSize, 79 DWORD dwResumeIndex, 80 LPCTSTR pszGroupName) 81 { 82 SC_HANDLE hSCManager; 83 DWORD BytesNeeded = 0; 84 DWORD ResumeHandle = dwResumeIndex; 85 DWORD NumServices = 0; 86 BOOL Ret; 87 88 hSCManager = OpenSCManager(NULL, 89 NULL, 90 SC_MANAGER_ENUMERATE_SERVICE); 91 if (hSCManager == NULL) 92 { 93 ReportLastError(); 94 return 0; 95 } 96 97 if (dwBufferSize == 0) 98 { 99 Ret = EnumServicesStatusEx(hSCManager, 100 SC_ENUM_PROCESS_INFO, 101 dwServiceType, 102 dwServiceState, 103 (LPBYTE)*pServiceStatus, 104 dwBufferSize, 105 &BytesNeeded, 106 &NumServices, 107 &ResumeHandle, 108 pszGroupName); 109 if ((Ret == 0) && (GetLastError() != ERROR_MORE_DATA)) 110 { 111 ReportLastError(); 112 return 0; 113 } 114 115 dwBufferSize = BytesNeeded; 116 } 117 118 *pServiceStatus = (ENUM_SERVICE_STATUS_PROCESS *) 119 HeapAlloc(GetProcessHeap(), 120 0, 121 dwBufferSize); 122 if (*pServiceStatus != NULL) 123 { 124 if (EnumServicesStatusEx(hSCManager, 125 SC_ENUM_PROCESS_INFO, 126 dwServiceType, 127 dwServiceState, 128 (LPBYTE)*pServiceStatus, 129 dwBufferSize, 130 &BytesNeeded, 131 &NumServices, 132 &ResumeHandle, 133 pszGroupName)) 134 { 135 CloseServiceHandle(hSCManager); 136 return NumServices; 137 } 138 } 139 140 ReportLastError(); 141 if (*pServiceStatus) 142 HeapFree(GetProcessHeap(), 0, *pServiceStatus); 143 144 CloseServiceHandle(hSCManager); 145 146 return NumServices; 147 } 148 149 150 static 151 BOOL 152 ParseQueryArguments( 153 IN LPCTSTR *ServiceArgs, 154 IN INT ArgCount, 155 OUT PDWORD pdwServiceType, 156 OUT PDWORD pdwServiceState, 157 OUT PDWORD pdwBufferSize, 158 OUT PDWORD pdwResumeIndex, 159 OUT LPCTSTR *ppszGroupName, 160 OUT LPCTSTR *ppszServiceName) 161 { 162 INT TmpCount, TmpIndex; 163 DWORD dwValue; 164 165 TmpCount = ArgCount; 166 TmpIndex = 0; 167 while (TmpCount > 0) 168 { 169 if (!lstrcmpi(ServiceArgs[TmpIndex], _T("type="))) 170 { 171 TmpIndex++; 172 TmpCount--; 173 174 if (TmpCount > 0) 175 { 176 if (!lstrcmpi(ServiceArgs[TmpIndex], _T("service"))) 177 { 178 *pdwServiceType = SERVICE_WIN32; 179 } 180 else if (!lstrcmpi(ServiceArgs[TmpIndex], _T("driver"))) 181 { 182 *pdwServiceType = SERVICE_DRIVER; 183 } 184 else if (!lstrcmpi(ServiceArgs[TmpIndex], _T("all"))) 185 { 186 *pdwServiceType = SERVICE_TYPE_ALL; 187 } 188 else if (!lstrcmpi(ServiceArgs[TmpIndex], _T("interact"))) 189 { 190 *pdwServiceType |= SERVICE_INTERACTIVE_PROCESS; 191 } 192 else 193 { 194 _tprintf(_T("ERROR following \"type=\"!\nMust be one of: all, driver, interact, service.\n")); 195 return FALSE; 196 } 197 198 TmpIndex++; 199 TmpCount--; 200 } 201 } 202 else if (!lstrcmpi(ServiceArgs[TmpIndex], _T("state="))) 203 { 204 TmpIndex++; 205 TmpCount--; 206 207 if (TmpCount > 0) 208 { 209 if (!lstrcmpi(ServiceArgs[TmpIndex], _T("active"))) 210 { 211 *pdwServiceState = SERVICE_ACTIVE; 212 } 213 else if (!lstrcmpi(ServiceArgs[TmpIndex], _T("inactive"))) 214 { 215 *pdwServiceState = SERVICE_INACTIVE; 216 } 217 else if (!lstrcmpi(ServiceArgs[TmpIndex], _T("all"))) 218 { 219 *pdwServiceState = SERVICE_STATE_ALL; 220 } 221 else 222 { 223 _tprintf(_T("ERROR following \"state=\"!\nMust be one of: active, all, inactive.\n")); 224 return FALSE; 225 } 226 227 TmpIndex++; 228 TmpCount--; 229 } 230 } 231 else if (!lstrcmpi(ServiceArgs[TmpIndex], _T("bufsize="))) 232 { 233 TmpIndex++; 234 TmpCount--; 235 236 if (TmpCount > 0) 237 { 238 dwValue = _tcstoul(ServiceArgs[TmpIndex], NULL, 10); 239 if (dwValue > 0) 240 { 241 *pdwBufferSize = dwValue; 242 } 243 244 TmpIndex++; 245 TmpCount--; 246 } 247 } 248 else if (!lstrcmpi(ServiceArgs[TmpIndex], _T("ri="))) 249 { 250 TmpIndex++; 251 TmpCount--; 252 253 if (TmpCount >= 0) 254 { 255 dwValue = _tcstoul(ServiceArgs[TmpIndex], NULL, 10); 256 if (dwValue > 0) 257 { 258 *pdwResumeIndex = dwValue; 259 } 260 261 TmpIndex++; 262 TmpCount--; 263 } 264 } 265 else if (!lstrcmpi(ServiceArgs[TmpIndex], _T("group="))) 266 { 267 TmpIndex++; 268 TmpCount--; 269 270 if (TmpCount > 0) 271 { 272 *ppszGroupName = ServiceArgs[TmpIndex]; 273 274 TmpIndex++; 275 TmpCount--; 276 } 277 } 278 else 279 { 280 *ppszServiceName = ServiceArgs[TmpIndex]; 281 282 TmpIndex++; 283 TmpCount--; 284 } 285 } 286 287 return TRUE; 288 } 289 290 291 BOOL 292 Query(LPCTSTR *ServiceArgs, 293 DWORD ArgCount, 294 BOOL bExtended) 295 { 296 LPENUM_SERVICE_STATUS_PROCESS pServiceStatus = NULL; 297 DWORD NumServices = 0; 298 DWORD dwServiceType = SERVICE_WIN32; 299 DWORD dwServiceState = SERVICE_ACTIVE; 300 DWORD dwBufferSize = 0; 301 DWORD dwResumeIndex = 0; 302 LPCTSTR pszGroupName = NULL; 303 LPCTSTR pszServiceName = NULL; 304 DWORD i; 305 306 #ifdef SCDBG 307 LPCTSTR *TmpArgs = ServiceArgs; 308 INT TmpCnt = ArgCount; 309 310 _tprintf(_T("Arguments:\n")); 311 while (TmpCnt) 312 { 313 _tprintf(_T(" %s\n"), *TmpArgs); 314 TmpArgs++; 315 TmpCnt--; 316 } 317 _tprintf(_T("\n")); 318 #endif /* SCDBG */ 319 320 /* Parse arguments */ 321 if (!ParseQueryArguments(ServiceArgs, 322 ArgCount, 323 &dwServiceType, 324 &dwServiceState, 325 &dwBufferSize, 326 &dwResumeIndex, 327 &pszGroupName, 328 &pszServiceName)) 329 return FALSE; 330 331 #ifdef SCDBG 332 _tprintf(_T("Service type: %lx\n"), dwServiceType); 333 _tprintf(_T("Service state: %lx\n"), dwServiceState); 334 _tprintf(_T("Buffer size: %lu\n"), dwBufferSize); 335 _tprintf(_T("Resume index: %lu\n"), dwResumeIndex); 336 _tprintf(_T("Group name: %s\n"), pszGroupName); 337 _tprintf(_T("Service name: %s\n"), pszServiceName); 338 #endif 339 340 if (pszServiceName) 341 { 342 /* Print only the requested service */ 343 344 LPSERVICE_STATUS_PROCESS pStatus; 345 346 pStatus = QueryService(pszServiceName); 347 if (pStatus) 348 { 349 PrintService(pszServiceName, 350 NULL, 351 pStatus, 352 bExtended); 353 354 HeapFree(GetProcessHeap(), 0, pStatus); 355 } 356 } 357 else 358 { 359 /* Print all matching services */ 360 361 NumServices = EnumServices(&pServiceStatus, 362 dwServiceType, 363 dwServiceState, 364 dwBufferSize, 365 dwResumeIndex, 366 pszGroupName); 367 if (NumServices == 0) 368 return FALSE; 369 370 for (i = 0; i < NumServices; i++) 371 { 372 PrintService(pServiceStatus[i].lpServiceName, 373 pServiceStatus[i].lpDisplayName, 374 &pServiceStatus[i].ServiceStatusProcess, 375 bExtended); 376 } 377 378 #ifdef SCDBG 379 _tprintf(_T("number : %lu\n"), NumServices); 380 #endif 381 382 if (pServiceStatus) 383 HeapFree(GetProcessHeap(), 0, pServiceStatus); 384 } 385 386 return TRUE; 387 } 388