- 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
This commit is contained in:
Aleksey Bragin 2010-09-18 08:41:06 +00:00
parent 2c10fb5d07
commit becc9ed282
4 changed files with 290 additions and 104 deletions

View file

@ -4,86 +4,265 @@
* FILE: base/system/sc/create.c * FILE: base/system/sc/create.c
* PURPOSE: Create a service * PURPOSE: Create a service
* COPYRIGHT: Copyright 2005 - 2006 Ged Murphy <gedmurphy@gmail.com> * COPYRIGHT: Copyright 2005 - 2006 Ged Murphy <gedmurphy@gmail.com>
* Roel Messiant <roelmessiant@gmail.com>
* *
*/ */
#include "sc.h" #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 hSCManager;
SC_HANDLE hSc; SC_HANDLE hSc;
BOOL bRet = FALSE; BOOL bRet = FALSE;
DWORD dwServiceType = SERVICE_WIN32_OWN_PROCESS; INT i;
DWORD dwStartType = SERVICE_DEMAND_START; INT Length;
DWORD dwErrorControl = SERVICE_ERROR_NORMAL; LPTSTR lpBuffer = NULL;
LPCTSTR lpBinaryPathName = NULL; SERVICE_CREATE_INFO ServiceInfo;
LPCTSTR lpLoadOrderGroup = NULL;
DWORD dwTagId = 0;
LPCTSTR lpDependencies = NULL;
LPCTSTR lpServiceStartName = NULL;
LPCTSTR lpPassword = NULL;
/* quick hack to get it working */ if (!ParseCreateArguments(ServiceArgs, ArgCount, &ServiceInfo))
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)
{ {
CreateUsage(); CreateUsage();
return FALSE; return FALSE;
} }
hSCManager = OpenSCManager(NULL, if (!ServiceInfo.dwServiceType)
NULL, ServiceInfo.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
SC_MANAGER_CREATE_SERVICE);
if (hSCManager == NULL) if (!ServiceInfo.dwStartType)
ServiceInfo.dwStartType = SERVICE_DEMAND_START;
if (!ServiceInfo.dwErrorControl)
ServiceInfo.dwErrorControl = SERVICE_ERROR_NORMAL;
if (ServiceInfo.lpDependencies)
{ {
ReportLastError(); Length = lstrlen(ServiceInfo.lpDependencies);
return FALSE;
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, #ifdef SCDBG
ServiceName, _tprintf(_T("service name - %s\n"), ServiceInfo.lpServiceName);
ServiceName, _tprintf(_T("display name - %s\n"), ServiceInfo.lpDisplayName);
SERVICE_ALL_ACCESS, _tprintf(_T("service type - %lu\n"), ServiceInfo.dwServiceType);
dwServiceType, _tprintf(_T("start type - %lu\n"), ServiceInfo.dwStartType);
dwStartType, _tprintf(_T("error control - %lu\n"), ServiceInfo.dwErrorControl);
dwErrorControl, _tprintf(_T("Binary path - %s\n"), ServiceInfo.lpBinaryPathName);
lpBinaryPathName, _tprintf(_T("load order group - %s\n"), ServiceInfo.lpLoadOrderGroup);
lpLoadOrderGroup, _tprintf(_T("tag - %lu\n"), ServiceInfo.dwTagId);
&dwTagId, _tprintf(_T("dependencies - %s\n"), ServiceInfo.lpDependencies);
lpDependencies, _tprintf(_T("account start name - %s\n"), ServiceInfo.lpServiceStartName);
lpServiceStartName, _tprintf(_T("account password - %s\n"), ServiceInfo.lpPassword);
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); CloseServiceHandle(hSCManager);
} }
else else
{ ReportLastError();
_tprintf(_T("[SC] CreateService SUCCESS\n"));
CloseServiceHandle(hSc); if (lpBuffer != NULL)
CloseServiceHandle(hSCManager); HeapFree(GetProcessHeap(), 0, lpBuffer);
bRet = TRUE;
}
return bRet; return bRet;
} }

View file

@ -67,11 +67,11 @@ ScControl(LPCTSTR Server, // remote machine name
} }
else if (!lstrcmpi(Command, _T("start"))) else if (!lstrcmpi(Command, _T("start")))
{ {
ServiceName = *ServiceArgs++; if (ArgCount > 0)
ArgCount--;
if (ServiceName)
{ {
ServiceName = *ServiceArgs++;
ArgCount--;
Start(ServiceName, Start(ServiceName,
ServiceArgs, ServiceArgs,
ArgCount); ArgCount);
@ -81,11 +81,11 @@ ScControl(LPCTSTR Server, // remote machine name
} }
else if (!lstrcmpi(Command, _T("pause"))) else if (!lstrcmpi(Command, _T("pause")))
{ {
ServiceName = *ServiceArgs++; if (ArgCount > 0)
ArgCount--;
if (ServiceName)
{ {
ServiceName = *ServiceArgs++;
ArgCount--;
Control(SERVICE_CONTROL_PAUSE, Control(SERVICE_CONTROL_PAUSE,
ServiceName, ServiceName,
ServiceArgs, ServiceArgs,
@ -96,11 +96,11 @@ ScControl(LPCTSTR Server, // remote machine name
} }
else if (!lstrcmpi(Command, _T("interrogate"))) else if (!lstrcmpi(Command, _T("interrogate")))
{ {
ServiceName = *ServiceArgs++; if (ArgCount > 0)
ArgCount--;
if (ServiceName)
{ {
ServiceName = *ServiceArgs++;
ArgCount--;
Control(SERVICE_CONTROL_INTERROGATE, Control(SERVICE_CONTROL_INTERROGATE,
ServiceName, ServiceName,
ServiceArgs, ServiceArgs,
@ -111,11 +111,11 @@ ScControl(LPCTSTR Server, // remote machine name
} }
else if (!lstrcmpi(Command, _T("stop"))) else if (!lstrcmpi(Command, _T("stop")))
{ {
ServiceName = *ServiceArgs++; if (ArgCount > 0)
ArgCount--;
if (ServiceName)
{ {
ServiceName = *ServiceArgs++;
ArgCount--;
Control(SERVICE_CONTROL_STOP, Control(SERVICE_CONTROL_STOP,
ServiceName, ServiceName,
ServiceArgs, ServiceArgs,
@ -126,11 +126,11 @@ ScControl(LPCTSTR Server, // remote machine name
} }
else if (!lstrcmpi(Command, _T("continue"))) else if (!lstrcmpi(Command, _T("continue")))
{ {
ServiceName = *ServiceArgs++; if (ArgCount > 0)
ArgCount--;
if (ServiceName)
{ {
ServiceName = *ServiceArgs++;
ArgCount--;
Control(SERVICE_CONTROL_CONTINUE, Control(SERVICE_CONTROL_CONTINUE,
ServiceName, ServiceName,
ServiceArgs, ServiceArgs,
@ -141,51 +141,49 @@ ScControl(LPCTSTR Server, // remote machine name
} }
else if (!lstrcmpi(Command, _T("delete"))) else if (!lstrcmpi(Command, _T("delete")))
{ {
ServiceName = *ServiceArgs++; if (ArgCount > 0)
ArgCount--; {
ServiceName = *ServiceArgs++;
ArgCount--;
if (ServiceName)
Delete(ServiceName); Delete(ServiceName);
}
else else
DeleteUsage(); DeleteUsage();
} }
else if (!lstrcmpi(Command, _T("create"))) else if (!lstrcmpi(Command, _T("create")))
{ {
ServiceName = *ServiceArgs++; Create(ServiceArgs, ArgCount);
ArgCount--;
if (*ServiceArgs)
Create(ServiceName,
ServiceArgs);
else
CreateUsage();
} }
else if (!lstrcmpi(Command, _T("control"))) else if (!lstrcmpi(Command, _T("control")))
{ {
INT CtlValue; INT CtlValue;
ServiceName = *ServiceArgs++; if (ArgCount > 1)
ArgCount--;
CtlValue = _ttoi(ServiceArgs[0]);
ServiceArgs++;
ArgCount--;
if (ServiceName)
{ {
if ((CtlValue >=128) && CtlValue <= 255) ServiceName = *ServiceArgs++;
{ ArgCount--;
CtlValue = _ttoi(ServiceArgs[0]);
ServiceArgs++;
ArgCount--;
if ((CtlValue >= 128) && (CtlValue <= 255))
Control(CtlValue, Control(CtlValue,
ServiceName, ServiceName,
ServiceArgs, ServiceArgs,
ArgCount); ArgCount);
else
return 0; ControlUsage();
}
} }
else
ContinueUsage(); ControlUsage();
} }
else
{
MainUsage();
}
return 0; return 0;
} }

View file

@ -7,7 +7,7 @@
/* control functions */ /* control functions */
BOOL Start(LPCTSTR ServiceName, LPCTSTR *ServiceArgs, INT ArgCount); 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 Delete(LPCTSTR ServiceName);
BOOL Control(DWORD Control, LPCTSTR ServiceName, LPCTSTR *Args, INT ArgCount); BOOL Control(DWORD Control, LPCTSTR ServiceName, LPCTSTR *Args, INT ArgCount);
BOOL Query(LPCTSTR *ServiceArgs, DWORD ArgCount, BOOL bExtended); BOOL Query(LPCTSTR *ServiceArgs, DWORD ArgCount, BOOL bExtended);
@ -29,3 +29,4 @@ VOID ConfigUsage(VOID);
VOID DescriptionUsage(VOID); VOID DescriptionUsage(VOID);
VOID DeleteUsage(VOID); VOID DeleteUsage(VOID);
VOID CreateUsage(VOID); VOID CreateUsage(VOID);
VOID ControlUsage(VOID);

View file

@ -118,7 +118,7 @@ VOID InterrogateUsage(VOID)
VOID StopUsage(VOID) VOID StopUsage(VOID)
{ {
_tprintf(_T("DESCRIPTION:\n") _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("USAGE:\n")
_T(" sc <server> stop [service name]\n")); _T(" sc <server> stop [service name]\n"));
} }
@ -126,7 +126,7 @@ VOID StopUsage(VOID)
VOID ContinueUsage(VOID) VOID ContinueUsage(VOID)
{ {
_tprintf(_T("DESCRIPTION:\n") _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("USAGE:\n")
_T(" sc <server> continue [service name]\n")); _T(" sc <server> continue [service name]\n"));
} }
@ -179,3 +179,11 @@ VOID CreateUsage(VOID)
_T(" DisplayName= <display name>\n") _T(" DisplayName= <display name>\n")
_T(" password= <password>\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"));
}