From becc9ed28249d1be717f27cecd26aa34c0051216 Mon Sep 17 00:00:00 2001 From: Aleksey Bragin Date: Sat, 18 Sep 2010 08:41:06 +0000 Subject: [PATCH] [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. svn path=/trunk/; revision=48800 --- reactos/base/applications/sc/create.c | 289 +++++++++++++++++++++----- reactos/base/applications/sc/sc.c | 90 ++++---- reactos/base/applications/sc/sc.h | 3 +- reactos/base/applications/sc/usage.c | 12 +- 4 files changed, 290 insertions(+), 104 deletions(-) diff --git a/reactos/base/applications/sc/create.c b/reactos/base/applications/sc/create.c index 85a064d1d74..00ae3325c41 100644 --- a/reactos/base/applications/sc/create.c +++ b/reactos/base/applications/sc/create.c @@ -4,86 +4,265 @@ * FILE: base/system/sc/create.c * PURPOSE: Create a service * COPYRIGHT: Copyright 2005 - 2006 Ged Murphy + * Roel Messiant * */ #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; + INT i; + INT Length; + LPTSTR lpBuffer = NULL; + SERVICE_CREATE_INFO ServiceInfo; - /* 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) + 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) { - ReportLastError(); - return FALSE; + 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; } - hSc = CreateService(hSCManager, - ServiceName, - ServiceName, - SERVICE_ALL_ACCESS, - dwServiceType, - dwStartType, - dwErrorControl, - lpBinaryPathName, - lpLoadOrderGroup, - &dwTagId, - lpDependencies, - lpServiceStartName, - lpPassword); +#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 - if (hSc == NULL) + hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE); + + if (hSCManager != NULL) { - ReportLastError(); + 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 - { - _tprintf(_T("[SC] CreateService SUCCESS\n")); + ReportLastError(); - CloseServiceHandle(hSc); - CloseServiceHandle(hSCManager); - bRet = TRUE; - } + if (lpBuffer != NULL) + HeapFree(GetProcessHeap(), 0, lpBuffer); return bRet; } diff --git a/reactos/base/applications/sc/sc.c b/reactos/base/applications/sc/sc.c index 9c45ed86d64..390e9fe2ade 100644 --- a/reactos/base/applications/sc/sc.c +++ b/reactos/base/applications/sc/sc.c @@ -67,11 +67,11 @@ ScControl(LPCTSTR Server, // remote machine name } 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 @@ ScControl(LPCTSTR Server, // remote machine name } 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 @@ ScControl(LPCTSTR Server, // remote machine name } 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 @@ ScControl(LPCTSTR Server, // remote machine name } 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 @@ ScControl(LPCTSTR Server, // remote machine name } 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 @@ ScControl(LPCTSTR Server, // remote machine name } else if (!lstrcmpi(Command, _T("delete"))) { - ServiceName = *ServiceArgs++; - ArgCount--; + if (ArgCount > 0) + { + ServiceName = *ServiceArgs++; + ArgCount--; - if (ServiceName) 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 (ArgCount > 1) { - if ((CtlValue >=128) && CtlValue <= 255) - { + ServiceName = *ServiceArgs++; + ArgCount--; + + CtlValue = _ttoi(ServiceArgs[0]); + ServiceArgs++; + ArgCount--; + + if ((CtlValue >= 128) && (CtlValue <= 255)) Control(CtlValue, ServiceName, ServiceArgs, ArgCount); - - return 0; - } + else + ControlUsage(); } - - ContinueUsage(); + else + ControlUsage(); } + else + { + MainUsage(); + } + return 0; } diff --git a/reactos/base/applications/sc/sc.h b/reactos/base/applications/sc/sc.h index cec74b921a1..52d939ea24f 100644 --- a/reactos/base/applications/sc/sc.h +++ b/reactos/base/applications/sc/sc.h @@ -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 ConfigUsage(VOID); VOID DescriptionUsage(VOID); VOID DeleteUsage(VOID); VOID CreateUsage(VOID); +VOID ControlUsage(VOID); diff --git a/reactos/base/applications/sc/usage.c b/reactos/base/applications/sc/usage.c index add5ea25f29..f4680ef1bd4 100644 --- a/reactos/base/applications/sc/usage.c +++ b/reactos/base/applications/sc/usage.c @@ -118,7 +118,7 @@ VOID InterrogateUsage(VOID) 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 stop [service name]\n")); } @@ -126,7 +126,7 @@ VOID StopUsage(VOID) 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 continue [service name]\n")); } @@ -179,3 +179,11 @@ VOID CreateUsage(VOID) _T(" DisplayName= \n") _T(" password= \n")); } + +VOID ControlUsage(VOID) +{ + _tprintf(_T("DESCRIPTION:\n") + _T(" Sends a CONTROL control request to a service.\n") + _T("USAGE:\n") + _T(" sc control [service name] \n")); +}