https://git.reactos.org/?p=reactos.git;a=commitdiff;h=47281571546797043d7f5…
commit 47281571546797043d7f5dad0bf5da5372055274
Author: Eric Kohl <eric.kohl(a)reactos.org>
AuthorDate: Sat Feb 17 19:26:06 2018 +0100
Commit: Eric Kohl <eric.kohl(a)reactos.org>
CommitDate: Sat Feb 17 19:28:16 2018 +0100
[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 de212dd230..5e5a4e84ac 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 caf82a4ae6..f08402207f 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 d9d925f3ec..54e04277b2 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 <gedmurphy(a)gmail.com>
- *
- */
-/*
- * TODO:
- * Allow calling of 2 options e.g.:
- * type= driver state= inactive
+ * Copyright 2018 Eric Kohl <eric.kohl(a)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++;
- }
-
-
- /* FIXME: parse options */
-
+ /* Print only the requested service */
- /* 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 3dbacee0c8..a896da6855 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 676355ce2f..598a6355c7 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 4bcf049f9d..d04907d212 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"));
}