Add the beginnings of sc.exe
authorGed Murphy <gedmurphy@reactos.org>
Thu, 27 Oct 2005 22:16:52 +0000 (22:16 +0000)
committerGed Murphy <gedmurphy@reactos.org>
Thu, 27 Oct 2005 22:16:52 +0000 (22:16 +0000)
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

reactos/subsys/system/sc/manage.c [new file with mode: 0644]
reactos/subsys/system/sc/query.c [new file with mode: 0644]
reactos/subsys/system/sc/sc.c [new file with mode: 0644]
reactos/subsys/system/sc/sc.h [new file with mode: 0644]
reactos/subsys/system/sc/sc.rc [new file with mode: 0644]
reactos/subsys/system/sc/sc.xml [new file with mode: 0644]
reactos/subsys/system/sc/usage.c [new file with mode: 0644]

diff --git a/reactos/subsys/system/sc/manage.c b/reactos/subsys/system/sc/manage.c
new file mode 100644 (file)
index 0000000..51d6063
--- /dev/null
@@ -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;
+
+}
+
+
diff --git a/reactos/subsys/system/sc/query.c b/reactos/subsys/system/sc/query.c
new file mode 100644 (file)
index 0000000..c9ea1ac
--- /dev/null
@@ -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);
+    }
+}
diff --git a/reactos/subsys/system/sc/sc.c b/reactos/subsys/system/sc/sc.c
new file mode 100644 (file)
index 0000000..dd44f5c
--- /dev/null
@@ -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();
+}
diff --git a/reactos/subsys/system/sc/sc.h b/reactos/subsys/system/sc/sc.h
new file mode 100644 (file)
index 0000000..c88a05b
--- /dev/null
@@ -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);
diff --git a/reactos/subsys/system/sc/sc.rc b/reactos/subsys/system/sc/sc.rc
new file mode 100644 (file)
index 0000000..8677743
--- /dev/null
@@ -0,0 +1,4 @@
+#define REACTOS_STR_FILE_DESCRIPTION   "Services control application\0"\r
+#define REACTOS_STR_INTERNAL_NAME      "sc\0"\r
+#define REACTOS_STR_ORIGINAL_FILENAME  "sc.exe\0"\r
+#include <reactos/version.rc>\r
diff --git a/reactos/subsys/system/sc/sc.xml b/reactos/subsys/system/sc/sc.xml
new file mode 100644 (file)
index 0000000..7f0dad6
--- /dev/null
@@ -0,0 +1,10 @@
+<module name="sc" type="win32cui" installbase="system32" installname="sc.exe">\r
+       <define name="__USE_W32API" />\r
+       <define name="DEFINE_GUID" />\r
+       <library>kernel32</library>\r
+       <file>sc.c</file>\r
+       <file>manage.c</file>\r
+       <file>query.c</file>\r
+       <file>usage.c</file>\r
+       <file>sc.rc</file>\r
+</module>\r
diff --git a/reactos/subsys/system/sc/usage.c b/reactos/subsys/system/sc/usage.c
new file mode 100644 (file)
index 0000000..f4d61a4
--- /dev/null
@@ -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;
+}