diff --git a/reactos/base/applications/sc/CMakeLists.txt b/reactos/base/applications/sc/CMakeLists.txt index baaddedd9ac..048db2f30e9 100644 --- a/reactos/base/applications/sc/CMakeLists.txt +++ b/reactos/base/applications/sc/CMakeLists.txt @@ -2,10 +2,12 @@ add_definitions(-DDEFINE_GUID) list(APPEND SOURCE + config.c control.c create.c delete.c description.c + misc.c print.c qc.c qfailure.c diff --git a/reactos/base/applications/sc/config.c b/reactos/base/applications/sc/config.c new file mode 100644 index 00000000000..295c4da62cc --- /dev/null +++ b/reactos/base/applications/sc/config.c @@ -0,0 +1,89 @@ +/* + * PROJECT: ReactOS Services + * LICENSE: GPL - See COPYING in the top level directory + * FILE: base/applications/sc/config.c + * PURPOSE: Set the service configuration + * COPYRIGHT: Copyright 2016 Eric Kohl + * + */ + +#include "sc.h" + +BOOL SetConfig(LPCTSTR *ServiceArgs, INT ArgCount) +{ + SC_HANDLE hManager = NULL; + SC_HANDLE hService = NULL; + BOOL bResult = TRUE; + SERVICE_CREATE_INFO ServiceInfo; + + if (!ParseCreateConfigArguments(ServiceArgs, ArgCount, TRUE, &ServiceInfo)) + { + SetConfigUsage(); + return FALSE; + } + +#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 + + hManager = OpenSCManager(NULL, + NULL, + SC_MANAGER_CONNECT); + if (hManager == NULL) + { + _tprintf(_T("[SC] OpenSCManager FAILED %lu:\n\n"), GetLastError()); + bResult = FALSE; + goto done; + } + + hService = OpenService(hManager, + ServiceInfo.lpServiceName, + SERVICE_CHANGE_CONFIG); + if (hService == NULL) + { + _tprintf(_T("[SC] OpenService FAILED %lu:\n\n"), GetLastError()); + bResult = FALSE; + goto done; + } + + if (!ChangeServiceConfig(hService, + ServiceInfo.dwServiceType, + ServiceInfo.dwStartType, + ServiceInfo.dwErrorControl, + ServiceInfo.lpBinaryPathName, + ServiceInfo.lpLoadOrderGroup, + ServiceInfo.bTagId ? &ServiceInfo.dwTagId : NULL, + ServiceInfo.lpDependencies, + ServiceInfo.lpServiceStartName, + ServiceInfo.lpPassword, + ServiceInfo.lpDisplayName)) + { + _tprintf(_T("[SC] ChangeServiceConfig FAILED %lu:\n\n"), GetLastError()); + bResult = FALSE; + goto done; + } + + _tprintf(_T("[SC] ChangeServiceConfig SUCCESS\n\n")); + +done: + if (bResult == FALSE) + ReportLastError(); + + if (hService) + CloseServiceHandle(hService); + + if (hManager) + CloseServiceHandle(hManager); + + return bResult; +} diff --git a/reactos/base/applications/sc/create.c b/reactos/base/applications/sc/create.c index 90ff47f986e..13982894f5c 100644 --- a/reactos/base/applications/sc/create.c +++ b/reactos/base/applications/sc/create.c @@ -10,163 +10,6 @@ #include "sc.h" -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; @@ -178,7 +21,7 @@ BOOL Create(LPCTSTR *ServiceArgs, INT ArgCount) LPTSTR lpBuffer = NULL; SERVICE_CREATE_INFO ServiceInfo; - if (!ParseCreateArguments(ServiceArgs, ArgCount, &ServiceInfo)) + if (!ParseCreateConfigArguments(ServiceArgs, ArgCount, FALSE, &ServiceInfo)) { CreateUsage(); return FALSE; diff --git a/reactos/base/applications/sc/misc.c b/reactos/base/applications/sc/misc.c new file mode 100644 index 00000000000..d1eff9cb154 --- /dev/null +++ b/reactos/base/applications/sc/misc.c @@ -0,0 +1,160 @@ +/* + * PROJECT: ReactOS Services + * LICENSE: GPL - See COPYING in the top level directory + * FILE: base/applications/sc/misc.c + * PURPOSE: Various functions + * COPYRIGHT: Copyright 2005 - 2006 Ged Murphy + * Roel Messiant + */ + +#include "sc.h" + +typedef struct +{ + LPCTSTR lpOption; + DWORD dwValue; +} OPTION_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 } +}; + + +BOOL +ParseCreateConfigArguments( + LPCTSTR *ServiceArgs, + INT ArgCount, + BOOL bChangeService, + OUT LPSERVICE_CREATE_INFO lpServiceInfo) +{ + INT i, ArgIndex = 1; + + if (ArgCount < 1) + return FALSE; + + ZeroMemory(lpServiceInfo, sizeof(SERVICE_CREATE_INFO)); + + if (bChangeService) + { + lpServiceInfo->dwServiceType = SERVICE_NO_CHANGE; + lpServiceInfo->dwStartType = SERVICE_NO_CHANGE; + lpServiceInfo->dwErrorControl = SERVICE_NO_CHANGE; + } + + 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)) + { + if (lpServiceInfo->dwServiceType == SERVICE_NO_CHANGE) + lpServiceInfo->dwServiceType = TypeOpts[i].dwValue; + else + 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); +} diff --git a/reactos/base/applications/sc/sc.c b/reactos/base/applications/sc/sc.c index 653e632efc8..215f2ee421c 100644 --- a/reactos/base/applications/sc/sc.c +++ b/reactos/base/applications/sc/sc.c @@ -264,6 +264,10 @@ ScControl(LPCTSTR Server, // remote machine name else SetDescriptionUsage(); } + else if (!lstrcmpi(Command, _T("config"))) + { + SetConfig(ServiceArgs, ArgCount); + } else { MainUsage(); diff --git a/reactos/base/applications/sc/sc.h b/reactos/base/applications/sc/sc.h index a0969af1096..4a611c3a9a1 100644 --- a/reactos/base/applications/sc/sc.h +++ b/reactos/base/applications/sc/sc.h @@ -11,6 +11,24 @@ #define SCDBG +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; + + /* control functions */ BOOL Start(LPCTSTR ServiceName, LPCTSTR *ServiceArgs, INT ArgCount); BOOL Create(LPCTSTR *ServiceArgs, INT ArgCount); @@ -22,6 +40,7 @@ LPSERVICE_STATUS_PROCESS QueryService(LPCTSTR ServiceName); BOOL SdShow(LPCTSTR ServiceName); BOOL SdSet(LPCTSTR ServiceName, LPCTSTR SecurityDescriptor); BOOL QueryConfig(LPCTSTR ServiceName); +BOOL SetConfig(LPCTSTR *ServiceArgs, INT ArgCount); BOOL QueryDescription(LPCTSTR ServiceName); BOOL SetDescription(LPCTSTR ServiceName, LPCTSTR Description); BOOL QueryFailure(LPCTSTR ServiceName); @@ -30,6 +49,14 @@ BOOL QueryFailure(LPCTSTR ServiceName); VOID PrintService(LPCTSTR ServiceName, LPSERVICE_STATUS_PROCESS pStatus, BOOL bExtended); VOID ReportLastError(VOID); +/* misc.c */ +BOOL +ParseCreateConfigArguments( + LPCTSTR *ServiceArgs, + INT ArgCount, + BOOL bChangeService, + OUT LPSERVICE_CREATE_INFO lpServiceInfo); + /* usage functions */ VOID MainUsage(VOID); VOID StartUsage(VOID); @@ -37,8 +64,6 @@ VOID PauseUsage(VOID); VOID InterrogateUsage(VOID); VOID ContinueUsage(VOID); VOID StopUsage(VOID); -VOID ConfigUsage(VOID); -VOID DescriptionUsage(VOID); VOID DeleteUsage(VOID); VOID CreateUsage(VOID); VOID ControlUsage(VOID); @@ -48,5 +73,6 @@ VOID QueryConfigUsage(VOID); VOID QueryDescriptionUsage(VOID); VOID QueryFailureUsage(VOID); VOID SetDescriptionUsage(VOID); +VOID SetConfigUsage(VOID); #endif /* _SC_PCH_ */ diff --git a/reactos/base/applications/sc/usage.c b/reactos/base/applications/sc/usage.c index 93a7de39b4f..3132ed808dc 100644 --- a/reactos/base/applications/sc/usage.c +++ b/reactos/base/applications/sc/usage.c @@ -33,7 +33,7 @@ VOID MainUsage(VOID) _T("\t interrogate : Sends a INTERROGATE control request to a service.\n") _T("\t continue : Sends a CONTINUE control request to a service.\n") _T("\t stop : Sends a STOP request to a service.\n") -// "\t config : Changes the configuration of a service (persistant).\n" + _T("\t config : Changes the configuration of a service (persistant).\n") _T("\t description : Changes the description of a service.\n") // "\t failure : Changes the actions taken by a service upon failure.\n" _T("\t qc : Queries the configuration information for a service.\n") @@ -134,21 +134,6 @@ VOID ContinueUsage(VOID) _T(" sc continue [service name]\n")); } - -VOID ConfigUsage(VOID) -{ - _tprintf(_T("not yet implemented\n")); -} - - -VOID DescriptionUsage(VOID) -{ - _tprintf(_T("DESCRIPTION:\n") - _T(" Sets the description string for a service.\n") - _T("USAGE:\n") - _T(" sc description [service name]\n")); -} - VOID DeleteUsage(VOID) { _tprintf(_T("DESCRIPTION:\n") @@ -237,4 +222,24 @@ VOID SetDescriptionUsage(VOID) _T(" Sets the description string of a service.\n") _T("USAGE:\n") _T(" sc description [service name] [description]\n")); -} \ No newline at end of file +} + +VOID SetConfigUsage(VOID) +{ + _tprintf(_T("DESCRIPTION:\n") + _T(" Modifies a service entry in the registry and Service Database.\n") + _T("USAGE:\n") + _T(" sc config [service name] ...\n") + _T("CONFIG OPTIONS:\n") + _T(" NOTE: The option name includes the equal sign.\n") + _T(" type= \n") + _T(" start= \n") + _T(" error= \n") + _T(" binPath= \n") + _T(" group= \n") + _T(" tag= \n") + _T(" depend= \n") + _T(" obj= \n") + _T(" DisplayName= \n") + _T(" password= \n")); +}