[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.
This commit is contained in:
Eric Kohl 2018-02-17 19:26:06 +01:00
parent ef8b17ed0d
commit 4728157154
6 changed files with 261 additions and 116 deletions

View file

@ -96,6 +96,7 @@ Control(DWORD Control,
StatusEx.dwServiceFlags = 0;
PrintService(ServiceName,
NULL,
&StatusEx,
FALSE);

View file

@ -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);

View file

@ -4,25 +4,11 @@
* FILE: base/applications/sc/query.c
* PURPOSE: queries service info
* COPYRIGHT: Copyright 2005 - 2006 Ged Murphy <gedmurphy@gmail.com>
*
*/
/*
* TODO:
* Allow calling of 2 options e.g.:
* type= driver state= inactive
* Copyright 2018 Eric Kohl <eric.kohl@reactos.org>
*/
#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;
}

View file

@ -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);

View file

@ -68,6 +68,7 @@ BOOL Start(LPCTSTR ServiceName, LPCTSTR *ServiceArgs, INT ArgCount)
if (pServiceInfo != NULL)
{
PrintService(ServiceName,
NULL,
pServiceInfo,
TRUE);

View file

@ -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"));
}