mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
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:
parent
5bd48cf0fa
commit
7b494e5fe8
7 changed files with 517 additions and 0 deletions
121
reactos/subsys/system/sc/manage.c
Normal file
121
reactos/subsys/system/sc/manage.c
Normal 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;
|
||||
|
||||
}
|
||||
|
||||
|
107
reactos/subsys/system/sc/query.c
Normal file
107
reactos/subsys/system/sc/query.c
Normal 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);
|
||||
}
|
||||
}
|
138
reactos/subsys/system/sc/sc.c
Normal file
138
reactos/subsys/system/sc/sc.c
Normal 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();
|
||||
}
|
21
reactos/subsys/system/sc/sc.h
Normal file
21
reactos/subsys/system/sc/sc.h
Normal 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);
|
4
reactos/subsys/system/sc/sc.rc
Normal file
4
reactos/subsys/system/sc/sc.rc
Normal 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>
|
10
reactos/subsys/system/sc/sc.xml
Normal file
10
reactos/subsys/system/sc/sc.xml
Normal 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>
|
116
reactos/subsys/system/sc/usage.c
Normal file
116
reactos/subsys/system/sc/usage.c
Normal 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;
|
||||
}
|
Loading…
Reference in a new issue