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