From 9b195556552cbe343dece149c4c893684a9120be Mon Sep 17 00:00:00 2001 From: Ged Murphy Date: Fri, 11 Nov 2005 17:28:13 +0000 Subject: [PATCH 1/1] functionality for sc query and queryex supports sc query sc query type= <...> sc query state <...> output as per MS utility added usage information for query functionality svn path=/trunk/; revision=19133 --- reactos/subsys/system/sc/query.c | 299 +++++++++++++++++++++++-------- reactos/subsys/system/sc/usage.c | 41 ++++- 2 files changed, 264 insertions(+), 76 deletions(-) diff --git a/reactos/subsys/system/sc/query.c b/reactos/subsys/system/sc/query.c index 968742daafe..f4ab2f09935 100644 --- a/reactos/subsys/system/sc/query.c +++ b/reactos/subsys/system/sc/query.c @@ -8,27 +8,32 @@ * Ged Murphy 20/10/05 Created * */ +/* + * TODO: + * Allow calling of 2 options e.g.: + * type= driver state= inactive + */ #include "sc.h" /* local function decs */ VOID PrintService(BOOL bExtended); -BOOL EnumServices(DWORD ServiceType, DWORD ServiceState); +BOOL EnumServices(LPCTSTR ServiceName, DWORD ServiceType, DWORD ServiceState); +BOOL QueryService(LPCTSTR ServiceName, BOOL bExtended); /* global variables */ static ENUM_SERVICE_STATUS_PROCESS *pServiceStatus = NULL; +DWORD NumServices = 0; -BOOL Query(LPCTSTR ServiceName, LPCTSTR *ServiceArgs, BOOL bExtended) +BOOL +Query(LPCTSTR ServiceName, LPCTSTR *ServiceArgs, BOOL bExtended) { - if (! ServiceName) + if (! ServiceName) /* display all running services and drivers */ { - /* display all running services and drivers */ - _tprintf(_T("No service name, displaying all services\n")); // test - /* get default values */ - EnumServices(SERVICE_WIN32, SERVICE_ACTIVE); + EnumServices(NULL, SERVICE_WIN32, SERVICE_ACTIVE); /* print default values */ PrintService(bExtended); @@ -37,13 +42,12 @@ BOOL Query(LPCTSTR ServiceName, LPCTSTR *ServiceArgs, BOOL bExtended) { LPCTSTR Type = *ServiceArgs; - _tprintf(_T("got type\narg = %s\n"), Type); // test if (_tcsicmp(Type, _T("driver")) == 0) - EnumServices(SERVICE_DRIVER, SERVICE_STATE_ALL); + EnumServices(NULL, SERVICE_DRIVER, SERVICE_ACTIVE); else if (_tcsicmp(Type, _T("service")) == 0) - EnumServices(SERVICE_WIN32, SERVICE_STATE_ALL); + EnumServices(NULL, SERVICE_WIN32, SERVICE_ACTIVE); else if (_tcsicmp(Type, _T("all")) == 0) - EnumServices(SERVICE_DRIVER|SERVICE_WIN32, SERVICE_STATE_ALL); + EnumServices(NULL, SERVICE_DRIVER|SERVICE_WIN32, SERVICE_ACTIVE); else { _tprintf(_T("\nERROR following \"type=\"!\n")); @@ -56,12 +60,10 @@ BOOL Query(LPCTSTR ServiceName, LPCTSTR *ServiceArgs, BOOL bExtended) { LPCTSTR State = *ServiceArgs; - if (_tcsicmp(State, _T("active")) == 0) - EnumServices(SERVICE_DRIVER|SERVICE_WIN32, SERVICE_ACTIVE); - else if (_tcsicmp(State, _T("inactive")) == 0) - EnumServices(SERVICE_DRIVER|SERVICE_WIN32, SERVICE_INACTIVE); + if (_tcsicmp(State, _T("inactive")) == 0) + EnumServices(NULL, SERVICE_WIN32, SERVICE_INACTIVE); else if (_tcsicmp(State, _T("all")) == 0) - EnumServices(SERVICE_DRIVER|SERVICE_WIN32, SERVICE_STATE_ALL); + EnumServices(NULL, SERVICE_WIN32, SERVICE_STATE_ALL); else { _tprintf(_T("\nERROR following \"state=\"!\n")); @@ -77,35 +79,138 @@ BOOL Query(LPCTSTR ServiceName, LPCTSTR *ServiceArgs, BOOL bExtended) else if(_tcsicmp(ServiceName, _T("group="))) */ - else + else /* print only the service requested */ { - /* print only the service requested */ - printf("Service name %s\n", ServiceName); // test + QueryService(ServiceName, bExtended); + } + + return TRUE; +} - /* get default values */ - EnumServices(SERVICE_WIN32, SERVICE_ACTIVE); - /* print default values */ - PrintService(bExtended); +BOOL +QueryService(LPCTSTR ServiceName, BOOL bExtended) +{ + SERVICE_STATUS_PROCESS *pServiceInfo = NULL; + SC_HANDLE hSc; + DWORD BufSiz = 0; + DWORD BytesNeeded = 0; + DWORD Ret; + + hSc = OpenService(hSCManager, ServiceName, SERVICE_QUERY_STATUS); + + if (hSc == NULL) + { + _tprintf(_T("QueryService: openService failed\n")); + ReportLastError(); + return FALSE; + } + + Ret = QueryServiceStatusEx(hSc, + SC_STATUS_PROCESS_INFO, + NULL, + BufSiz, + &BytesNeeded); + + if ((Ret != 0) || (GetLastError() != ERROR_INSUFFICIENT_BUFFER)) + { + _tprintf(_T("QueryService: First call to QueryServiceStatusEx failed : ")); + ReportLastError(); + return FALSE; + } + else /* Call function again if required size was returned */ + { + /* reserve memory for service info array */ + pServiceInfo = (SERVICE_STATUS_PROCESS *) + HeapAlloc(GetProcessHeap(), 0, BytesNeeded); + if (pServiceInfo == NULL) + { + _tprintf(_T("QueryService: Failed to allocate memory : ")); + ReportLastError(); + return FALSE; + } + + /* fill array with service info */ + if (! QueryServiceStatusEx(hSc, + SC_STATUS_PROCESS_INFO, + (LPBYTE)pServiceInfo, + BytesNeeded, + &BytesNeeded)) + { + _tprintf(_T("QueryService: Second call to QueryServiceStatusEx failed : ")); + ReportLastError(); + HeapFree(GetProcessHeap(), 0, pServiceInfo); + return FALSE; + } } + - return TRUE; + _tprintf(_T("SERVICE_NAME: %s\n"), ServiceName); + + _tprintf(_T("\tTYPE : %x "), + (unsigned int)pServiceInfo->dwServiceType); + switch (pServiceInfo->dwServiceType) + { + case 1 : _tprintf(_T("KERNEL_DRIVER\n")); break; + case 2 : _tprintf(_T("FILE_SYSTEM_DRIVER\n")); break; + case 16 : _tprintf(_T("WIN32_OWN_PROCESS\n")); break; + case 32 : _tprintf(_T("WIN32_SHARE_PROCESS\n")); break; + default : _tprintf(_T("\n")); break; + } + + _tprintf(_T("\tSTATE : %x "), + (unsigned int)pServiceInfo->dwCurrentState); + switch (pServiceInfo->dwCurrentState) + { + case 1 : _tprintf(_T("STOPPED\n")); break; + case 2 : _tprintf(_T("START_PENDING\n")); break; + case 3 : _tprintf(_T("STOP_PENDING\n")); break; + case 4 : _tprintf(_T("RUNNING\n")); break; + case 5 : _tprintf(_T("CONTINUE_PENDING\n")); break; + case 6 : _tprintf(_T("PAUSE_PENDING\n")); break; + case 7 : _tprintf(_T("PAUSED\n")); break; + default : _tprintf(_T("\n")); break; + } + +// _tprintf(_T("\n\taccepted : 0x%x\n\n"), +// pServiceStatus[i].ServiceStatusProcess.dwControlsAccepted); +// (STOPPABLE,NOT_PAUSABLE,ACCEPTS_SHUTDOWN) + + _tprintf(_T("\tWIN32_EXIT_CODE : %d (0x%x)\n"), + (unsigned int)pServiceInfo->dwWin32ExitCode, + (unsigned int)pServiceInfo->dwWin32ExitCode); + _tprintf(_T("\tSERVICE_EXIT_CODE : %d (0x%x)\n"), + (unsigned int)pServiceInfo->dwServiceSpecificExitCode, + (unsigned int)pServiceInfo->dwServiceSpecificExitCode); + _tprintf(_T("\tCHECKPOINT : 0x%x\n"), + (unsigned int)pServiceInfo->dwCheckPoint); + _tprintf(_T("\tWAIT_HINT : 0x%x\n"), + (unsigned int)pServiceInfo->dwWaitHint); + if (bExtended) + { + _tprintf(_T("\tPID : %lu\n"), + pServiceInfo->dwProcessId); + _tprintf(_T("\tFLAGS : %lu\n"), + pServiceInfo->dwServiceFlags); + } + + HeapFree(GetProcessHeap(), 0, pServiceInfo); + + return TRUE; } -BOOL EnumServices(DWORD ServiceType, DWORD ServiceState) +BOOL +EnumServices(LPCTSTR ServiceName, DWORD ServiceType, DWORD ServiceState) { - //SC_HANDLE hSc; DWORD BufSize = 0; DWORD BytesNeeded = 0; - DWORD NumServices = 0; DWORD ResumeHandle = 0; - -// hSc = OpenService(hSCManager, ServiceName, SERVICE_QUERY_STATUS); + DWORD Ret; /* determine required buffer size */ - if (! EnumServicesStatusEx(hSCManager, + Ret = EnumServicesStatusEx(hSCManager, SC_ENUM_PROCESS_INFO, ServiceType, ServiceState, @@ -114,39 +219,45 @@ BOOL EnumServices(DWORD ServiceType, DWORD ServiceState) &BytesNeeded, &NumServices, &ResumeHandle, - 0)) + 0); + + if ((Ret != 0) && (GetLastError() != ERROR_MORE_DATA)) + { + _tprintf(_T("EnumServices: First call to EnumServicesStatusEx failed : ")); + ReportLastError(); + return FALSE; + } + else /* Call function again if required size was returned */ { - /* Call function again if required size was returned */ - if (GetLastError() == ERROR_MORE_DATA) + /* reserve memory for service info array */ + pServiceStatus = (ENUM_SERVICE_STATUS_PROCESS *) + HeapAlloc(GetProcessHeap(), 0, BytesNeeded); + if (pServiceStatus == NULL) { - /* reserve memory for service info array */ - pServiceStatus = (ENUM_SERVICE_STATUS_PROCESS *) malloc(BytesNeeded); - - /* fill array with service info */ - if (! EnumServicesStatusEx(hSCManager, - SC_ENUM_PROCESS_INFO, - SERVICE_DRIVER | SERVICE_WIN32, - SERVICE_STATE_ALL, - (LPBYTE)pServiceStatus, - BufSize, - &BytesNeeded, - &NumServices, - &ResumeHandle, - 0)) - { - _tprintf(_T("Second call to EnumServicesStatusEx failed : ")); - ReportLastError(); - return FALSE; - } + _tprintf(_T("EnumServices: Failed to allocate memory : ")); + ReportLastError(); + return FALSE; } - else /* exit on failure */ + + /* fill array with service info */ + if (! EnumServicesStatusEx(hSCManager, + SC_ENUM_PROCESS_INFO, + ServiceType, + ServiceState, + (LPBYTE)pServiceStatus, + BytesNeeded, + &BytesNeeded, + &NumServices, + &ResumeHandle, + 0)) { - _tprintf(_T("First call to EnumServicesStatusEx failed : ")); + _tprintf(_T("EnumServices: Second call to EnumServicesStatusEx failed : ")); ReportLastError(); + HeapFree(GetProcessHeap(), 0, pServiceStatus); return FALSE; } } - + return TRUE; } @@ -154,26 +265,64 @@ BOOL EnumServices(DWORD ServiceType, DWORD ServiceState) VOID PrintService(BOOL bExtended) { - _tprintf(_T("SERVICE_NAME: %s\n"), pServiceStatus->lpServiceName); - _tprintf(_T("DISPLAY_NAME: %s\n"), pServiceStatus->lpDisplayName); - _tprintf(_T("TYPE : %lu\n"), - pServiceStatus->ServiceStatusProcess.dwServiceType); - _tprintf(_T("STATE : %lu\n"), - pServiceStatus->ServiceStatusProcess.dwCurrentState); - // (STOPPABLE,NOT_PAUSABLE,ACCEPTS_SHUTDOWN) - _tprintf(_T("WIN32_EXIT_CODE : %lu \n"), - pServiceStatus->ServiceStatusProcess.dwWin32ExitCode); - _tprintf(_T("SERVICE_EXIT_CODE : %lu \n"), - pServiceStatus->ServiceStatusProcess.dwServiceSpecificExitCode); - _tprintf(_T("CHECKPOINT : %lu\n"), - pServiceStatus->ServiceStatusProcess.dwCheckPoint); - _tprintf(_T("WAIT_HINT : %lu\n"), - pServiceStatus->ServiceStatusProcess.dwWaitHint); - if (bExtended) + int i; + + for (i=0; i < NumServices; i++) { - _tprintf(_T("PID : %lu\n"), - pServiceStatus->ServiceStatusProcess.dwProcessId); - _tprintf(_T("FLAGS : %lu\n"), - pServiceStatus->ServiceStatusProcess.dwServiceFlags); + + _tprintf(_T("SERVICE_NAME: %s\n"), pServiceStatus[i].lpServiceName); + _tprintf(_T("DISPLAY_NAME: %s\n"), pServiceStatus[i].lpDisplayName); + + _tprintf(_T("\tTYPE : %x "), + (unsigned int)pServiceStatus[i].ServiceStatusProcess.dwServiceType); + switch (pServiceStatus[i].ServiceStatusProcess.dwServiceType) + { + case 1 : _tprintf(_T("KERNEL_DRIVER\n")); break; + case 2 : _tprintf(_T("FILE_SYSTEM_DRIVER\n")); break; + case 16 : _tprintf(_T("WIN32_OWN_PROCESS\n")); break; + case 32 : _tprintf(_T("WIN32_SHARE_PROCESS\n")); break; + default : _tprintf(_T("\n")); break; + } + + _tprintf(_T("\tSTATE : %x "), + (unsigned int)pServiceStatus[i].ServiceStatusProcess.dwCurrentState); + + switch (pServiceStatus[i].ServiceStatusProcess.dwCurrentState) + { + case 1 : _tprintf(_T("STOPPED\n")); break; + case 2 : _tprintf(_T("START_PENDING\n")); break; + case 3 : _tprintf(_T("STOP_PENDING\n")); break; + case 4 : _tprintf(_T("RUNNING\n")); break; + case 5 : _tprintf(_T("CONTINUE_PENDING\n")); break; + case 6 : _tprintf(_T("PAUSE_PENDING\n")); break; + case 7 : _tprintf(_T("PAUSED\n")); break; + default : _tprintf(_T("\n")); break; + } + + // _tprintf(_T("\n\taccepted : 0x%x\n\n"), + // pServiceStatus[i].ServiceStatusProcess.dwControlsAccepted); + // (STOPPABLE,NOT_PAUSABLE,ACCEPTS_SHUTDOWN) + + _tprintf(_T("\tWIN32_EXIT_CODE : %d (0x%x)\n"), + (unsigned int)pServiceStatus[i].ServiceStatusProcess.dwWin32ExitCode, + (unsigned int)pServiceStatus[i].ServiceStatusProcess.dwWin32ExitCode); + _tprintf(_T("\tSERVICE_EXIT_CODE : %d (0x%x)\n"), + (unsigned int)pServiceStatus[i].ServiceStatusProcess.dwServiceSpecificExitCode, + (unsigned int)pServiceStatus[i].ServiceStatusProcess.dwServiceSpecificExitCode); + _tprintf(_T("\tCHECKPOINT : 0x%x\n"), + (unsigned int)pServiceStatus[i].ServiceStatusProcess.dwCheckPoint); + _tprintf(_T("\tWAIT_HINT : 0x%x\n"), + (unsigned int)pServiceStatus[i].ServiceStatusProcess.dwWaitHint); + if (bExtended) + { + _tprintf(_T("\tPID : %lu\n"), + pServiceStatus[i].ServiceStatusProcess.dwProcessId); + _tprintf(_T("\tFLAGS : %lu\n"), + pServiceStatus[i].ServiceStatusProcess.dwServiceFlags); + } + + _tprintf(_T("\n")); } + + _tprintf(_T("number : %lu\n"), NumServices); } diff --git a/reactos/subsys/system/sc/usage.c b/reactos/subsys/system/sc/usage.c index b92cd069119..813ed9e31fa 100644 --- a/reactos/subsys/system/sc/usage.c +++ b/reactos/subsys/system/sc/usage.c @@ -8,11 +8,13 @@ * Ged Murphy 20/10/05 Created * */ - +#include #include "sc.h" INT MainUsage(VOID) { + TCHAR c; + _tprintf(_T("DESCRIPTION:\n") _T("\tSC is a command line program used for communicating with\n") _T("\tthe Service Control Manager and its services.\n") @@ -52,6 +54,43 @@ INT MainUsage(VOID) // "\t Lock : Locks the SCM Database\n") // "\t QueryLock : Queries the LockStatus for the SCM Database\n") + _tprintf(_T("\nWould you like to see help for the QUERY and QUERYEX commands? [ y | n ]: ")); + c = _getch(); // _gettch isn't defined in our tchar.h + _tprintf(_T("%c\n"), c); + if (tolower(c) == 'y') + { + _tprintf(_T("QUERY and QUERYEX OPTIONS :\n") + _T(" If the query command is followed by a service name, the status\n") + _T(" for that service is returned. Further options do not apply in\n") + _T(" this case. If the query command is followed by nothing or one of\n") + _T(" the options listed below, the services are enumerated.\n") + _T(" type= Type of services to enumerate (driver, service, all)\n") + _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") + _T("sc queryex messenger - Displays extended status for the messenger service\n") + _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 type= service type= interact - Enumerates all interactive services\n")); +// _T("sc query type= driver group= NDIS - Enumerates all NDIS drivers\n")); + } + + return 0; } -- 2.17.1