- Move ParseCreateArguments to the misc.c file, rename it to ParseCreateConfigArguments and tweak it for use in the config command.
- Implement the config command.

svn path=/trunk/; revision=71633
This commit is contained in:
Eric Kohl 2016-06-13 19:43:02 +00:00
parent fc0c674649
commit fdf12baa2b
7 changed files with 306 additions and 177 deletions

View file

@ -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

View file

@ -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;
}

View file

@ -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;

View file

@ -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 <gedmurphy@gmail.com>
* Roel Messiant <roelmessiant@gmail.com>
*/
#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);
}

View file

@ -264,6 +264,10 @@ ScControl(LPCTSTR Server, // remote machine name
else
SetDescriptionUsage();
}
else if (!lstrcmpi(Command, _T("config")))
{
SetConfig(ServiceArgs, ArgCount);
}
else
{
MainUsage();

View file

@ -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_ */

View file

@ -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 <server> 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 <server> 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 <server> description [service name] [description]\n"));
}
}
VOID SetConfigUsage(VOID)
{
_tprintf(_T("DESCRIPTION:\n")
_T(" Modifies a service entry in the registry and Service Database.\n")
_T("USAGE:\n")
_T(" sc <server> config [service name] <option1> <option2>...\n")
_T("CONFIG OPTIONS:\n")
_T(" NOTE: The option name includes the equal sign.\n")
_T(" type= <own|share|interact|kernel|filesys|rec>\n")
_T(" start= <boot|system|auto|demand|disabled>\n")
_T(" error= <normal|severe|critical|ignore>\n")
_T(" binPath= <BinaryPathName>\n")
_T(" group= <LoadOrderGroup>\n")
_T(" tag= <yes|no>\n")
_T(" depend= <Dependencies(separated by / (forward slash))>\n")
_T(" obj= <AccountName|ObjectName>\n")
_T(" DisplayName= <display name>\n")
_T(" password= <password>\n"));
}