Add the beginnings of sc.exe

Very early stages and completley untested. Not adding to build.
Putting in SVN for the sole reason of keeping a development log

svn path=/trunk/; revision=18812
This commit is contained in:
Ged Murphy 2005-10-27 22:16:52 +00:00
parent 5bd48cf0fa
commit 7b494e5fe8
7 changed files with 517 additions and 0 deletions

View file

@ -0,0 +1,121 @@
#include "sc.h"
extern SC_HANDLE hSCManager; // declared in sc.c
BOOL Start(INT ArgCount, TCHAR **Args)
{
SC_HANDLE hSc;
LPCTSTR ServiceName = *Args++;
LPCTSTR *ServiceArgs = &*Args;
hSc = OpenService(hSCManager, ServiceName, SERVICE_ALL_ACCESS);
if (hSc == NULL)
{
dprintf("openService failed\n");
ReportLastError();
return FALSE;
}
if (! StartService(hSc, ArgCount, ServiceArgs))
{
dprintf("DeleteService failed\n");
ReportLastError();
return FALSE;
}
CloseServiceHandle(hSc);
return TRUE;
}
BOOL Create(TCHAR **Args)
{
SC_HANDLE hSc;
LPCTSTR Name = *Args;
LPCTSTR BinaryPathName = *++Args;
hSc = CreateService(hSCManager,
Name,
Name,
SERVICE_ALL_ACCESS,
SERVICE_WIN32_OWN_PROCESS,
SERVICE_DEMAND_START,
SERVICE_ERROR_NORMAL,
BinaryPathName,
NULL,
NULL,
NULL,
NULL,
NULL);
if (hSc == NULL)
{
dprintf("CreateService failed (%d)\n");
ReportLastError();
return FALSE;
}
else
{
CloseServiceHandle(hSc);
return TRUE;
}
}
BOOL Delete(TCHAR **Args)
{
SC_HANDLE hSc;
LPCTSTR ServiceName = *Args;
hSc = OpenService(hSCManager, ServiceName, DELETE);
if (hSc == NULL)
{
dprintf("openService failed\n");
ReportLastError();
return FALSE;
}
if (! DeleteService(hSc))
{
dprintf("DeleteService failed\n");
ReportLastError();
return FALSE;
}
CloseServiceHandle(hSc);
return TRUE;
}
BOOL Control(DWORD Control, TCHAR **Args)
{
SC_HANDLE hSc;
SERVICE_STATUS Status;
LPCTSTR ServiceName = *Args;
hSc = OpenService(hSCManager, ServiceName, DELETE);
if (hSc == NULL)
{
dprintf("openService failed\n");
ReportLastError();
return FALSE;
}
if (! ControlService(hSc, Control, &Status))
{
dprintf("controlService failed\n");
ReportLastError();
return FALSE;
}
CloseServiceHandle(hSc);
return TRUE;
}

View file

@ -0,0 +1,107 @@
#include "sc.h"
extern SC_HANDLE hSCManager; /* declared in sc.c */
BOOL
Query(TCHAR **Args, BOOL bExtended)
{
SC_HANDLE hSc;
ENUM_SERVICE_STATUS_PROCESS *pServiceStatus = NULL;
DWORD BufSize = 0;
DWORD BytesNeeded;
DWORD NumServices;
DWORD ResumeHandle;
INT i;
/* determine required buffer size */
EnumServicesStatusEx(hSCManager,
SC_ENUM_PROCESS_INFO,
SERVICE_DRIVER | SERVICE_WIN32,
SERVICE_STATE_ALL,
(LPBYTE)pServiceStatus,
BufSize,
&BytesNeeded,
&NumServices,
&ResumeHandle,
0);
/* exit on failure */
if (GetLastError() != ERROR_MORE_DATA)
{
ReportLastError();
return FALSE;
}
/* reserve memory for service info array */
pServiceStatus = (ENUM_SERVICE_STATUS_PROCESS *) malloc(BytesNeeded);
/* fill array with service info */
if (! EnumServicesStatusEx(hSCManager,
SC_ENUM_PROCESS_INFO,
SERVICE_DRIVER | SERVICE_WIN32,
SERVICE_STATE_ALL,
(LPBYTE)pServiceStatus,
BufSize,
&BytesNeeded,
&NumServices,
&ResumeHandle,
0))
{
dprintf("Call to EnumServicesStatusEx failed : ");
ReportLastError();
return FALSE;
}
/*
for (i=0; i<NumServices; i++)
{
if (Args == NULL)
{
if (pServiceStatus[i]->dwServiceType == SERVICE_WIN32 &&
pServiceStatus[i]->dwServiceState == SERVICE_ACTIVE)
PrintService(pServiceStatus[i], bExtended);
continue;
}
if(_tcsicmp(Args[0], _T("type="))
else if(_tcsicmp(Args[0], _T("state="))
else if(_tcsicmp(Args[0], _T("bufsize="))
else if(_tcsicmp(Args[0], _T("ri="))
else if(_tcsicmp(Args[0], _T("group="))
*/
}
VOID
PrintService(ENUM_SERVICE_STATUS_PROCESS *pServiceStatus,
BOOL bExtended)
{
dprintf("SERVICE_NAME: %s\n", pServiceStatus->lpServiceName);
dprintf("DISPLAY_NAME: %s\n", pServiceStatus->lpDisplayName);
dprintf("TYPE : %lu\n",
pServiceStatus->ServiceStatusProcess.dwServiceType);
dprintf("STATE : %lu\n",
pServiceStatus->ServiceStatusProcess.dwCurrentState);
// (STOPPABLE,NOT_PAUSABLE,ACCEPTS_SHUTDOWN)
dprintf("WIN32_EXIT_CODE : %lu \n",
pServiceStatus->ServiceStatusProcess.dwWin32ExitCode);
dprintf("SERVICE_EXIT_CODE : %lu \n",
pServiceStatus->ServiceStatusProcess.dwServiceSpecificExitCode);
dprintf("CHECKPOINT : %lu\n",
pServiceStatus->ServiceStatusProcess.dwCheckPoint);
dprintf("WAIT_HINT : %lu\n",
pServiceStatus->ServiceStatusProcess.dwWaitHint);
if (bExtended)
{
dprintf("PID : %lu\n",
pServiceStatus->ServiceStatusProcess.dwProcessId);
dprintf("FLAGS : %lu\n",
pServiceStatus->ServiceStatusProcess.dwServiceFlags);
}
}

View file

@ -0,0 +1,138 @@
#include "sc.h"
HANDLE OutputHandle;
HANDLE InputHandle;
SC_HANDLE hSCManager;
VOID dprintf(TCHAR* fmt, ...)
{
va_list args;
char buffer[255];
va_start(args, fmt);
wvsprintfA(buffer, fmt, args);
WriteConsole(OutputHandle, buffer, lstrlenA(buffer), NULL, NULL);
va_end(args);
}
DWORD ReportLastError(VOID)
{
LPVOID lpMsgBuf;
DWORD RetVal;
DWORD ErrorCode = GetLastError();
if (ErrorCode != ERROR_SUCCESS)
{
if ((RetVal = FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
ErrorCode,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
(LPTSTR) &lpMsgBuf,
0,
NULL )))
{
_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, LPCTSTR Command, TCHAR **Args)
{
if (MachineName)
{
dprintf("Remote service control is not yet implemented\n");
return 2;
}
hSCManager = OpenSCManager(MachineName, NULL, SC_MANAGER_ALL_ACCESS);
if (hSCManager == NULL)
{
dprintf("[SC] OpenSCManager FAILED \n");
ReportLastError();
return -1;
}
if (_tcsicmp(Command, _T("query")) == 0)
Query(Args, FALSE);
else if (_tcsicmp(Command, _T("queryex")) == 0)
Query(Args, TRUE);
else if (_tcsicmp(Command, _T("start")) == 0)
{
/*if (! **Args)
StartUsage();
else
Start(Args);*/
}
else if (_tcsicmp(Command, _T("pause")) == 0)
Control(SERVICE_CONTROL_PAUSE, ++Args);
else if (_tcsicmp(Command, _T("interrogate")) == 0)
Control(SERVICE_CONTROL_INTERROGATE, ++Args);
else if (_tcsicmp(Command, _T("interrogate")) == 0)
Control(SERVICE_CONTROL_INTERROGATE, ++Args);
else if (_tcsicmp(Command, _T("continue")) == 0)
Control(SERVICE_CONTROL_CONTINUE, ++Args);
else if (_tcsicmp(Command, _T("delete")) == 0)
Delete(Args);
else if (_tcsicmp(Command, _T("create")) == 0)
Create(Args);
else if (_tcsicmp(Command, _T("control")) == 0)
Control((DWORD)NULL, Args);
return 0;
}
int main(int argc, char* argv[])
{
LPTSTR MachineName = NULL; // remote machine
LPCTSTR Command = argv[1]; // sc command
TCHAR **Args = NULL; // rest of args
/* initialize standard input / output and get handles */
AllocConsole();
InputHandle = GetStdHandle(STD_INPUT_HANDLE);
OutputHandle = GetStdHandle(STD_OUTPUT_HANDLE);
if (argc < 2)
return MainUsage();
/* get server name */
if ((argv[1][0] == '\\') && (argv[1][1] == '\\'))
{
if (argc < 3)
return MainUsage();
_tcscpy(MachineName, argv[1]);
Command = argv[2];
Args = &argv[3];
return ScControl(MachineName, Command, Args);
}
else
{
Args = &argv[2];
return ScControl(MachineName, Command, Args);
}
return MainUsage();
}

View file

@ -0,0 +1,21 @@
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
DWORD ReportLastError(VOID);
VOID dprintf(TCHAR* fmt, ...);
INT MainUsage(VOID);
INT StartUsage(VOID);
INT PauseUsage(VOID);
INT InterrogateUsage(VOID);
INT ContinueUsage(VOID);
INT StopUsage(VOID);
INT ConfigUsage(VOID);
INT DescriptionUsage(VOID);
BOOL Query(TCHAR **Args, BOOL bExtended);
BOOL Start(INT ArgCount, TCHAR **Args);
BOOL Create(TCHAR **Args);
BOOL Delete(TCHAR **Args);
BOOL Control(DWORD Control, TCHAR **Args);

View file

@ -0,0 +1,4 @@
#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>

View file

@ -0,0 +1,10 @@
<module name="sc" type="win32cui" installbase="system32" installname="sc.exe">
<define name="__USE_W32API" />
<define name="DEFINE_GUID" />
<library>kernel32</library>
<file>sc.c</file>
<file>manage.c</file>
<file>query.c</file>
<file>usage.c</file>
<file>sc.rc</file>
</module>

View file

@ -0,0 +1,116 @@
#include "sc.h"
INT MainUsage(VOID)
{
dprintf("DESCRIPTION:\n");
dprintf("\tSC is a command line program used for communicating with\n");
dprintf("\tthe Service Control Manager and its services.\n");
dprintf("USAGE:\n");
dprintf("\tsc <server> [command] [service name] <option1> <option2>...\n");
dprintf("\tThe optional parameter <server> has the form \"\\ServerName\"\n");
dprintf("\tFurther help on commands can be obtained by typing: \"sc [command]\"\n");
dprintf("\tService Commands:\n");
dprintf("\t query : Queries the status for a service, or\n");
dprintf("\t enumerates the status for types of services.\n");
dprintf("\t queryex : Queries the extended status for a service, or\n");
// dprintf("\t enumerates the status for types of services.\n");
dprintf("\t start : Starts a service.\n");
dprintf("\t pause : Sends a PAUSE control request to a service.\n");
dprintf("\t interrogate : Sends a INTERROGATE control request to a service.\n");
// dprintf("\t continue : Sends a CONTINUE control request to a service.\n");
dprintf("\t stop : Sends a STOP request to a service.\n");
// dprintf("\t config : Changes the configuration of a service (persistant).\n");
// dprintf("\t description : Changes the description of a service.\n");
// dprintf("\t failure : Changes the actions taken by a service upon failure.\n");
// dprintf("\t qc : Queries the configuration information for a service.\n");
// dprintf("\t qdescription : Queries the description for a service.\n");
// dprintf("\t qfailure : Queries the actions taken by a service upon failure.\n");
dprintf("\t delete : Deletes a service (from the registry).\n");
dprintf("\t create : Creates a service. (adds it to the registry).\n");
dprintf("\t control : Sends a control to a service.\n");
// dprintf("\t sdshow : Displays a service's security descriptor.\n");
// dprintf("\t sdset : Sets a service's security descriptor.\n");
// dprintf("\t GetDisplayName : Gets the DisplayName for a service.\n");
// dprintf("\t GetKeyName : Gets the ServiceKeyName for a service.\n");
// dprintf("\t EnumDepend : Enumerates Service Dependencies.\n");
// dprintf("\n");
// dprintf("\tService Name Independant Commands:\n");
// dprintf("\t boot : (ok | bad) Indicates whether the last boot should\n");
// dprintf("\t be saved as the last-known-good boot configuration\n");
// dprintf("\t Lock : Locks the SCM Database\n");
// dprintf("\t QueryLock : Queries the LockStatus for the SCM Database\n");
return 0;
}
INT StartUsage(VOID)
{
dprintf("DESCRIPTION:\n");
dprintf(" Starts a service running.\n");
dprintf("USAGE:\n");
dprintf(" sc <server> start [service name] <arg1> <arg2> ...\n");
return 0;
}
INT PauseUsage(VOID)
{
dprintf("DESCRIPTION:\n");
dprintf(" Sends a PAUSE control request to a service.\n");
dprintf("USAGE:\n");
dprintf(" sc <server> pause [service name]\n");
return 0;
}
INT InterrogateUsage(VOID)
{
dprintf("DESCRIPTION:\n");
dprintf(" Sends an INTERROGATE control request to a service.\n");
dprintf("USAGE:\n");
dprintf(" sc <server> interrogate [service name]\n");
return 0;
}
INT ContinueUsage(VOID)
{
dprintf("DESCRIPTION:\n");
dprintf(" Sends an CONTINUE control request to a service.\n");
dprintf("USAGE:\n");
dprintf(" sc <server> continue [service name]\n");
return 0;
}
INT StopUsage(VOID)
{
dprintf("DESCRIPTION:\n");
dprintf(" Sends an STOP control request to a service.\n");
dprintf("USAGE:\n");
dprintf(" sc <server> stop [service name]\n");
return 0;
}
INT ConfigUsage(VOID)
{
dprintf("not yet implemented\n");
return 0;
}
INT DescriptionUsage(VOID)
{
dprintf("DESCRIPTION:\n");
dprintf(" Sets the description string for a service.\n");
dprintf("USAGE:\n");
dprintf(" sc <server> description [service name]\n");
return 0;
}