#include "services.h"
#include <winnls.h>
+#include <strsafe.h>
#define NDEBUG
#include <debug.h>
SERVICE_EXECUTE,
SERVICE_ALL_ACCESS};
+DWORD g_dwServiceBits = 0;
/* FUNCTIONS ***************************************************************/
case SERVICE_CONTROL_PAUSE:
case SERVICE_CONTROL_CONTINUE:
+ case SERVICE_CONTROL_PARAMCHANGE:
+ case SERVICE_CONTROL_NETBINDADD:
+ case SERVICE_CONTROL_NETBINDREMOVE:
+ case SERVICE_CONTROL_NETBINDENABLE:
+ case SERVICE_CONTROL_NETBINDDISABLE:
DesiredAccess = SERVICE_PAUSE_CONTINUE;
break;
if ((dwControlsAccepted & SERVICE_ACCEPT_PAUSE_CONTINUE) == 0)
return ERROR_INVALID_SERVICE_CONTROL;
break;
+
+ case SERVICE_CONTROL_PARAMCHANGE:
+ if ((dwControlsAccepted & SERVICE_ACCEPT_PARAMCHANGE) == 0)
+ return ERROR_INVALID_SERVICE_CONTROL;
+ break;
+
+ case SERVICE_CONTROL_NETBINDADD:
+ case SERVICE_CONTROL_NETBINDREMOVE:
+ case SERVICE_CONTROL_NETBINDENABLE:
+ case SERVICE_CONTROL_NETBINDDISABLE:
+ if ((dwControlsAccepted & SERVICE_ACCEPT_NETBINDCHANGE) == 0)
+ return ERROR_INVALID_SERVICE_CONTROL;
+ break;
}
/* Send control code to the service */
- dwError = ScmControlService(lpService,
+ dwError = ScmControlService(lpService->lpImage->hControlPipe,
+ lpService->lpServiceName,
+ (SERVICE_STATUS_HANDLE)lpService,
dwControl);
/* Return service status information */
if (dwError == ERROR_SUCCESS)
{
- if (dwControl == SERVICE_CONTROL_STOP ||
- dwControl == SERVICE_CONTROL_PAUSE ||
- dwControl == SERVICE_CONTROL_CONTINUE)
- {
- /* Log a successful send control */
+ if (dwControl == SERVICE_CONTROL_STOP ||
+ dwControl == SERVICE_CONTROL_PAUSE ||
+ dwControl == SERVICE_CONTROL_CONTINUE)
+ {
+ /* Log a successful send control */
- switch (dwControl)
- {
- case SERVICE_CONTROL_STOP:
- uID = IDS_SERVICE_STOP;
- break;
+ switch (dwControl)
+ {
+ case SERVICE_CONTROL_STOP:
+ uID = IDS_SERVICE_STOP;
+ break;
- case SERVICE_CONTROL_PAUSE:
- uID = IDS_SERVICE_PAUSE;
- break;
+ case SERVICE_CONTROL_PAUSE:
+ uID = IDS_SERVICE_PAUSE;
+ break;
- case SERVICE_CONTROL_CONTINUE:
- uID = IDS_SERVICE_RESUME;
- break;
- }
- LoadStringW(GetModuleHandle(NULL), uID, szLogBuffer, 80);
+ case SERVICE_CONTROL_CONTINUE:
+ uID = IDS_SERVICE_RESUME;
+ break;
+ }
+ LoadStringW(GetModuleHandle(NULL), uID, szLogBuffer, ARRAYSIZE(szLogBuffer));
- lpLogStrings[0] = lpService->lpDisplayName;
- lpLogStrings[1] = szLogBuffer;
+ lpLogStrings[0] = lpService->lpDisplayName;
+ lpLogStrings[1] = szLogBuffer;
- ScmLogEvent(EVENT_SERVICE_CONTROL_SUCCESS,
- EVENTLOG_INFORMATION_TYPE,
- 2,
- lpLogStrings);
- }
+ ScmLogEvent(EVENT_SERVICE_CONTROL_SUCCESS,
+ EVENTLOG_INFORMATION_TYPE,
+ 2,
+ lpLogStrings);
+ }
}
return dwError;
/* Restore the previous service type */
lpService->Status.dwServiceType = dwPreviousType;
+ /* Dereference a stopped service */
+ if ((lpServiceStatus->dwServiceType & SERVICE_WIN32) &&
+ (lpServiceStatus->dwCurrentState == SERVICE_STOPPED))
+ {
+ /* Decrement the image run counter */
+ lpService->lpImage->dwImageRunCount--;
+
+ /* If we just stopped the last running service... */
+ if (lpService->lpImage->dwImageRunCount == 0)
+ {
+ /* Stop the dispatcher thread */
+ ScmControlService(lpService->lpImage->hControlPipe,
+ L"",
+ (SERVICE_STATUS_HANDLE)lpService,
+ SERVICE_CONTROL_STOP);
+
+ /* Remove the service image */
+ ScmRemoveServiceImage(lpService->lpImage);
+ lpService->lpImage = NULL;
+ }
+ }
+
/* Unlock the service database */
ScmUnlockDatabase();
(lpServiceStatus->dwWin32ExitCode != ERROR_SUCCESS))
{
/* Log a failed service stop */
- swprintf(szLogBuffer, L"%lu", lpServiceStatus->dwWin32ExitCode);
+ StringCchPrintfW(szLogBuffer, ARRAYSIZE(szLogBuffer),
+ L"%lu", lpServiceStatus->dwWin32ExitCode);
lpLogStrings[0] = lpService->lpDisplayName;
lpLogStrings[1] = szLogBuffer;
break;
}
- LoadStringW(GetModuleHandle(NULL), uID, szLogBuffer, 80);
+ LoadStringW(GetModuleHandle(NULL), uID, szLogBuffer, ARRAYSIZE(szLogBuffer));
lpLogStrings[0] = lpService->lpDisplayName;
lpLogStrings[1] = szLogBuffer;
int bUpdateImmediately,
wchar_t *lpString)
{
- UNIMPLEMENTED;
- return ERROR_CALL_NOT_IMPLEMENTED;
+ PSERVICE pService;
+
+ DPRINT("RI_ScSetServiceBitsW(%p %lx %d %d %S)\n",
+ hServiceStatus, dwServiceBits, bSetBitsOn,
+ bUpdateImmediately, lpString);
+
+ if (ScmShutdown)
+ return ERROR_SHUTDOWN_IN_PROGRESS;
+
+ if (lpString != NULL)
+ return ERROR_INVALID_PARAMETER;
+
+ if (hServiceStatus == 0)
+ {
+ DPRINT("hServiceStatus == NULL!\n");
+ return ERROR_INVALID_HANDLE;
+ }
+
+ // FIXME: Validate the status handle
+ pService = (PSERVICE)hServiceStatus;
+
+ if (bSetBitsOn)
+ {
+ DPRINT("Old service bits: %08lx\n", pService->dwServiceBits);
+ DPRINT("Old global service bits: %08lx\n", g_dwServiceBits);
+ pService->dwServiceBits |= dwServiceBits;
+ g_dwServiceBits |= dwServiceBits;
+ DPRINT("New service bits: %08lx\n", pService->dwServiceBits);
+ DPRINT("New global service bits: %08lx\n", g_dwServiceBits);
+ }
+ else
+ {
+ DPRINT("Old service bits: %08lx\n", pService->dwServiceBits);
+ DPRINT("Old global service bits: %08lx\n", g_dwServiceBits);
+ pService->dwServiceBits &= ~dwServiceBits;
+ g_dwServiceBits &= ~dwServiceBits;
+ DPRINT("New service bits: %08lx\n", pService->dwServiceBits);
+ DPRINT("New global service bits: %08lx\n", g_dwServiceBits);
+ }
+
+ return ERROR_SUCCESS;
}
goto done;
}
-DPRINT1("\n");
/* Write the security descriptor */
dwError = ScmWriteSecurityDescriptor(hServiceKey,
lpService->pSecurityDescriptor);
int bUpdateImmediately,
char *lpString)
{
- UNIMPLEMENTED;
- return ERROR_CALL_NOT_IMPLEMENTED;
+ if (ScmShutdown)
+ return ERROR_SHUTDOWN_IN_PROGRESS;
+
+ if (lpString != NULL)
+ return ERROR_INVALID_PARAMETER;
+
+ return RI_ScSetServiceBitsW(hServiceStatus,
+ dwServiceBits,
+ bSetBitsOn,
+ bUpdateImmediately,
+ NULL);
}
SC_RPC_HANDLE hService,
SC_RPC_CONFIG_INFOA Info)
{
- SC_RPC_CONFIG_INFOW InfoW;
+ SC_RPC_CONFIG_INFOW InfoW = { 0 };
DWORD dwRet, dwLength;
PVOID ptr = NULL;
DPRINT("RChangeServiceConfig2A() called\n");
DPRINT("dwInfoLevel = %lu\n", Info.dwInfoLevel);
+ if ((Info.dwInfoLevel < SERVICE_CONFIG_DESCRIPTION) ||
+ (Info.dwInfoLevel > SERVICE_CONFIG_FAILURE_ACTIONS))
+ return ERROR_INVALID_LEVEL;
+
InfoW.dwInfoLevel = Info.dwInfoLevel;
if (InfoW.dwInfoLevel == SERVICE_CONFIG_DESCRIPTION)
if (ScmShutdown)
return ERROR_SHUTDOWN_IN_PROGRESS;
+ if ((Info.dwInfoLevel < SERVICE_CONFIG_DESCRIPTION) ||
+ (Info.dwInfoLevel > SERVICE_CONFIG_FAILURE_ACTIONS))
+ return ERROR_INVALID_LEVEL;
+
hSvc = ScmGetServiceFromHandle(hService);
if (hSvc == NULL)
{
if (ScmShutdown)
return ERROR_SHUTDOWN_IN_PROGRESS;
+ if ((dwInfoLevel < SERVICE_CONFIG_DESCRIPTION) ||
+ (dwInfoLevel > SERVICE_CONFIG_FAILURE_ACTIONS))
+ return ERROR_INVALID_LEVEL;
+
hSvc = ScmGetServiceFromHandle(hService);
if (hSvc == NULL)
{
if (ScmShutdown)
return ERROR_SHUTDOWN_IN_PROGRESS;
+ if ((dwInfoLevel < SERVICE_CONFIG_DESCRIPTION) ||
+ (dwInfoLevel > SERVICE_CONFIG_FAILURE_ACTIONS))
+ return ERROR_INVALID_LEVEL;
+
hSvc = ScmGetServiceFromHandle(hService);
if (hSvc == NULL)
{