Author: gedmurphy Date: Thu Aug 31 21:59:02 2006 New Revision: 23848
URL: http://svn.reactos.org/svn/reactos?rev=23848&view=rev Log: first commit of an overhaul of sc.exe - establish a connection to the SCM for each separate request, allowing the minimum privlidges required, instead of a generic (over privlidged) one. - start to move service printing to separate functions and reduce code duplication - make output 100% as per Windows - fix some commands, e.g. 'interrogate' - improve error checking - improve code structure
Added: trunk/reactos/base/applications/sc/print.c Modified: trunk/reactos/base/applications/sc/control.c trunk/reactos/base/applications/sc/create.c trunk/reactos/base/applications/sc/delete.c trunk/reactos/base/applications/sc/query.c trunk/reactos/base/applications/sc/sc.c trunk/reactos/base/applications/sc/sc.h trunk/reactos/base/applications/sc/sc.rbuild trunk/reactos/base/applications/sc/sc.rc trunk/reactos/base/applications/sc/start.c trunk/reactos/base/applications/sc/usage.c
Modified: trunk/reactos/base/applications/sc/control.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/sc/contro... ============================================================================== --- trunk/reactos/base/applications/sc/control.c (original) +++ trunk/reactos/base/applications/sc/control.c Thu Aug 31 21:59:02 2006 @@ -1,61 +1,95 @@ /* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS SC utility - * FILE: subsys/system/sc/control.c - * PURPOSE: control ReactOS services - * PROGRAMMERS: Ged Murphy (gedmurphy@gmail.com) - * REVISIONS: - * Ged Murphy 20/10/05 Created + * PROJECT: ReactOS Services + * LICENSE: GPL - See COPYING in the top level directory + * FILE: base/system/sc/control.c + * PURPOSE: Stops, pauses and resumes a service + * COPYRIGHT: Copyright 2005 - 2006 Ged Murphy gedmurphy@gmail.com * */
#include "sc.h"
-/* - * handles the following commands: - * control, continue, interrogate, pause, stop - */ +BOOL +Control(DWORD Control, + LPCTSTR ServiceName, + LPCTSTR *Args, + INT ArgCount) +{ + SC_HANDLE hSCManager = NULL; + SC_HANDLE hSc = NULL; + SERVICE_STATUS Status; + DWORD dwDesiredAccess = 0;
-BOOL Control(DWORD Control, LPCTSTR ServiceName, LPCTSTR *Args) +#ifdef SCDBG { - SC_HANDLE hSc; - SERVICE_STATUS Status; - -#ifdef SCDBG - /* testing */ - _tprintf(_T("service to control - %s\n\n"), ServiceName); - _tprintf(_T("command - %lu\n\n"), Control); - _tprintf(_T("Arguments :\n")); - while (*Args) + LPCTSTR *TmpArgs = Args; + INT TmpCnt = ArgCount; + _tprintf(_T("service to control - %s\n"), ServiceName); + _tprintf(_T("command - %lu\n"), Control); + _tprintf(_T("Arguments:\n")); + while (TmpCnt) { - printf("%s\n", *Args); - Args++; + _tprintf(_T(" %s\n"), *TmpArgs); + TmpArgs++; + TmpCnt--; } + _tprintf(_T("\n")); +} #endif /* SCDBG */
- hSc = OpenService(hSCManager, ServiceName, - SERVICE_INTERROGATE | SERVICE_PAUSE_CONTINUE | - SERVICE_STOP | SERVICE_USER_DEFINED_CONTROL | - SERVICE_QUERY_STATUS); + switch (Control) + { + case SERVICE_CONTROL_STOP: + dwDesiredAccess = SERVICE_STOP; + break;
- if (hSc == NULL) - { - _tprintf(_T("openService failed\n")); - ReportLastError(); - return FALSE; + case SERVICE_CONTROL_PAUSE: + dwDesiredAccess = SERVICE_PAUSE_CONTINUE; + break; + + case SERVICE_CONTROL_CONTINUE: + dwDesiredAccess = SERVICE_PAUSE_CONTINUE; + break; + + case SERVICE_CONTROL_INTERROGATE: + dwDesiredAccess = SERVICE_INTERROGATE; + break; + + case SERVICE_CONTROL_SHUTDOWN: + dwDesiredAccess = -1; + break; + }
- if (! ControlService(hSc, Control, &Status)) + hSCManager = OpenSCManager(NULL, + NULL, + SC_MANAGER_CONNECT); + if (hSCManager != NULL) { - _tprintf(_T("[SC] controlService FAILED %lu:\n\n"), GetLastError()); - ReportLastError(); - return FALSE; + hSc = OpenService(hSCManager, + ServiceName, + dwDesiredAccess); + if (hSc != NULL) + { + if (ControlService(hSc, + Control, + &Status)) + { + PrintService(ServiceName, + &Status); + + CloseServiceHandle(hSc); + CloseServiceHandle(hSCManager); + + return TRUE; + } + } + else + _tprintf(_T("[SC] OpenService FAILED %lu:\n\n"), GetLastError()); }
- CloseServiceHandle(hSc); - - /* print the status information */ - - return TRUE; - + ReportLastError(); + if (hSc) CloseServiceHandle(hSc); + if (hSCManager) CloseServiceHandle(hSCManager); + return FALSE; }
Modified: trunk/reactos/base/applications/sc/create.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/sc/create... ============================================================================== --- trunk/reactos/base/applications/sc/create.c (original) +++ trunk/reactos/base/applications/sc/create.c Thu Aug 31 21:59:02 2006 @@ -1,11 +1,9 @@ /* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS SC utility - * FILE: subsys/system/sc/create.c - * PURPOSE: control ReactOS services - * PROGRAMMERS: Ged Murphy (gedmurphy@gmail.com) - * REVISIONS: - * Ged Murphy 20/10/05 Created + * PROJECT: ReactOS Services + * LICENSE: GPL - See COPYING in the top level directory + * FILE: base/system/sc/create.c + * PURPOSE: Create a service + * COPYRIGHT: Copyright 2005 - 2006 Ged Murphy gedmurphy@gmail.com * */
@@ -13,46 +11,81 @@
BOOL Create(LPCTSTR ServiceName, LPCTSTR *ServiceArgs) { + SC_HANDLE hSCManager; SC_HANDLE hSc; - LPCTSTR BinaryPathName = *++ServiceArgs; -// LPCTSTR *Options = ++ServiceArgs; - - if ((! ServiceName) || (! BinaryPathName)) - return CreateUsage(); + BOOL bRet = FALSE;
-#ifdef SCDBG - /* testing */ - printf("service to create - %s\n", ServiceName); - printf("Binary path - %s\n", BinaryPathName); - printf("Arguments :\n"); - while (*Options) + DWORD dwServiceType = SERVICE_WIN32_OWN_PROCESS; + DWORD dwStartType = SERVICE_DEMAND_START; + DWORD dwErrorControl = SERVICE_ERROR_NORMAL; + LPCTSTR lpBinaryPathName = NULL; + LPCTSTR lpLoadOrderGroup = NULL; + LPDWORD lpdwTagId = NULL; + LPCTSTR lpDependencies = NULL; + LPCTSTR lpServiceStartName = NULL; + LPCTSTR lpPassword = NULL; + + /* quick hack to get it working */ + lpBinaryPathName = *ServiceArgs; + +#ifdef SCDBG +{ + _tprintf(_T("service name - %s\n"), ServiceName); + _tprintf(_T("display name - %s\n"), ServiceName); + _tprintf(_T("service type - %lu\n"), dwServiceType); + _tprintf(_T("start type - %lu\n"), dwStartType); + _tprintf(_T("error control - %lu\n"), dwErrorControl); + _tprintf(_T("Binary path - %s\n"), lpBinaryPathName); + _tprintf(_T("load order group - %s\n"), lpLoadOrderGroup); + _tprintf(_T("tag - %lu\n"), lpdwTagId); + _tprintf(_T("dependincies - %s\n"), lpDependencies); + _tprintf(_T("account start name - %s\n"), lpServiceStartName); + _tprintf(_T("account password - %s\n"), lpPassword); +} +#endif + + if (!ServiceName) { - printf("%s\n", *Options); - Options++; + CreateUsage(); + return FALSE; } -#endif + + hSCManager = OpenSCManager(NULL, + NULL, + SC_MANAGER_CREATE_SERVICE); + if (hSCManager == NULL) + { + ReportLastError(); + return FALSE; + } + hSc = CreateService(hSCManager, ServiceName, ServiceName, SERVICE_ALL_ACCESS, - SERVICE_WIN32_OWN_PROCESS, - SERVICE_DEMAND_START, - SERVICE_ERROR_NORMAL, - BinaryPathName, - NULL, - NULL, - NULL, - NULL, - NULL); + dwServiceType, + dwStartType, + dwErrorControl, + lpBinaryPathName, + lpLoadOrderGroup, + lpdwTagId, + lpDependencies, + lpServiceStartName, + lpPassword);
if (hSc == NULL) { - _tprintf(_T("CreateService failed\n")); ReportLastError(); - return FALSE; + CloseServiceHandle(hSCManager); + } + else + { + _tprintf(_T("[SC] CreateService SUCCESS\n")); + + CloseServiceHandle(hSc); + CloseServiceHandle(hSCManager); + bRet = TRUE; }
- _tprintf(_T("[SC] CreateService SUCCESS\n")); - CloseServiceHandle(hSc); - return TRUE; + return bRet; }
Modified: trunk/reactos/base/applications/sc/delete.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/sc/delete... ============================================================================== --- trunk/reactos/base/applications/sc/delete.c (original) +++ trunk/reactos/base/applications/sc/delete.c Thu Aug 31 21:59:02 2006 @@ -1,11 +1,9 @@ /* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS SC utility - * FILE: subsys/system/sc/delete.c - * PURPOSE: control ReactOS services - * PROGRAMMERS: Ged Murphy (gedmurphy@gmail.com) - * REVISIONS: - * Ged Murphy 20/10/05 Created + * PROJECT: ReactOS Services + * LICENSE: GPL - See COPYING in the top level directory + * FILE: base/system/sc/delete.c + * PURPOSE: Delete a service + * COPYRIGHT: Copyright 2005 - 2006 Ged Murphy gedmurphy@gmail.com * */
@@ -13,30 +11,39 @@
BOOL Delete(LPCTSTR ServiceName) { - SC_HANDLE hSc; + SC_HANDLE hSCManager = NULL; + SC_HANDLE hSc = NULL;
-#ifdef SCDBG - /* testing */ - printf("service to delete - %s\n\n", ServiceName); +#ifdef SCDBG +{ + _tprintf(_T("service to delete - %s\n\n"), ServiceName); +} #endif
- hSc = OpenService(hSCManager, ServiceName, DELETE); + hSCManager = OpenSCManager(NULL, + NULL, + SC_MANAGER_CONNECT); + if (hSCManager != NULL) + { + hSc = OpenService(hSCManager, ServiceName, DELETE); + if (hSc != NULL) + { + if (DeleteService(hSc)) + { + _tprintf(_T("[SC] DeleteService SUCCESS\n"));
- if (hSc == NULL) - { - _tprintf(_T("openService failed\n")); - ReportLastError(); - return FALSE; + CloseServiceHandle(hSc); + CloseServiceHandle(hSCManager); + + return TRUE; + } + } }
- if (! DeleteService(hSc)) - { - _tprintf(_T("DeleteService failed\n")); - ReportLastError(); - return FALSE; - } + ReportLastError();
- _tprintf(_T("[SC] DeleteService SUCCESS\n")); - CloseServiceHandle(hSc); - return TRUE; + if (hSc) CloseServiceHandle(hSc); + if (hSCManager) CloseServiceHandle(hSCManager); + + return FALSE; }
Added: trunk/reactos/base/applications/sc/print.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/sc/print.... ============================================================================== --- trunk/reactos/base/applications/sc/print.c (added) +++ trunk/reactos/base/applications/sc/print.c Thu Aug 31 21:59:02 2006 @@ -1,0 +1,84 @@ +#include "sc.h" + + +VOID +PrintServiceEx(LPCTSTR lpServiceName, + LPSERVICE_STATUS_PROCESS pStatusEx) +{ + SERVICE_STATUS Status; + + /*FIXME: quick hack, assign values 1 by 1 */ + CopyMemory(&Status, pStatusEx, sizeof(SERVICE_STATUS)); + + PrintService(lpServiceName, + &Status); + + _tprintf(_T("\tPID : %lu\n"), + pStatusEx->dwProcessId); + _tprintf(_T("\tFLAGS : %lu\n"), + pStatusEx->dwServiceFlags); +} + + +VOID +PrintService(LPCTSTR lpServiceName, + LPSERVICE_STATUS pStatus) +{ + _tprintf(_T("SERVICE_NAME: %s\n"), lpServiceName); + + _tprintf(_T("\tTYPE : %x "), + (unsigned int)pStatus->dwServiceType); + switch (pStatus->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)pStatus->dwCurrentState); + + switch (pStatus->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("\t\t\t\t(")); + + if (pStatus->dwControlsAccepted & SERVICE_ACCEPT_STOP) + _tprintf(_T("STOPPABLE,")); + else + _tprintf(_T("NOT_STOPPABLE,")); + + if (pStatus->dwControlsAccepted & SERVICE_ACCEPT_PAUSE_CONTINUE) + _tprintf(_T("PAUSABLE,")); + else + _tprintf(_T("NOT_PAUSABLE,")); + + if (pStatus->dwControlsAccepted & SERVICE_ACCEPT_SHUTDOWN) + _tprintf(_T("???")); + else + _tprintf(_T("IGNORES_SHUTDOWN")); + + _tprintf(_T(")\n")); + + _tprintf(_T("\tWIN32_EXIT_CODE : %d (0x%x)\n"), + (unsigned int)pStatus->dwWin32ExitCode, + (unsigned int)pStatus->dwWin32ExitCode); + _tprintf(_T("\tSERVICE_EXIT_CODE : %d (0x%x)\n"), + (unsigned int)pStatus->dwServiceSpecificExitCode, + (unsigned int)pStatus->dwServiceSpecificExitCode); + _tprintf(_T("\tCHECKPOINT : 0x%x\n"), + (unsigned int)pStatus->dwCheckPoint); + _tprintf(_T("\tWAIT_HINT : 0x%x\n"), + (unsigned int)pStatus->dwWaitHint); +}
Modified: trunk/reactos/base/applications/sc/query.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/sc/query.... ============================================================================== --- trunk/reactos/base/applications/sc/query.c (original) +++ trunk/reactos/base/applications/sc/query.c Thu Aug 31 21:59:02 2006 @@ -17,7 +17,7 @@ #include "sc.h"
/* local function decs */ -VOID PrintService(BOOL bExtended); +VOID PrintService2(BOOL bExtended); BOOL EnumServices(DWORD ServiceType, DWORD ServiceState); BOOL QueryService(LPCTSTR ServiceName, BOOL bExtended);
@@ -33,14 +33,14 @@ { /* get default values */ EnumServices(SERVICE_WIN32, SERVICE_ACTIVE); - + /* print default values */ - PrintService(bExtended); + PrintService2(bExtended); } else if (_tcsicmp(ServiceName, _T("type=")) == 0) { LPCTSTR Type = *ServiceArgs; - + if (_tcsicmp(Type, _T("driver")) == 0) EnumServices(SERVICE_DRIVER, SERVICE_ACTIVE); else if (_tcsicmp(Type, _T("service")) == 0) @@ -52,8 +52,8 @@ _tprintf(_T("\nERROR following "type="!\n")); _tprintf(_T("Must be "driver" or "service" or "all"\n")); } - - PrintService(bExtended); + + PrintService2(bExtended); } else if(_tcsicmp(ServiceName, _T("state=")) == 0) { @@ -68,8 +68,8 @@ _tprintf(_T("\nERROR following "state="!\n")); _tprintf(_T("Must be "active" or "inactive" or "all"\n")); } - - PrintService(bExtended); + + PrintService2(bExtended); } /* else if(_tcsicmp(ServiceName, _T("bufsize="))) @@ -82,7 +82,7 @@ { QueryService(ServiceName, bExtended); } - + return TRUE; }
@@ -90,11 +90,21 @@ BOOL QueryService(LPCTSTR ServiceName, BOOL bExtended) { + SC_HANDLE hSCManager; SERVICE_STATUS_PROCESS *pServiceInfo = NULL; SC_HANDLE hSc; DWORD BufSiz = 0; DWORD BytesNeeded = 0; DWORD Ret; + + hSCManager = OpenSCManager(NULL, + NULL, + SC_MANAGER_CONNECT); + if (hSCManager == NULL) + { + ReportLastError(); + return FALSE; + }
hSc = OpenService(hSCManager, ServiceName, SERVICE_QUERY_STATUS);
@@ -143,7 +153,7 @@ } }
- + _tprintf(_T("SERVICE_NAME: %s\n"), ServiceName);
_tprintf(_T("\tTYPE : %x "), @@ -193,7 +203,7 @@ _tprintf(_T("\tFLAGS : %lu\n"), pServiceInfo->dwServiceFlags); } - + HeapFree(GetProcessHeap(), 0, pServiceInfo);
return TRUE; @@ -203,10 +213,20 @@ BOOL EnumServices(DWORD ServiceType, DWORD ServiceState) { + SC_HANDLE hSCManager; DWORD BufSize = 0; DWORD BytesNeeded = 0; DWORD ResumeHandle = 0; DWORD Ret; + + hSCManager = OpenSCManager(NULL, + NULL, + SC_MANAGER_ENUMERATE_SERVICE); + if (hSCManager == NULL) + { + ReportLastError(); + return FALSE; + }
/* determine required buffer size */ Ret = EnumServicesStatusEx(hSCManager, @@ -262,10 +282,10 @@
VOID -PrintService(BOOL bExtended) +PrintService2(BOOL bExtended) { DWORD i; - + for (i=0; i < NumServices; i++) {
@@ -322,6 +342,6 @@
_tprintf(_T("\n")); } - + _tprintf(_T("number : %lu\n"), NumServices); }
Modified: trunk/reactos/base/applications/sc/sc.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/sc/sc.c?r... ============================================================================== --- trunk/reactos/base/applications/sc/sc.c (original) +++ trunk/reactos/base/applications/sc/sc.c Thu Aug 31 21:59:02 2006 @@ -1,11 +1,9 @@ /* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS SC utility - * FILE: subsys/system/sc/sc.c - * PURPOSE: control ReactOS services - * PROGRAMMERS: Ged Murphy (gedmurphy@gmail.com) - * REVISIONS: - * Ged Murphy 20/10/05 Created + * PROJECT: ReactOS Services + * LICENSE: GPL - See COPYING in the top level directory + * FILE: base/system/sc/sc.c + * PURPOSE: parse command line + * COPYRIGHT: Copyright 2005 - 2006 Ged Murphy gedmurphy@gmail.com * */
@@ -13,13 +11,14 @@
SC_HANDLE hSCManager;
-DWORD ReportLastError(VOID) +VOID +ReportLastError(VOID) { LPVOID lpMsgBuf; DWORD RetVal;
DWORD ErrorCode = GetLastError(); - if (ErrorCode != ERROR_SUCCESS) + if (ErrorCode != ERROR_SUCCESS) { RetVal = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | @@ -34,106 +33,133 @@ if (RetVal != 0) { _tprintf(_T("%s"), (LPTSTR)lpMsgBuf); - LocalFree(lpMsgBuf); - /* return number of TCHAR's stored in output buffer - * excluding '\0' - as FormatMessage does*/ - return RetVal; - } - } - return 0; -} - - -INT ScControl(LPTSTR MachineName, // remote machine name - LPCTSTR Command, // sc command - LPCTSTR ServiceName, // name of service - LPCTSTR *ServiceArgs, // any options - DWORD ArgCount) // argument counter -{ - /* count trailing arguments */ - ArgCount -= 3; - - if (MachineName) + } + } +} + + +static INT +ScControl(LPCTSTR Server, // remote machine name + LPCTSTR Command, // sc command + LPCTSTR ServiceName, // name of service + LPCTSTR *ServiceArgs, // any options + DWORD ArgCount) // argument counter +{ + if (Server) { _tprintf(_T("Remote service control is not yet implemented\n")); return 2; } - - /* if we are emurating the services, we don't need administrator access */ - if ( (_tcsicmp(Command, _T("query")) == 0) || (_tcsicmp(Command, _T("queryex")) == 0) ) - hSCManager = OpenSCManager(MachineName, NULL, SC_MANAGER_ENUMERATE_SERVICE); - else - hSCManager = OpenSCManager(MachineName, NULL, SC_MANAGER_ALL_ACCESS); - if (hSCManager == NULL) - { - _tprintf(_T("[SC] OpenSCManager FAILED %lu:\n\n"), GetLastError()); - ReportLastError(); - return -1; - } - - /* emurate command */ - if (_tcsicmp(Command, _T("query")) == 0) - Query(ServiceName, ServiceArgs, FALSE); - - else if (_tcsicmp(Command, _T("queryex")) == 0) - Query(ServiceName, ServiceArgs, TRUE); - - else if (_tcsicmp(Command, _T("start")) == 0) - { - if (ServiceName) - Start(ServiceName, ServiceArgs, ArgCount); + + if (!lstrcmpi(Command, _T("query"))) + { + Query(ServiceName, + ServiceArgs, + FALSE); + } + else if (!lstrcmpi(Command, _T("queryex"))) + { + Query(ServiceName, + ServiceArgs, + TRUE); + } + else if (!lstrcmpi(Command, _T("start"))) + { + if (ServiceName) + { + Start(ServiceName, + ServiceArgs, + ArgCount); + } else StartUsage(); } - else if (_tcsicmp(Command, _T("pause")) == 0) - { - if (ServiceName) - Control(SERVICE_CONTROL_PAUSE, ServiceName, ServiceArgs); + else if (!lstrcmpi(Command, _T("pause"))) + { + if (ServiceName) + { + Control(SERVICE_CONTROL_PAUSE, + ServiceName, + ServiceArgs, + ArgCount); + } else PauseUsage(); } - else if (_tcsicmp(Command, _T("interrogate")) == 0) - { - if (ServiceName) - Control(SERVICE_CONTROL_INTERROGATE, ServiceName, ServiceArgs); + else if (!lstrcmpi(Command, _T("interrogate"))) + { + if (ServiceName) + { + Control(SERVICE_CONTROL_INTERROGATE, + ServiceName, + ServiceArgs, + ArgCount); + } else InterrogateUsage(); } - else if (_tcsicmp(Command, _T("stop")) == 0) - { - if (ServiceName) - Control(SERVICE_CONTROL_STOP, ServiceName, ServiceArgs); + else if (!lstrcmpi(Command, _T("stop"))) + { + if (ServiceName) + { + Control(SERVICE_CONTROL_STOP, + ServiceName, + ServiceArgs, + ArgCount); + } else StopUsage(); } - else if (_tcsicmp(Command, _T("continue")) == 0) - { - if (ServiceName) - Control(SERVICE_CONTROL_CONTINUE, ServiceName, ServiceArgs); + else if (!lstrcmpi(Command, _T("continue"))) + { + if (ServiceName) + { + Control(SERVICE_CONTROL_CONTINUE, + ServiceName, + ServiceArgs, + ArgCount); + } else ContinueUsage(); } - else if (_tcsicmp(Command, _T("delete")) == 0) + else if (!lstrcmpi(Command, _T("delete"))) { if (ServiceName) Delete(ServiceName); else DeleteUsage(); } - else if (_tcsicmp(Command, _T("create")) == 0) + else if (!lstrcmpi(Command, _T("create"))) { if (*ServiceArgs) - Create(ServiceName, ServiceArgs); + Create(ServiceName, + ServiceArgs); else CreateUsage(); } - else if (_tcsicmp(Command, _T("control")) == 0) - { - if (ServiceName) - Control(0, ServiceName, ServiceArgs); - else - ContinueUsage(); + else if (!lstrcmpi(Command, _T("control"))) + { + INT CtlValue; + + CtlValue = _ttoi(ServiceArgs[0]); + ServiceArgs++; + ArgCount--; + + if (ServiceName) + { + if ((CtlValue >=128) && CtlValue <= 255) + { + Control(CtlValue, + ServiceName, + ServiceArgs, + ArgCount); + + return 0; + } + } + + ContinueUsage(); } return 0; } @@ -144,31 +170,47 @@
int _tmain(int argc, LPCTSTR argv[]) { - LPTSTR MachineName = NULL; // remote machine - LPCTSTR Command = NULL; // sc command - LPCTSTR ServiceName = NULL; // Name of service + LPCTSTR Server = NULL; // remote machine + LPCTSTR Command = NULL; // sc command + LPCTSTR ServiceName = NULL; // name of service
if (argc < 2) - return MainUsage(); + { + MainUsage(); + return -1; + }
/* get server name */ if ((argv[1][0] == '\') && (argv[1][1] == '\')) { if (argc < 3) - return MainUsage(); - - _tcscpy(MachineName, argv[1]); + { + MainUsage(); + return -1; + } + + Server = argv[1]; Command = argv[2]; if (argc > 3) ServiceName = argv[3]; - return ScControl(MachineName, Command, ServiceName, &argv[4], argc); + + return ScControl(Server, + Command, + ServiceName, + &argv[4], + argc-4); } else { Command = argv[1]; if (argc > 2) ServiceName = argv[2]; - return ScControl(MachineName, Command, ServiceName, &argv[3], argc); + + return ScControl(Server, + Command, + ServiceName, + &argv[3], + argc-3); } }
@@ -191,13 +233,13 @@ } swprintf(argvW[i], L"%hs", argv[i]); } - + if (j == 0) { /* no error converting the parameters, call wmain() */ Ret = wmain(argc, (LPCTSTR *)argvW); } - + /* free the arguments */ for (i = 0; i < argc; i++) { @@ -206,7 +248,7 @@ } free(argvW); } - + return Ret; } #endif
Modified: trunk/reactos/base/applications/sc/sc.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/sc/sc.h?r... ============================================================================== --- trunk/reactos/base/applications/sc/sc.h (original) +++ trunk/reactos/base/applications/sc/sc.h Thu Aug 31 21:59:02 2006 @@ -3,28 +3,29 @@ #include <stdio.h> #include <tchar.h>
-extern SC_HANDLE hSCManager; // declared in sc.c +#define SCDBG
-//#define SCDBG +VOID PrintService(LPCTSTR ServiceName, LPSERVICE_STATUS pStatus); +VOID PrintServiceEx(LPCTSTR ServiceName, LPSERVICE_STATUS_PROCESS pStatus);
/* control functions */ BOOL Query(LPCTSTR ServiceName, LPCTSTR *ServiceArgs, BOOL bExtended); BOOL Start(LPCTSTR ServiceName, LPCTSTR *ServiceArgs, INT ArgCount); BOOL Create(LPCTSTR ServiceName, LPCTSTR *ServiceArgs); BOOL Delete(LPCTSTR ServiceName); -BOOL Control(DWORD Control, LPCTSTR ServiceName, LPCTSTR *Args); +BOOL Control(DWORD Control, LPCTSTR ServiceName, LPCTSTR *Args, INT ArgCount);
/* print and error functions */ -DWORD ReportLastError(VOID); +VOID ReportLastError(VOID);
/* usage functions */ -INT MainUsage(VOID); -INT StartUsage(VOID); -INT PauseUsage(VOID); -INT InterrogateUsage(VOID); -INT ContinueUsage(VOID); -INT StopUsage(VOID); -INT ConfigUsage(VOID); -INT DescriptionUsage(VOID); -INT DeleteUsage(VOID); -INT CreateUsage(VOID); +VOID MainUsage(VOID); +VOID StartUsage(VOID); +VOID PauseUsage(VOID); +VOID InterrogateUsage(VOID); +VOID ContinueUsage(VOID); +VOID StopUsage(VOID); +VOID ConfigUsage(VOID); +VOID DescriptionUsage(VOID); +VOID DeleteUsage(VOID); +VOID CreateUsage(VOID);
Modified: trunk/reactos/base/applications/sc/sc.rbuild URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/sc/sc.rbu... ============================================================================== --- trunk/reactos/base/applications/sc/sc.rbuild (original) +++ trunk/reactos/base/applications/sc/sc.rbuild Thu Aug 31 21:59:02 2006 @@ -7,12 +7,13 @@ <define name="_UNICODE" /> <library>kernel32</library> <library>advapi32</library> - <file>sc.c</file> - <file>start.c</file> - <file>query.c</file> <file>control.c</file> <file>create.c</file> <file>delete.c</file> + <file>print.c</file> + <file>query.c</file> + <file>sc.c</file> + <file>start.c</file> <file>usage.c</file> <file>sc.rc</file> <pch>sc.h</pch>
Modified: trunk/reactos/base/applications/sc/sc.rc URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/sc/sc.rc?... ============================================================================== --- trunk/reactos/base/applications/sc/sc.rc (original) +++ trunk/reactos/base/applications/sc/sc.rc Thu Aug 31 21:59:02 2006 @@ -1,4 +1,10 @@ +#include <windows.h> +#include <commctrl.h> +#include "resource.h" + #define REACTOS_STR_FILE_DESCRIPTION "Services control application\0" #define REACTOS_STR_INTERNAL_NAME "sc\0" #define REACTOS_STR_ORIGINAL_FILENAME "sc.exe\0" #include <reactos/version.rc> + +//#include "En.rc"
Modified: trunk/reactos/base/applications/sc/start.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/sc/start.... ============================================================================== --- trunk/reactos/base/applications/sc/start.c (original) +++ trunk/reactos/base/applications/sc/start.c Thu Aug 31 21:59:02 2006 @@ -1,11 +1,9 @@ /* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS SC utility - * FILE: subsys/system/sc/start.c - * PURPOSE: control ReactOS services - * PROGRAMMERS: Ged Murphy (gedmurphy@gmail.com) - * REVISIONS: - * Ged Murphy 20/10/05 Created + * PROJECT: ReactOS Services + * LICENSE: GPL - See COPYING in the top level directory + * FILE: base/system/sc/start.c + * PURPOSE: Start a service + * COPYRIGHT: Copyright 2005 - 2006 Ged Murphy gedmurphy@gmail.com * */
@@ -13,99 +11,91 @@
BOOL Start(LPCTSTR ServiceName, LPCTSTR *ServiceArgs, INT ArgCount) { - SC_HANDLE hSc; - SERVICE_STATUS_PROCESS ServiceStatus, ServiceStatus2; - DWORD BytesNeeded; + SC_HANDLE hSCManager = NULL; + SC_HANDLE hSc = NULL; + LPSERVICE_STATUS_PROCESS pServiceInfo = NULL; + DWORD BufSiz = 0; + DWORD BytesNeeded = 0; + DWORD Ret;
-#ifdef SCDBG - /* testing */ - _tprintf(_T("service to start - %s\n\n"), ServiceName); - _tprintf(_T("Arguments :\n")); - while (*ServiceArgs) +#ifdef SCDBG +{ + LPCTSTR *TmpArgs = ServiceArgs; + INT TmpCnt = ArgCount; + _tprintf(_T("service to control - %s\n"), ServiceName); + _tprintf(_T("Arguments:\n")); + while (TmpCnt) { - printf("%s\n", *ServiceArgs); - ServiceArgs++; + _tprintf(_T(" %s\n"), *TmpArgs); + TmpArgs++; + TmpCnt--; } -#endif + _tprintf(_T("\n")); +} +#endif /* SCDBG */
- /* get a handle to the service requested for starting */ - hSc = OpenService(hSCManager, ServiceName, SERVICE_ALL_ACCESS); + hSCManager = OpenSCManager(NULL, + NULL, + SC_MANAGER_CONNECT); + if (hSCManager == NULL) + goto fail; + + hSc = OpenService(hSCManager, + ServiceName, + SERVICE_START | SERVICE_QUERY_STATUS);
if (hSc == NULL) { _tprintf(_T("openService failed\n")); - ReportLastError(); - return FALSE; + goto fail; }
- /* start the service opened */ - if (! StartService(hSc, ArgCount, ServiceArgs)) + if (! StartService(hSc, + ArgCount, + ServiceArgs)) { _tprintf(_T("[SC] StartService FAILED %lu:\n\n"), GetLastError()); - ReportLastError(); - return FALSE; - } - - if (! QueryServiceStatusEx( - hSc, - SC_STATUS_PROCESS_INFO, - (LPBYTE)&ServiceStatus, - sizeof(SERVICE_STATUS_PROCESS), - &BytesNeeded)) - { - _tprintf(_T("QueryServiceStatusEx 1 failed\n")); - ReportLastError(); - return FALSE; + goto fail; }
- - while (ServiceStatus.dwCurrentState == SERVICE_START_PENDING) + Ret = QueryServiceStatusEx(hSc, + SC_STATUS_PROCESS_INFO, + NULL, + BufSiz, + &BytesNeeded); + if ((Ret != 0) || (GetLastError() != ERROR_INSUFFICIENT_BUFFER)) //FIXME: check this + goto fail; + + + pServiceInfo = (LPSERVICE_STATUS_PROCESS)HeapAlloc(GetProcessHeap(), + 0, + BytesNeeded); + if (pServiceInfo == NULL) + goto fail; + + if (!QueryServiceStatusEx(hSc, + SC_STATUS_PROCESS_INFO, + (LPBYTE)pServiceInfo, + BytesNeeded, + &BytesNeeded)) { - /* wait before checking status */ - Sleep(ServiceStatus.dwWaitHint); - - /* check status again */ - if (! QueryServiceStatusEx( - hSc, - SC_STATUS_PROCESS_INFO, - (LPBYTE)&ServiceStatus, - sizeof(SERVICE_STATUS_PROCESS), - &BytesNeeded)) - { - _tprintf(_T("QueryServiceStatusEx 2 failed\n")); - ReportLastError(); - return FALSE; - } + goto fail; }
- QueryServiceStatusEx(hSc, SC_STATUS_PROCESS_INFO, (LPBYTE)&ServiceStatus2, - sizeof(SERVICE_STATUS_PROCESS), &BytesNeeded); + PrintServiceEx(ServiceName, + pServiceInfo);
+ HeapFree(GetProcessHeap(), 0, pServiceInfo); CloseServiceHandle(hSc); - - if (ServiceStatus.dwCurrentState == SERVICE_RUNNING) - { - _tprintf(_T("\nSERVICE_NAME: %s\n"), ServiceName); - _tprintf(_T("\tTYPE : %lu\n"), ServiceStatus2.dwServiceType); - _tprintf(_T("\tSTATE : %lu\n"), ServiceStatus2.dwCurrentState); - _tprintf(_T("\tWIN32_EXIT_CODE : %lu\n"), ServiceStatus2.dwWin32ExitCode); - _tprintf(_T("\tCHECKPOINT : %lu\n"), ServiceStatus2.dwCheckPoint); - _tprintf(_T("\tWAIT_HINT : %lu\n"), ServiceStatus2.dwWaitHint); - _tprintf(_T("\tPID : %lu\n"), ServiceStatus2.dwProcessId); - _tprintf(_T("\tFLAGS : %lu\n"), ServiceStatus2.dwServiceFlags); + CloseServiceHandle(hSCManager);
- return TRUE; - } - else - { - _tprintf(_T("Failed to start %s\n"), ServiceName); - _tprintf(_T("Curent state: %lu\n"), ServiceStatus.dwCurrentState); - _tprintf(_T("Exit code: %lu\n"), ServiceStatus.dwWin32ExitCode); - _tprintf(_T("Service Specific exit code: %lu\n"), - ServiceStatus.dwServiceSpecificExitCode); - _tprintf(_T("Check point: %lu\n"), ServiceStatus.dwCheckPoint); - _tprintf(_T("Wait hint: %lu\n"), ServiceStatus.dwWaitHint); - - return FALSE; - } + return TRUE; + +fail: + ReportLastError(); + if (pServiceInfo) HeapFree(GetProcessHeap(), 0, pServiceInfo); + if (hSc) CloseServiceHandle(hSc); + if (hSCManager) CloseServiceHandle(hSCManager); + return FALSE; + }
Modified: trunk/reactos/base/applications/sc/usage.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/sc/usage.... ============================================================================== --- trunk/reactos/base/applications/sc/usage.c (original) +++ trunk/reactos/base/applications/sc/usage.c Thu Aug 31 21:59:02 2006 @@ -10,7 +10,7 @@ */ #include "sc.h"
-INT MainUsage(VOID) +VOID MainUsage(VOID) { INT c;
@@ -88,84 +88,67 @@ _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; }
-INT StartUsage(VOID) +VOID StartUsage(VOID) { _tprintf(_T("DESCRIPTION:\n") _T(" Starts a service running.\n") _T("USAGE:\n") _T(" sc <server> start [service name] <arg1> <arg2> ...\n")); - - return 0; }
-INT PauseUsage(VOID) +VOID PauseUsage(VOID) { _tprintf(_T("DESCRIPTION:\n") _T(" Sends a PAUSE control request to a service.\n") _T("USAGE:\n") _T(" sc <server> pause [service name]\n")); - - return 0; }
-INT InterrogateUsage(VOID) +VOID InterrogateUsage(VOID) { _tprintf(_T("DESCRIPTION:\n") _T(" Sends an INTERROGATE control request to a service.\n") _T("USAGE:\n") _T(" sc <server> interrogate [service name]\n")); - - return 0; }
-INT StopUsage(VOID) +VOID StopUsage(VOID) { _tprintf(_T("DESCRIPTION:\n") _T(" Sends an STOP control request to a service.\n") _T("USAGE:\n") _T(" sc <server> stop [service name]\n")); - - return 0; }
-INT ContinueUsage(VOID) +VOID ContinueUsage(VOID) { _tprintf(_T("DESCRIPTION:\n") _T(" Sends an CONTINUE control request to a service.\n") _T("USAGE:\n") _T(" sc <server> continue [service name]\n")); - - return 0; }
-INT ConfigUsage(VOID) +VOID ConfigUsage(VOID) { _tprintf(_T("not yet implemented\n")); - - return 0; }
-INT DescriptionUsage(VOID) +VOID DescriptionUsage(VOID) { _tprintf(_T("DESCRIPTION:\n") _T(" Sets the description string for a service.\n") _T("USAGE:\n") _T(" sc <server> description [service name]\n")); - - return 0; }
-INT DeleteUsage(VOID) +VOID DeleteUsage(VOID) { _tprintf(_T("DESCRIPTION:\n") _T(" Deletes a service entry from the registry.\n") @@ -174,11 +157,9 @@ _T(" for deletion.\n") _T("USAGE:\n") _T(" sc <server> delete [service name]\n")); - - return 0; }
-INT CreateUsage(VOID) +VOID CreateUsage(VOID) { _tprintf(_T("Creates a service entry in the registry and Service Database.\n") _T("SYNTAX:\n") @@ -199,6 +180,4 @@ _T(" (default = LocalSystem)\n") _T(" DisplayName= <display name>\n") _T(" password= <password>\n")); - - return 0; }