From 158e4c116adc544a51f803b0695281633a2af08d Mon Sep 17 00:00:00 2001 From: Ged Murphy Date: Thu, 31 Aug 2006 17:59:02 +0000 Subject: [PATCH] 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 svn path=/trunk/; revision=23848 --- reactos/base/applications/sc/control.c | 116 ++++++++++------ reactos/base/applications/sc/create.c | 111 +++++++++------ reactos/base/applications/sc/delete.c | 59 ++++---- reactos/base/applications/sc/print.c | 84 ++++++++++++ reactos/base/applications/sc/query.c | 48 +++++-- reactos/base/applications/sc/sc.c | 182 +++++++++++++++---------- reactos/base/applications/sc/sc.h | 29 ++-- reactos/base/applications/sc/sc.rbuild | 7 +- reactos/base/applications/sc/sc.rc | 6 + reactos/base/applications/sc/start.c | 156 ++++++++++----------- reactos/base/applications/sc/usage.c | 41 ++---- 11 files changed, 518 insertions(+), 321 deletions(-) create mode 100644 reactos/base/applications/sc/print.c diff --git a/reactos/base/applications/sc/control.c b/reactos/base/applications/sc/control.c index 2fac5fe6198..e8652917deb 100644 --- a/reactos/base/applications/sc/control.c +++ b/reactos/base/applications/sc/control.c @@ -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 * */ #include "sc.h" -/* - * handles the following commands: - * control, continue, interrogate, pause, stop - */ - -BOOL Control(DWORD Control, LPCTSTR ServiceName, LPCTSTR *Args) +BOOL +Control(DWORD Control, + LPCTSTR ServiceName, + LPCTSTR *Args, + INT ArgCount) { - SC_HANDLE hSc; + SC_HANDLE hSCManager = NULL; + SC_HANDLE hSc = NULL; SERVICE_STATUS Status; + DWORD dwDesiredAccess = 0; -#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) +#ifdef SCDBG +{ + 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); - - if (hSc == NULL) + switch (Control) { - _tprintf(_T("openService failed\n")); - ReportLastError(); - return FALSE; + case SERVICE_CONTROL_STOP: + dwDesiredAccess = SERVICE_STOP; + break; + + 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; } diff --git a/reactos/base/applications/sc/create.c b/reactos/base/applications/sc/create.c index 89e1ea5a2e8..9c14096507b 100644 --- a/reactos/base/applications/sc/create.c +++ b/reactos/base/applications/sc/create.c @@ -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 * */ @@ -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 - hSc = CreateService(hSCManager, - ServiceName, - ServiceName, - SERVICE_ALL_ACCESS, - SERVICE_WIN32_OWN_PROCESS, - SERVICE_DEMAND_START, - SERVICE_ERROR_NORMAL, - BinaryPathName, - NULL, - NULL, - NULL, - NULL, - NULL); - if (hSc == NULL) + hSCManager = OpenSCManager(NULL, + NULL, + SC_MANAGER_CREATE_SERVICE); + if (hSCManager == NULL) { - _tprintf(_T("CreateService failed\n")); ReportLastError(); return FALSE; } - _tprintf(_T("[SC] CreateService SUCCESS\n")); - CloseServiceHandle(hSc); - return TRUE; + hSc = CreateService(hSCManager, + ServiceName, + ServiceName, + SERVICE_ALL_ACCESS, + dwServiceType, + dwStartType, + dwErrorControl, + lpBinaryPathName, + lpLoadOrderGroup, + lpdwTagId, + lpDependencies, + lpServiceStartName, + lpPassword); + + if (hSc == NULL) + { + ReportLastError(); + CloseServiceHandle(hSCManager); + } + else + { + _tprintf(_T("[SC] CreateService SUCCESS\n")); + + CloseServiceHandle(hSc); + CloseServiceHandle(hSCManager); + bRet = TRUE; + } + + return bRet; } diff --git a/reactos/base/applications/sc/delete.c b/reactos/base/applications/sc/delete.c index 2873108ee3e..fea18b60e53 100644 --- a/reactos/base/applications/sc/delete.c +++ b/reactos/base/applications/sc/delete.c @@ -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 * */ @@ -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); - - if (hSc == NULL) + hSCManager = OpenSCManager(NULL, + NULL, + SC_MANAGER_CONNECT); + if (hSCManager != NULL) { - _tprintf(_T("openService failed\n")); - ReportLastError(); - return FALSE; + hSc = OpenService(hSCManager, ServiceName, DELETE); + if (hSc != NULL) + { + if (DeleteService(hSc)) + { + _tprintf(_T("[SC] DeleteService SUCCESS\n")); + + 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; } diff --git a/reactos/base/applications/sc/print.c b/reactos/base/applications/sc/print.c new file mode 100644 index 00000000000..57ec7f10761 --- /dev/null +++ b/reactos/base/applications/sc/print.c @@ -0,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); +} diff --git a/reactos/base/applications/sc/query.c b/reactos/base/applications/sc/query.c index c9515844690..e4534a2f143 100644 --- a/reactos/base/applications/sc/query.c +++ b/reactos/base/applications/sc/query.c @@ -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 @@ Query(LPCTSTR ServiceName, LPCTSTR *ServiceArgs, BOOL bExtended) { /* 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 @@ Query(LPCTSTR ServiceName, LPCTSTR *ServiceArgs, BOOL bExtended) _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 @@ Query(LPCTSTR ServiceName, LPCTSTR *ServiceArgs, BOOL bExtended) _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 @@ Query(LPCTSTR ServiceName, LPCTSTR *ServiceArgs, BOOL bExtended) { QueryService(ServiceName, bExtended); } - + return TRUE; } @@ -90,12 +90,22 @@ Query(LPCTSTR ServiceName, LPCTSTR *ServiceArgs, BOOL bExtended) 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); if (hSc == NULL) @@ -143,7 +153,7 @@ QueryService(LPCTSTR ServiceName, BOOL bExtended) } } - + _tprintf(_T("SERVICE_NAME: %s\n"), ServiceName); _tprintf(_T("\tTYPE : %x "), @@ -193,7 +203,7 @@ QueryService(LPCTSTR ServiceName, BOOL bExtended) _tprintf(_T("\tFLAGS : %lu\n"), pServiceInfo->dwServiceFlags); } - + HeapFree(GetProcessHeap(), 0, pServiceInfo); return TRUE; @@ -203,11 +213,21 @@ QueryService(LPCTSTR ServiceName, BOOL bExtended) 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, SC_ENUM_PROCESS_INFO, @@ -262,10 +282,10 @@ EnumServices(DWORD ServiceType, DWORD ServiceState) VOID -PrintService(BOOL bExtended) +PrintService2(BOOL bExtended) { DWORD i; - + for (i=0; i < NumServices; i++) { @@ -322,6 +342,6 @@ PrintService(BOOL bExtended) _tprintf(_T("\n")); } - + _tprintf(_T("number : %lu\n"), NumServices); } diff --git a/reactos/base/applications/sc/sc.c b/reactos/base/applications/sc/sc.c index de8333d5306..bc7953461a6 100644 --- a/reactos/base/applications/sc/sc.c +++ b/reactos/base/applications/sc/sc.c @@ -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 * */ @@ -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 @@ DWORD ReportLastError(VOID) 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 +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 { - /* count trailing arguments */ - ArgCount -= 3; - - if (MachineName) + 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 (!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); + { + Start(ServiceName, + ServiceArgs, + ArgCount); + } else StartUsage(); } - else if (_tcsicmp(Command, _T("pause")) == 0) + else if (!lstrcmpi(Command, _T("pause"))) { if (ServiceName) - Control(SERVICE_CONTROL_PAUSE, ServiceName, ServiceArgs); + { + Control(SERVICE_CONTROL_PAUSE, + ServiceName, + ServiceArgs, + ArgCount); + } else PauseUsage(); } - else if (_tcsicmp(Command, _T("interrogate")) == 0) + else if (!lstrcmpi(Command, _T("interrogate"))) { if (ServiceName) - Control(SERVICE_CONTROL_INTERROGATE, ServiceName, ServiceArgs); + { + Control(SERVICE_CONTROL_INTERROGATE, + ServiceName, + ServiceArgs, + ArgCount); + } else InterrogateUsage(); } - else if (_tcsicmp(Command, _T("stop")) == 0) + else if (!lstrcmpi(Command, _T("stop"))) { if (ServiceName) - Control(SERVICE_CONTROL_STOP, ServiceName, ServiceArgs); + { + Control(SERVICE_CONTROL_STOP, + ServiceName, + ServiceArgs, + ArgCount); + } else StopUsage(); } - else if (_tcsicmp(Command, _T("continue")) == 0) + else if (!lstrcmpi(Command, _T("continue"))) { if (ServiceName) - Control(SERVICE_CONTROL_CONTINUE, ServiceName, ServiceArgs); + { + 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) + else if (!lstrcmpi(Command, _T("control"))) { + INT CtlValue; + + CtlValue = _ttoi(ServiceArgs[0]); + ServiceArgs++; + ArgCount--; + if (ServiceName) - Control(0, ServiceName, ServiceArgs); - else - ContinueUsage(); + { + if ((CtlValue >=128) && CtlValue <= 255) + { + Control(CtlValue, + ServiceName, + ServiceArgs, + ArgCount); + + return 0; + } + } + + ContinueUsage(); } return 0; } @@ -144,31 +170,47 @@ static 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(); + { + MainUsage(); + return -1; + } - _tcscpy(MachineName, argv[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 @@ int main( int argc, char **argv ) } 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 @@ int main( int argc, char **argv ) } free(argvW); } - + return Ret; } #endif diff --git a/reactos/base/applications/sc/sc.h b/reactos/base/applications/sc/sc.h index f6c977c1b26..8c80468183d 100644 --- a/reactos/base/applications/sc/sc.h +++ b/reactos/base/applications/sc/sc.h @@ -3,28 +3,29 @@ #include #include -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); diff --git a/reactos/base/applications/sc/sc.rbuild b/reactos/base/applications/sc/sc.rbuild index c5b82fca2c1..f5d358fa66b 100644 --- a/reactos/base/applications/sc/sc.rbuild +++ b/reactos/base/applications/sc/sc.rbuild @@ -7,12 +7,13 @@ kernel32 advapi32 - sc.c - start.c - query.c control.c create.c delete.c + print.c + query.c + sc.c + start.c usage.c sc.rc sc.h diff --git a/reactos/base/applications/sc/sc.rc b/reactos/base/applications/sc/sc.rc index 86777430848..b46b010878f 100644 --- a/reactos/base/applications/sc/sc.rc +++ b/reactos/base/applications/sc/sc.rc @@ -1,4 +1,10 @@ +#include +#include +#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 + +//#include "En.rc" diff --git a/reactos/base/applications/sc/start.c b/reactos/base/applications/sc/start.c index bb4277d74ae..05a6427f688 100644 --- a/reactos/base/applications/sc/start.c +++ b/reactos/base/applications/sc/start.c @@ -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 * */ @@ -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; + goto fail; } - - if (! QueryServiceStatusEx( - hSc, - SC_STATUS_PROCESS_INFO, - (LPBYTE)&ServiceStatus, - sizeof(SERVICE_STATUS_PROCESS), - &BytesNeeded)) + + 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)) { - _tprintf(_T("QueryServiceStatusEx 1 failed\n")); - ReportLastError(); - return FALSE; + goto fail; } - - while (ServiceStatus.dwCurrentState == SERVICE_START_PENDING) - { - /* 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; - } - } - - 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; + +fail: + ReportLastError(); + if (pServiceInfo) HeapFree(GetProcessHeap(), 0, pServiceInfo); + if (hSc) CloseServiceHandle(hSc); + if (hSCManager) CloseServiceHandle(hSCManager); + return FALSE; - 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; - } } diff --git a/reactos/base/applications/sc/usage.c b/reactos/base/applications/sc/usage.c index eb0254229a8..af19ce92b16 100644 --- a/reactos/base/applications/sc/usage.c +++ b/reactos/base/applications/sc/usage.c @@ -10,7 +10,7 @@ */ #include "sc.h" -INT MainUsage(VOID) +VOID MainUsage(VOID) { INT c; @@ -88,84 +88,67 @@ INT MainUsage(VOID) _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 start [service name] ...\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 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 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 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 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 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 @@ INT DeleteUsage(VOID) _T(" for deletion.\n") _T("USAGE:\n") _T(" sc 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 @@ INT CreateUsage(VOID) _T(" (default = LocalSystem)\n") _T(" DisplayName= \n") _T(" password= \n")); - - return 0; }