Author: fireball Date: Sat Sep 18 08:41:06 2010 New Revision: 48800
URL: http://svn.reactos.org/svn/reactos?rev=48800&view=rev Log: [SC] - Roel Messiant: Fix a crash when running some operations in sc without providing arguments. Also, provide usage information for the control and unknown commands. - Aleksey Bragin: Take Ged Murphy's comments into account and change pointer arithmetic to a convenient style. See issue #5611 for more details.
Modified: trunk/reactos/base/applications/sc/create.c trunk/reactos/base/applications/sc/sc.c trunk/reactos/base/applications/sc/sc.h trunk/reactos/base/applications/sc/usage.c
Modified: trunk/reactos/base/applications/sc/create.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/sc/create... ============================================================================== --- trunk/reactos/base/applications/sc/create.c [iso-8859-1] (original) +++ trunk/reactos/base/applications/sc/create.c [iso-8859-1] Sat Sep 18 08:41:06 2010 @@ -4,86 +4,265 @@ * FILE: base/system/sc/create.c * PURPOSE: Create a service * COPYRIGHT: Copyright 2005 - 2006 Ged Murphy gedmurphy@gmail.com + * Roel Messiant roelmessiant@gmail.com * */
#include "sc.h"
-BOOL Create(LPCTSTR ServiceName, LPCTSTR *ServiceArgs) + +typedef struct +{ + LPCTSTR lpOption; + DWORD dwValue; +} OPTION_INFO; + +typedef struct +{ + LPCTSTR lpServiceName; + LPCTSTR lpDisplayName; + DWORD dwServiceType; + DWORD dwStartType; + DWORD dwErrorControl; + LPCTSTR lpBinaryPathName; + LPCTSTR lpLoadOrderGroup; + DWORD dwTagId; + LPCTSTR lpDependencies; + LPCTSTR lpServiceStartName; + LPCTSTR lpPassword; + + BOOL bTagId; +} SERVICE_CREATE_INFO, *LPSERVICE_CREATE_INFO; + + +static const OPTION_INFO TypeOpts[] = +{ + { _T("own"), SERVICE_WIN32_OWN_PROCESS }, + { _T("share"), SERVICE_WIN32_SHARE_PROCESS }, + { _T("interact"), SERVICE_INTERACTIVE_PROCESS }, + { _T("kernel"), SERVICE_KERNEL_DRIVER }, + { _T("filesys"), SERVICE_FILE_SYSTEM_DRIVER }, + { _T("rec"), SERVICE_RECOGNIZER_DRIVER } +}; + +static const OPTION_INFO StartOpts[] = +{ + { _T("boot"), SERVICE_BOOT_START }, + { _T("system"), SERVICE_SYSTEM_START }, + { _T("auto"), SERVICE_AUTO_START }, + { _T("demand"), SERVICE_DEMAND_START }, + { _T("disabled"), SERVICE_DISABLED } +}; + +static const OPTION_INFO ErrorOpts[] = +{ + { _T("normal"), SERVICE_ERROR_NORMAL }, + { _T("severe"), SERVICE_ERROR_SEVERE }, + { _T("critical"), SERVICE_ERROR_CRITICAL }, + { _T("ignore"), SERVICE_ERROR_IGNORE } +}; + +static const OPTION_INFO TagOpts[] = +{ + { _T("yes"), TRUE }, + { _T("no"), FALSE } +}; + + +static BOOL ParseCreateArguments( + LPCTSTR *ServiceArgs, + INT ArgCount, + OUT LPSERVICE_CREATE_INFO lpServiceInfo +) +{ + INT i, ArgIndex = 1; + + if (ArgCount < 1) + return FALSE; + + ZeroMemory(lpServiceInfo, sizeof(SERVICE_CREATE_INFO)); + + lpServiceInfo->lpServiceName = ServiceArgs[0]; + + ArgCount--; + + while (ArgCount > 1) + { + if (!lstrcmpi(ServiceArgs[ArgIndex], _T("type="))) + { + for (i = 0; i < sizeof(TypeOpts) / sizeof(TypeOpts[0]); i++) + if (!lstrcmpi(ServiceArgs[ArgIndex + 1], TypeOpts[i].lpOption)) + { + lpServiceInfo->dwServiceType |= TypeOpts[i].dwValue; + break; + } + + if (i == sizeof(TypeOpts) / sizeof(TypeOpts[0])) + break; + } + else if (!lstrcmpi(ServiceArgs[ArgIndex], _T("start="))) + { + for (i = 0; i < sizeof(StartOpts) / sizeof(StartOpts[0]); i++) + if (!lstrcmpi(ServiceArgs[ArgIndex + 1], StartOpts[i].lpOption)) + { + lpServiceInfo->dwStartType = StartOpts[i].dwValue; + break; + } + + if (i == sizeof(StartOpts) / sizeof(StartOpts[0])) + break; + } + else if (!lstrcmpi(ServiceArgs[ArgIndex], _T("error="))) + { + for (i = 0; i < sizeof(ErrorOpts) / sizeof(ErrorOpts[0]); i++) + if (!lstrcmpi(ServiceArgs[ArgIndex + 1], ErrorOpts[i].lpOption)) + { + lpServiceInfo->dwErrorControl = ErrorOpts[i].dwValue; + break; + } + + if (i == sizeof(ErrorOpts) / sizeof(ErrorOpts[0])) + break; + } + else if (!lstrcmpi(ServiceArgs[ArgIndex], _T("tag="))) + { + for (i = 0; i < sizeof(TagOpts) / sizeof(TagOpts[0]); i++) + if (!lstrcmpi(ServiceArgs[ArgIndex + 1], TagOpts[i].lpOption)) + { + lpServiceInfo->bTagId = TagOpts[i].dwValue; + break; + } + + if (i == sizeof(TagOpts) / sizeof(TagOpts[0])) + break; + } + else if (!lstrcmpi(ServiceArgs[ArgIndex], _T("binpath="))) + { + lpServiceInfo->lpBinaryPathName = ServiceArgs[ArgIndex + 1]; + } + else if (!lstrcmpi(ServiceArgs[ArgIndex], _T("group="))) + { + lpServiceInfo->lpLoadOrderGroup = ServiceArgs[ArgIndex + 1]; + } + else if (!lstrcmpi(ServiceArgs[ArgIndex], _T("depend="))) + { + lpServiceInfo->lpDependencies = ServiceArgs[ArgIndex + 1]; + } + else if (!lstrcmpi(ServiceArgs[ArgIndex], _T("obj="))) + { + lpServiceInfo->lpServiceStartName = ServiceArgs[ArgIndex + 1]; + } + else if (!lstrcmpi(ServiceArgs[ArgIndex], _T("displayname="))) + { + lpServiceInfo->lpDisplayName = ServiceArgs[ArgIndex + 1]; + } + else if (!lstrcmpi(ServiceArgs[ArgIndex], _T("password="))) + { + lpServiceInfo->lpPassword = ServiceArgs[ArgIndex + 1]; + } + + ArgIndex += 2; + ArgCount -= 2; + } + + return (ArgCount == 0); +} + +BOOL Create(LPCTSTR *ServiceArgs, INT ArgCount) { SC_HANDLE hSCManager; SC_HANDLE hSc; BOOL bRet = FALSE;
- DWORD dwServiceType = SERVICE_WIN32_OWN_PROCESS; - DWORD dwStartType = SERVICE_DEMAND_START; - DWORD dwErrorControl = SERVICE_ERROR_NORMAL; - LPCTSTR lpBinaryPathName = NULL; - LPCTSTR lpLoadOrderGroup = NULL; - DWORD dwTagId = 0; - LPCTSTR lpDependencies = NULL; - LPCTSTR lpServiceStartName = NULL; - LPCTSTR lpPassword = NULL; - - /* quick hack to get it working */ - lpBinaryPathName = *ServiceArgs; - -#ifdef SCDBG - _tprintf(_T("service name - %s\n"), ServiceName); - _tprintf(_T("display name - %s\n"), ServiceName); - _tprintf(_T("service type - %lu\n"), dwServiceType); - _tprintf(_T("start type - %lu\n"), dwStartType); - _tprintf(_T("error control - %lu\n"), dwErrorControl); - _tprintf(_T("Binary path - %s\n"), lpBinaryPathName); - _tprintf(_T("load order group - %s\n"), lpLoadOrderGroup); - _tprintf(_T("tag - %lu\n"), dwTagId); - _tprintf(_T("dependincies - %s\n"), lpDependencies); - _tprintf(_T("account start name - %s\n"), lpServiceStartName); - _tprintf(_T("account password - %s\n"), lpPassword); -#endif - - if (!ServiceName) + INT i; + INT Length; + LPTSTR lpBuffer = NULL; + SERVICE_CREATE_INFO ServiceInfo; + + if (!ParseCreateArguments(ServiceArgs, ArgCount, &ServiceInfo)) { CreateUsage(); return FALSE; }
- hSCManager = OpenSCManager(NULL, - NULL, - SC_MANAGER_CREATE_SERVICE); - if (hSCManager == NULL) - { + if (!ServiceInfo.dwServiceType) + ServiceInfo.dwServiceType = SERVICE_WIN32_OWN_PROCESS; + + if (!ServiceInfo.dwStartType) + ServiceInfo.dwStartType = SERVICE_DEMAND_START; + + if (!ServiceInfo.dwErrorControl) + ServiceInfo.dwErrorControl = SERVICE_ERROR_NORMAL; + + if (ServiceInfo.lpDependencies) + { + Length = lstrlen(ServiceInfo.lpDependencies); + + lpBuffer = HeapAlloc(GetProcessHeap(), + 0, + (Length + 2) * sizeof(TCHAR)); + + for (i = 0; i < Length; i++) + if (ServiceInfo.lpDependencies[i] == _T('/')) + lpBuffer[i] = 0; + else + lpBuffer[i] = ServiceInfo.lpDependencies[i]; + + lpBuffer[Length] = 0; + lpBuffer[Length + 1] = 0; + + ServiceInfo.lpDependencies = lpBuffer; + } + +#ifdef SCDBG + _tprintf(_T("service name - %s\n"), ServiceInfo.lpServiceName); + _tprintf(_T("display name - %s\n"), ServiceInfo.lpDisplayName); + _tprintf(_T("service type - %lu\n"), ServiceInfo.dwServiceType); + _tprintf(_T("start type - %lu\n"), ServiceInfo.dwStartType); + _tprintf(_T("error control - %lu\n"), ServiceInfo.dwErrorControl); + _tprintf(_T("Binary path - %s\n"), ServiceInfo.lpBinaryPathName); + _tprintf(_T("load order group - %s\n"), ServiceInfo.lpLoadOrderGroup); + _tprintf(_T("tag - %lu\n"), ServiceInfo.dwTagId); + _tprintf(_T("dependencies - %s\n"), ServiceInfo.lpDependencies); + _tprintf(_T("account start name - %s\n"), ServiceInfo.lpServiceStartName); + _tprintf(_T("account password - %s\n"), ServiceInfo.lpPassword); +#endif + + hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE); + + if (hSCManager != NULL) + { + hSc = CreateService(hSCManager, + ServiceInfo.lpServiceName, + ServiceInfo.lpDisplayName, + SERVICE_ALL_ACCESS, + ServiceInfo.dwServiceType, + ServiceInfo.dwStartType, + ServiceInfo.dwErrorControl, + ServiceInfo.lpBinaryPathName, + ServiceInfo.lpLoadOrderGroup, + ServiceInfo.bTagId ? &ServiceInfo.dwTagId : NULL, + ServiceInfo.lpDependencies, + ServiceInfo.lpServiceStartName, + ServiceInfo.lpPassword); + + if (hSc != NULL) + { + _tprintf(_T("[SC] CreateService SUCCESS\n")); + + CloseServiceHandle(hSc); + bRet = TRUE; + } + else + ReportLastError(); + + CloseServiceHandle(hSCManager); + } + else ReportLastError(); - return FALSE; - } - - hSc = CreateService(hSCManager, - ServiceName, - ServiceName, - SERVICE_ALL_ACCESS, - dwServiceType, - dwStartType, - dwErrorControl, - lpBinaryPathName, - lpLoadOrderGroup, - &dwTagId, - lpDependencies, - lpServiceStartName, - lpPassword); - - if (hSc == NULL) - { - ReportLastError(); - CloseServiceHandle(hSCManager); - } - else - { - _tprintf(_T("[SC] CreateService SUCCESS\n")); - - CloseServiceHandle(hSc); - CloseServiceHandle(hSCManager); - bRet = TRUE; - } + + if (lpBuffer != NULL) + HeapFree(GetProcessHeap(), 0, lpBuffer);
return bRet; }
Modified: trunk/reactos/base/applications/sc/sc.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/sc/sc.c?r... ============================================================================== --- trunk/reactos/base/applications/sc/sc.c [iso-8859-1] (original) +++ trunk/reactos/base/applications/sc/sc.c [iso-8859-1] Sat Sep 18 08:41:06 2010 @@ -67,11 +67,11 @@ } else if (!lstrcmpi(Command, _T("start"))) { - ServiceName = *ServiceArgs++; - ArgCount--; - - if (ServiceName) - { + if (ArgCount > 0) + { + ServiceName = *ServiceArgs++; + ArgCount--; + Start(ServiceName, ServiceArgs, ArgCount); @@ -81,11 +81,11 @@ } else if (!lstrcmpi(Command, _T("pause"))) { - ServiceName = *ServiceArgs++; - ArgCount--; - - if (ServiceName) - { + if (ArgCount > 0) + { + ServiceName = *ServiceArgs++; + ArgCount--; + Control(SERVICE_CONTROL_PAUSE, ServiceName, ServiceArgs, @@ -96,11 +96,11 @@ } else if (!lstrcmpi(Command, _T("interrogate"))) { - ServiceName = *ServiceArgs++; - ArgCount--; - - if (ServiceName) - { + if (ArgCount > 0) + { + ServiceName = *ServiceArgs++; + ArgCount--; + Control(SERVICE_CONTROL_INTERROGATE, ServiceName, ServiceArgs, @@ -111,11 +111,11 @@ } else if (!lstrcmpi(Command, _T("stop"))) { - ServiceName = *ServiceArgs++; - ArgCount--; - - if (ServiceName) - { + if (ArgCount > 0) + { + ServiceName = *ServiceArgs++; + ArgCount--; + Control(SERVICE_CONTROL_STOP, ServiceName, ServiceArgs, @@ -126,11 +126,11 @@ } else if (!lstrcmpi(Command, _T("continue"))) { - ServiceName = *ServiceArgs++; - ArgCount--; - - if (ServiceName) - { + if (ArgCount > 0) + { + ServiceName = *ServiceArgs++; + ArgCount--; + Control(SERVICE_CONTROL_CONTINUE, ServiceName, ServiceArgs, @@ -141,51 +141,49 @@ } else if (!lstrcmpi(Command, _T("delete"))) { - ServiceName = *ServiceArgs++; - ArgCount--; - - if (ServiceName) + if (ArgCount > 0) + { + ServiceName = *ServiceArgs++; + ArgCount--; + Delete(ServiceName); + } else DeleteUsage(); } else if (!lstrcmpi(Command, _T("create"))) { - ServiceName = *ServiceArgs++; - ArgCount--; - - if (*ServiceArgs) - Create(ServiceName, - ServiceArgs); - else - CreateUsage(); + Create(ServiceArgs, ArgCount); } else if (!lstrcmpi(Command, _T("control"))) { INT CtlValue;
- ServiceName = *ServiceArgs++; - ArgCount--; - - CtlValue = _ttoi(ServiceArgs[0]); - ServiceArgs++; - ArgCount--; - - if (ServiceName) - { - if ((CtlValue >=128) && CtlValue <= 255) - { + if (ArgCount > 1) + { + ServiceName = *ServiceArgs++; + ArgCount--; + + CtlValue = _ttoi(ServiceArgs[0]); + ServiceArgs++; + ArgCount--; + + if ((CtlValue >= 128) && (CtlValue <= 255)) Control(CtlValue, ServiceName, ServiceArgs, ArgCount); - - return 0; - } - } - - ContinueUsage(); - } + else + ControlUsage(); + } + else + ControlUsage(); + } + else + { + MainUsage(); + } + return 0; }
Modified: trunk/reactos/base/applications/sc/sc.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/sc/sc.h?r... ============================================================================== --- trunk/reactos/base/applications/sc/sc.h [iso-8859-1] (original) +++ trunk/reactos/base/applications/sc/sc.h [iso-8859-1] Sat Sep 18 08:41:06 2010 @@ -7,7 +7,7 @@
/* control functions */ BOOL Start(LPCTSTR ServiceName, LPCTSTR *ServiceArgs, INT ArgCount); -BOOL Create(LPCTSTR ServiceName, LPCTSTR *ServiceArgs); +BOOL Create(LPCTSTR *ServiceArgs, INT ArgCount); BOOL Delete(LPCTSTR ServiceName); BOOL Control(DWORD Control, LPCTSTR ServiceName, LPCTSTR *Args, INT ArgCount); BOOL Query(LPCTSTR *ServiceArgs, DWORD ArgCount, BOOL bExtended); @@ -29,3 +29,4 @@ VOID DescriptionUsage(VOID); VOID DeleteUsage(VOID); VOID CreateUsage(VOID); +VOID ControlUsage(VOID);
Modified: trunk/reactos/base/applications/sc/usage.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/sc/usage.... ============================================================================== --- trunk/reactos/base/applications/sc/usage.c [iso-8859-1] (original) +++ trunk/reactos/base/applications/sc/usage.c [iso-8859-1] Sat Sep 18 08:41:06 2010 @@ -118,7 +118,7 @@ VOID StopUsage(VOID) { _tprintf(_T("DESCRIPTION:\n") - _T(" Sends an STOP control request to a service.\n") + _T(" Sends a STOP control request to a service.\n") _T("USAGE:\n") _T(" sc <server> stop [service name]\n")); } @@ -126,7 +126,7 @@ VOID ContinueUsage(VOID) { _tprintf(_T("DESCRIPTION:\n") - _T(" Sends an CONTINUE control request to a service.\n") + _T(" Sends a CONTINUE control request to a service.\n") _T("USAGE:\n") _T(" sc <server> continue [service name]\n")); } @@ -179,3 +179,11 @@ _T(" DisplayName= <display name>\n") _T(" password= <password>\n")); } + +VOID ControlUsage(VOID) +{ + _tprintf(_T("DESCRIPTION:\n") + _T(" Sends a CONTROL control request to a service.\n") + _T("USAGE:\n") + _T(" sc <server> control [service name] <value>\n")); +}