mirror of
https://github.com/reactos/reactos.git
synced 2025-02-21 16:04:57 +00:00
[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:
parent
ef8b17ed0d
commit
4728157154
6 changed files with 261 additions and 116 deletions
|
@ -96,6 +96,7 @@ Control(DWORD Control,
|
|||
StatusEx.dwServiceFlags = 0;
|
||||
|
||||
PrintService(ServiceName,
|
||||
NULL,
|
||||
&StatusEx,
|
||||
FALSE);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -68,6 +68,7 @@ BOOL Start(LPCTSTR ServiceName, LPCTSTR *ServiceArgs, INT ArgCount)
|
|||
if (pServiceInfo != NULL)
|
||||
{
|
||||
PrintService(ServiceName,
|
||||
NULL,
|
||||
pServiceInfo,
|
||||
TRUE);
|
||||
|
||||
|
|
|
@ -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"));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue