reactos/base/applications/sc/misc.c
2018-08-04 19:19:34 +02:00

327 lines
9 KiB
C

/*
* 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);
}
BOOL
ParseFailureActions(
IN LPCTSTR lpActions,
OUT DWORD *pcActions,
OUT SC_ACTION **ppActions)
{
SC_ACTION *pActions = NULL;
LPTSTR pStringBuffer = NULL;
LPTSTR p;
INT_PTR nLength;
INT nCount = 0;
*pcActions = 0;
*ppActions = NULL;
nLength = _tcslen(lpActions);
/* Allocate the string buffer */
pStringBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (nLength + 2) * sizeof(TCHAR));
if (pStringBuffer == NULL)
{
return FALSE;
}
/* Copy the actions string into the string buffer */
CopyMemory(pStringBuffer, lpActions, nLength * sizeof(TCHAR));
/* Replace all slashes by null characters */
p = pStringBuffer;
while (*p != _T('\0'))
{
if (*p == _T('/'))
*p = _T('\0');
p++;
}
/* Count the arguments in the buffer */
p = pStringBuffer;
while (*p != _T('\0'))
{
nCount++;
nLength = _tcslen(p);
p = (LPTSTR)((LONG_PTR)p + ((nLength + 1) * sizeof(TCHAR)));
}
/* Allocate the actions buffer */
pActions = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nCount / 2 * sizeof(SC_ACTION));
if (pActions == NULL)
{
HeapFree(GetProcessHeap(), 0, pStringBuffer);
return FALSE;
}
/* Parse the string buffer */
nCount = 0;
p = pStringBuffer;
while (*p != _T('\0'))
{
nLength = _tcslen(p);
if (nCount % 2 == 0)
{
/* Action */
if (!lstrcmpi(p, _T("reboot")))
pActions[nCount / 2].Type = SC_ACTION_REBOOT;
else if (!lstrcmpi(p, _T("restart")))
pActions[nCount / 2].Type = SC_ACTION_RESTART;
else if (!lstrcmpi(p, _T("run")))
pActions[nCount / 2].Type = SC_ACTION_RUN_COMMAND;
else
break;
}
else
{
/* Delay */
pActions[nCount / 2].Delay = _tcstoul(p, NULL, 10);
if (pActions[nCount / 2].Delay == 0 && errno == ERANGE)
break;
}
p = (LPTSTR)((LONG_PTR)p + ((nLength + 1) * sizeof(TCHAR)));
nCount++;
}
/* Free the string buffer */
HeapFree(GetProcessHeap(), 0, pStringBuffer);
*pcActions = nCount / 2;
*ppActions = pActions;
return TRUE;
}
BOOL
ParseFailureArguments(
IN LPCTSTR *ServiceArgs,
IN INT ArgCount,
OUT LPCTSTR *ppServiceName,
OUT LPSERVICE_FAILURE_ACTIONS pFailureActions)
{
INT ArgIndex = 1;
LPCTSTR lpActions = NULL;
LPCTSTR lpReset = NULL;
if (ArgCount < 1)
return FALSE;
ZeroMemory(pFailureActions, sizeof(SERVICE_FAILURE_ACTIONS));
*ppServiceName = ServiceArgs[0];
ArgCount--;
while (ArgCount > 1)
{
if (!lstrcmpi(ServiceArgs[ArgIndex], _T("actions=")))
{
lpActions = (LPTSTR)ServiceArgs[ArgIndex + 1];
}
else if (!lstrcmpi(ServiceArgs[ArgIndex], _T("command=")))
{
pFailureActions->lpCommand = (LPTSTR)ServiceArgs[ArgIndex + 1];
}
else if (!lstrcmpi(ServiceArgs[ArgIndex], _T("reboot=")))
{
pFailureActions->lpRebootMsg = (LPTSTR)ServiceArgs[ArgIndex + 1];
}
else if (!lstrcmpi(ServiceArgs[ArgIndex], _T("reset=")))
{
lpReset = (LPTSTR)ServiceArgs[ArgIndex + 1];
}
ArgIndex += 2;
ArgCount -= 2;
}
if ((lpReset == NULL && lpActions != NULL) ||
(lpReset != NULL && lpActions == NULL))
{
_tprintf(_T("ERROR: The reset and actions options must be used simultaneously.\n\n"));
return FALSE;
}
if (lpReset != NULL)
{
if (!lstrcmpi(lpReset, _T("infinite")))
pFailureActions->dwResetPeriod = INFINITE;
else
pFailureActions->dwResetPeriod = _ttoi(lpReset);
}
if (lpActions != NULL)
{
if (!ParseFailureActions(lpActions,
&pFailureActions->cActions,
&pFailureActions->lpsaActions))
{
return FALSE;
}
}
return (ArgCount == 0);
}