[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; StatusEx.dwServiceFlags = 0;
PrintService(ServiceName, PrintService(ServiceName,
NULL,
&StatusEx, &StatusEx,
FALSE); FALSE);

View file

@ -11,11 +11,15 @@
VOID VOID
PrintService(LPCTSTR lpServiceName, PrintService(LPCTSTR lpServiceName,
LPCTSTR lpDisplayName,
LPSERVICE_STATUS_PROCESS pStatus, LPSERVICE_STATUS_PROCESS pStatus,
BOOL bExtended) BOOL bExtended)
{ {
_tprintf(_T("SERVICE_NAME: %s\n"), lpServiceName); _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. // Re-use PrintServiceStatus(), as SERVICE_STATUS_PROCESS is in fact an extension of SERVICE_STATUS.
PrintServiceStatus((LPSERVICE_STATUS)pStatus); PrintServiceStatus((LPSERVICE_STATUS)pStatus);

View file

@ -4,25 +4,11 @@
* FILE: base/applications/sc/query.c * FILE: base/applications/sc/query.c
* PURPOSE: queries service info * PURPOSE: queries service info
* COPYRIGHT: Copyright 2005 - 2006 Ged Murphy <gedmurphy@gmail.com> * COPYRIGHT: Copyright 2005 - 2006 Ged Murphy <gedmurphy@gmail.com>
* * Copyright 2018 Eric Kohl <eric.kohl@reactos.org>
*/
/*
* TODO:
* Allow calling of 2 options e.g.:
* type= driver state= inactive
*/ */
#include "sc.h" #include "sc.h"
LPTSTR QueryOpts[] = {
_T("type="),
_T("state="),
_T("bufsize="),
_T("ri="),
_T("group="),
};
LPSERVICE_STATUS_PROCESS LPSERVICE_STATUS_PROCESS
QueryService(LPCTSTR ServiceName) QueryService(LPCTSTR ServiceName)
{ {
@ -84,17 +70,20 @@ fail:
} }
static BOOL static
DWORD
EnumServices(ENUM_SERVICE_STATUS_PROCESS **pServiceStatus, EnumServices(ENUM_SERVICE_STATUS_PROCESS **pServiceStatus,
DWORD ServiceType, DWORD dwServiceType,
DWORD ServiceState) DWORD dwServiceState,
DWORD dwBufferSize,
DWORD dwResumeIndex,
LPCTSTR pszGroupName)
{ {
SC_HANDLE hSCManager; SC_HANDLE hSCManager;
DWORD BufSize = 0;
DWORD BytesNeeded = 0; DWORD BytesNeeded = 0;
DWORD ResumeHandle = 0; DWORD ResumeHandle = dwResumeIndex;
DWORD NumServices = 0; DWORD NumServices = 0;
DWORD Ret; BOOL Ret;
hSCManager = OpenSCManager(NULL, hSCManager = OpenSCManager(NULL,
NULL, NULL,
@ -102,44 +91,51 @@ EnumServices(ENUM_SERVICE_STATUS_PROCESS **pServiceStatus,
if (hSCManager == NULL) if (hSCManager == NULL)
{ {
ReportLastError(); ReportLastError();
return FALSE; return 0;
} }
if (dwBufferSize == 0)
{
Ret = EnumServicesStatusEx(hSCManager, Ret = EnumServicesStatusEx(hSCManager,
SC_ENUM_PROCESS_INFO, SC_ENUM_PROCESS_INFO,
ServiceType, dwServiceType,
ServiceState, dwServiceState,
(LPBYTE)*pServiceStatus, (LPBYTE)*pServiceStatus,
BufSize, dwBufferSize,
&BytesNeeded, &BytesNeeded,
&NumServices, &NumServices,
&ResumeHandle, &ResumeHandle,
0); pszGroupName);
if ((Ret == 0) && (GetLastError() != ERROR_MORE_DATA))
if ((Ret == 0) && (GetLastError() == ERROR_MORE_DATA))
{ {
ReportLastError();
return 0;
}
dwBufferSize = BytesNeeded;
}
*pServiceStatus = (ENUM_SERVICE_STATUS_PROCESS *) *pServiceStatus = (ENUM_SERVICE_STATUS_PROCESS *)
HeapAlloc(GetProcessHeap(), HeapAlloc(GetProcessHeap(),
0, 0,
BytesNeeded); dwBufferSize);
if (*pServiceStatus != NULL) if (*pServiceStatus != NULL)
{ {
if (EnumServicesStatusEx(hSCManager, if (EnumServicesStatusEx(hSCManager,
SC_ENUM_PROCESS_INFO, SC_ENUM_PROCESS_INFO,
ServiceType, dwServiceType,
ServiceState, dwServiceState,
(LPBYTE)*pServiceStatus, (LPBYTE)*pServiceStatus,
BytesNeeded, dwBufferSize,
&BytesNeeded, &BytesNeeded,
&NumServices, &NumServices,
&ResumeHandle, &ResumeHandle,
0)) pszGroupName))
{ {
CloseServiceHandle(hSCManager); CloseServiceHandle(hSCManager);
return NumServices; return NumServices;
} }
} }
}
ReportLastError(); ReportLastError();
if (*pServiceStatus) if (*pServiceStatus)
@ -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 BOOL
Query(LPCTSTR *ServiceArgs, Query(LPCTSTR *ServiceArgs,
DWORD ArgCount, DWORD ArgCount,
@ -158,17 +295,18 @@ Query(LPCTSTR *ServiceArgs,
{ {
LPENUM_SERVICE_STATUS_PROCESS pServiceStatus = NULL; LPENUM_SERVICE_STATUS_PROCESS pServiceStatus = NULL;
DWORD NumServices = 0; DWORD NumServices = 0;
//DWORD ServiceType; DWORD dwServiceType = SERVICE_WIN32;
//DWORD ServiceState; DWORD dwServiceState = SERVICE_ACTIVE;
BOOL bServiceName = TRUE; DWORD dwBufferSize = 0;
DWORD OptSize, i; DWORD dwResumeIndex = 0;
LPCTSTR pszGroupName = NULL;
LPCTSTR *TmpArgs; LPCTSTR pszServiceName = NULL;
INT TmpCnt; DWORD i;
#ifdef SCDBG #ifdef SCDBG
TmpArgs = ServiceArgs; LPCTSTR *TmpArgs = ServiceArgs;
TmpCnt = ArgCount; INT TmpCnt = ArgCount;
_tprintf(_T("Arguments:\n")); _tprintf(_T("Arguments:\n"));
while (TmpCnt) while (TmpCnt)
{ {
@ -179,66 +317,69 @@ Query(LPCTSTR *ServiceArgs,
_tprintf(_T("\n")); _tprintf(_T("\n"));
#endif /* SCDBG */ #endif /* SCDBG */
/* display all running services and drivers */ /* Parse arguments */
if (ArgCount == 0) if (!ParseQueryArguments(ServiceArgs,
{ ArgCount,
NumServices = EnumServices(&pServiceStatus, &dwServiceType,
SERVICE_WIN32, &dwServiceState,
SERVICE_ACTIVE); &dwBufferSize,
&dwResumeIndex,
if (NumServices != 0) &pszGroupName,
{ &pszServiceName))
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;
}
return FALSE; return FALSE;
}
TmpArgs = ServiceArgs; #ifdef SCDBG
TmpCnt = ArgCount; _tprintf(_T("Service type: %lx\n"), dwServiceType);
OptSize = sizeof(QueryOpts) / sizeof(QueryOpts[0]); _tprintf(_T("Service state: %lx\n"), dwServiceState);
while (TmpCnt--) _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++) /* Print only the requested service */
{
if (!lstrcmpi(*TmpArgs, QueryOpts[i]))
{
bServiceName = FALSE;
}
}
TmpArgs++;
}
/* FIXME: parse options */
/* print only the service requested */
if (bServiceName)
{
LPSERVICE_STATUS_PROCESS pStatus; LPSERVICE_STATUS_PROCESS pStatus;
LPCTSTR ServiceName = *ServiceArgs;
pStatus = QueryService(ServiceName); pStatus = QueryService(pszServiceName);
if (pStatus) if (pStatus)
{ {
PrintService(ServiceName, PrintService(pszServiceName,
NULL,
pStatus, pStatus,
bExtended); 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; return TRUE;
} }

View file

@ -56,7 +56,7 @@ BOOL GetKeyName(LPCTSTR ServiceName);
BOOL EnumDepend(LPCTSTR ServiceName); BOOL EnumDepend(LPCTSTR ServiceName);
/* print and error functions */ /* 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 PrintServiceStatus(LPSERVICE_STATUS pStatus);
VOID ReportLastError(VOID); VOID ReportLastError(VOID);

View file

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

View file

@ -68,14 +68,12 @@ VOID MainUsage(VOID)
_T(" (default = service)\n") _T(" (default = service)\n")
_T(" state= State of services to enumerate (inactive, all)\n") _T(" state= State of services to enumerate (inactive, all)\n")
_T(" (default = active)\n") _T(" (default = active)\n")
/*
_T(" bufsize= The size (in bytes) of the enumeration buffer\n") _T(" bufsize= The size (in bytes) of the enumeration buffer\n")
_T(" (default = 4096)\n") _T(" (default = 4096)\n")
_T(" ri= The resume index number at which to begin the enumeration\n") _T(" ri= The resume index number at which to begin the enumeration\n")
_T(" (default = 0)\n") _T(" (default = 0)\n")
_T(" group= Service group to enumerate\n") _T(" group= Service group to enumerate\n")
_T(" (default = all groups)\n") _T(" (default = all groups)\n")
*/
_T("SYNTAX EXAMPLES\n") _T("SYNTAX EXAMPLES\n")
_T("sc query - Enumerates status for active services & drivers\n") _T("sc query - Enumerates status for active services & drivers\n")
_T("sc query messenger - Displays status for the messenger service\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= driver - Enumerates only active drivers\n")
_T("sc query type= service - Enumerates only Win32 services\n") _T("sc query type= service - Enumerates only Win32 services\n")
_T("sc query state= all - Enumerates all services & drivers\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 bufsize= 50 - Enumerates with a 50 byte buffer.\n")
// _T("sc query ri= 14 - Enumerates with resume index = 14\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 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= service type= interact - Enumerates all interactive services\n")
_T("sc query type= driver group= NDIS - Enumerates all NDIS drivers\n")); _T("sc query type= driver group= NDIS - Enumerates all NDIS drivers\n"));
} }