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
Added: trunk/reactos/subsys/system/sc/
Added: trunk/reactos/subsys/system/sc/manage.c
Added: trunk/reactos/subsys/system/sc/query.c
Added: trunk/reactos/subsys/system/sc/sc.c
Added: trunk/reactos/subsys/system/sc/sc.h
Added: trunk/reactos/subsys/system/sc/sc.rc
Added: trunk/reactos/subsys/system/sc/sc.xml
Added: trunk/reactos/subsys/system/sc/usage.c
_____
Added: trunk/reactos/subsys/system/sc/manage.c
--- trunk/reactos/subsys/system/sc/manage.c 2005-10-27 22:10:33 UTC
(rev 18811)
+++ trunk/reactos/subsys/system/sc/manage.c 2005-10-27 22:16:52 UTC
(rev 18812)
@@ -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;
+
+}
+
+
Property changes on: trunk/reactos/subsys/system/sc/manage.c
___________________________________________________________________
Name: svn:keywords
+ Author Date Id Revision
Name: svn:eol-style
+ native
_____
Added: trunk/reactos/subsys/system/sc/query.c
--- trunk/reactos/subsys/system/sc/query.c 2005-10-27 22:10:33 UTC
(rev 18811)
+++ trunk/reactos/subsys/system/sc/query.c 2005-10-27 22:16:52 UTC
(rev 18812)
@@ -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);
+ }
+}
Property changes on: trunk/reactos/subsys/system/sc/query.c
___________________________________________________________________
Name: svn:keywords
+ Author Date Id Revision
Name: svn:eol-style
+ native
_____
Added: trunk/reactos/subsys/system/sc/sc.c
--- trunk/reactos/subsys/system/sc/sc.c 2005-10-27 22:10:33 UTC (rev
18811)
+++ trunk/reactos/subsys/system/sc/sc.c 2005-10-27 22:16:52 UTC (rev
18812)
@@ -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();
+}
Property changes on: trunk/reactos/subsys/system/sc/sc.c
___________________________________________________________________
Name: svn:keywords
+ Author Date Id Revision
Name: svn:eol-style
+ native
_____
Added: trunk/reactos/subsys/system/sc/sc.h
--- trunk/reactos/subsys/system/sc/sc.h 2005-10-27 22:10:33 UTC (rev
18811)
+++ trunk/reactos/subsys/system/sc/sc.h 2005-10-27 22:16:52 UTC (rev
18812)
@@ -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);
Property changes on: trunk/reactos/subsys/system/sc/sc.h
___________________________________________________________________
Name: svn:keywords
+ Author Date Id Revision
Name: svn:eol-style
+ native
_____
Added: trunk/reactos/subsys/system/sc/sc.rc
--- trunk/reactos/subsys/system/sc/sc.rc 2005-10-27 22:10:33 UTC
(rev 18811)
+++ trunk/reactos/subsys/system/sc/sc.rc 2005-10-27 22:16:52 UTC
(rev 18812)
@@ -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>
_____
Added: trunk/reactos/subsys/system/sc/sc.xml
--- trunk/reactos/subsys/system/sc/sc.xml 2005-10-27 22:10:33 UTC
(rev 18811)
+++ trunk/reactos/subsys/system/sc/sc.xml 2005-10-27 22:16:52 UTC
(rev 18812)
@@ -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>
_____
Added: trunk/reactos/subsys/system/sc/usage.c
--- trunk/reactos/subsys/system/sc/usage.c 2005-10-27 22:10:33 UTC
(rev 18811)
+++ trunk/reactos/subsys/system/sc/usage.c 2005-10-27 22:16:52 UTC
(rev 18812)
@@ -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;
+}
Property changes on: trunk/reactos/subsys/system/sc/usage.c
___________________________________________________________________
Name: svn:keywords
+ Author Date Id Revision
Name: svn:eol-style
+ native