From 47281571546797043d7f5dad0bf5da5372055274 Mon Sep 17 00:00:00 2001 From: Eric Kohl Date: Sat, 17 Feb 2018 19:26:06 +0100 Subject: [PATCH] [SC] Implement missing query/queryex options - PrintService: Print optional display name. - MainUsage: Print missing query options. - Parse query options and use them to enumerate services. --- base/applications/sc/control.c | 1 + base/applications/sc/print.c | 4 + base/applications/sc/query.c | 361 +++++++++++++++++++++++---------- base/applications/sc/sc.h | 2 +- base/applications/sc/start.c | 1 + base/applications/sc/usage.c | 8 +- 6 files changed, 261 insertions(+), 116 deletions(-) diff --git a/base/applications/sc/control.c b/base/applications/sc/control.c index de212dd2300..5e5a4e84aca 100644 --- a/base/applications/sc/control.c +++ b/base/applications/sc/control.c @@ -96,6 +96,7 @@ Control(DWORD Control, StatusEx.dwServiceFlags = 0; PrintService(ServiceName, + NULL, &StatusEx, FALSE); diff --git a/base/applications/sc/print.c b/base/applications/sc/print.c index caf82a4ae62..f08402207f7 100644 --- a/base/applications/sc/print.c +++ b/base/applications/sc/print.c @@ -11,11 +11,15 @@ VOID PrintService(LPCTSTR lpServiceName, + LPCTSTR lpDisplayName, LPSERVICE_STATUS_PROCESS pStatus, BOOL bExtended) { _tprintf(_T("SERVICE_NAME: %s\n"), lpServiceName); + if (lpDisplayName) + _tprintf(_T("DISPLAY_NAME: %s\n"), lpDisplayName); + // Re-use PrintServiceStatus(), as SERVICE_STATUS_PROCESS is in fact an extension of SERVICE_STATUS. PrintServiceStatus((LPSERVICE_STATUS)pStatus); diff --git a/base/applications/sc/query.c b/base/applications/sc/query.c index d9d925f3ec7..54e04277b2b 100644 --- a/base/applications/sc/query.c +++ b/base/applications/sc/query.c @@ -4,25 +4,11 @@ * FILE: base/applications/sc/query.c * PURPOSE: queries service info * COPYRIGHT: Copyright 2005 - 2006 Ged Murphy - * - */ -/* - * TODO: - * Allow calling of 2 options e.g.: - * type= driver state= inactive + * Copyright 2018 Eric Kohl */ #include "sc.h" -LPTSTR QueryOpts[] = { - _T("type="), - _T("state="), - _T("bufsize="), - _T("ri="), - _T("group="), -}; - - LPSERVICE_STATUS_PROCESS QueryService(LPCTSTR ServiceName) { @@ -84,17 +70,20 @@ fail: } -static BOOL +static +DWORD EnumServices(ENUM_SERVICE_STATUS_PROCESS **pServiceStatus, - DWORD ServiceType, - DWORD ServiceState) + DWORD dwServiceType, + DWORD dwServiceState, + DWORD dwBufferSize, + DWORD dwResumeIndex, + LPCTSTR pszGroupName) { SC_HANDLE hSCManager; - DWORD BufSize = 0; DWORD BytesNeeded = 0; - DWORD ResumeHandle = 0; + DWORD ResumeHandle = dwResumeIndex; DWORD NumServices = 0; - DWORD Ret; + BOOL Ret; hSCManager = OpenSCManager(NULL, NULL, @@ -102,42 +91,49 @@ EnumServices(ENUM_SERVICE_STATUS_PROCESS **pServiceStatus, if (hSCManager == NULL) { ReportLastError(); - return FALSE; + return 0; } - Ret = EnumServicesStatusEx(hSCManager, - SC_ENUM_PROCESS_INFO, - ServiceType, - ServiceState, - (LPBYTE)*pServiceStatus, - BufSize, - &BytesNeeded, - &NumServices, - &ResumeHandle, - 0); - - if ((Ret == 0) && (GetLastError() == ERROR_MORE_DATA)) + if (dwBufferSize == 0) { - *pServiceStatus = (ENUM_SERVICE_STATUS_PROCESS *) - HeapAlloc(GetProcessHeap(), - 0, - BytesNeeded); - if (*pServiceStatus != NULL) + Ret = EnumServicesStatusEx(hSCManager, + SC_ENUM_PROCESS_INFO, + dwServiceType, + dwServiceState, + (LPBYTE)*pServiceStatus, + dwBufferSize, + &BytesNeeded, + &NumServices, + &ResumeHandle, + pszGroupName); + if ((Ret == 0) && (GetLastError() != ERROR_MORE_DATA)) { - if (EnumServicesStatusEx(hSCManager, - SC_ENUM_PROCESS_INFO, - ServiceType, - ServiceState, - (LPBYTE)*pServiceStatus, - BytesNeeded, - &BytesNeeded, - &NumServices, - &ResumeHandle, - 0)) - { - CloseServiceHandle(hSCManager); - return NumServices; - } + ReportLastError(); + return 0; + } + + dwBufferSize = BytesNeeded; + } + + *pServiceStatus = (ENUM_SERVICE_STATUS_PROCESS *) + HeapAlloc(GetProcessHeap(), + 0, + dwBufferSize); + if (*pServiceStatus != NULL) + { + if (EnumServicesStatusEx(hSCManager, + SC_ENUM_PROCESS_INFO, + dwServiceType, + dwServiceState, + (LPBYTE)*pServiceStatus, + dwBufferSize, + &BytesNeeded, + &NumServices, + &ResumeHandle, + pszGroupName)) + { + CloseServiceHandle(hSCManager); + return NumServices; } } @@ -151,6 +147,147 @@ EnumServices(ENUM_SERVICE_STATUS_PROCESS **pServiceStatus, } +static +BOOL +ParseQueryArguments( + IN LPCTSTR *ServiceArgs, + IN INT ArgCount, + OUT PDWORD pdwServiceType, + OUT PDWORD pdwServiceState, + OUT PDWORD pdwBufferSize, + OUT PDWORD pdwResumeIndex, + OUT LPCTSTR *ppszGroupName, + OUT LPCTSTR *ppszServiceName) +{ + INT TmpCount, TmpIndex; + DWORD dwValue; + + TmpCount = ArgCount; + TmpIndex = 0; + while (TmpCount > 0) + { + if (!lstrcmpi(ServiceArgs[TmpIndex], _T("type="))) + { + TmpIndex++; + TmpCount--; + + if (TmpCount > 0) + { + if (!lstrcmpi(ServiceArgs[TmpIndex], _T("service"))) + { + *pdwServiceType = SERVICE_WIN32; + } + else if (!lstrcmpi(ServiceArgs[TmpIndex], _T("driver"))) + { + *pdwServiceType = SERVICE_DRIVER; + } + else if (!lstrcmpi(ServiceArgs[TmpIndex], _T("all"))) + { + *pdwServiceType = SERVICE_TYPE_ALL; + } + else if (!lstrcmpi(ServiceArgs[TmpIndex], _T("interact"))) + { + *pdwServiceType |= SERVICE_INTERACTIVE_PROCESS; + } + else + { + _tprintf(_T("ERROR following \"type=\"!\nMust be \"driver\" or \"service\"\n")); + return FALSE; + } + + TmpIndex++; + TmpCount--; + } + } + else if (!lstrcmpi(ServiceArgs[TmpIndex], _T("state="))) + { + TmpIndex++; + TmpCount--; + + if (TmpCount > 0) + { + if (!lstrcmpi(ServiceArgs[TmpIndex], _T("active"))) + { + *pdwServiceState = SERVICE_ACTIVE; + } + else if (!lstrcmpi(ServiceArgs[TmpIndex], _T("inactive"))) + { + *pdwServiceState = SERVICE_INACTIVE; + } + else if (!lstrcmpi(ServiceArgs[TmpIndex], _T("all"))) + { + *pdwServiceState = SERVICE_STATE_ALL; + } + else + { + _tprintf(_T("ERROR following \"state=\"!\nMust be \"inactive\" or \"all\"\n")); + return FALSE; + } + + TmpIndex++; + TmpCount--; + } + } + else if (!lstrcmpi(ServiceArgs[TmpIndex], _T("bufsize="))) + { + TmpIndex++; + TmpCount--; + + if (TmpCount > 0) + { + dwValue = _tcstoul(ServiceArgs[TmpIndex], NULL, 10); + if (dwValue > 0) + { + *pdwBufferSize = dwValue; + } + + TmpIndex++; + TmpCount--; + } + } + else if (!lstrcmpi(ServiceArgs[TmpIndex], _T("ri="))) + { + TmpIndex++; + TmpCount--; + + if (TmpCount >= 0) + { + dwValue = _tcstoul(ServiceArgs[TmpIndex], NULL, 10); + if (dwValue > 0) + { + *pdwResumeIndex = dwValue; + } + + TmpIndex++; + TmpCount--; + } + } + else if (!lstrcmpi(ServiceArgs[TmpIndex], _T("group="))) + { + TmpIndex++; + TmpCount--; + + if (TmpCount > 0) + { + *ppszGroupName = ServiceArgs[TmpIndex]; + + TmpIndex++; + TmpCount--; + } + } + else + { + *ppszServiceName = ServiceArgs[TmpIndex]; + + TmpIndex++; + TmpCount--; + } + } + + return TRUE; +} + + BOOL Query(LPCTSTR *ServiceArgs, DWORD ArgCount, @@ -158,17 +295,18 @@ Query(LPCTSTR *ServiceArgs, { LPENUM_SERVICE_STATUS_PROCESS pServiceStatus = NULL; DWORD NumServices = 0; - //DWORD ServiceType; - //DWORD ServiceState; - BOOL bServiceName = TRUE; - DWORD OptSize, i; - - LPCTSTR *TmpArgs; - INT TmpCnt; + DWORD dwServiceType = SERVICE_WIN32; + DWORD dwServiceState = SERVICE_ACTIVE; + DWORD dwBufferSize = 0; + DWORD dwResumeIndex = 0; + LPCTSTR pszGroupName = NULL; + LPCTSTR pszServiceName = NULL; + DWORD i; #ifdef SCDBG - TmpArgs = ServiceArgs; - TmpCnt = ArgCount; + LPCTSTR *TmpArgs = ServiceArgs; + INT TmpCnt = ArgCount; + _tprintf(_T("Arguments:\n")); while (TmpCnt) { @@ -179,66 +317,69 @@ Query(LPCTSTR *ServiceArgs, _tprintf(_T("\n")); #endif /* SCDBG */ - /* display all running services and drivers */ - if (ArgCount == 0) - { - NumServices = EnumServices(&pServiceStatus, - SERVICE_WIN32, - SERVICE_ACTIVE); - - if (NumServices != 0) - { - for (i=0; i < NumServices; i++) - { - PrintService(pServiceStatus[i].lpServiceName, - &pServiceStatus[i].ServiceStatusProcess, - bExtended); - } - - _tprintf(_T("number : %lu\n"), NumServices); - - if (pServiceStatus) - HeapFree(GetProcessHeap(), 0, pServiceStatus); - - return TRUE; - } - + /* Parse arguments */ + if (!ParseQueryArguments(ServiceArgs, + ArgCount, + &dwServiceType, + &dwServiceState, + &dwBufferSize, + &dwResumeIndex, + &pszGroupName, + &pszServiceName)) return FALSE; - } - TmpArgs = ServiceArgs; - TmpCnt = ArgCount; - OptSize = sizeof(QueryOpts) / sizeof(QueryOpts[0]); - while (TmpCnt--) +#ifdef SCDBG + _tprintf(_T("Service type: %lx\n"), dwServiceType); + _tprintf(_T("Service state: %lx\n"), dwServiceState); + _tprintf(_T("Buffer size: %lu\n"), dwBufferSize); + _tprintf(_T("Resume index: %lu\n"), dwResumeIndex); + _tprintf(_T("Group name: %s\n"), pszGroupName); + _tprintf(_T("Service name: %s\n"), pszServiceName); +#endif + + if (pszServiceName) { - for (i=0; i < OptSize; i++) - { - if (!lstrcmpi(*TmpArgs, QueryOpts[i])) - { - bServiceName = FALSE; - } - } - TmpArgs++; - } + /* Print only the requested service */ - - /* FIXME: parse options */ - - - /* print only the service requested */ - if (bServiceName) - { LPSERVICE_STATUS_PROCESS pStatus; - LPCTSTR ServiceName = *ServiceArgs; - pStatus = QueryService(ServiceName); + pStatus = QueryService(pszServiceName); if (pStatus) { - PrintService(ServiceName, + PrintService(pszServiceName, + NULL, pStatus, bExtended); } } + else + { + /* Print all matching services */ + + NumServices = EnumServices(&pServiceStatus, + dwServiceType, + dwServiceState, + dwBufferSize, + dwResumeIndex, + pszGroupName); + if (NumServices == 0) + return FALSE; + + for (i = 0; i < NumServices; i++) + { + PrintService(pServiceStatus[i].lpServiceName, + pServiceStatus[i].lpDisplayName, + &pServiceStatus[i].ServiceStatusProcess, + bExtended); + } + +#ifdef SCDBG + _tprintf(_T("number : %lu\n"), NumServices); +#endif + + if (pServiceStatus) + HeapFree(GetProcessHeap(), 0, pServiceStatus); + } return TRUE; } diff --git a/base/applications/sc/sc.h b/base/applications/sc/sc.h index 3dbacee0c86..a896da68558 100644 --- a/base/applications/sc/sc.h +++ b/base/applications/sc/sc.h @@ -56,7 +56,7 @@ BOOL GetKeyName(LPCTSTR ServiceName); BOOL EnumDepend(LPCTSTR ServiceName); /* print and error functions */ -VOID PrintService(LPCTSTR ServiceName, LPSERVICE_STATUS_PROCESS pStatus, BOOL bExtended); +VOID PrintService(LPCTSTR ServiceName, LPCTSTR DisplayName, LPSERVICE_STATUS_PROCESS pStatus, BOOL bExtended); VOID PrintServiceStatus(LPSERVICE_STATUS pStatus); VOID ReportLastError(VOID); diff --git a/base/applications/sc/start.c b/base/applications/sc/start.c index 676355ce2f4..598a6355c7f 100644 --- a/base/applications/sc/start.c +++ b/base/applications/sc/start.c @@ -68,6 +68,7 @@ BOOL Start(LPCTSTR ServiceName, LPCTSTR *ServiceArgs, INT ArgCount) if (pServiceInfo != NULL) { PrintService(ServiceName, + NULL, pServiceInfo, TRUE); diff --git a/base/applications/sc/usage.c b/base/applications/sc/usage.c index 4bcf049f9de..d04907d212f 100644 --- a/base/applications/sc/usage.c +++ b/base/applications/sc/usage.c @@ -68,14 +68,12 @@ VOID MainUsage(VOID) _T(" (default = service)\n") _T(" state= State of services to enumerate (inactive, all)\n") _T(" (default = active)\n") -/* _T(" bufsize= The size (in bytes) of the enumeration buffer\n") _T(" (default = 4096)\n") _T(" ri= The resume index number at which to begin the enumeration\n") _T(" (default = 0)\n") _T(" group= Service group to enumerate\n") _T(" (default = all groups)\n") -*/ _T("SYNTAX EXAMPLES\n") _T("sc query - Enumerates status for active services & drivers\n") _T("sc query messenger - Displays status for the messenger service\n") @@ -83,9 +81,9 @@ VOID MainUsage(VOID) _T("sc query type= driver - Enumerates only active drivers\n") _T("sc query type= service - Enumerates only Win32 services\n") _T("sc query state= all - Enumerates all services & drivers\n") -// _T("sc query bufsize= 50 - Enumerates with a 50 byte buffer.\n") -// _T("sc query ri= 14 - Enumerates with resume index = 14\n") -// _T("sc queryex group= "" - Enumerates active services not in a group\n") + _T("sc query bufsize= 50 - Enumerates with a 50 byte buffer.\n") + _T("sc query ri= 14 - Enumerates with resume index = 14\n") + _T("sc queryex group= "" - Enumerates active services not in a group\n") _T("sc query type= service type= interact - Enumerates all interactive services\n") _T("sc query type= driver group= NDIS - Enumerates all NDIS drivers\n")); }