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
This commit is contained in:
Ged Murphy 2006-08-31 17:59:02 +00:00
parent 8537a75fba
commit 158e4c116a
11 changed files with 518 additions and 321 deletions

View file

@ -1,61 +1,95 @@
/* /*
* COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS Services
* PROJECT: ReactOS SC utility * LICENSE: GPL - See COPYING in the top level directory
* FILE: subsys/system/sc/control.c * FILE: base/system/sc/control.c
* PURPOSE: control ReactOS services * PURPOSE: Stops, pauses and resumes a service
* PROGRAMMERS: Ged Murphy (gedmurphy@gmail.com) * COPYRIGHT: Copyright 2005 - 2006 Ged Murphy <gedmurphy@gmail.com>
* REVISIONS:
* Ged Murphy 20/10/05 Created
* *
*/ */
#include "sc.h" #include "sc.h"
/* BOOL
* handles the following commands: Control(DWORD Control,
* control, continue, interrogate, pause, stop LPCTSTR ServiceName,
*/ LPCTSTR *Args,
INT ArgCount)
BOOL Control(DWORD Control, LPCTSTR ServiceName, LPCTSTR *Args)
{ {
SC_HANDLE hSc; SC_HANDLE hSCManager = NULL;
SC_HANDLE hSc = NULL;
SERVICE_STATUS Status; SERVICE_STATUS Status;
DWORD dwDesiredAccess = 0;
#ifdef SCDBG #ifdef SCDBG
/* testing */ {
_tprintf(_T("service to control - %s\n\n"), ServiceName); LPCTSTR *TmpArgs = Args;
_tprintf(_T("command - %lu\n\n"), Control); INT TmpCnt = ArgCount;
_tprintf(_T("Arguments :\n")); _tprintf(_T("service to control - %s\n"), ServiceName);
while (*Args) _tprintf(_T("command - %lu\n"), Control);
_tprintf(_T("Arguments:\n"));
while (TmpCnt)
{ {
printf("%s\n", *Args); _tprintf(_T(" %s\n"), *TmpArgs);
Args++; TmpArgs++;
TmpCnt--;
} }
_tprintf(_T("\n"));
}
#endif /* SCDBG */ #endif /* SCDBG */
hSc = OpenService(hSCManager, ServiceName, switch (Control)
SERVICE_INTERROGATE | SERVICE_PAUSE_CONTINUE |
SERVICE_STOP | SERVICE_USER_DEFINED_CONTROL |
SERVICE_QUERY_STATUS);
if (hSc == NULL)
{ {
_tprintf(_T("openService failed\n")); case SERVICE_CONTROL_STOP:
ReportLastError(); dwDesiredAccess = SERVICE_STOP;
return FALSE; 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()); hSc = OpenService(hSCManager,
ReportLastError(); ServiceName,
return FALSE; 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); ReportLastError();
if (hSc) CloseServiceHandle(hSc);
/* print the status information */ if (hSCManager) CloseServiceHandle(hSCManager);
return FALSE;
return TRUE;
} }

View file

@ -1,11 +1,9 @@
/* /*
* COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS Services
* PROJECT: ReactOS SC utility * LICENSE: GPL - See COPYING in the top level directory
* FILE: subsys/system/sc/create.c * FILE: base/system/sc/create.c
* PURPOSE: control ReactOS services * PURPOSE: Create a service
* PROGRAMMERS: Ged Murphy (gedmurphy@gmail.com) * COPYRIGHT: Copyright 2005 - 2006 Ged Murphy <gedmurphy@gmail.com>
* REVISIONS:
* Ged Murphy 20/10/05 Created
* *
*/ */
@ -13,46 +11,81 @@
BOOL Create(LPCTSTR ServiceName, LPCTSTR *ServiceArgs) BOOL Create(LPCTSTR ServiceName, LPCTSTR *ServiceArgs)
{ {
SC_HANDLE hSCManager;
SC_HANDLE hSc; SC_HANDLE hSc;
LPCTSTR BinaryPathName = *++ServiceArgs; BOOL bRet = FALSE;
// LPCTSTR *Options = ++ServiceArgs;
if ((! ServiceName) || (! BinaryPathName)) DWORD dwServiceType = SERVICE_WIN32_OWN_PROCESS;
return CreateUsage(); 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 #ifdef SCDBG
/* testing */ {
printf("service to create - %s\n", ServiceName); _tprintf(_T("service name - %s\n"), ServiceName);
printf("Binary path - %s\n", BinaryPathName); _tprintf(_T("display name - %s\n"), ServiceName);
printf("Arguments :\n"); _tprintf(_T("service type - %lu\n"), dwServiceType);
while (*Options) _tprintf(_T("start type - %lu\n"), dwStartType);
{ _tprintf(_T("error control - %lu\n"), dwErrorControl);
printf("%s\n", *Options); _tprintf(_T("Binary path - %s\n"), lpBinaryPathName);
Options++; _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 #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) if (!ServiceName)
{
CreateUsage();
return FALSE;
}
hSCManager = OpenSCManager(NULL,
NULL,
SC_MANAGER_CREATE_SERVICE);
if (hSCManager == NULL)
{ {
_tprintf(_T("CreateService failed\n"));
ReportLastError(); ReportLastError();
return FALSE; return FALSE;
} }
_tprintf(_T("[SC] CreateService SUCCESS\n")); hSc = CreateService(hSCManager,
CloseServiceHandle(hSc); ServiceName,
return TRUE; 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;
} }

View file

@ -1,11 +1,9 @@
/* /*
* COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS Services
* PROJECT: ReactOS SC utility * LICENSE: GPL - See COPYING in the top level directory
* FILE: subsys/system/sc/delete.c * FILE: base/system/sc/delete.c
* PURPOSE: control ReactOS services * PURPOSE: Delete a service
* PROGRAMMERS: Ged Murphy (gedmurphy@gmail.com) * COPYRIGHT: Copyright 2005 - 2006 Ged Murphy <gedmurphy@gmail.com>
* REVISIONS:
* Ged Murphy 20/10/05 Created
* *
*/ */
@ -13,30 +11,39 @@
BOOL Delete(LPCTSTR ServiceName) BOOL Delete(LPCTSTR ServiceName)
{ {
SC_HANDLE hSc; SC_HANDLE hSCManager = NULL;
SC_HANDLE hSc = NULL;
#ifdef SCDBG #ifdef SCDBG
/* testing */ {
printf("service to delete - %s\n\n", ServiceName); _tprintf(_T("service to delete - %s\n\n"), ServiceName);
}
#endif #endif
hSc = OpenService(hSCManager, ServiceName, DELETE); hSCManager = OpenSCManager(NULL,
NULL,
if (hSc == NULL) SC_MANAGER_CONNECT);
if (hSCManager != NULL)
{ {
_tprintf(_T("openService failed\n")); hSc = OpenService(hSCManager, ServiceName, DELETE);
ReportLastError(); if (hSc != NULL)
return FALSE; {
if (DeleteService(hSc))
{
_tprintf(_T("[SC] DeleteService SUCCESS\n"));
CloseServiceHandle(hSc);
CloseServiceHandle(hSCManager);
return TRUE;
}
}
} }
if (! DeleteService(hSc)) ReportLastError();
{
_tprintf(_T("DeleteService failed\n"));
ReportLastError();
return FALSE;
}
_tprintf(_T("[SC] DeleteService SUCCESS\n")); if (hSc) CloseServiceHandle(hSc);
CloseServiceHandle(hSc); if (hSCManager) CloseServiceHandle(hSCManager);
return TRUE;
return FALSE;
} }

View file

@ -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);
}

View file

@ -17,7 +17,7 @@
#include "sc.h" #include "sc.h"
/* local function decs */ /* local function decs */
VOID PrintService(BOOL bExtended); VOID PrintService2(BOOL bExtended);
BOOL EnumServices(DWORD ServiceType, DWORD ServiceState); BOOL EnumServices(DWORD ServiceType, DWORD ServiceState);
BOOL QueryService(LPCTSTR ServiceName, BOOL bExtended); BOOL QueryService(LPCTSTR ServiceName, BOOL bExtended);
@ -35,7 +35,7 @@ Query(LPCTSTR ServiceName, LPCTSTR *ServiceArgs, BOOL bExtended)
EnumServices(SERVICE_WIN32, SERVICE_ACTIVE); EnumServices(SERVICE_WIN32, SERVICE_ACTIVE);
/* print default values */ /* print default values */
PrintService(bExtended); PrintService2(bExtended);
} }
else if (_tcsicmp(ServiceName, _T("type=")) == 0) else if (_tcsicmp(ServiceName, _T("type=")) == 0)
{ {
@ -53,7 +53,7 @@ Query(LPCTSTR ServiceName, LPCTSTR *ServiceArgs, BOOL bExtended)
_tprintf(_T("Must be \"driver\" or \"service\" or \"all\"\n")); _tprintf(_T("Must be \"driver\" or \"service\" or \"all\"\n"));
} }
PrintService(bExtended); PrintService2(bExtended);
} }
else if(_tcsicmp(ServiceName, _T("state=")) == 0) else if(_tcsicmp(ServiceName, _T("state=")) == 0)
{ {
@ -69,7 +69,7 @@ Query(LPCTSTR ServiceName, LPCTSTR *ServiceArgs, BOOL bExtended)
_tprintf(_T("Must be \"active\" or \"inactive\" or \"all\"\n")); _tprintf(_T("Must be \"active\" or \"inactive\" or \"all\"\n"));
} }
PrintService(bExtended); PrintService2(bExtended);
} }
/* /*
else if(_tcsicmp(ServiceName, _T("bufsize="))) else if(_tcsicmp(ServiceName, _T("bufsize=")))
@ -90,12 +90,22 @@ Query(LPCTSTR ServiceName, LPCTSTR *ServiceArgs, BOOL bExtended)
BOOL BOOL
QueryService(LPCTSTR ServiceName, BOOL bExtended) QueryService(LPCTSTR ServiceName, BOOL bExtended)
{ {
SC_HANDLE hSCManager;
SERVICE_STATUS_PROCESS *pServiceInfo = NULL; SERVICE_STATUS_PROCESS *pServiceInfo = NULL;
SC_HANDLE hSc; SC_HANDLE hSc;
DWORD BufSiz = 0; DWORD BufSiz = 0;
DWORD BytesNeeded = 0; DWORD BytesNeeded = 0;
DWORD Ret; DWORD Ret;
hSCManager = OpenSCManager(NULL,
NULL,
SC_MANAGER_CONNECT);
if (hSCManager == NULL)
{
ReportLastError();
return FALSE;
}
hSc = OpenService(hSCManager, ServiceName, SERVICE_QUERY_STATUS); hSc = OpenService(hSCManager, ServiceName, SERVICE_QUERY_STATUS);
if (hSc == NULL) if (hSc == NULL)
@ -203,11 +213,21 @@ QueryService(LPCTSTR ServiceName, BOOL bExtended)
BOOL BOOL
EnumServices(DWORD ServiceType, DWORD ServiceState) EnumServices(DWORD ServiceType, DWORD ServiceState)
{ {
SC_HANDLE hSCManager;
DWORD BufSize = 0; DWORD BufSize = 0;
DWORD BytesNeeded = 0; DWORD BytesNeeded = 0;
DWORD ResumeHandle = 0; DWORD ResumeHandle = 0;
DWORD Ret; DWORD Ret;
hSCManager = OpenSCManager(NULL,
NULL,
SC_MANAGER_ENUMERATE_SERVICE);
if (hSCManager == NULL)
{
ReportLastError();
return FALSE;
}
/* determine required buffer size */ /* determine required buffer size */
Ret = EnumServicesStatusEx(hSCManager, Ret = EnumServicesStatusEx(hSCManager,
SC_ENUM_PROCESS_INFO, SC_ENUM_PROCESS_INFO,
@ -262,7 +282,7 @@ EnumServices(DWORD ServiceType, DWORD ServiceState)
VOID VOID
PrintService(BOOL bExtended) PrintService2(BOOL bExtended)
{ {
DWORD i; DWORD i;

View file

@ -1,11 +1,9 @@
/* /*
* COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS Services
* PROJECT: ReactOS SC utility * LICENSE: GPL - See COPYING in the top level directory
* FILE: subsys/system/sc/sc.c * FILE: base/system/sc/sc.c
* PURPOSE: control ReactOS services * PURPOSE: parse command line
* PROGRAMMERS: Ged Murphy (gedmurphy@gmail.com) * COPYRIGHT: Copyright 2005 - 2006 Ged Murphy <gedmurphy@gmail.com>
* REVISIONS:
* Ged Murphy 20/10/05 Created
* *
*/ */
@ -13,7 +11,8 @@
SC_HANDLE hSCManager; SC_HANDLE hSCManager;
DWORD ReportLastError(VOID) VOID
ReportLastError(VOID)
{ {
LPVOID lpMsgBuf; LPVOID lpMsgBuf;
DWORD RetVal; DWORD RetVal;
@ -34,106 +33,133 @@ DWORD ReportLastError(VOID)
if (RetVal != 0) if (RetVal != 0)
{ {
_tprintf(_T("%s"), (LPTSTR)lpMsgBuf); _tprintf(_T("%s"), (LPTSTR)lpMsgBuf);
LocalFree(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 static INT
LPCTSTR Command, // sc command ScControl(LPCTSTR Server, // remote machine name
LPCTSTR ServiceName, // name of service LPCTSTR Command, // sc command
LPCTSTR *ServiceArgs, // any options LPCTSTR ServiceName, // name of service
DWORD ArgCount) // argument counter LPCTSTR *ServiceArgs, // any options
DWORD ArgCount) // argument counter
{ {
/* count trailing arguments */ if (Server)
ArgCount -= 3;
if (MachineName)
{ {
_tprintf(_T("Remote service control is not yet implemented\n")); _tprintf(_T("Remote service control is not yet implemented\n"));
return 2; return 2;
} }
/* if we are emurating the services, we don't need administrator access */ if (!lstrcmpi(Command, _T("query")))
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()); Query(ServiceName,
ReportLastError(); ServiceArgs,
return -1; FALSE);
} }
else if (!lstrcmpi(Command, _T("queryex")))
/* emurate command */ {
if (_tcsicmp(Command, _T("query")) == 0) Query(ServiceName,
Query(ServiceName, ServiceArgs, FALSE); ServiceArgs,
TRUE);
else if (_tcsicmp(Command, _T("queryex")) == 0) }
Query(ServiceName, ServiceArgs, TRUE); else if (!lstrcmpi(Command, _T("start")))
else if (_tcsicmp(Command, _T("start")) == 0)
{ {
if (ServiceName) if (ServiceName)
Start(ServiceName, ServiceArgs, ArgCount); {
Start(ServiceName,
ServiceArgs,
ArgCount);
}
else else
StartUsage(); StartUsage();
} }
else if (_tcsicmp(Command, _T("pause")) == 0) else if (!lstrcmpi(Command, _T("pause")))
{ {
if (ServiceName) if (ServiceName)
Control(SERVICE_CONTROL_PAUSE, ServiceName, ServiceArgs); {
Control(SERVICE_CONTROL_PAUSE,
ServiceName,
ServiceArgs,
ArgCount);
}
else else
PauseUsage(); PauseUsage();
} }
else if (_tcsicmp(Command, _T("interrogate")) == 0) else if (!lstrcmpi(Command, _T("interrogate")))
{ {
if (ServiceName) if (ServiceName)
Control(SERVICE_CONTROL_INTERROGATE, ServiceName, ServiceArgs); {
Control(SERVICE_CONTROL_INTERROGATE,
ServiceName,
ServiceArgs,
ArgCount);
}
else else
InterrogateUsage(); InterrogateUsage();
} }
else if (_tcsicmp(Command, _T("stop")) == 0) else if (!lstrcmpi(Command, _T("stop")))
{ {
if (ServiceName) if (ServiceName)
Control(SERVICE_CONTROL_STOP, ServiceName, ServiceArgs); {
Control(SERVICE_CONTROL_STOP,
ServiceName,
ServiceArgs,
ArgCount);
}
else else
StopUsage(); StopUsage();
} }
else if (_tcsicmp(Command, _T("continue")) == 0) else if (!lstrcmpi(Command, _T("continue")))
{ {
if (ServiceName) if (ServiceName)
Control(SERVICE_CONTROL_CONTINUE, ServiceName, ServiceArgs); {
Control(SERVICE_CONTROL_CONTINUE,
ServiceName,
ServiceArgs,
ArgCount);
}
else else
ContinueUsage(); ContinueUsage();
} }
else if (_tcsicmp(Command, _T("delete")) == 0) else if (!lstrcmpi(Command, _T("delete")))
{ {
if (ServiceName) if (ServiceName)
Delete(ServiceName); Delete(ServiceName);
else else
DeleteUsage(); DeleteUsage();
} }
else if (_tcsicmp(Command, _T("create")) == 0) else if (!lstrcmpi(Command, _T("create")))
{ {
if (*ServiceArgs) if (*ServiceArgs)
Create(ServiceName, ServiceArgs); Create(ServiceName,
ServiceArgs);
else else
CreateUsage(); CreateUsage();
} }
else if (_tcsicmp(Command, _T("control")) == 0) else if (!lstrcmpi(Command, _T("control")))
{ {
INT CtlValue;
CtlValue = _ttoi(ServiceArgs[0]);
ServiceArgs++;
ArgCount--;
if (ServiceName) if (ServiceName)
Control(0, ServiceName, ServiceArgs); {
else if ((CtlValue >=128) && CtlValue <= 255)
ContinueUsage(); {
Control(CtlValue,
ServiceName,
ServiceArgs,
ArgCount);
return 0;
}
}
ContinueUsage();
} }
return 0; return 0;
} }
@ -144,31 +170,47 @@ static
int _tmain(int argc, LPCTSTR argv[]) int _tmain(int argc, LPCTSTR argv[])
{ {
LPTSTR MachineName = NULL; // remote machine LPCTSTR Server = NULL; // remote machine
LPCTSTR Command = NULL; // sc command LPCTSTR Command = NULL; // sc command
LPCTSTR ServiceName = NULL; // Name of service LPCTSTR ServiceName = NULL; // name of service
if (argc < 2) if (argc < 2)
return MainUsage(); {
MainUsage();
return -1;
}
/* get server name */ /* get server name */
if ((argv[1][0] == '\\') && (argv[1][1] == '\\')) if ((argv[1][0] == '\\') && (argv[1][1] == '\\'))
{ {
if (argc < 3) if (argc < 3)
return MainUsage(); {
MainUsage();
return -1;
}
_tcscpy(MachineName, argv[1]); Server = argv[1];
Command = argv[2]; Command = argv[2];
if (argc > 3) if (argc > 3)
ServiceName = argv[3]; ServiceName = argv[3];
return ScControl(MachineName, Command, ServiceName, &argv[4], argc);
return ScControl(Server,
Command,
ServiceName,
&argv[4],
argc-4);
} }
else else
{ {
Command = argv[1]; Command = argv[1];
if (argc > 2) if (argc > 2)
ServiceName = argv[2]; ServiceName = argv[2];
return ScControl(MachineName, Command, ServiceName, &argv[3], argc);
return ScControl(Server,
Command,
ServiceName,
&argv[3],
argc-3);
} }
} }

View file

@ -3,28 +3,29 @@
#include <stdio.h> #include <stdio.h>
#include <tchar.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 */ /* control functions */
BOOL Query(LPCTSTR ServiceName, LPCTSTR *ServiceArgs, BOOL bExtended); BOOL Query(LPCTSTR ServiceName, LPCTSTR *ServiceArgs, BOOL bExtended);
BOOL Start(LPCTSTR ServiceName, LPCTSTR *ServiceArgs, INT ArgCount); BOOL Start(LPCTSTR ServiceName, LPCTSTR *ServiceArgs, INT ArgCount);
BOOL Create(LPCTSTR ServiceName, LPCTSTR *ServiceArgs); BOOL Create(LPCTSTR ServiceName, LPCTSTR *ServiceArgs);
BOOL Delete(LPCTSTR ServiceName); 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 */ /* print and error functions */
DWORD ReportLastError(VOID); VOID ReportLastError(VOID);
/* usage functions */ /* usage functions */
INT MainUsage(VOID); VOID MainUsage(VOID);
INT StartUsage(VOID); VOID StartUsage(VOID);
INT PauseUsage(VOID); VOID PauseUsage(VOID);
INT InterrogateUsage(VOID); VOID InterrogateUsage(VOID);
INT ContinueUsage(VOID); VOID ContinueUsage(VOID);
INT StopUsage(VOID); VOID StopUsage(VOID);
INT ConfigUsage(VOID); VOID ConfigUsage(VOID);
INT DescriptionUsage(VOID); VOID DescriptionUsage(VOID);
INT DeleteUsage(VOID); VOID DeleteUsage(VOID);
INT CreateUsage(VOID); VOID CreateUsage(VOID);

View file

@ -7,12 +7,13 @@
<define name="_UNICODE" /> <define name="_UNICODE" />
<library>kernel32</library> <library>kernel32</library>
<library>advapi32</library> <library>advapi32</library>
<file>sc.c</file>
<file>start.c</file>
<file>query.c</file>
<file>control.c</file> <file>control.c</file>
<file>create.c</file> <file>create.c</file>
<file>delete.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>usage.c</file>
<file>sc.rc</file> <file>sc.rc</file>
<pch>sc.h</pch> <pch>sc.h</pch>

View file

@ -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_FILE_DESCRIPTION "Services control application\0"
#define REACTOS_STR_INTERNAL_NAME "sc\0" #define REACTOS_STR_INTERNAL_NAME "sc\0"
#define REACTOS_STR_ORIGINAL_FILENAME "sc.exe\0" #define REACTOS_STR_ORIGINAL_FILENAME "sc.exe\0"
#include <reactos/version.rc> #include <reactos/version.rc>
//#include "En.rc"

View file

@ -1,11 +1,9 @@
/* /*
* COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS Services
* PROJECT: ReactOS SC utility * LICENSE: GPL - See COPYING in the top level directory
* FILE: subsys/system/sc/start.c * FILE: base/system/sc/start.c
* PURPOSE: control ReactOS services * PURPOSE: Start a service
* PROGRAMMERS: Ged Murphy (gedmurphy@gmail.com) * COPYRIGHT: Copyright 2005 - 2006 Ged Murphy <gedmurphy@gmail.com>
* REVISIONS:
* Ged Murphy 20/10/05 Created
* *
*/ */
@ -13,99 +11,91 @@
BOOL Start(LPCTSTR ServiceName, LPCTSTR *ServiceArgs, INT ArgCount) BOOL Start(LPCTSTR ServiceName, LPCTSTR *ServiceArgs, INT ArgCount)
{ {
SC_HANDLE hSc; SC_HANDLE hSCManager = NULL;
SERVICE_STATUS_PROCESS ServiceStatus, ServiceStatus2; SC_HANDLE hSc = NULL;
DWORD BytesNeeded; LPSERVICE_STATUS_PROCESS pServiceInfo = NULL;
DWORD BufSiz = 0;
DWORD BytesNeeded = 0;
DWORD Ret;
#ifdef SCDBG #ifdef SCDBG
/* testing */ {
_tprintf(_T("service to start - %s\n\n"), ServiceName); LPCTSTR *TmpArgs = ServiceArgs;
_tprintf(_T("Arguments :\n")); INT TmpCnt = ArgCount;
while (*ServiceArgs) _tprintf(_T("service to control - %s\n"), ServiceName);
_tprintf(_T("Arguments:\n"));
while (TmpCnt)
{ {
printf("%s\n", *ServiceArgs); _tprintf(_T(" %s\n"), *TmpArgs);
ServiceArgs++; TmpArgs++;
TmpCnt--;
} }
#endif _tprintf(_T("\n"));
}
#endif /* SCDBG */
/* get a handle to the service requested for starting */ hSCManager = OpenSCManager(NULL,
hSc = OpenService(hSCManager, ServiceName, SERVICE_ALL_ACCESS); NULL,
SC_MANAGER_CONNECT);
if (hSCManager == NULL)
goto fail;
hSc = OpenService(hSCManager,
ServiceName,
SERVICE_START | SERVICE_QUERY_STATUS);
if (hSc == NULL) if (hSc == NULL)
{ {
_tprintf(_T("openService failed\n")); _tprintf(_T("openService failed\n"));
ReportLastError(); goto fail;
return FALSE;
} }
/* start the service opened */ if (! StartService(hSc,
if (! StartService(hSc, ArgCount, ServiceArgs)) ArgCount,
ServiceArgs))
{ {
_tprintf(_T("[SC] StartService FAILED %lu:\n\n"), GetLastError()); _tprintf(_T("[SC] StartService FAILED %lu:\n\n"), GetLastError());
ReportLastError(); goto fail;
return FALSE;
} }
if (! QueryServiceStatusEx( Ret = QueryServiceStatusEx(hSc,
hSc, SC_STATUS_PROCESS_INFO,
SC_STATUS_PROCESS_INFO, NULL,
(LPBYTE)&ServiceStatus, BufSiz,
sizeof(SERVICE_STATUS_PROCESS), &BytesNeeded);
&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")); goto fail;
ReportLastError();
return FALSE;
} }
PrintServiceEx(ServiceName,
pServiceInfo);
while (ServiceStatus.dwCurrentState == SERVICE_START_PENDING) HeapFree(GetProcessHeap(), 0, pServiceInfo);
{
/* 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);
CloseServiceHandle(hSc); CloseServiceHandle(hSc);
CloseServiceHandle(hSCManager);
if (ServiceStatus.dwCurrentState == SERVICE_RUNNING) return TRUE;
{
_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);
return TRUE; fail:
} ReportLastError();
else if (pServiceInfo) HeapFree(GetProcessHeap(), 0, pServiceInfo);
{ if (hSc) CloseServiceHandle(hSc);
_tprintf(_T("Failed to start %s\n"), ServiceName); if (hSCManager) CloseServiceHandle(hSCManager);
_tprintf(_T("Curent state: %lu\n"), ServiceStatus.dwCurrentState); return FALSE;
_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;
}
} }

View file

@ -10,7 +10,7 @@
*/ */
#include "sc.h" #include "sc.h"
INT MainUsage(VOID) VOID MainUsage(VOID)
{ {
INT c; 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= service type= interact - Enumerates all interactive services\n"));
// _T("sc query type= driver group= NDIS - Enumerates all NDIS drivers\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") _tprintf(_T("DESCRIPTION:\n")
_T(" Starts a service running.\n") _T(" Starts a service running.\n")
_T("USAGE:\n") _T("USAGE:\n")
_T(" sc <server> start [service name] <arg1> <arg2> ...\n")); _T(" sc <server> start [service name] <arg1> <arg2> ...\n"));
return 0;
} }
INT PauseUsage(VOID) VOID PauseUsage(VOID)
{ {
_tprintf(_T("DESCRIPTION:\n") _tprintf(_T("DESCRIPTION:\n")
_T(" Sends a PAUSE control request to a service.\n") _T(" Sends a PAUSE control request to a service.\n")
_T("USAGE:\n") _T("USAGE:\n")
_T(" sc <server> pause [service name]\n")); _T(" sc <server> pause [service name]\n"));
return 0;
} }
INT InterrogateUsage(VOID) VOID InterrogateUsage(VOID)
{ {
_tprintf(_T("DESCRIPTION:\n") _tprintf(_T("DESCRIPTION:\n")
_T(" Sends an INTERROGATE control request to a service.\n") _T(" Sends an INTERROGATE control request to a service.\n")
_T("USAGE:\n") _T("USAGE:\n")
_T(" sc <server> interrogate [service name]\n")); _T(" sc <server> interrogate [service name]\n"));
return 0;
} }
INT StopUsage(VOID) VOID StopUsage(VOID)
{ {
_tprintf(_T("DESCRIPTION:\n") _tprintf(_T("DESCRIPTION:\n")
_T(" Sends an STOP control request to a service.\n") _T(" Sends an STOP control request to a service.\n")
_T("USAGE:\n") _T("USAGE:\n")
_T(" sc <server> stop [service name]\n")); _T(" sc <server> stop [service name]\n"));
return 0;
} }
INT ContinueUsage(VOID) VOID ContinueUsage(VOID)
{ {
_tprintf(_T("DESCRIPTION:\n") _tprintf(_T("DESCRIPTION:\n")
_T(" Sends an CONTINUE control request to a service.\n") _T(" Sends an CONTINUE control request to a service.\n")
_T("USAGE:\n") _T("USAGE:\n")
_T(" sc <server> continue [service name]\n")); _T(" sc <server> continue [service name]\n"));
return 0;
} }
INT ConfigUsage(VOID) VOID ConfigUsage(VOID)
{ {
_tprintf(_T("not yet implemented\n")); _tprintf(_T("not yet implemented\n"));
return 0;
} }
INT DescriptionUsage(VOID) VOID DescriptionUsage(VOID)
{ {
_tprintf(_T("DESCRIPTION:\n") _tprintf(_T("DESCRIPTION:\n")
_T(" Sets the description string for a service.\n") _T(" Sets the description string for a service.\n")
_T("USAGE:\n") _T("USAGE:\n")
_T(" sc <server> description [service name]\n")); _T(" sc <server> description [service name]\n"));
return 0;
} }
INT DeleteUsage(VOID) VOID DeleteUsage(VOID)
{ {
_tprintf(_T("DESCRIPTION:\n") _tprintf(_T("DESCRIPTION:\n")
_T(" Deletes a service entry from the registry.\n") _T(" Deletes a service entry from the registry.\n")
@ -174,11 +157,9 @@ INT DeleteUsage(VOID)
_T(" for deletion.\n") _T(" for deletion.\n")
_T("USAGE:\n") _T("USAGE:\n")
_T(" sc <server> delete [service name]\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") _tprintf(_T("Creates a service entry in the registry and Service Database.\n")
_T("SYNTAX:\n") _T("SYNTAX:\n")
@ -199,6 +180,4 @@ INT CreateUsage(VOID)
_T(" (default = LocalSystem)\n") _T(" (default = LocalSystem)\n")
_T(" DisplayName= <display name>\n") _T(" DisplayName= <display name>\n")
_T(" password= <password>\n")); _T(" password= <password>\n"));
return 0;
} }