2005-07-31 12:11:56 +00:00
|
|
|
|
/*
|
2007-09-06 14:51:38 +00:00
|
|
|
|
* PROJECT: ReactOS Service Control Manager
|
|
|
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
|
|
|
|
* FILE: base/system/services/rpcserver.c
|
|
|
|
|
* PURPOSE: RPC server interface for the advapi32 calls
|
|
|
|
|
* COPYRIGHT: Copyright 2005-2006 Eric Kohl
|
|
|
|
|
* Copyright 2006-2007 Herv<EFBFBD> Poussineau <hpoussin@reactos.org>
|
|
|
|
|
* Copyright 2007 Ged Murphy <gedmurphy@reactos.org>
|
|
|
|
|
*
|
2005-07-31 12:11:56 +00:00
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/* INCLUDES ****************************************************************/
|
|
|
|
|
|
|
|
|
|
#include "services.h"
|
|
|
|
|
#include "svcctl_s.h"
|
|
|
|
|
|
|
|
|
|
#define NDEBUG
|
|
|
|
|
#include <debug.h>
|
|
|
|
|
|
|
|
|
|
/* GLOBALS *****************************************************************/
|
|
|
|
|
|
|
|
|
|
#define MANAGER_TAG 0x72674D68 /* 'hMgr' */
|
|
|
|
|
#define SERVICE_TAG 0x63765368 /* 'hSvc' */
|
|
|
|
|
|
|
|
|
|
typedef struct _SCMGR_HANDLE
|
|
|
|
|
{
|
2005-10-22 19:46:00 +00:00
|
|
|
|
DWORD Tag;
|
|
|
|
|
DWORD RefCount;
|
|
|
|
|
DWORD DesiredAccess;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
} SCMGR_HANDLE;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct _MANAGER_HANDLE
|
|
|
|
|
{
|
2005-10-22 19:46:00 +00:00
|
|
|
|
SCMGR_HANDLE Handle;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-10-22 19:46:00 +00:00
|
|
|
|
/* FIXME: Insert more data here */
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-10-22 19:46:00 +00:00
|
|
|
|
WCHAR DatabaseName[1];
|
2005-07-31 12:11:56 +00:00
|
|
|
|
} MANAGER_HANDLE, *PMANAGER_HANDLE;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct _SERVICE_HANDLE
|
|
|
|
|
{
|
2005-10-22 19:46:00 +00:00
|
|
|
|
SCMGR_HANDLE Handle;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-10-22 19:46:00 +00:00
|
|
|
|
DWORD DesiredAccess;
|
|
|
|
|
PSERVICE ServiceEntry;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-10-22 19:46:00 +00:00
|
|
|
|
/* FIXME: Insert more data here */
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
|
|
} SERVICE_HANDLE, *PSERVICE_HANDLE;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define SC_MANAGER_READ \
|
|
|
|
|
(STANDARD_RIGHTS_READ | \
|
|
|
|
|
SC_MANAGER_QUERY_LOCK_STATUS | \
|
|
|
|
|
SC_MANAGER_ENUMERATE_SERVICE)
|
|
|
|
|
|
|
|
|
|
#define SC_MANAGER_WRITE \
|
|
|
|
|
(STANDARD_RIGHTS_WRITE | \
|
|
|
|
|
SC_MANAGER_MODIFY_BOOT_CONFIG | \
|
|
|
|
|
SC_MANAGER_CREATE_SERVICE)
|
|
|
|
|
|
|
|
|
|
#define SC_MANAGER_EXECUTE \
|
|
|
|
|
(STANDARD_RIGHTS_EXECUTE | \
|
|
|
|
|
SC_MANAGER_LOCK | \
|
|
|
|
|
SC_MANAGER_ENUMERATE_SERVICE | \
|
|
|
|
|
SC_MANAGER_CONNECT | \
|
|
|
|
|
SC_MANAGER_CREATE_SERVICE)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define SERVICE_READ \
|
|
|
|
|
(STANDARD_RIGHTS_READ | \
|
|
|
|
|
SERVICE_INTERROGATE | \
|
|
|
|
|
SERVICE_ENUMERATE_DEPENDENTS | \
|
|
|
|
|
SERVICE_QUERY_STATUS | \
|
|
|
|
|
SERVICE_QUERY_CONFIG)
|
|
|
|
|
|
|
|
|
|
#define SERVICE_WRITE \
|
|
|
|
|
(STANDARD_RIGHTS_WRITE | \
|
|
|
|
|
SERVICE_CHANGE_CONFIG)
|
|
|
|
|
|
|
|
|
|
#define SERVICE_EXECUTE \
|
|
|
|
|
(STANDARD_RIGHTS_EXECUTE | \
|
|
|
|
|
SERVICE_USER_DEFINED_CONTROL | \
|
|
|
|
|
SERVICE_PAUSE_CONTINUE | \
|
|
|
|
|
SERVICE_STOP | \
|
|
|
|
|
SERVICE_START)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* VARIABLES ***************************************************************/
|
|
|
|
|
|
|
|
|
|
static GENERIC_MAPPING
|
|
|
|
|
ScmManagerMapping = {SC_MANAGER_READ,
|
|
|
|
|
SC_MANAGER_WRITE,
|
|
|
|
|
SC_MANAGER_EXECUTE,
|
|
|
|
|
SC_MANAGER_ALL_ACCESS};
|
|
|
|
|
|
|
|
|
|
static GENERIC_MAPPING
|
|
|
|
|
ScmServiceMapping = {SERVICE_READ,
|
|
|
|
|
SERVICE_WRITE,
|
|
|
|
|
SERVICE_EXECUTE,
|
|
|
|
|
SC_MANAGER_ALL_ACCESS};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* FUNCTIONS ***************************************************************/
|
|
|
|
|
|
|
|
|
|
VOID
|
|
|
|
|
ScmStartRpcServer(VOID)
|
|
|
|
|
{
|
2005-10-22 19:46:00 +00:00
|
|
|
|
RPC_STATUS Status;
|
|
|
|
|
|
2008-04-10 14:49:04 +00:00
|
|
|
|
DPRINT("ScmStartRpcServer() called\n");
|
2005-10-22 19:46:00 +00:00
|
|
|
|
|
|
|
|
|
Status = RpcServerUseProtseqEpW(L"ncacn_np",
|
|
|
|
|
10,
|
|
|
|
|
L"\\pipe\\ntsvcs",
|
|
|
|
|
NULL);
|
|
|
|
|
if (Status != RPC_S_OK)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2008-01-18 10:08:49 +00:00
|
|
|
|
Status = RpcServerRegisterIf(svcctl_v2_0_s_ifspec,
|
2005-10-22 19:46:00 +00:00
|
|
|
|
NULL,
|
|
|
|
|
NULL);
|
|
|
|
|
if (Status != RPC_S_OK)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("RpcServerRegisterIf() failed (Status %lx)\n", Status);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Status = RpcServerListen(1, 20, TRUE);
|
|
|
|
|
if (Status != RPC_S_OK)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("RpcServerListen() failed (Status %lx)\n", Status);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2008-04-10 14:49:04 +00:00
|
|
|
|
DPRINT("ScmStartRpcServer() done\n");
|
2005-07-31 12:11:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static DWORD
|
|
|
|
|
ScmCreateManagerHandle(LPWSTR lpDatabaseName,
|
|
|
|
|
SC_HANDLE *Handle)
|
|
|
|
|
{
|
2005-10-22 19:46:00 +00:00
|
|
|
|
PMANAGER_HANDLE Ptr;
|
2005-10-09 20:24:00 +00:00
|
|
|
|
|
2005-10-22 19:46:00 +00:00
|
|
|
|
if (lpDatabaseName == NULL)
|
|
|
|
|
lpDatabaseName = SERVICES_ACTIVE_DATABASEW;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2008-08-29 10:34:23 +00:00
|
|
|
|
if (wcsicmp(lpDatabaseName,SERVICES_FAILED_DATABASEW)==0)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Database %S, does not exist\n",lpDatabaseName);
|
|
|
|
|
return ERROR_DATABASE_DOES_NOT_EXIST;
|
|
|
|
|
}
|
|
|
|
|
else if (wcsicmp(lpDatabaseName, SERVICES_ACTIVE_DATABASEW) != 0)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Invalid Database name %S.\n",lpDatabaseName);
|
|
|
|
|
return ERROR_INVALID_NAME;
|
|
|
|
|
}
|
|
|
|
|
|
2007-01-05 20:22:44 +00:00
|
|
|
|
Ptr = (MANAGER_HANDLE*) HeapAlloc(GetProcessHeap(),
|
2005-10-22 19:46:00 +00:00
|
|
|
|
HEAP_ZERO_MEMORY,
|
|
|
|
|
sizeof(MANAGER_HANDLE) + wcslen(lpDatabaseName) * sizeof(WCHAR));
|
|
|
|
|
if (Ptr == NULL)
|
|
|
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-10-22 19:46:00 +00:00
|
|
|
|
Ptr->Handle.Tag = MANAGER_TAG;
|
|
|
|
|
Ptr->Handle.RefCount = 1;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-10-22 19:46:00 +00:00
|
|
|
|
/* FIXME: initialize more data here */
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-10-22 19:46:00 +00:00
|
|
|
|
wcscpy(Ptr->DatabaseName, lpDatabaseName);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-10-22 19:46:00 +00:00
|
|
|
|
*Handle = (SC_HANDLE)Ptr;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-10-22 19:46:00 +00:00
|
|
|
|
return ERROR_SUCCESS;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static DWORD
|
|
|
|
|
ScmCreateServiceHandle(PSERVICE lpServiceEntry,
|
|
|
|
|
SC_HANDLE *Handle)
|
|
|
|
|
{
|
2005-10-22 19:46:00 +00:00
|
|
|
|
PSERVICE_HANDLE Ptr;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2007-01-05 20:22:44 +00:00
|
|
|
|
Ptr = (SERVICE_HANDLE*) HeapAlloc(GetProcessHeap(),
|
2005-10-22 19:46:00 +00:00
|
|
|
|
HEAP_ZERO_MEMORY,
|
|
|
|
|
sizeof(SERVICE_HANDLE));
|
|
|
|
|
if (Ptr == NULL)
|
|
|
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-10-22 19:46:00 +00:00
|
|
|
|
Ptr->Handle.Tag = SERVICE_TAG;
|
|
|
|
|
Ptr->Handle.RefCount = 1;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-10-22 19:46:00 +00:00
|
|
|
|
/* FIXME: initialize more data here */
|
|
|
|
|
Ptr->ServiceEntry = lpServiceEntry;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-10-22 19:46:00 +00:00
|
|
|
|
*Handle = (SC_HANDLE)Ptr;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-10-22 19:46:00 +00:00
|
|
|
|
return ERROR_SUCCESS;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static DWORD
|
|
|
|
|
ScmCheckAccess(SC_HANDLE Handle,
|
|
|
|
|
DWORD dwDesiredAccess)
|
|
|
|
|
{
|
2005-10-22 19:46:00 +00:00
|
|
|
|
PMANAGER_HANDLE hMgr;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-10-22 19:46:00 +00:00
|
|
|
|
hMgr = (PMANAGER_HANDLE)Handle;
|
|
|
|
|
if (hMgr->Handle.Tag == MANAGER_TAG)
|
|
|
|
|
{
|
|
|
|
|
RtlMapGenericMask(&dwDesiredAccess,
|
|
|
|
|
&ScmManagerMapping);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-10-22 19:46:00 +00:00
|
|
|
|
hMgr->Handle.DesiredAccess = dwDesiredAccess;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-10-22 19:46:00 +00:00
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
else if (hMgr->Handle.Tag == SERVICE_TAG)
|
|
|
|
|
{
|
|
|
|
|
RtlMapGenericMask(&dwDesiredAccess,
|
|
|
|
|
&ScmServiceMapping);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-10-22 19:46:00 +00:00
|
|
|
|
hMgr->Handle.DesiredAccess = dwDesiredAccess;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-10-22 19:46:00 +00:00
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
|
}
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-10-22 19:46:00 +00:00
|
|
|
|
return ERROR_INVALID_HANDLE;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2005-11-24 11:03:23 +00:00
|
|
|
|
DWORD
|
2006-01-01 15:32:40 +00:00
|
|
|
|
ScmAssignNewTag(PSERVICE lpService)
|
2005-11-24 11:03:23 +00:00
|
|
|
|
{
|
|
|
|
|
/* FIXME */
|
2006-01-01 15:32:40 +00:00
|
|
|
|
DPRINT("Assigning new tag to service %S\n", lpService->lpServiceName);
|
|
|
|
|
lpService->dwTag = 0;
|
2005-11-24 11:03:23 +00:00
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2005-07-31 12:11:56 +00:00
|
|
|
|
/* Function 0 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD RCloseServiceHandle(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle,
|
|
|
|
|
LPSC_RPC_HANDLE hSCObject)
|
2005-07-31 12:11:56 +00:00
|
|
|
|
{
|
2005-10-22 19:46:00 +00:00
|
|
|
|
PMANAGER_HANDLE hManager;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DPRINT("RCloseServiceHandle() called\n");
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2008-04-10 14:49:04 +00:00
|
|
|
|
DPRINT("hSCObject = %p\n", *hSCObject);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2008-04-10 14:49:04 +00:00
|
|
|
|
if (*hSCObject == 0)
|
2005-10-22 19:46:00 +00:00
|
|
|
|
return ERROR_INVALID_HANDLE;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2008-04-10 14:49:04 +00:00
|
|
|
|
hManager = (PMANAGER_HANDLE)*hSCObject;
|
2005-10-22 19:46:00 +00:00
|
|
|
|
if (hManager->Handle.Tag == MANAGER_TAG)
|
2005-07-31 12:11:56 +00:00
|
|
|
|
{
|
2005-10-22 19:46:00 +00:00
|
|
|
|
DPRINT("Found manager handle\n");
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-10-22 19:46:00 +00:00
|
|
|
|
hManager->Handle.RefCount--;
|
|
|
|
|
if (hManager->Handle.RefCount == 0)
|
|
|
|
|
{
|
|
|
|
|
/* FIXME: add cleanup code */
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-10-22 19:46:00 +00:00
|
|
|
|
HeapFree(GetProcessHeap(), 0, hManager);
|
|
|
|
|
}
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DPRINT("RCloseServiceHandle() done\n");
|
2005-10-22 19:46:00 +00:00
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
else if (hManager->Handle.Tag == SERVICE_TAG)
|
2005-07-31 12:11:56 +00:00
|
|
|
|
{
|
2005-10-22 19:46:00 +00:00
|
|
|
|
DPRINT("Found service handle\n");
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-10-22 19:46:00 +00:00
|
|
|
|
hManager->Handle.RefCount--;
|
|
|
|
|
if (hManager->Handle.RefCount == 0)
|
|
|
|
|
{
|
|
|
|
|
/* FIXME: add cleanup code */
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-10-22 19:46:00 +00:00
|
|
|
|
HeapFree(GetProcessHeap(), 0, hManager);
|
|
|
|
|
}
|
|
|
|
|
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DPRINT("RCloseServiceHandle() done\n");
|
2005-10-22 19:46:00 +00:00
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
|
}
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-10-22 19:46:00 +00:00
|
|
|
|
DPRINT1("Invalid handle tag (Tag %lx)\n", hManager->Handle.Tag);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-10-22 19:46:00 +00:00
|
|
|
|
return ERROR_INVALID_HANDLE;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Function 1 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD RControlService(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle,
|
|
|
|
|
SC_RPC_HANDLE hService,
|
|
|
|
|
DWORD dwControl,
|
|
|
|
|
LPSERVICE_STATUS lpServiceStatus)
|
2005-07-31 12:11:56 +00:00
|
|
|
|
{
|
2005-10-22 19:46:00 +00:00
|
|
|
|
PSERVICE_HANDLE hSvc;
|
|
|
|
|
PSERVICE lpService;
|
2005-11-13 14:15:08 +00:00
|
|
|
|
ACCESS_MASK DesiredAccess;
|
2005-11-20 20:18:00 +00:00
|
|
|
|
DWORD dwError = ERROR_SUCCESS;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DPRINT("RControlService() called\n");
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-10-30 13:13:53 +00:00
|
|
|
|
if (ScmShutdown)
|
|
|
|
|
return ERROR_SHUTDOWN_IN_PROGRESS;
|
|
|
|
|
|
2005-11-13 14:15:08 +00:00
|
|
|
|
/* Check the service handle */
|
2005-10-22 19:46:00 +00:00
|
|
|
|
hSvc = (PSERVICE_HANDLE)hService;
|
2008-03-26 17:44:08 +00:00
|
|
|
|
if (!hSvc || hSvc->Handle.Tag != SERVICE_TAG)
|
2005-10-22 19:46:00 +00:00
|
|
|
|
{
|
|
|
|
|
DPRINT1("Invalid handle tag!\n");
|
|
|
|
|
return ERROR_INVALID_HANDLE;
|
|
|
|
|
}
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-11-13 14:15:08 +00:00
|
|
|
|
/* Check access rights */
|
|
|
|
|
switch (dwControl)
|
|
|
|
|
{
|
|
|
|
|
case SERVICE_CONTROL_STOP:
|
|
|
|
|
DesiredAccess = SERVICE_STOP;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case SERVICE_CONTROL_PAUSE:
|
|
|
|
|
case SERVICE_CONTROL_CONTINUE:
|
|
|
|
|
DesiredAccess = SERVICE_PAUSE_CONTINUE;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case SERVICE_INTERROGATE:
|
|
|
|
|
DesiredAccess = SERVICE_INTERROGATE;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
if (dwControl >= 128 && dwControl <= 255)
|
|
|
|
|
DesiredAccess = SERVICE_USER_DEFINED_CONTROL;
|
|
|
|
|
else
|
|
|
|
|
DesiredAccess = SERVICE_QUERY_CONFIG |
|
|
|
|
|
SERVICE_CHANGE_CONFIG |
|
|
|
|
|
SERVICE_QUERY_STATUS |
|
|
|
|
|
SERVICE_START |
|
|
|
|
|
SERVICE_PAUSE_CONTINUE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-11-13 14:15:08 +00:00
|
|
|
|
if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
|
|
|
|
|
DesiredAccess))
|
|
|
|
|
return ERROR_ACCESS_DENIED;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-11-13 14:15:08 +00:00
|
|
|
|
/* Check the service entry point */
|
2005-10-22 19:46:00 +00:00
|
|
|
|
lpService = hSvc->ServiceEntry;
|
|
|
|
|
if (lpService == NULL)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("lpService == NULL!\n");
|
|
|
|
|
return ERROR_INVALID_HANDLE;
|
|
|
|
|
}
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-11-20 20:18:00 +00:00
|
|
|
|
if (lpService->Status.dwServiceType & SERVICE_DRIVER)
|
|
|
|
|
{
|
|
|
|
|
/* Send control code to the driver */
|
|
|
|
|
dwError = ScmControlDriver(lpService,
|
|
|
|
|
dwControl,
|
|
|
|
|
lpServiceStatus);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2006-12-26 01:29:22 +00:00
|
|
|
|
/* Send control code to the service */
|
2005-11-20 20:18:00 +00:00
|
|
|
|
dwError = ScmControlService(lpService,
|
|
|
|
|
dwControl,
|
|
|
|
|
lpServiceStatus);
|
|
|
|
|
}
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-10-22 19:46:00 +00:00
|
|
|
|
/* Return service status information */
|
|
|
|
|
RtlCopyMemory(lpServiceStatus,
|
|
|
|
|
&lpService->Status,
|
|
|
|
|
sizeof(SERVICE_STATUS));
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-11-20 20:18:00 +00:00
|
|
|
|
return dwError;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Function 2 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD RDeleteService(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle,
|
|
|
|
|
SC_RPC_HANDLE hService)
|
2005-07-31 12:11:56 +00:00
|
|
|
|
{
|
2005-10-22 19:46:00 +00:00
|
|
|
|
PSERVICE_HANDLE hSvc;
|
|
|
|
|
PSERVICE lpService;
|
|
|
|
|
DWORD dwError;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DPRINT("RDeleteService() called\n");
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-10-30 13:13:53 +00:00
|
|
|
|
if (ScmShutdown)
|
|
|
|
|
return ERROR_SHUTDOWN_IN_PROGRESS;
|
|
|
|
|
|
2005-10-22 19:46:00 +00:00
|
|
|
|
hSvc = (PSERVICE_HANDLE)hService;
|
2008-03-26 17:44:08 +00:00
|
|
|
|
if (!hSvc || hSvc->Handle.Tag != SERVICE_TAG)
|
2005-10-22 19:46:00 +00:00
|
|
|
|
return ERROR_INVALID_HANDLE;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-10-22 19:46:00 +00:00
|
|
|
|
if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
|
2008-07-10 11:45:06 +00:00
|
|
|
|
DELETE))
|
2005-10-22 19:46:00 +00:00
|
|
|
|
return ERROR_ACCESS_DENIED;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-10-22 19:46:00 +00:00
|
|
|
|
lpService = hSvc->ServiceEntry;
|
|
|
|
|
if (lpService == NULL)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("lpService == NULL!\n");
|
|
|
|
|
return ERROR_INVALID_HANDLE;
|
|
|
|
|
}
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-10-22 19:46:00 +00:00
|
|
|
|
/* FIXME: Acquire service database lock exclusively */
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-10-30 21:52:23 +00:00
|
|
|
|
if (lpService->bDeleted)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("The service has already been marked for delete!\n");
|
|
|
|
|
return ERROR_SERVICE_MARKED_FOR_DELETE;
|
|
|
|
|
}
|
|
|
|
|
|
2005-10-22 19:46:00 +00:00
|
|
|
|
/* Mark service for delete */
|
2005-10-30 21:52:23 +00:00
|
|
|
|
lpService->bDeleted = TRUE;
|
|
|
|
|
|
2005-10-22 19:46:00 +00:00
|
|
|
|
dwError = ScmMarkServiceForDelete(lpService);
|
2005-10-09 20:24:00 +00:00
|
|
|
|
|
2005-10-22 19:46:00 +00:00
|
|
|
|
/* FIXME: Release service database lock */
|
2005-10-09 20:24:00 +00:00
|
|
|
|
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DPRINT("RDeleteService() done\n");
|
2005-10-09 20:24:00 +00:00
|
|
|
|
|
2005-10-22 19:46:00 +00:00
|
|
|
|
return dwError;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Function 3 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD RLockServiceDatabase(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle,
|
|
|
|
|
SC_RPC_HANDLE hSCManager,
|
|
|
|
|
LPSC_RPC_LOCK lpLock)
|
2005-07-31 12:11:56 +00:00
|
|
|
|
{
|
2005-10-22 19:46:00 +00:00
|
|
|
|
PMANAGER_HANDLE hMgr;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DPRINT("RLockServiceDatabase() called\n");
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2008-04-10 14:49:04 +00:00
|
|
|
|
*lpLock = 0;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-10-22 19:46:00 +00:00
|
|
|
|
hMgr = (PMANAGER_HANDLE)hSCManager;
|
2008-03-26 17:44:08 +00:00
|
|
|
|
if (!hMgr || hMgr->Handle.Tag != MANAGER_TAG)
|
2005-10-22 19:46:00 +00:00
|
|
|
|
return ERROR_INVALID_HANDLE;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-10-22 19:46:00 +00:00
|
|
|
|
if (!RtlAreAllAccessesGranted(hMgr->Handle.DesiredAccess,
|
|
|
|
|
SC_MANAGER_LOCK))
|
|
|
|
|
return ERROR_ACCESS_DENIED;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-12-25 14:45:30 +00:00
|
|
|
|
// return ScmLockDatabase(0, hMgr->0xC, hLock);
|
|
|
|
|
|
2005-10-22 19:46:00 +00:00
|
|
|
|
/* FIXME: Lock the database */
|
2008-04-10 14:49:04 +00:00
|
|
|
|
*lpLock = (void *)0x12345678; /* Dummy! */
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-10-22 19:46:00 +00:00
|
|
|
|
return ERROR_SUCCESS;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Function 4 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD RQueryServiceObjectSecurity(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle,
|
|
|
|
|
SC_RPC_HANDLE hService,
|
|
|
|
|
SECURITY_INFORMATION dwSecurityInformation,
|
|
|
|
|
LPBYTE lpSecurityDescriptor,
|
|
|
|
|
DWORD cbBufSize,
|
|
|
|
|
LPBOUNDED_DWORD_256K pcbBytesNeeded)
|
2005-07-31 12:11:56 +00:00
|
|
|
|
{
|
2005-12-25 14:45:30 +00:00
|
|
|
|
#if 0
|
2005-12-23 15:56:51 +00:00
|
|
|
|
PSERVICE_HANDLE hSvc;
|
|
|
|
|
PSERVICE lpService;
|
|
|
|
|
ULONG DesiredAccess = 0;
|
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
DWORD dwBytesNeeded;
|
|
|
|
|
DWORD dwError;
|
|
|
|
|
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DPRINT("RQueryServiceObjectSecurity() called\n");
|
2005-12-23 15:56:51 +00:00
|
|
|
|
|
|
|
|
|
hSvc = (PSERVICE_HANDLE)hService;
|
2008-03-26 17:44:08 +00:00
|
|
|
|
if (!hSvc || hSvc->Handle.Tag != SERVICE_TAG)
|
2005-12-23 15:56:51 +00:00
|
|
|
|
{
|
|
|
|
|
DPRINT1("Invalid handle tag!\n");
|
|
|
|
|
return ERROR_INVALID_HANDLE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (dwSecurityInformation & (DACL_SECURITY_INFORMATION ||
|
|
|
|
|
GROUP_SECURITY_INFORMATION ||
|
|
|
|
|
OWNER_SECURITY_INFORMATION))
|
|
|
|
|
DesiredAccess |= READ_CONTROL;
|
|
|
|
|
|
|
|
|
|
if (dwSecurityInformation & SACL_SECURITY_INFORMATION)
|
|
|
|
|
DesiredAccess |= ACCESS_SYSTEM_SECURITY;
|
|
|
|
|
|
|
|
|
|
if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
|
|
|
|
|
DesiredAccess))
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
|
|
|
|
|
return ERROR_ACCESS_DENIED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lpService = hSvc->ServiceEntry;
|
|
|
|
|
if (lpService == NULL)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("lpService == NULL!\n");
|
|
|
|
|
return ERROR_INVALID_HANDLE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* FIXME: Lock the service list */
|
|
|
|
|
|
|
|
|
|
Status = RtlQuerySecurityObject(lpService->lpSecurityDescriptor,
|
|
|
|
|
dwSecurityInformation,
|
|
|
|
|
(PSECURITY_DESCRIPTOR)lpSecurityDescriptor,
|
|
|
|
|
dwSecuityDescriptorSize,
|
|
|
|
|
&dwBytesNeeded);
|
|
|
|
|
|
|
|
|
|
/* FIXME: Unlock the service list */
|
|
|
|
|
|
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
*pcbBytesNeeded = dwBytesNeeded;
|
|
|
|
|
dwError = STATUS_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
else if (Status == STATUS_BUFFER_TOO_SMALL)
|
|
|
|
|
{
|
|
|
|
|
*pcbBytesNeeded = dwBytesNeeded;
|
|
|
|
|
dwError = ERROR_INSUFFICIENT_BUFFER;
|
|
|
|
|
}
|
|
|
|
|
else if (Status == STATUS_BAD_DESCRIPTOR_FORMAT)
|
|
|
|
|
{
|
|
|
|
|
dwError = ERROR_GEN_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
dwError = RtlNtStatusToDosError(Status);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return dwError;
|
2005-12-25 14:45:30 +00:00
|
|
|
|
#endif
|
2008-04-10 14:49:04 +00:00
|
|
|
|
UNIMPLEMENTED;
|
2005-12-25 14:45:30 +00:00
|
|
|
|
return ERROR_CALL_NOT_IMPLEMENTED;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Function 5 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD RSetServiceObjectSecurity(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle,
|
|
|
|
|
SC_RPC_HANDLE hService,
|
|
|
|
|
DWORD dwSecurityInformation,
|
|
|
|
|
LPBYTE lpSecurityDescriptor,
|
|
|
|
|
DWORD dwSecuityDescriptorSize)
|
2005-07-31 12:11:56 +00:00
|
|
|
|
{
|
2005-12-25 14:45:30 +00:00
|
|
|
|
PSERVICE_HANDLE hSvc;
|
|
|
|
|
PSERVICE lpService;
|
|
|
|
|
ULONG DesiredAccess = 0;
|
|
|
|
|
HANDLE hToken = NULL;
|
|
|
|
|
HKEY hServiceKey;
|
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
DWORD dwError;
|
|
|
|
|
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DPRINT1("RSetServiceObjectSecurity() called\n");
|
2005-12-25 14:45:30 +00:00
|
|
|
|
|
|
|
|
|
hSvc = (PSERVICE_HANDLE)hService;
|
2008-03-26 17:44:08 +00:00
|
|
|
|
if (!hSvc || hSvc->Handle.Tag != SERVICE_TAG)
|
2005-12-25 14:45:30 +00:00
|
|
|
|
{
|
|
|
|
|
DPRINT1("Invalid handle tag!\n");
|
|
|
|
|
return ERROR_INVALID_HANDLE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (dwSecurityInformation == 0 ||
|
2006-10-13 21:14:07 +00:00
|
|
|
|
dwSecurityInformation & ~(OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION
|
|
|
|
|
| DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION))
|
|
|
|
|
return ERROR_INVALID_PARAMETER;
|
2005-12-25 14:45:30 +00:00
|
|
|
|
|
|
|
|
|
if (!RtlValidSecurityDescriptor((PSECURITY_DESCRIPTOR)lpSecurityDescriptor))
|
2006-10-13 21:14:07 +00:00
|
|
|
|
return ERROR_INVALID_PARAMETER;
|
2005-12-25 14:45:30 +00:00
|
|
|
|
|
|
|
|
|
if (dwSecurityInformation & SACL_SECURITY_INFORMATION)
|
|
|
|
|
DesiredAccess |= ACCESS_SYSTEM_SECURITY;
|
|
|
|
|
|
|
|
|
|
if (dwSecurityInformation & DACL_SECURITY_INFORMATION)
|
2006-10-13 21:14:07 +00:00
|
|
|
|
DesiredAccess |= WRITE_DAC;
|
2005-12-25 14:45:30 +00:00
|
|
|
|
|
|
|
|
|
if (dwSecurityInformation & (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION))
|
2006-10-13 21:14:07 +00:00
|
|
|
|
DesiredAccess |= WRITE_OWNER;
|
2005-12-25 14:45:30 +00:00
|
|
|
|
|
|
|
|
|
if ((dwSecurityInformation & OWNER_SECURITY_INFORMATION) &&
|
|
|
|
|
(((PSECURITY_DESCRIPTOR)lpSecurityDescriptor)->Owner == NULL))
|
2006-10-13 21:14:07 +00:00
|
|
|
|
return ERROR_INVALID_PARAMETER;
|
2005-12-25 14:45:30 +00:00
|
|
|
|
|
|
|
|
|
if ((dwSecurityInformation & GROUP_SECURITY_INFORMATION) &&
|
|
|
|
|
(((PSECURITY_DESCRIPTOR)lpSecurityDescriptor)->Group == NULL))
|
2006-10-13 21:14:07 +00:00
|
|
|
|
return ERROR_INVALID_PARAMETER;
|
2005-12-25 14:45:30 +00:00
|
|
|
|
|
|
|
|
|
if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
|
|
|
|
|
DesiredAccess))
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
|
|
|
|
|
return ERROR_ACCESS_DENIED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lpService = hSvc->ServiceEntry;
|
|
|
|
|
if (lpService == NULL)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("lpService == NULL!\n");
|
|
|
|
|
return ERROR_INVALID_HANDLE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (lpService->bDeleted)
|
2006-10-13 21:14:07 +00:00
|
|
|
|
return ERROR_SERVICE_MARKED_FOR_DELETE;
|
2005-12-25 14:45:30 +00:00
|
|
|
|
|
2006-10-13 21:14:07 +00:00
|
|
|
|
RpcImpersonateClient(NULL);
|
2005-12-25 14:45:30 +00:00
|
|
|
|
|
|
|
|
|
Status = NtOpenThreadToken(NtCurrentThread(),
|
|
|
|
|
8,
|
2006-10-13 21:14:07 +00:00
|
|
|
|
TRUE,
|
2005-12-25 14:45:30 +00:00
|
|
|
|
&hToken);
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
return RtlNtStatusToDosError(Status);
|
|
|
|
|
|
2006-10-13 21:14:07 +00:00
|
|
|
|
RpcRevertToSelf();
|
2005-12-25 14:45:30 +00:00
|
|
|
|
|
|
|
|
|
/* FIXME: Lock service database */
|
|
|
|
|
|
2006-10-13 21:14:07 +00:00
|
|
|
|
#if 0
|
2005-12-25 14:45:30 +00:00
|
|
|
|
Status = RtlSetSecurityObject(dwSecurityInformation,
|
|
|
|
|
(PSECURITY_DESCRIPTOR)lpSecurityDescriptor,
|
|
|
|
|
&lpService->lpSecurityDescriptor,
|
|
|
|
|
&ScmServiceMapping,
|
|
|
|
|
hToken);
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
dwError = RtlNtStatusToDosError(Status);
|
|
|
|
|
goto Done;
|
|
|
|
|
}
|
2006-10-13 21:14:07 +00:00
|
|
|
|
#endif
|
2005-12-25 14:45:30 +00:00
|
|
|
|
|
|
|
|
|
dwError = ScmOpenServiceKey(lpService->lpServiceName,
|
2006-10-13 21:14:07 +00:00
|
|
|
|
READ_CONTROL | KEY_CREATE_SUB_KEY | KEY_SET_VALUE,
|
2005-12-25 14:45:30 +00:00
|
|
|
|
&hServiceKey);
|
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
|
goto Done;
|
|
|
|
|
|
2008-04-10 14:49:04 +00:00
|
|
|
|
UNIMPLEMENTED;
|
2006-10-13 21:14:07 +00:00
|
|
|
|
dwError = ERROR_SUCCESS;
|
2005-12-25 14:45:30 +00:00
|
|
|
|
// dwError = ScmWriteSecurityDescriptor(hServiceKey,
|
|
|
|
|
// lpService->lpSecurityDescriptor);
|
|
|
|
|
|
|
|
|
|
RegFlushKey(hServiceKey);
|
|
|
|
|
RegCloseKey(hServiceKey);
|
|
|
|
|
|
2006-10-13 21:14:07 +00:00
|
|
|
|
Done:
|
2005-12-25 14:45:30 +00:00
|
|
|
|
|
|
|
|
|
if (hToken != NULL)
|
|
|
|
|
NtClose(hToken);
|
|
|
|
|
|
|
|
|
|
/* FIXME: Unlock service database */
|
|
|
|
|
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DPRINT("RSetServiceObjectSecurity() done (Error %lu)\n", dwError);
|
2005-12-25 14:45:30 +00:00
|
|
|
|
|
|
|
|
|
return dwError;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Function 6 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD RQueryServiceStatus(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle,
|
|
|
|
|
SC_RPC_HANDLE hService,
|
|
|
|
|
LPSERVICE_STATUS lpServiceStatus)
|
2005-07-31 12:11:56 +00:00
|
|
|
|
{
|
2005-10-22 19:46:00 +00:00
|
|
|
|
PSERVICE_HANDLE hSvc;
|
|
|
|
|
PSERVICE lpService;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DPRINT("RQueryServiceStatus() called\n");
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-10-30 13:13:53 +00:00
|
|
|
|
if (ScmShutdown)
|
|
|
|
|
return ERROR_SHUTDOWN_IN_PROGRESS;
|
|
|
|
|
|
2005-10-22 19:46:00 +00:00
|
|
|
|
hSvc = (PSERVICE_HANDLE)hService;
|
2008-03-26 17:44:08 +00:00
|
|
|
|
if (!hSvc || hSvc->Handle.Tag != SERVICE_TAG)
|
2005-10-22 19:46:00 +00:00
|
|
|
|
{
|
|
|
|
|
DPRINT1("Invalid handle tag!\n");
|
|
|
|
|
return ERROR_INVALID_HANDLE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
|
|
|
|
|
SERVICE_QUERY_STATUS))
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
|
|
|
|
|
return ERROR_ACCESS_DENIED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lpService = hSvc->ServiceEntry;
|
|
|
|
|
if (lpService == NULL)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("lpService == NULL!\n");
|
|
|
|
|
return ERROR_INVALID_HANDLE;
|
|
|
|
|
}
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-10-22 19:46:00 +00:00
|
|
|
|
/* Return service status information */
|
|
|
|
|
RtlCopyMemory(lpServiceStatus,
|
|
|
|
|
&lpService->Status,
|
|
|
|
|
sizeof(SERVICE_STATUS));
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-10-22 19:46:00 +00:00
|
|
|
|
return ERROR_SUCCESS;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Function 7 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD RSetServiceStatus(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle,
|
|
|
|
|
SC_RPC_HANDLE hServiceStatus,
|
|
|
|
|
LPSERVICE_STATUS lpServiceStatus)
|
2005-07-31 12:11:56 +00:00
|
|
|
|
{
|
2007-07-10 14:49:51 +00:00
|
|
|
|
PSERVICE lpService;
|
|
|
|
|
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DPRINT("RSetServiceStatus() called\n");
|
2007-07-10 14:49:51 +00:00
|
|
|
|
|
|
|
|
|
if (ScmShutdown)
|
|
|
|
|
return ERROR_SHUTDOWN_IN_PROGRESS;
|
|
|
|
|
|
2007-09-12 08:41:00 +00:00
|
|
|
|
lpService = ScmGetServiceEntryByClientHandle((ULONG)hServiceStatus);
|
2007-07-10 14:49:51 +00:00
|
|
|
|
if (lpService == NULL)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("lpService == NULL!\n");
|
|
|
|
|
return ERROR_INVALID_HANDLE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RtlCopyMemory(&lpService->Status,
|
|
|
|
|
lpServiceStatus,
|
|
|
|
|
sizeof(SERVICE_STATUS));
|
|
|
|
|
|
|
|
|
|
DPRINT("Set %S to %lu\n", lpService->lpDisplayName, lpService->Status.dwCurrentState);
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DPRINT("RSetServiceStatus() done\n");
|
2007-07-10 14:49:51 +00:00
|
|
|
|
|
|
|
|
|
return ERROR_SUCCESS;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Function 8 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD RUnlockServiceDatabase(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle,
|
|
|
|
|
LPSC_RPC_LOCK Lock)
|
2005-07-31 12:11:56 +00:00
|
|
|
|
{
|
2008-04-10 14:49:04 +00:00
|
|
|
|
UNIMPLEMENTED;
|
2005-10-22 19:46:00 +00:00
|
|
|
|
return ERROR_SUCCESS;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Function 9 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD RNotifyBootConfigStatus(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle,
|
|
|
|
|
SVCCTL_HANDLEW lpMachineName,
|
|
|
|
|
DWORD BootAcceptable)
|
2005-07-31 12:11:56 +00:00
|
|
|
|
{
|
2008-04-10 14:49:04 +00:00
|
|
|
|
UNIMPLEMENTED;
|
2005-12-25 14:45:30 +00:00
|
|
|
|
return ERROR_CALL_NOT_IMPLEMENTED;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2005-12-23 15:56:51 +00:00
|
|
|
|
/* Function 10 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD RSetServiceBitsW(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle,
|
|
|
|
|
SC_RPC_HANDLE hServiceStatus,
|
|
|
|
|
DWORD dwServiceBits,
|
|
|
|
|
int bSetBitsOn,
|
|
|
|
|
int bUpdateImmediately,
|
|
|
|
|
wchar_t *lpString)
|
|
|
|
|
{
|
|
|
|
|
UNIMPLEMENTED;
|
2005-12-25 14:45:30 +00:00
|
|
|
|
return ERROR_CALL_NOT_IMPLEMENTED;
|
2005-12-23 15:56:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2005-10-22 18:59:39 +00:00
|
|
|
|
/* Function 11 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD RChangeServiceConfigW(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle,
|
|
|
|
|
SC_RPC_HANDLE hService,
|
|
|
|
|
DWORD dwServiceType,
|
|
|
|
|
DWORD dwStartType,
|
|
|
|
|
DWORD dwErrorControl,
|
|
|
|
|
LPWSTR lpBinaryPathName,
|
|
|
|
|
LPWSTR lpLoadOrderGroup,
|
|
|
|
|
LPDWORD lpdwTagId,
|
|
|
|
|
LPBYTE lpDependencies,
|
|
|
|
|
DWORD dwDependSize,
|
|
|
|
|
LPWSTR lpServiceStartName,
|
|
|
|
|
LPBYTE lpPassword,
|
|
|
|
|
DWORD dwPwSize,
|
|
|
|
|
LPWSTR lpDisplayName)
|
2005-10-22 18:59:39 +00:00
|
|
|
|
{
|
2005-10-30 13:13:53 +00:00
|
|
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
|
|
|
PSERVICE_HANDLE hSvc;
|
|
|
|
|
PSERVICE lpService = NULL;
|
2005-11-17 12:49:37 +00:00
|
|
|
|
HKEY hServiceKey = NULL;
|
2005-10-30 13:13:53 +00:00
|
|
|
|
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DPRINT("RChangeServiceConfigW() called\n");
|
2005-11-07 10:53:52 +00:00
|
|
|
|
DPRINT("dwServiceType = %lu\n", dwServiceType);
|
|
|
|
|
DPRINT("dwStartType = %lu\n", dwStartType);
|
|
|
|
|
DPRINT("dwErrorControl = %lu\n", dwErrorControl);
|
|
|
|
|
DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName);
|
|
|
|
|
DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup);
|
|
|
|
|
DPRINT("lpDisplayName = %S\n", lpDisplayName);
|
2005-10-23 19:50:05 +00:00
|
|
|
|
|
2005-10-30 13:13:53 +00:00
|
|
|
|
if (ScmShutdown)
|
|
|
|
|
return ERROR_SHUTDOWN_IN_PROGRESS;
|
|
|
|
|
|
|
|
|
|
hSvc = (PSERVICE_HANDLE)hService;
|
2008-03-26 17:44:08 +00:00
|
|
|
|
if (!hSvc || hSvc->Handle.Tag != SERVICE_TAG)
|
2005-10-30 13:13:53 +00:00
|
|
|
|
{
|
|
|
|
|
DPRINT1("Invalid handle tag!\n");
|
|
|
|
|
return ERROR_INVALID_HANDLE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
|
|
|
|
|
SERVICE_CHANGE_CONFIG))
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
|
|
|
|
|
return ERROR_ACCESS_DENIED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lpService = hSvc->ServiceEntry;
|
|
|
|
|
if (lpService == NULL)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("lpService == NULL!\n");
|
|
|
|
|
return ERROR_INVALID_HANDLE;
|
|
|
|
|
}
|
|
|
|
|
|
2005-10-30 21:52:23 +00:00
|
|
|
|
/* FIXME: Lock database exclusively */
|
|
|
|
|
|
|
|
|
|
if (lpService->bDeleted)
|
|
|
|
|
{
|
|
|
|
|
/* FIXME: Unlock database */
|
|
|
|
|
DPRINT1("The service has already been marked for delete!\n");
|
|
|
|
|
return ERROR_SERVICE_MARKED_FOR_DELETE;
|
|
|
|
|
}
|
|
|
|
|
|
2005-11-17 12:49:37 +00:00
|
|
|
|
/* Open the service key */
|
|
|
|
|
dwError = ScmOpenServiceKey(lpService->szServiceName,
|
2005-11-24 11:03:23 +00:00
|
|
|
|
KEY_SET_VALUE,
|
2005-11-17 12:49:37 +00:00
|
|
|
|
&hServiceKey);
|
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
|
|
/* Write service data to the registry */
|
|
|
|
|
/* Set the display name */
|
|
|
|
|
if (lpDisplayName != NULL && *lpDisplayName != 0)
|
|
|
|
|
{
|
|
|
|
|
RegSetValueExW(hServiceKey,
|
|
|
|
|
L"DisplayName",
|
|
|
|
|
0,
|
|
|
|
|
REG_SZ,
|
|
|
|
|
(LPBYTE)lpDisplayName,
|
|
|
|
|
(wcslen(lpDisplayName) + 1) * sizeof(WCHAR));
|
2005-11-24 11:03:23 +00:00
|
|
|
|
/* FIXME: update lpService->lpDisplayName */
|
2005-11-17 12:49:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (dwServiceType != SERVICE_NO_CHANGE)
|
|
|
|
|
{
|
|
|
|
|
/* Set the service type */
|
|
|
|
|
dwError = RegSetValueExW(hServiceKey,
|
|
|
|
|
L"Type",
|
|
|
|
|
0,
|
|
|
|
|
REG_DWORD,
|
|
|
|
|
(LPBYTE)&dwServiceType,
|
|
|
|
|
sizeof(DWORD));
|
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
|
goto done;
|
2005-12-18 19:50:53 +00:00
|
|
|
|
|
|
|
|
|
lpService->Status.dwServiceType = dwServiceType;
|
2005-11-17 12:49:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (dwStartType != SERVICE_NO_CHANGE)
|
|
|
|
|
{
|
|
|
|
|
/* Set the start value */
|
|
|
|
|
dwError = RegSetValueExW(hServiceKey,
|
|
|
|
|
L"Start",
|
|
|
|
|
0,
|
|
|
|
|
REG_DWORD,
|
|
|
|
|
(LPBYTE)&dwStartType,
|
|
|
|
|
sizeof(DWORD));
|
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
|
goto done;
|
2005-12-18 19:50:53 +00:00
|
|
|
|
|
2005-11-24 11:03:23 +00:00
|
|
|
|
lpService->dwStartType = dwStartType;
|
2005-11-17 12:49:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (dwErrorControl != SERVICE_NO_CHANGE)
|
|
|
|
|
{
|
|
|
|
|
/* Set the error control value */
|
|
|
|
|
dwError = RegSetValueExW(hServiceKey,
|
|
|
|
|
L"ErrorControl",
|
|
|
|
|
0,
|
|
|
|
|
REG_DWORD,
|
|
|
|
|
(LPBYTE)&dwErrorControl,
|
|
|
|
|
sizeof(DWORD));
|
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
|
goto done;
|
2005-12-18 19:50:53 +00:00
|
|
|
|
|
2005-11-24 11:03:23 +00:00
|
|
|
|
lpService->dwErrorControl = dwErrorControl;
|
2005-11-17 12:49:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
/* FIXME: set the new ImagePath value */
|
|
|
|
|
|
|
|
|
|
/* Set the image path */
|
|
|
|
|
if (dwServiceType & SERVICE_WIN32)
|
|
|
|
|
{
|
|
|
|
|
if (lpBinaryPathName != NULL && *lpBinaryPathName != 0)
|
|
|
|
|
{
|
|
|
|
|
dwError = RegSetValueExW(hServiceKey,
|
|
|
|
|
L"ImagePath",
|
|
|
|
|
0,
|
|
|
|
|
REG_EXPAND_SZ,
|
|
|
|
|
(LPBYTE)lpBinaryPathName,
|
|
|
|
|
(wcslen(lpBinaryPathName) + 1) * sizeof(WCHAR));
|
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
|
goto done;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (dwServiceType & SERVICE_DRIVER)
|
|
|
|
|
{
|
|
|
|
|
if (lpImagePath != NULL && *lpImagePath != 0)
|
|
|
|
|
{
|
|
|
|
|
dwError = RegSetValueExW(hServiceKey,
|
|
|
|
|
L"ImagePath",
|
|
|
|
|
0,
|
|
|
|
|
REG_EXPAND_SZ,
|
|
|
|
|
(LPBYTE)lpImagePath,
|
|
|
|
|
(wcslen(lpImagePath) + 1) *sizeof(WCHAR));
|
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
|
goto done;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* Set the group name */
|
|
|
|
|
if (lpLoadOrderGroup != NULL && *lpLoadOrderGroup != 0)
|
|
|
|
|
{
|
|
|
|
|
dwError = RegSetValueExW(hServiceKey,
|
|
|
|
|
L"Group",
|
|
|
|
|
0,
|
|
|
|
|
REG_SZ,
|
|
|
|
|
(LPBYTE)lpLoadOrderGroup,
|
|
|
|
|
(wcslen(lpLoadOrderGroup) + 1) * sizeof(WCHAR));
|
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
|
goto done;
|
2005-11-24 11:03:23 +00:00
|
|
|
|
/* FIXME: update lpService->lpServiceGroup */
|
2005-11-17 12:49:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (lpdwTagId != NULL)
|
|
|
|
|
{
|
2006-01-01 15:32:40 +00:00
|
|
|
|
dwError = ScmAssignNewTag(lpService);
|
2005-11-24 11:03:23 +00:00
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
|
goto done;
|
2006-01-01 15:32:40 +00:00
|
|
|
|
|
2005-11-24 11:03:23 +00:00
|
|
|
|
dwError = RegSetValueExW(hServiceKey,
|
|
|
|
|
L"Tag",
|
|
|
|
|
0,
|
|
|
|
|
REG_DWORD,
|
|
|
|
|
(LPBYTE)&lpService->dwTag,
|
|
|
|
|
sizeof(DWORD));
|
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
|
goto done;
|
2006-01-01 15:32:40 +00:00
|
|
|
|
|
2005-11-24 11:03:23 +00:00
|
|
|
|
*lpdwTagId = lpService->dwTag;
|
2005-11-17 12:49:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Write dependencies */
|
|
|
|
|
if (lpDependencies != NULL && *lpDependencies != 0)
|
|
|
|
|
{
|
|
|
|
|
dwError = ScmWriteDependencies(hServiceKey,
|
2008-04-10 14:49:04 +00:00
|
|
|
|
(LPWSTR)lpDependencies,
|
|
|
|
|
dwDependSize);
|
2005-11-17 12:49:37 +00:00
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
|
goto done;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (lpPassword != NULL)
|
|
|
|
|
{
|
|
|
|
|
/* FIXME: Write password */
|
|
|
|
|
}
|
2005-10-30 13:13:53 +00:00
|
|
|
|
|
2005-10-30 21:52:23 +00:00
|
|
|
|
/* FIXME: Unlock database */
|
|
|
|
|
|
2005-11-17 12:49:37 +00:00
|
|
|
|
done:
|
|
|
|
|
if (hServiceKey != NULL)
|
|
|
|
|
RegCloseKey(hServiceKey);
|
|
|
|
|
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DPRINT("RChangeServiceConfigW() done (Error %lu)\n", dwError);
|
2005-10-30 13:13:53 +00:00
|
|
|
|
|
|
|
|
|
return dwError;
|
2005-10-22 18:59:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
2008-01-14 11:46:14 +00:00
|
|
|
|
/* Create a path suitable for the bootloader out of the full path */
|
|
|
|
|
DWORD
|
|
|
|
|
ScmConvertToBootPathName(wchar_t *CanonName, wchar_t **RelativeName)
|
|
|
|
|
{
|
|
|
|
|
DWORD ServiceNameLen, BufferSize, ExpandedLen;
|
|
|
|
|
WCHAR Dest;
|
|
|
|
|
WCHAR *Expanded;
|
|
|
|
|
UNICODE_STRING NtPathName, SystemRoot, LinkTarget;
|
|
|
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
HANDLE SymbolicLinkHandle;
|
|
|
|
|
|
|
|
|
|
DPRINT("ScmConvertToBootPathName %S\n", CanonName);
|
|
|
|
|
|
|
|
|
|
ServiceNameLen = wcslen(CanonName);
|
|
|
|
|
/* First check, if it's already good */
|
|
|
|
|
if (ServiceNameLen > 12 &&
|
|
|
|
|
!wcsnicmp(L"\\SystemRoot\\", CanonName, 12))
|
|
|
|
|
{
|
|
|
|
|
*RelativeName = LocalAlloc(LMEM_ZEROINIT, ServiceNameLen * sizeof(WCHAR) + sizeof(WCHAR));
|
|
|
|
|
|
|
|
|
|
if (*RelativeName == NULL)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Error allocating memory for boot driver name!\n");
|
|
|
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Copy it */
|
|
|
|
|
wcscpy(*RelativeName, CanonName);
|
|
|
|
|
|
|
|
|
|
DPRINT1("Bootdriver name %S\n", *RelativeName);
|
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If it has %SystemRoot% prefix, substitute it to \System*/
|
|
|
|
|
if (ServiceNameLen > 13 &&
|
|
|
|
|
!wcsnicmp(L"%SystemRoot%\\", CanonName, 13))
|
|
|
|
|
{
|
|
|
|
|
/* There is no +sizeof(wchar_t) because the name is less by 1 wchar */
|
|
|
|
|
*RelativeName = LocalAlloc(LMEM_ZEROINIT, ServiceNameLen * sizeof(WCHAR));
|
|
|
|
|
|
|
|
|
|
if (*RelativeName == NULL)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Error allocating memory for boot driver name!\n");
|
|
|
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Copy it */
|
|
|
|
|
wcscpy(*RelativeName, L"\\SystemRoot\\");
|
|
|
|
|
wcscat(*RelativeName, CanonName + 13);
|
|
|
|
|
|
|
|
|
|
DPRINT1("Bootdriver name %S\n", *RelativeName);
|
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Get buffer size needed for expanding env strings */
|
|
|
|
|
BufferSize = ExpandEnvironmentStringsW(L"%SystemRoot%\\", &Dest, 1);
|
|
|
|
|
|
|
|
|
|
if (BufferSize <= 1)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Error during a call to ExpandEnvironmentStringsW()\n");
|
|
|
|
|
return ERROR_INVALID_ENVIRONMENT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Allocate memory, since the size is known now */
|
|
|
|
|
Expanded = LocalAlloc(LMEM_ZEROINIT, BufferSize * sizeof(WCHAR) + sizeof(WCHAR));
|
|
|
|
|
if (!Expanded)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Error allocating memory for boot driver name!\n");
|
|
|
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Expand it */
|
|
|
|
|
if (ExpandEnvironmentStringsW(L"%SystemRoot%\\", Expanded, BufferSize) >
|
|
|
|
|
BufferSize)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Error during a call to ExpandEnvironmentStringsW()\n");
|
|
|
|
|
LocalFree(Expanded);
|
|
|
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Convert to NY-style path */
|
|
|
|
|
if (!RtlDosPathNameToNtPathName_U(Expanded, &NtPathName, NULL, NULL))
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Error during a call to RtlDosPathNameToNtPathName_U()\n");
|
|
|
|
|
return ERROR_INVALID_ENVIRONMENT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DPRINT("Converted to NT-style %wZ\n", &NtPathName);
|
|
|
|
|
|
|
|
|
|
/* No need to keep the dos-path anymore */
|
|
|
|
|
LocalFree(Expanded);
|
|
|
|
|
|
|
|
|
|
/* Copy it to the allocated place */
|
|
|
|
|
Expanded = LocalAlloc(LMEM_ZEROINIT, NtPathName.Length + sizeof(WCHAR));
|
|
|
|
|
if (!Expanded)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Error allocating memory for boot driver name!\n");
|
|
|
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ExpandedLen = NtPathName.Length / sizeof(WCHAR);
|
|
|
|
|
wcsncpy(Expanded, NtPathName.Buffer, ExpandedLen);
|
|
|
|
|
Expanded[ExpandedLen] = 0;
|
|
|
|
|
|
|
|
|
|
if (ServiceNameLen > ExpandedLen &&
|
|
|
|
|
!wcsnicmp(Expanded, CanonName, ExpandedLen))
|
|
|
|
|
{
|
|
|
|
|
/* Only \SystemRoot\ is missing */
|
|
|
|
|
*RelativeName = LocalAlloc(LMEM_ZEROINIT,
|
|
|
|
|
(ServiceNameLen - ExpandedLen) * sizeof(WCHAR) + 13*sizeof(WCHAR));
|
|
|
|
|
|
|
|
|
|
if (*RelativeName == NULL)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Error allocating memory for boot driver name!\n");
|
|
|
|
|
LocalFree(Expanded);
|
|
|
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
wcscpy(*RelativeName, L"\\SystemRoot\\");
|
|
|
|
|
wcscat(*RelativeName, CanonName + ExpandedLen);
|
|
|
|
|
|
|
|
|
|
RtlFreeUnicodeString(&NtPathName);
|
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* The most complex case starts here */
|
|
|
|
|
RtlInitUnicodeString(&SystemRoot, L"\\SystemRoot");
|
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
|
|
|
&SystemRoot,
|
|
|
|
|
OBJ_CASE_INSENSITIVE,
|
|
|
|
|
NULL,
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
/* Open this symlink */
|
|
|
|
|
Status = NtOpenSymbolicLinkObject(&SymbolicLinkHandle, SYMBOLIC_LINK_QUERY, &ObjectAttributes);
|
|
|
|
|
|
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
LinkTarget.Length = 0;
|
|
|
|
|
LinkTarget.MaximumLength = 0;
|
|
|
|
|
|
|
|
|
|
DPRINT("Opened symbolic link object\n");
|
|
|
|
|
|
|
|
|
|
Status = NtQuerySymbolicLinkObject(SymbolicLinkHandle, &LinkTarget, &BufferSize);
|
|
|
|
|
if (NT_SUCCESS(Status) || Status == STATUS_BUFFER_TOO_SMALL)
|
|
|
|
|
{
|
|
|
|
|
/* Check if required buffer size is sane */
|
|
|
|
|
if (BufferSize > 0xFFFD)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Too large buffer required\n");
|
|
|
|
|
*RelativeName = 0;
|
|
|
|
|
|
|
|
|
|
if (SymbolicLinkHandle) NtClose(SymbolicLinkHandle);
|
|
|
|
|
LocalFree(Expanded);
|
|
|
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Alloc the string */
|
|
|
|
|
LinkTarget.Buffer = LocalAlloc(LMEM_ZEROINIT, BufferSize + sizeof(WCHAR));
|
|
|
|
|
if (!LinkTarget.Buffer)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Unable to alloc buffer\n");
|
|
|
|
|
if (SymbolicLinkHandle) NtClose(SymbolicLinkHandle);
|
|
|
|
|
LocalFree(Expanded);
|
|
|
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Do a real query now */
|
|
|
|
|
LinkTarget.Length = BufferSize;
|
|
|
|
|
LinkTarget.MaximumLength = LinkTarget.Length + sizeof(WCHAR);
|
|
|
|
|
|
|
|
|
|
Status = NtQuerySymbolicLinkObject(SymbolicLinkHandle, &LinkTarget, &BufferSize);
|
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
DPRINT("LinkTarget: %wZ\n", &LinkTarget);
|
|
|
|
|
|
|
|
|
|
ExpandedLen = LinkTarget.Length / sizeof(WCHAR);
|
|
|
|
|
if ((ServiceNameLen > ExpandedLen) &&
|
|
|
|
|
!wcsnicmp(LinkTarget.Buffer, CanonName, ExpandedLen))
|
|
|
|
|
{
|
|
|
|
|
*RelativeName = LocalAlloc(LMEM_ZEROINIT,
|
|
|
|
|
(ServiceNameLen - ExpandedLen) * sizeof(WCHAR) + 13*sizeof(WCHAR));
|
|
|
|
|
|
|
|
|
|
if (*RelativeName == NULL)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Unable to alloc buffer\n");
|
|
|
|
|
if (SymbolicLinkHandle) NtClose(SymbolicLinkHandle);
|
|
|
|
|
LocalFree(Expanded);
|
|
|
|
|
RtlFreeUnicodeString(&NtPathName);
|
|
|
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Copy it over, substituting the first part
|
|
|
|
|
with SystemRoot */
|
|
|
|
|
wcscpy(*RelativeName, L"\\SystemRoot\\");
|
|
|
|
|
wcscat(*RelativeName, CanonName+ExpandedLen+1);
|
|
|
|
|
|
|
|
|
|
/* Cleanup */
|
|
|
|
|
if (SymbolicLinkHandle) NtClose(SymbolicLinkHandle);
|
|
|
|
|
LocalFree(Expanded);
|
|
|
|
|
RtlFreeUnicodeString(&NtPathName);
|
|
|
|
|
|
|
|
|
|
/* Return success */
|
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (SymbolicLinkHandle) NtClose(SymbolicLinkHandle);
|
|
|
|
|
LocalFree(Expanded);
|
|
|
|
|
RtlFreeUnicodeString(&NtPathName);
|
|
|
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Error, Status = %08X\n", Status);
|
|
|
|
|
if (SymbolicLinkHandle) NtClose(SymbolicLinkHandle);
|
|
|
|
|
LocalFree(Expanded);
|
|
|
|
|
RtlFreeUnicodeString(&NtPathName);
|
|
|
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Error, Status = %08X\n", Status);
|
|
|
|
|
if (SymbolicLinkHandle) NtClose(SymbolicLinkHandle);
|
|
|
|
|
LocalFree(Expanded);
|
|
|
|
|
RtlFreeUnicodeString(&NtPathName);
|
|
|
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Error, Status = %08X\n", Status);
|
|
|
|
|
LocalFree(Expanded);
|
|
|
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Failure */
|
|
|
|
|
*RelativeName = NULL;
|
|
|
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DWORD
|
|
|
|
|
ScmCanonDriverImagePath(DWORD dwStartType,
|
|
|
|
|
wchar_t *lpServiceName,
|
|
|
|
|
wchar_t **lpCanonName)
|
|
|
|
|
{
|
|
|
|
|
DWORD ServiceNameLen, Result;
|
|
|
|
|
UNICODE_STRING NtServiceName;
|
|
|
|
|
WCHAR *RelativeName;
|
|
|
|
|
WCHAR *SourceName = lpServiceName;
|
|
|
|
|
|
|
|
|
|
/* Calculate the length of the service's name */
|
|
|
|
|
ServiceNameLen = wcslen(lpServiceName);
|
|
|
|
|
|
|
|
|
|
/* 12 is wcslen(L"\\SystemRoot\\") */
|
|
|
|
|
if (ServiceNameLen > 12 &&
|
|
|
|
|
!wcsnicmp(L"\\SystemRoot\\", lpServiceName, 12))
|
|
|
|
|
{
|
|
|
|
|
/* SystemRoot prefix is already included */
|
|
|
|
|
|
|
|
|
|
*lpCanonName = LocalAlloc(LMEM_ZEROINIT, ServiceNameLen * sizeof(WCHAR) + sizeof(WCHAR));
|
|
|
|
|
|
|
|
|
|
if (*lpCanonName == NULL)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Error allocating memory for canonized service name!\n");
|
|
|
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If it's a boot-time driver, it must be systemroot relative */
|
|
|
|
|
if (dwStartType == SERVICE_BOOT_START)
|
|
|
|
|
SourceName += 12;
|
|
|
|
|
|
|
|
|
|
/* Copy it */
|
|
|
|
|
wcscpy(*lpCanonName, SourceName);
|
|
|
|
|
|
|
|
|
|
DPRINT("Canonicalized name %S\n", *lpCanonName);
|
|
|
|
|
return NO_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Check if it has %SystemRoot% (len=13) */
|
|
|
|
|
if (ServiceNameLen > 13 &&
|
2008-01-14 17:26:46 +00:00
|
|
|
|
!wcsnicmp(L"%%SystemRoot%%\\", lpServiceName, 13))
|
2008-01-14 11:46:14 +00:00
|
|
|
|
{
|
|
|
|
|
/* Substitute %SystemRoot% with \\SystemRoot\\ */
|
|
|
|
|
*lpCanonName = LocalAlloc(LMEM_ZEROINIT, ServiceNameLen * sizeof(WCHAR) + sizeof(WCHAR));
|
|
|
|
|
|
|
|
|
|
if (*lpCanonName == NULL)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Error allocating memory for canonized service name!\n");
|
|
|
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If it's a boot-time driver, it must be systemroot relative */
|
|
|
|
|
if (dwStartType == SERVICE_BOOT_START)
|
|
|
|
|
wcscpy(*lpCanonName, L"\\SystemRoot\\");
|
|
|
|
|
|
2008-01-14 12:31:35 +00:00
|
|
|
|
wcscat(*lpCanonName, lpServiceName + 13);
|
2008-01-14 11:46:14 +00:00
|
|
|
|
|
|
|
|
|
DPRINT("Canonicalized name %S\n", *lpCanonName);
|
|
|
|
|
return NO_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Check if it's a relative path name */
|
|
|
|
|
if (lpServiceName[0] != L'\\' && lpServiceName[1] != L':')
|
|
|
|
|
{
|
|
|
|
|
*lpCanonName = LocalAlloc(LMEM_ZEROINIT, ServiceNameLen * sizeof(WCHAR) + sizeof(WCHAR));
|
|
|
|
|
|
|
|
|
|
if (*lpCanonName == NULL)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Error allocating memory for canonized service name!\n");
|
|
|
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Just copy it over without changing */
|
|
|
|
|
wcscpy(*lpCanonName, lpServiceName);
|
|
|
|
|
|
|
|
|
|
return NO_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* It seems to be a DOS path, convert it */
|
|
|
|
|
if (!RtlDosPathNameToNtPathName_U(lpServiceName, &NtServiceName, NULL, NULL))
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("RtlDosPathNameToNtPathName_U() failed!\n");
|
|
|
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*lpCanonName = LocalAlloc(LMEM_ZEROINIT, NtServiceName.Length + sizeof(WCHAR));
|
|
|
|
|
|
|
|
|
|
if (*lpCanonName == NULL)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Error allocating memory for canonized service name!\n");
|
|
|
|
|
RtlFreeUnicodeString(&NtServiceName);
|
|
|
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Copy the string */
|
|
|
|
|
wcsncpy(*lpCanonName, NtServiceName.Buffer, NtServiceName.Length / sizeof(WCHAR));
|
|
|
|
|
|
|
|
|
|
/* The unicode string is not needed anymore */
|
|
|
|
|
RtlFreeUnicodeString(&NtServiceName);
|
|
|
|
|
|
|
|
|
|
if (dwStartType != SERVICE_BOOT_START)
|
|
|
|
|
{
|
|
|
|
|
DPRINT("Canonicalized name %S\n", *lpCanonName);
|
|
|
|
|
return NO_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* The service is boot-started, so must be relative */
|
|
|
|
|
Result = ScmConvertToBootPathName(*lpCanonName, &RelativeName);
|
|
|
|
|
if (Result)
|
|
|
|
|
{
|
|
|
|
|
/* There is a problem, free name and return */
|
|
|
|
|
LocalFree(*lpCanonName);
|
|
|
|
|
DPRINT1("Error converting named!\n");
|
|
|
|
|
return Result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ASSERT(RelativeName);
|
|
|
|
|
|
|
|
|
|
/* Copy that string */
|
|
|
|
|
wcscpy(*lpCanonName, RelativeName + 12);
|
|
|
|
|
|
|
|
|
|
/* Free the allocated buffer */
|
|
|
|
|
LocalFree(RelativeName);
|
|
|
|
|
|
|
|
|
|
DPRINT("Canonicalized name %S\n", *lpCanonName);
|
|
|
|
|
|
|
|
|
|
/* Success */
|
|
|
|
|
return NO_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
2005-10-22 18:59:39 +00:00
|
|
|
|
|
2005-07-31 12:11:56 +00:00
|
|
|
|
/* Function 12 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD RCreateServiceW(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle,
|
|
|
|
|
SC_RPC_HANDLE hSCManager,
|
|
|
|
|
LPWSTR lpServiceName,
|
|
|
|
|
LPWSTR lpDisplayName,
|
|
|
|
|
DWORD dwDesiredAccess,
|
|
|
|
|
DWORD dwServiceType,
|
|
|
|
|
DWORD dwStartType,
|
|
|
|
|
DWORD dwErrorControl,
|
|
|
|
|
LPWSTR lpBinaryPathName,
|
|
|
|
|
LPWSTR lpLoadOrderGroup,
|
|
|
|
|
LPDWORD lpdwTagId,
|
|
|
|
|
LPBYTE lpDependencies,
|
|
|
|
|
DWORD dwDependSize,
|
|
|
|
|
LPWSTR lpServiceStartName,
|
|
|
|
|
LPBYTE lpPassword,
|
|
|
|
|
DWORD dwPwSize,
|
|
|
|
|
LPSC_RPC_HANDLE lpServiceHandle)
|
2005-07-31 12:11:56 +00:00
|
|
|
|
{
|
2005-10-09 20:24:00 +00:00
|
|
|
|
PMANAGER_HANDLE hManager;
|
|
|
|
|
DWORD dwError = ERROR_SUCCESS;
|
2005-10-23 06:19:15 +00:00
|
|
|
|
PSERVICE lpService = NULL;
|
|
|
|
|
SC_HANDLE hServiceHandle = NULL;
|
2005-10-09 20:24:00 +00:00
|
|
|
|
LPWSTR lpImagePath = NULL;
|
2005-10-23 06:19:15 +00:00
|
|
|
|
HKEY hServiceKey = NULL;
|
2005-10-09 20:24:00 +00:00
|
|
|
|
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DPRINT("RCreateServiceW() called\n");
|
2005-11-07 10:53:52 +00:00
|
|
|
|
DPRINT("lpServiceName = %S\n", lpServiceName);
|
|
|
|
|
DPRINT("lpDisplayName = %S\n", lpDisplayName);
|
|
|
|
|
DPRINT("dwDesiredAccess = %lx\n", dwDesiredAccess);
|
|
|
|
|
DPRINT("dwServiceType = %lu\n", dwServiceType);
|
|
|
|
|
DPRINT("dwStartType = %lu\n", dwStartType);
|
|
|
|
|
DPRINT("dwErrorControl = %lu\n", dwErrorControl);
|
|
|
|
|
DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName);
|
|
|
|
|
DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup);
|
2005-10-09 20:24:00 +00:00
|
|
|
|
|
2005-10-30 13:13:53 +00:00
|
|
|
|
if (ScmShutdown)
|
|
|
|
|
return ERROR_SHUTDOWN_IN_PROGRESS;
|
|
|
|
|
|
2005-10-09 20:24:00 +00:00
|
|
|
|
hManager = (PMANAGER_HANDLE)hSCManager;
|
2008-03-26 17:44:08 +00:00
|
|
|
|
if (!hManager || hManager->Handle.Tag != MANAGER_TAG)
|
2005-10-09 20:24:00 +00:00
|
|
|
|
{
|
|
|
|
|
DPRINT1("Invalid manager handle!\n");
|
|
|
|
|
return ERROR_INVALID_HANDLE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Check access rights */
|
|
|
|
|
if (!RtlAreAllAccessesGranted(hManager->Handle.DesiredAccess,
|
|
|
|
|
SC_MANAGER_CREATE_SERVICE))
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Insufficient access rights! 0x%lx\n",
|
|
|
|
|
hManager->Handle.DesiredAccess);
|
|
|
|
|
return ERROR_ACCESS_DENIED;
|
|
|
|
|
}
|
|
|
|
|
|
2005-10-23 06:19:15 +00:00
|
|
|
|
/* Fail if the service already exists! */
|
|
|
|
|
if (ScmGetServiceEntryByName(lpServiceName) != NULL)
|
|
|
|
|
return ERROR_SERVICE_EXISTS;
|
2005-10-09 20:24:00 +00:00
|
|
|
|
|
|
|
|
|
if (dwServiceType & SERVICE_DRIVER)
|
|
|
|
|
{
|
2008-01-14 11:46:14 +00:00
|
|
|
|
dwError = ScmCanonDriverImagePath(dwStartType,
|
|
|
|
|
lpBinaryPathName,
|
|
|
|
|
&lpImagePath);
|
2008-01-13 14:22:55 +00:00
|
|
|
|
|
2008-01-14 11:46:14 +00:00
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
|
goto done;
|
2005-10-09 20:24:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
2005-10-23 06:19:15 +00:00
|
|
|
|
/* Allocate a new service entry */
|
|
|
|
|
dwError = ScmCreateNewServiceRecord(lpServiceName,
|
|
|
|
|
&lpService);
|
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
|
goto done;
|
2005-10-09 20:24:00 +00:00
|
|
|
|
|
2005-10-23 06:19:15 +00:00
|
|
|
|
/* Fill the new service entry */
|
|
|
|
|
lpService->Status.dwServiceType = dwServiceType;
|
|
|
|
|
lpService->dwStartType = dwStartType;
|
|
|
|
|
lpService->dwErrorControl = dwErrorControl;
|
2005-10-09 20:24:00 +00:00
|
|
|
|
|
2005-10-30 13:13:53 +00:00
|
|
|
|
/* Fill the display name */
|
|
|
|
|
if (lpDisplayName != NULL &&
|
|
|
|
|
*lpDisplayName != 0 &&
|
|
|
|
|
wcsicmp(lpService->lpDisplayName, lpDisplayName) != 0)
|
|
|
|
|
{
|
2007-01-05 20:22:44 +00:00
|
|
|
|
lpService->lpDisplayName = (WCHAR*) HeapAlloc(GetProcessHeap(), 0,
|
2005-10-30 13:13:53 +00:00
|
|
|
|
(wcslen(lpDisplayName) + 1) * sizeof(WCHAR));
|
|
|
|
|
if (lpService->lpDisplayName == NULL)
|
|
|
|
|
{
|
|
|
|
|
dwError = ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
|
goto done;
|
|
|
|
|
}
|
|
|
|
|
wcscpy(lpService->lpDisplayName, lpDisplayName);
|
|
|
|
|
}
|
|
|
|
|
|
2006-01-01 15:32:40 +00:00
|
|
|
|
/* Assign the service to a group */
|
|
|
|
|
if (lpLoadOrderGroup != NULL && *lpLoadOrderGroup != 0)
|
|
|
|
|
{
|
|
|
|
|
dwError = ScmSetServiceGroup(lpService,
|
|
|
|
|
lpLoadOrderGroup);
|
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
|
goto done;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Assign a new tag */
|
|
|
|
|
if (lpdwTagId != NULL)
|
|
|
|
|
{
|
|
|
|
|
dwError = ScmAssignNewTag(lpService);
|
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
|
goto done;
|
|
|
|
|
}
|
|
|
|
|
|
2005-10-09 20:24:00 +00:00
|
|
|
|
/* Write service data to the registry */
|
|
|
|
|
/* Create the service key */
|
2005-11-06 11:56:56 +00:00
|
|
|
|
dwError = ScmCreateServiceKey(lpServiceName,
|
|
|
|
|
KEY_WRITE,
|
|
|
|
|
&hServiceKey);
|
2005-10-09 20:24:00 +00:00
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
|
goto done;
|
|
|
|
|
|
2005-10-23 06:19:15 +00:00
|
|
|
|
/* Set the display name */
|
2005-10-22 18:59:39 +00:00
|
|
|
|
if (lpDisplayName != NULL && *lpDisplayName != 0)
|
2005-10-09 20:24:00 +00:00
|
|
|
|
{
|
|
|
|
|
RegSetValueExW(hServiceKey,
|
|
|
|
|
L"DisplayName",
|
|
|
|
|
0,
|
|
|
|
|
REG_SZ,
|
|
|
|
|
(LPBYTE)lpDisplayName,
|
|
|
|
|
(wcslen(lpDisplayName) + 1) * sizeof(WCHAR));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Set the service type */
|
|
|
|
|
dwError = RegSetValueExW(hServiceKey,
|
|
|
|
|
L"Type",
|
|
|
|
|
0,
|
|
|
|
|
REG_DWORD,
|
|
|
|
|
(LPBYTE)&dwServiceType,
|
|
|
|
|
sizeof(DWORD));
|
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
|
|
/* Set the start value */
|
|
|
|
|
dwError = RegSetValueExW(hServiceKey,
|
|
|
|
|
L"Start",
|
|
|
|
|
0,
|
|
|
|
|
REG_DWORD,
|
|
|
|
|
(LPBYTE)&dwStartType,
|
|
|
|
|
sizeof(DWORD));
|
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
|
|
/* Set the error control value */
|
|
|
|
|
dwError = RegSetValueExW(hServiceKey,
|
|
|
|
|
L"ErrorControl",
|
|
|
|
|
0,
|
|
|
|
|
REG_DWORD,
|
|
|
|
|
(LPBYTE)&dwErrorControl,
|
|
|
|
|
sizeof(DWORD));
|
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
|
|
/* Set the image path */
|
|
|
|
|
if (dwServiceType & SERVICE_WIN32)
|
|
|
|
|
{
|
|
|
|
|
dwError = RegSetValueExW(hServiceKey,
|
|
|
|
|
L"ImagePath",
|
|
|
|
|
0,
|
2005-10-23 06:19:15 +00:00
|
|
|
|
REG_EXPAND_SZ,
|
2005-10-09 20:24:00 +00:00
|
|
|
|
(LPBYTE)lpBinaryPathName,
|
|
|
|
|
(wcslen(lpBinaryPathName) + 1) * sizeof(WCHAR));
|
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
|
goto done;
|
|
|
|
|
}
|
|
|
|
|
else if (dwServiceType & SERVICE_DRIVER)
|
|
|
|
|
{
|
|
|
|
|
dwError = RegSetValueExW(hServiceKey,
|
|
|
|
|
L"ImagePath",
|
|
|
|
|
0,
|
2005-10-23 06:19:15 +00:00
|
|
|
|
REG_EXPAND_SZ,
|
2005-10-09 20:24:00 +00:00
|
|
|
|
(LPBYTE)lpImagePath,
|
2008-01-13 13:44:14 +00:00
|
|
|
|
(wcslen(lpImagePath) + 1) * sizeof(WCHAR));
|
2005-10-09 20:24:00 +00:00
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
|
goto done;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Set the group name */
|
|
|
|
|
if (lpLoadOrderGroup != NULL && *lpLoadOrderGroup != 0)
|
|
|
|
|
{
|
|
|
|
|
dwError = RegSetValueExW(hServiceKey,
|
|
|
|
|
L"Group",
|
|
|
|
|
0,
|
|
|
|
|
REG_SZ,
|
|
|
|
|
(LPBYTE)lpLoadOrderGroup,
|
|
|
|
|
(wcslen(lpLoadOrderGroup) + 1) * sizeof(WCHAR));
|
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
|
goto done;
|
|
|
|
|
}
|
|
|
|
|
|
2005-10-23 06:19:15 +00:00
|
|
|
|
if (lpdwTagId != NULL)
|
|
|
|
|
{
|
2005-11-24 11:03:23 +00:00
|
|
|
|
dwError = RegSetValueExW(hServiceKey,
|
|
|
|
|
L"Tag",
|
|
|
|
|
0,
|
|
|
|
|
REG_DWORD,
|
|
|
|
|
(LPBYTE)&lpService->dwTag,
|
|
|
|
|
sizeof(DWORD));
|
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
|
goto done;
|
2005-10-23 06:19:15 +00:00
|
|
|
|
}
|
|
|
|
|
|
2005-10-23 19:50:05 +00:00
|
|
|
|
/* Write dependencies */
|
2005-10-22 18:59:39 +00:00
|
|
|
|
if (lpDependencies != NULL && *lpDependencies != 0)
|
|
|
|
|
{
|
2005-10-23 19:50:05 +00:00
|
|
|
|
dwError = ScmWriteDependencies(hServiceKey,
|
2008-04-10 14:49:04 +00:00
|
|
|
|
(LPWSTR)lpDependencies,
|
|
|
|
|
dwDependSize);
|
2005-10-23 19:50:05 +00:00
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
|
goto done;
|
2005-10-22 18:59:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (lpPassword != NULL)
|
|
|
|
|
{
|
|
|
|
|
/* FIXME: Write password */
|
|
|
|
|
}
|
|
|
|
|
|
2005-10-23 06:19:15 +00:00
|
|
|
|
dwError = ScmCreateServiceHandle(lpService,
|
|
|
|
|
&hServiceHandle);
|
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
|
|
dwError = ScmCheckAccess(hServiceHandle,
|
|
|
|
|
dwDesiredAccess);
|
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
|
goto done;
|
|
|
|
|
|
2005-10-09 20:24:00 +00:00
|
|
|
|
done:;
|
|
|
|
|
if (hServiceKey != NULL)
|
|
|
|
|
RegCloseKey(hServiceKey);
|
|
|
|
|
|
2005-10-23 06:19:15 +00:00
|
|
|
|
if (dwError == ERROR_SUCCESS)
|
|
|
|
|
{
|
2008-04-10 14:49:04 +00:00
|
|
|
|
DPRINT("hService %p\n", hServiceHandle);
|
|
|
|
|
*lpServiceHandle = (unsigned long)hServiceHandle; /* FIXME: 64 bit portability */
|
2005-10-23 06:19:15 +00:00
|
|
|
|
|
|
|
|
|
if (lpdwTagId != NULL)
|
2005-11-24 11:03:23 +00:00
|
|
|
|
*lpdwTagId = lpService->dwTag;
|
2005-10-23 06:19:15 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2005-10-30 13:13:53 +00:00
|
|
|
|
/* Release the display name buffer */
|
2007-07-09 01:52:35 +00:00
|
|
|
|
if (lpService->lpServiceName != NULL)
|
2005-10-30 13:13:53 +00:00
|
|
|
|
HeapFree(GetProcessHeap(), 0, lpService->lpDisplayName);
|
|
|
|
|
|
2007-12-04 17:21:46 +00:00
|
|
|
|
if (hServiceHandle)
|
2005-10-23 06:19:15 +00:00
|
|
|
|
{
|
|
|
|
|
/* Remove the service handle */
|
|
|
|
|
HeapFree(GetProcessHeap(), 0, hServiceHandle);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (lpService != NULL)
|
|
|
|
|
{
|
|
|
|
|
/* FIXME: remove the service entry */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2005-10-09 20:24:00 +00:00
|
|
|
|
if (lpImagePath != NULL)
|
|
|
|
|
HeapFree(GetProcessHeap(), 0, lpImagePath);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DPRINT("RCreateServiceW() done (Error %lu)\n", dwError);
|
2005-10-09 20:24:00 +00:00
|
|
|
|
|
|
|
|
|
return dwError;
|
|
|
|
|
}
|
|
|
|
|
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-12-18 19:50:53 +00:00
|
|
|
|
/* Function 13 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD REnumDependentServicesW(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle,
|
|
|
|
|
SC_RPC_HANDLE hService,
|
|
|
|
|
DWORD dwServiceState,
|
|
|
|
|
LPBYTE lpServices,
|
|
|
|
|
DWORD cbBufSize,
|
|
|
|
|
LPBOUNDED_DWORD_256K pcbBytesNeeded,
|
|
|
|
|
LPBOUNDED_DWORD_256K lpServicesReturned)
|
2005-12-18 19:50:53 +00:00
|
|
|
|
{
|
|
|
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
|
|
|
|
2008-04-10 14:49:04 +00:00
|
|
|
|
UNIMPLEMENTED;
|
2006-01-01 12:00:13 +00:00
|
|
|
|
*pcbBytesNeeded = 0;
|
|
|
|
|
*lpServicesReturned = 0;
|
2005-12-18 19:50:53 +00:00
|
|
|
|
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DPRINT1("REnumDependentServicesW() done (Error %lu)\n", dwError);
|
2005-12-18 19:50:53 +00:00
|
|
|
|
|
|
|
|
|
return dwError;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Function 14 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD REnumServicesStatusW(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle,
|
|
|
|
|
SC_RPC_HANDLE hSCManager,
|
|
|
|
|
DWORD dwServiceType,
|
|
|
|
|
DWORD dwServiceState,
|
|
|
|
|
LPBYTE lpBuffer,
|
|
|
|
|
DWORD dwBufSize,
|
|
|
|
|
LPBOUNDED_DWORD_256K pcbBytesNeeded,
|
|
|
|
|
LPBOUNDED_DWORD_256K lpServicesReturned,
|
|
|
|
|
LPBOUNDED_DWORD_256K lpResumeHandle)
|
2005-12-18 19:50:53 +00:00
|
|
|
|
{
|
|
|
|
|
PMANAGER_HANDLE hManager;
|
|
|
|
|
PSERVICE lpService;
|
|
|
|
|
DWORD dwError = ERROR_SUCCESS;
|
2005-12-25 14:45:30 +00:00
|
|
|
|
PLIST_ENTRY ServiceEntry;
|
|
|
|
|
PSERVICE CurrentService;
|
|
|
|
|
DWORD dwState;
|
|
|
|
|
DWORD dwRequiredSize;
|
|
|
|
|
DWORD dwServiceCount;
|
|
|
|
|
DWORD dwSize;
|
|
|
|
|
DWORD dwLastResumeCount;
|
|
|
|
|
LPENUM_SERVICE_STATUSW lpStatusPtr;
|
|
|
|
|
LPWSTR lpStringPtr;
|
2005-12-18 19:50:53 +00:00
|
|
|
|
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DPRINT("REnumServicesStatusW() called\n");
|
2005-12-18 19:50:53 +00:00
|
|
|
|
|
|
|
|
|
if (ScmShutdown)
|
|
|
|
|
return ERROR_SHUTDOWN_IN_PROGRESS;
|
|
|
|
|
|
|
|
|
|
hManager = (PMANAGER_HANDLE)hSCManager;
|
2008-03-26 17:44:08 +00:00
|
|
|
|
if (!hManager || hManager->Handle.Tag != MANAGER_TAG)
|
2005-12-18 19:50:53 +00:00
|
|
|
|
{
|
|
|
|
|
DPRINT1("Invalid manager handle!\n");
|
|
|
|
|
return ERROR_INVALID_HANDLE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Check access rights */
|
|
|
|
|
if (!RtlAreAllAccessesGranted(hManager->Handle.DesiredAccess,
|
|
|
|
|
SC_MANAGER_ENUMERATE_SERVICE))
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Insufficient access rights! 0x%lx\n",
|
|
|
|
|
hManager->Handle.DesiredAccess);
|
|
|
|
|
return ERROR_ACCESS_DENIED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*pcbBytesNeeded = 0;
|
|
|
|
|
*lpServicesReturned = 0;
|
|
|
|
|
|
2005-12-25 14:45:30 +00:00
|
|
|
|
dwLastResumeCount = *lpResumeHandle;
|
|
|
|
|
|
2006-12-26 01:29:22 +00:00
|
|
|
|
/* FIXME: Lock the service list shared */
|
2005-12-18 19:50:53 +00:00
|
|
|
|
|
2005-12-25 14:45:30 +00:00
|
|
|
|
lpService = ScmGetServiceEntryByResumeCount(dwLastResumeCount);
|
2005-12-18 19:50:53 +00:00
|
|
|
|
if (lpService == NULL)
|
|
|
|
|
{
|
2005-12-25 14:45:30 +00:00
|
|
|
|
dwError = ERROR_SUCCESS;
|
|
|
|
|
goto Done;
|
2005-12-18 19:50:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
2005-12-25 14:45:30 +00:00
|
|
|
|
dwRequiredSize = 0;
|
|
|
|
|
dwServiceCount = 0;
|
2005-12-18 19:50:53 +00:00
|
|
|
|
|
2005-12-25 14:45:30 +00:00
|
|
|
|
for (ServiceEntry = &lpService->ServiceListEntry;
|
|
|
|
|
ServiceEntry != &ServiceListHead;
|
|
|
|
|
ServiceEntry = ServiceEntry->Flink)
|
|
|
|
|
{
|
|
|
|
|
CurrentService = CONTAINING_RECORD(ServiceEntry,
|
|
|
|
|
SERVICE,
|
|
|
|
|
ServiceListEntry);
|
2005-12-18 19:50:53 +00:00
|
|
|
|
|
2005-12-25 14:45:30 +00:00
|
|
|
|
if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
|
|
|
|
|
continue;
|
2005-12-18 19:50:53 +00:00
|
|
|
|
|
2005-12-25 14:45:30 +00:00
|
|
|
|
dwState = SERVICE_ACTIVE;
|
|
|
|
|
if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
|
|
|
|
|
dwState = SERVICE_INACTIVE;
|
2005-12-18 19:50:53 +00:00
|
|
|
|
|
2005-12-25 14:45:30 +00:00
|
|
|
|
if ((dwState & dwServiceState) == 0)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
dwSize = sizeof(ENUM_SERVICE_STATUSW) +
|
|
|
|
|
((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
|
|
|
|
|
((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
|
|
|
|
|
|
|
|
|
|
if (dwRequiredSize + dwSize <= dwBufSize)
|
|
|
|
|
{
|
|
|
|
|
DPRINT("Service name: %S fit\n", CurrentService->lpServiceName);
|
|
|
|
|
dwRequiredSize += dwSize;
|
|
|
|
|
dwServiceCount++;
|
|
|
|
|
dwLastResumeCount = CurrentService->dwResumeCount;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
DPRINT("Service name: %S no fit\n", CurrentService->lpServiceName);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DPRINT("dwRequiredSize: %lu\n", dwRequiredSize);
|
|
|
|
|
DPRINT("dwServiceCount: %lu\n", dwServiceCount);
|
|
|
|
|
|
|
|
|
|
for (;
|
|
|
|
|
ServiceEntry != &ServiceListHead;
|
|
|
|
|
ServiceEntry = ServiceEntry->Flink)
|
|
|
|
|
{
|
|
|
|
|
CurrentService = CONTAINING_RECORD(ServiceEntry,
|
|
|
|
|
SERVICE,
|
|
|
|
|
ServiceListEntry);
|
|
|
|
|
|
|
|
|
|
if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
dwState = SERVICE_ACTIVE;
|
|
|
|
|
if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
|
|
|
|
|
dwState = SERVICE_INACTIVE;
|
|
|
|
|
|
|
|
|
|
if ((dwState & dwServiceState) == 0)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
dwRequiredSize += (sizeof(ENUM_SERVICE_STATUSW) +
|
|
|
|
|
((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
|
|
|
|
|
((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR)));
|
|
|
|
|
|
|
|
|
|
dwError = ERROR_MORE_DATA;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize);
|
|
|
|
|
|
|
|
|
|
*lpResumeHandle = dwLastResumeCount;
|
|
|
|
|
*lpServicesReturned = dwServiceCount;
|
|
|
|
|
*pcbBytesNeeded = dwRequiredSize;
|
|
|
|
|
|
2008-04-10 14:49:04 +00:00
|
|
|
|
lpStatusPtr = (LPENUM_SERVICE_STATUSW)lpBuffer;
|
|
|
|
|
lpStringPtr = (LPWSTR)((ULONG_PTR)lpBuffer +
|
2005-12-26 15:06:46 +00:00
|
|
|
|
dwServiceCount * sizeof(ENUM_SERVICE_STATUSW));
|
2005-12-25 14:45:30 +00:00
|
|
|
|
|
|
|
|
|
dwRequiredSize = 0;
|
|
|
|
|
for (ServiceEntry = &lpService->ServiceListEntry;
|
|
|
|
|
ServiceEntry != &ServiceListHead;
|
|
|
|
|
ServiceEntry = ServiceEntry->Flink)
|
|
|
|
|
{
|
|
|
|
|
CurrentService = CONTAINING_RECORD(ServiceEntry,
|
|
|
|
|
SERVICE,
|
|
|
|
|
ServiceListEntry);
|
|
|
|
|
|
|
|
|
|
if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
dwState = SERVICE_ACTIVE;
|
|
|
|
|
if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
|
|
|
|
|
dwState = SERVICE_INACTIVE;
|
|
|
|
|
|
|
|
|
|
if ((dwState & dwServiceState) == 0)
|
|
|
|
|
continue;
|
2005-12-18 19:50:53 +00:00
|
|
|
|
|
2005-12-25 14:45:30 +00:00
|
|
|
|
dwSize = sizeof(ENUM_SERVICE_STATUSW) +
|
|
|
|
|
((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
|
|
|
|
|
((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
|
2005-12-18 19:50:53 +00:00
|
|
|
|
|
2005-12-25 14:45:30 +00:00
|
|
|
|
if (dwRequiredSize + dwSize <= dwBufSize)
|
|
|
|
|
{
|
|
|
|
|
/* Copy the service name */
|
|
|
|
|
wcscpy(lpStringPtr,
|
|
|
|
|
CurrentService->lpServiceName);
|
2008-04-10 14:49:04 +00:00
|
|
|
|
lpStatusPtr->lpServiceName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpBuffer);
|
2005-12-25 14:45:30 +00:00
|
|
|
|
lpStringPtr += (wcslen(CurrentService->lpServiceName) + 1);
|
|
|
|
|
|
|
|
|
|
/* Copy the display name */
|
|
|
|
|
wcscpy(lpStringPtr,
|
|
|
|
|
CurrentService->lpDisplayName);
|
2008-04-10 14:49:04 +00:00
|
|
|
|
lpStatusPtr->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpBuffer);
|
2005-12-25 14:45:30 +00:00
|
|
|
|
lpStringPtr += (wcslen(CurrentService->lpDisplayName) + 1);
|
|
|
|
|
|
|
|
|
|
/* Copy the status information */
|
|
|
|
|
memcpy(&lpStatusPtr->ServiceStatus,
|
|
|
|
|
&CurrentService->Status,
|
|
|
|
|
sizeof(SERVICE_STATUS));
|
|
|
|
|
|
|
|
|
|
lpStatusPtr++;
|
|
|
|
|
dwRequiredSize += dwSize;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Done:;
|
2006-12-26 01:29:22 +00:00
|
|
|
|
/* FIXME: Unlock the service list */
|
2005-12-25 14:45:30 +00:00
|
|
|
|
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DPRINT("REnumServicesStatusW() done (Error %lu)\n", dwError);
|
2005-12-18 19:50:53 +00:00
|
|
|
|
|
|
|
|
|
return dwError;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2005-07-31 12:11:56 +00:00
|
|
|
|
/* Function 15 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD ROpenSCManagerW(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle,
|
|
|
|
|
LPWSTR lpMachineName,
|
|
|
|
|
LPWSTR lpDatabaseName,
|
|
|
|
|
DWORD dwDesiredAccess,
|
|
|
|
|
LPSC_RPC_HANDLE lpScHandle)
|
2005-07-31 12:11:56 +00:00
|
|
|
|
{
|
2005-10-22 19:46:00 +00:00
|
|
|
|
DWORD dwError;
|
|
|
|
|
SC_HANDLE hHandle;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DPRINT("ROpenSCManagerW() called\n");
|
2005-10-22 19:46:00 +00:00
|
|
|
|
DPRINT("lpMachineName = %p\n", lpMachineName);
|
|
|
|
|
DPRINT("lpMachineName: %S\n", lpMachineName);
|
|
|
|
|
DPRINT("lpDataBaseName = %p\n", lpDatabaseName);
|
|
|
|
|
DPRINT("lpDataBaseName: %S\n", lpDatabaseName);
|
|
|
|
|
DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-10-30 13:13:53 +00:00
|
|
|
|
if (ScmShutdown)
|
|
|
|
|
return ERROR_SHUTDOWN_IN_PROGRESS;
|
|
|
|
|
|
2008-04-10 14:49:04 +00:00
|
|
|
|
if (!lpScHandle)
|
|
|
|
|
return ERROR_INVALID_PARAMETER;
|
2008-03-26 17:44:08 +00:00
|
|
|
|
|
2005-10-22 19:46:00 +00:00
|
|
|
|
dwError = ScmCreateManagerHandle(lpDatabaseName,
|
|
|
|
|
&hHandle);
|
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("ScmCreateManagerHandle() failed (Error %lu)\n", dwError);
|
|
|
|
|
return dwError;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Check the desired access */
|
|
|
|
|
dwError = ScmCheckAccess(hHandle,
|
|
|
|
|
dwDesiredAccess | SC_MANAGER_CONNECT);
|
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError);
|
|
|
|
|
HeapFree(GetProcessHeap(), 0, hHandle);
|
|
|
|
|
return dwError;
|
|
|
|
|
}
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2008-04-10 14:49:04 +00:00
|
|
|
|
*lpScHandle = (unsigned long)hHandle; /* FIXME: 64 bit portability */
|
|
|
|
|
DPRINT("*hScm = %p\n", *lpScHandle);
|
2005-10-22 19:46:00 +00:00
|
|
|
|
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DPRINT("ROpenSCManagerW() done\n");
|
2005-10-22 19:46:00 +00:00
|
|
|
|
|
|
|
|
|
return ERROR_SUCCESS;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Function 16 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD ROpenServiceW(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle,
|
|
|
|
|
SC_RPC_HANDLE hSCManager,
|
|
|
|
|
LPWSTR lpServiceName,
|
|
|
|
|
DWORD dwDesiredAccess,
|
|
|
|
|
LPSC_RPC_HANDLE lpServiceHandle)
|
2005-07-31 12:11:56 +00:00
|
|
|
|
{
|
2005-10-22 19:46:00 +00:00
|
|
|
|
PSERVICE lpService;
|
|
|
|
|
PMANAGER_HANDLE hManager;
|
|
|
|
|
SC_HANDLE hHandle;
|
|
|
|
|
DWORD dwError;
|
|
|
|
|
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DPRINT("ROpenServiceW() called\n");
|
2008-04-10 14:49:04 +00:00
|
|
|
|
DPRINT("hSCManager = %p\n", hSCManager);
|
2005-10-22 19:46:00 +00:00
|
|
|
|
DPRINT("lpServiceName = %p\n", lpServiceName);
|
|
|
|
|
DPRINT("lpServiceName: %S\n", lpServiceName);
|
|
|
|
|
DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess);
|
|
|
|
|
|
2005-10-30 13:13:53 +00:00
|
|
|
|
if (ScmShutdown)
|
|
|
|
|
return ERROR_SHUTDOWN_IN_PROGRESS;
|
|
|
|
|
|
2008-04-10 14:49:04 +00:00
|
|
|
|
if (!lpServiceHandle)
|
|
|
|
|
return ERROR_INVALID_PARAMETER;
|
2008-03-26 17:44:08 +00:00
|
|
|
|
|
2008-08-29 10:34:23 +00:00
|
|
|
|
if (!lpServiceName)
|
|
|
|
|
return ERROR_INVALID_ADDRESS;
|
|
|
|
|
|
2005-10-22 19:46:00 +00:00
|
|
|
|
hManager = (PMANAGER_HANDLE)hSCManager;
|
2008-03-26 17:44:08 +00:00
|
|
|
|
if (!hManager || hManager->Handle.Tag != MANAGER_TAG)
|
2005-10-22 19:46:00 +00:00
|
|
|
|
{
|
|
|
|
|
DPRINT1("Invalid manager handle!\n");
|
|
|
|
|
return ERROR_INVALID_HANDLE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* FIXME: Lock the service list */
|
|
|
|
|
|
|
|
|
|
/* Get service database entry */
|
|
|
|
|
lpService = ScmGetServiceEntryByName(lpServiceName);
|
|
|
|
|
if (lpService == NULL)
|
|
|
|
|
{
|
2005-11-07 10:53:52 +00:00
|
|
|
|
DPRINT("Could not find a service!\n");
|
2005-10-22 19:46:00 +00:00
|
|
|
|
return ERROR_SERVICE_DOES_NOT_EXIST;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Create a service handle */
|
|
|
|
|
dwError = ScmCreateServiceHandle(lpService,
|
|
|
|
|
&hHandle);
|
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("ScmCreateServiceHandle() failed (Error %lu)\n", dwError);
|
|
|
|
|
return dwError;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Check the desired access */
|
|
|
|
|
dwError = ScmCheckAccess(hHandle,
|
|
|
|
|
dwDesiredAccess);
|
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError);
|
|
|
|
|
HeapFree(GetProcessHeap(), 0, hHandle);
|
|
|
|
|
return dwError;
|
|
|
|
|
}
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2008-04-10 14:49:04 +00:00
|
|
|
|
*lpServiceHandle = (unsigned long)hHandle; /* FIXME: 64 bit portability */
|
|
|
|
|
DPRINT("*hService = %p\n", *lpServiceHandle);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DPRINT("ROpenServiceW() done\n");
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-10-22 19:46:00 +00:00
|
|
|
|
return ERROR_SUCCESS;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2005-12-18 19:50:53 +00:00
|
|
|
|
/* Function 17 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD RQueryServiceConfigW(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle,
|
|
|
|
|
SC_RPC_HANDLE hService,
|
|
|
|
|
LPBYTE lpBuf, //LPQUERY_SERVICE_CONFIGW lpServiceConfig,
|
|
|
|
|
DWORD cbBufSize,
|
|
|
|
|
LPBOUNDED_DWORD_8K pcbBytesNeeded)
|
2005-12-18 19:50:53 +00:00
|
|
|
|
{
|
2008-04-10 14:49:04 +00:00
|
|
|
|
LPQUERY_SERVICE_CONFIGW lpServiceConfig = (LPQUERY_SERVICE_CONFIGW)lpBuf;
|
2005-12-18 19:50:53 +00:00
|
|
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
|
|
|
PSERVICE_HANDLE hSvc;
|
|
|
|
|
PSERVICE lpService = NULL;
|
|
|
|
|
HKEY hServiceKey = NULL;
|
|
|
|
|
LPWSTR lpImagePath = NULL;
|
2007-09-06 09:18:23 +00:00
|
|
|
|
LPWSTR lpServiceStartName = NULL;
|
2005-12-18 19:50:53 +00:00
|
|
|
|
DWORD dwRequiredSize;
|
|
|
|
|
LPQUERY_SERVICE_CONFIGW lpConfig;
|
|
|
|
|
LPWSTR lpStr;
|
|
|
|
|
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DPRINT("RQueryServiceConfigW() called\n");
|
2005-12-18 19:50:53 +00:00
|
|
|
|
|
|
|
|
|
if (ScmShutdown)
|
|
|
|
|
return ERROR_SHUTDOWN_IN_PROGRESS;
|
|
|
|
|
|
|
|
|
|
hSvc = (PSERVICE_HANDLE)hService;
|
2008-03-26 17:44:08 +00:00
|
|
|
|
if (!hSvc || hSvc->Handle.Tag != SERVICE_TAG)
|
2005-12-18 19:50:53 +00:00
|
|
|
|
{
|
|
|
|
|
DPRINT1("Invalid handle tag!\n");
|
|
|
|
|
return ERROR_INVALID_HANDLE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
|
|
|
|
|
SERVICE_QUERY_CONFIG))
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
|
|
|
|
|
return ERROR_ACCESS_DENIED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lpService = hSvc->ServiceEntry;
|
|
|
|
|
if (lpService == NULL)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("lpService == NULL!\n");
|
|
|
|
|
return ERROR_INVALID_HANDLE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* FIXME: Lock the service database shared */
|
|
|
|
|
|
|
|
|
|
dwError = ScmOpenServiceKey(lpService->lpServiceName,
|
|
|
|
|
KEY_READ,
|
|
|
|
|
&hServiceKey);
|
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
|
goto Done;
|
|
|
|
|
|
|
|
|
|
dwError = ScmReadString(hServiceKey,
|
|
|
|
|
L"ImagePath",
|
|
|
|
|
&lpImagePath);
|
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
|
goto Done;
|
|
|
|
|
|
2007-09-06 09:18:23 +00:00
|
|
|
|
ScmReadString(hServiceKey,
|
|
|
|
|
L"ObjectName",
|
|
|
|
|
&lpServiceStartName);
|
|
|
|
|
|
2005-12-18 19:50:53 +00:00
|
|
|
|
dwRequiredSize = sizeof(QUERY_SERVICE_CONFIGW);
|
|
|
|
|
|
|
|
|
|
if (lpImagePath != NULL)
|
|
|
|
|
dwRequiredSize += ((wcslen(lpImagePath) + 1) * sizeof(WCHAR));
|
|
|
|
|
|
2005-12-31 22:42:41 +00:00
|
|
|
|
if (lpService->lpGroup != NULL)
|
|
|
|
|
dwRequiredSize += ((wcslen(lpService->lpGroup->lpGroupName) + 1) * sizeof(WCHAR));
|
2005-12-18 19:50:53 +00:00
|
|
|
|
|
|
|
|
|
/* FIXME: Add Dependencies length*/
|
|
|
|
|
|
2007-09-06 09:18:23 +00:00
|
|
|
|
if (lpServiceStartName != NULL)
|
|
|
|
|
dwRequiredSize += ((wcslen(lpServiceStartName) + 1) * sizeof(WCHAR));
|
2005-12-18 19:50:53 +00:00
|
|
|
|
|
|
|
|
|
if (lpService->lpDisplayName != NULL)
|
|
|
|
|
dwRequiredSize += ((wcslen(lpService->lpDisplayName) + 1) * sizeof(WCHAR));
|
|
|
|
|
|
|
|
|
|
if (lpServiceConfig == NULL || cbBufSize < dwRequiredSize)
|
|
|
|
|
{
|
|
|
|
|
dwError = ERROR_INSUFFICIENT_BUFFER;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
lpConfig = (LPQUERY_SERVICE_CONFIGW)lpServiceConfig;
|
|
|
|
|
lpConfig->dwServiceType = lpService->Status.dwServiceType;
|
|
|
|
|
lpConfig->dwStartType = lpService->dwStartType;
|
|
|
|
|
lpConfig->dwErrorControl = lpService->dwErrorControl;
|
|
|
|
|
lpConfig->dwTagId = lpService->dwTag;
|
|
|
|
|
|
|
|
|
|
lpStr = (LPWSTR)(lpConfig + 1);
|
|
|
|
|
|
|
|
|
|
if (lpImagePath != NULL)
|
|
|
|
|
{
|
|
|
|
|
wcscpy(lpStr, lpImagePath);
|
|
|
|
|
lpConfig->lpBinaryPathName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
|
|
|
|
|
lpStr += (wcslen(lpImagePath) + 1);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
lpConfig->lpBinaryPathName = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2005-12-31 22:42:41 +00:00
|
|
|
|
if (lpService->lpGroup != NULL)
|
2005-12-18 19:50:53 +00:00
|
|
|
|
{
|
2005-12-31 22:42:41 +00:00
|
|
|
|
wcscpy(lpStr, lpService->lpGroup->lpGroupName);
|
2005-12-18 19:50:53 +00:00
|
|
|
|
lpConfig->lpLoadOrderGroup = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
|
2005-12-31 22:42:41 +00:00
|
|
|
|
lpStr += (wcslen(lpService->lpGroup->lpGroupName) + 1);
|
2005-12-18 19:50:53 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
lpConfig->lpLoadOrderGroup = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* FIXME: Append Dependencies */
|
|
|
|
|
lpConfig->lpDependencies = NULL;
|
|
|
|
|
|
2007-09-06 09:18:23 +00:00
|
|
|
|
if (lpServiceStartName != NULL)
|
|
|
|
|
{
|
|
|
|
|
wcscpy(lpStr, lpServiceStartName);
|
|
|
|
|
lpConfig->lpServiceStartName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
|
|
|
|
|
lpStr += (wcslen(lpServiceStartName) + 1);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
lpConfig->lpServiceStartName = NULL;
|
|
|
|
|
}
|
2005-12-18 19:50:53 +00:00
|
|
|
|
|
|
|
|
|
if (lpService->lpDisplayName != NULL)
|
|
|
|
|
{
|
|
|
|
|
wcscpy(lpStr, lpService->lpDisplayName);
|
|
|
|
|
lpConfig->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
lpConfig->lpDisplayName = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (pcbBytesNeeded != NULL)
|
|
|
|
|
*pcbBytesNeeded = dwRequiredSize;
|
|
|
|
|
|
|
|
|
|
Done:;
|
|
|
|
|
if (lpImagePath != NULL)
|
|
|
|
|
HeapFree(GetProcessHeap(), 0, lpImagePath);
|
|
|
|
|
|
2007-09-06 09:18:23 +00:00
|
|
|
|
if (lpServiceStartName != NULL)
|
|
|
|
|
HeapFree(GetProcessHeap(), 0, lpServiceStartName);
|
|
|
|
|
|
2005-12-18 19:50:53 +00:00
|
|
|
|
if (hServiceKey != NULL)
|
|
|
|
|
RegCloseKey(hServiceKey);
|
|
|
|
|
|
|
|
|
|
/* FIXME: Unlock the service database */
|
|
|
|
|
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DPRINT("RQueryServiceConfigW() done\n");
|
2005-12-18 19:50:53 +00:00
|
|
|
|
|
|
|
|
|
return dwError;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2005-12-25 14:45:30 +00:00
|
|
|
|
/* Function 18 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD RQueryServiceLockStatusW(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle,
|
|
|
|
|
SC_RPC_HANDLE hSCManager,
|
|
|
|
|
LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus,
|
|
|
|
|
DWORD cbBufSize,
|
|
|
|
|
LPBOUNDED_DWORD_4K pcbBytesNeeded)
|
2005-12-25 14:45:30 +00:00
|
|
|
|
{
|
2008-04-10 14:49:04 +00:00
|
|
|
|
UNIMPLEMENTED;
|
2005-12-25 14:45:30 +00:00
|
|
|
|
return ERROR_CALL_NOT_IMPLEMENTED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Function 19 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD RStartServiceW(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle,
|
|
|
|
|
SC_RPC_HANDLE hService,
|
|
|
|
|
DWORD argc,
|
|
|
|
|
LPSTRING_PTRSW argv)
|
2005-12-31 11:33:46 +00:00
|
|
|
|
{
|
|
|
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
|
|
|
PSERVICE_HANDLE hSvc;
|
|
|
|
|
PSERVICE lpService = NULL;
|
|
|
|
|
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DPRINT("RStartServiceW() called\n");
|
2005-12-31 11:33:46 +00:00
|
|
|
|
|
|
|
|
|
if (ScmShutdown)
|
|
|
|
|
return ERROR_SHUTDOWN_IN_PROGRESS;
|
|
|
|
|
|
|
|
|
|
hSvc = (PSERVICE_HANDLE)hService;
|
2008-03-26 17:44:08 +00:00
|
|
|
|
if (!hSvc || hSvc->Handle.Tag != SERVICE_TAG)
|
2005-12-31 11:33:46 +00:00
|
|
|
|
{
|
|
|
|
|
DPRINT1("Invalid handle tag!\n");
|
|
|
|
|
return ERROR_INVALID_HANDLE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
|
|
|
|
|
SERVICE_START))
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
|
|
|
|
|
return ERROR_ACCESS_DENIED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lpService = hSvc->ServiceEntry;
|
|
|
|
|
if (lpService == NULL)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("lpService == NULL!\n");
|
|
|
|
|
return ERROR_INVALID_HANDLE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (lpService->dwStartType == SERVICE_DISABLED)
|
|
|
|
|
return ERROR_SERVICE_DISABLED;
|
|
|
|
|
|
|
|
|
|
if (lpService->bDeleted)
|
|
|
|
|
return ERROR_SERVICE_MARKED_FOR_DELETE;
|
|
|
|
|
|
2008-04-10 14:49:04 +00:00
|
|
|
|
if (argv) {
|
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
|
argv = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2006-06-03 11:47:04 +00:00
|
|
|
|
/* Start the service */
|
2008-04-10 14:49:04 +00:00
|
|
|
|
dwError = ScmStartService(lpService, argc, (LPWSTR *)argv);
|
2005-12-31 11:33:46 +00:00
|
|
|
|
|
|
|
|
|
return dwError;
|
|
|
|
|
}
|
2005-12-25 14:45:30 +00:00
|
|
|
|
|
|
|
|
|
|
2005-10-30 13:13:53 +00:00
|
|
|
|
/* Function 20 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD RGetServiceDisplayNameW(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle,
|
|
|
|
|
SC_RPC_HANDLE hSCManager,
|
|
|
|
|
LPWSTR lpServiceName,
|
|
|
|
|
LPWSTR lpDisplayName,
|
|
|
|
|
DWORD *lpcchBuffer)
|
2005-10-30 13:13:53 +00:00
|
|
|
|
{
|
|
|
|
|
// PMANAGER_HANDLE hManager;
|
|
|
|
|
PSERVICE lpService;
|
|
|
|
|
DWORD dwLength;
|
|
|
|
|
DWORD dwError;
|
|
|
|
|
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DPRINT("RGetServiceDisplayNameW() called\n");
|
2008-04-10 14:49:04 +00:00
|
|
|
|
DPRINT("hSCManager = %p\n", hSCManager);
|
2005-12-18 19:50:53 +00:00
|
|
|
|
DPRINT("lpServiceName: %S\n", lpServiceName);
|
|
|
|
|
DPRINT("lpDisplayName: %p\n", lpDisplayName);
|
|
|
|
|
DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer);
|
2005-10-30 13:13:53 +00:00
|
|
|
|
|
|
|
|
|
// hManager = (PMANAGER_HANDLE)hSCManager;
|
|
|
|
|
// if (hManager->Handle.Tag != MANAGER_TAG)
|
|
|
|
|
// {
|
|
|
|
|
// DPRINT1("Invalid manager handle!\n");
|
|
|
|
|
// return ERROR_INVALID_HANDLE;
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
/* Get service database entry */
|
|
|
|
|
lpService = ScmGetServiceEntryByName(lpServiceName);
|
|
|
|
|
if (lpService == NULL)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Could not find a service!\n");
|
2008-08-29 10:01:06 +00:00
|
|
|
|
|
|
|
|
|
/* If the service could not be found and lpcchBuffer is 0, windows
|
|
|
|
|
puts null in lpDisplayName and puts 1 in lpcchBuffer */
|
|
|
|
|
if (*lpcchBuffer == 0)
|
|
|
|
|
{
|
|
|
|
|
*lpcchBuffer = 1;
|
|
|
|
|
*lpDisplayName = '\0';
|
|
|
|
|
}
|
|
|
|
|
|
2005-10-30 13:13:53 +00:00
|
|
|
|
return ERROR_SERVICE_DOES_NOT_EXIST;
|
|
|
|
|
}
|
|
|
|
|
|
2008-08-29 10:01:06 +00:00
|
|
|
|
if (!lpService->lpDisplayName)
|
|
|
|
|
{
|
|
|
|
|
dwLength = wcslen(lpService->lpServiceName);
|
2005-10-30 13:13:53 +00:00
|
|
|
|
|
2008-08-29 10:01:06 +00:00
|
|
|
|
if (lpServiceName != NULL &&
|
|
|
|
|
*lpcchBuffer > dwLength)
|
|
|
|
|
{
|
|
|
|
|
wcscpy(lpDisplayName, lpService->lpServiceName);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
2005-10-30 13:13:53 +00:00
|
|
|
|
{
|
2008-08-29 10:01:06 +00:00
|
|
|
|
dwLength = wcslen(lpService->lpDisplayName);
|
|
|
|
|
|
|
|
|
|
if (lpDisplayName != NULL &&
|
|
|
|
|
*lpcchBuffer > dwLength)
|
|
|
|
|
{
|
|
|
|
|
wcscpy(lpDisplayName, lpService->lpDisplayName);
|
|
|
|
|
}
|
2005-10-30 13:13:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dwError = (*lpcchBuffer > dwLength) ? ERROR_SUCCESS : ERROR_INSUFFICIENT_BUFFER;
|
|
|
|
|
|
|
|
|
|
*lpcchBuffer = dwLength;
|
|
|
|
|
|
|
|
|
|
return dwError;
|
|
|
|
|
}
|
|
|
|
|
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-10-30 21:52:23 +00:00
|
|
|
|
/* Function 21 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD RGetServiceKeyNameW(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle,
|
|
|
|
|
SC_RPC_HANDLE hSCManager,
|
|
|
|
|
LPWSTR lpDisplayName,
|
|
|
|
|
LPWSTR lpServiceName,
|
|
|
|
|
DWORD *lpcchBuffer)
|
2005-10-30 21:52:23 +00:00
|
|
|
|
{
|
|
|
|
|
// PMANAGER_HANDLE hManager;
|
|
|
|
|
PSERVICE lpService;
|
|
|
|
|
DWORD dwLength;
|
|
|
|
|
DWORD dwError;
|
|
|
|
|
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DPRINT("RGetServiceKeyNameW() called\n");
|
2008-04-10 14:49:04 +00:00
|
|
|
|
DPRINT("hSCManager = %p\n", hSCManager);
|
2005-12-18 19:50:53 +00:00
|
|
|
|
DPRINT("lpDisplayName: %S\n", lpDisplayName);
|
|
|
|
|
DPRINT("lpServiceName: %p\n", lpServiceName);
|
|
|
|
|
DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer);
|
2005-10-30 21:52:23 +00:00
|
|
|
|
|
|
|
|
|
// hManager = (PMANAGER_HANDLE)hSCManager;
|
|
|
|
|
// if (hManager->Handle.Tag != MANAGER_TAG)
|
|
|
|
|
// {
|
|
|
|
|
// DPRINT1("Invalid manager handle!\n");
|
|
|
|
|
// return ERROR_INVALID_HANDLE;
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
/* Get service database entry */
|
|
|
|
|
lpService = ScmGetServiceEntryByDisplayName(lpDisplayName);
|
|
|
|
|
if (lpService == NULL)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Could not find a service!\n");
|
2008-08-29 10:01:06 +00:00
|
|
|
|
|
|
|
|
|
/* If the service could not be found and lpcchBuffer is 0, windows
|
|
|
|
|
puts null in lpDisplayName and puts 2 in lpcchBuffer */
|
|
|
|
|
if (*lpcchBuffer == 0)
|
|
|
|
|
{
|
|
|
|
|
*lpcchBuffer = 2;
|
|
|
|
|
*lpServiceName = '\0';
|
|
|
|
|
}
|
|
|
|
|
|
2005-10-30 21:52:23 +00:00
|
|
|
|
return ERROR_SERVICE_DOES_NOT_EXIST;
|
|
|
|
|
}
|
|
|
|
|
|
2008-08-29 10:01:06 +00:00
|
|
|
|
dwLength = wcslen(lpService->lpServiceName);
|
2005-10-30 21:52:23 +00:00
|
|
|
|
|
|
|
|
|
if (lpServiceName != NULL &&
|
2008-08-29 10:01:06 +00:00
|
|
|
|
*lpcchBuffer > dwLength)
|
2005-10-30 21:52:23 +00:00
|
|
|
|
{
|
|
|
|
|
wcscpy(lpServiceName, lpService->lpServiceName);
|
2008-08-29 10:01:06 +00:00
|
|
|
|
*lpcchBuffer = dwLength;
|
|
|
|
|
return ERROR_SUCCESS;
|
2005-10-30 21:52:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dwError = (*lpcchBuffer > dwLength) ? ERROR_SUCCESS : ERROR_INSUFFICIENT_BUFFER;
|
|
|
|
|
|
2008-08-29 10:01:06 +00:00
|
|
|
|
*lpcchBuffer = dwLength * 2;
|
2005-10-30 21:52:23 +00:00
|
|
|
|
|
|
|
|
|
return dwError;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2005-12-25 14:45:30 +00:00
|
|
|
|
/* Function 22 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD RSetServiceBitsA(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle,
|
|
|
|
|
SC_RPC_HANDLE hServiceStatus,
|
|
|
|
|
DWORD dwServiceBits,
|
|
|
|
|
int bSetBitsOn,
|
|
|
|
|
int bUpdateImmediately,
|
|
|
|
|
char *lpString)
|
|
|
|
|
{
|
|
|
|
|
UNIMPLEMENTED;
|
2005-12-25 14:45:30 +00:00
|
|
|
|
return ERROR_CALL_NOT_IMPLEMENTED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Function 23 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD RChangeServiceConfigA(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle,
|
|
|
|
|
SC_RPC_HANDLE hService,
|
|
|
|
|
DWORD dwServiceType,
|
|
|
|
|
DWORD dwStartType,
|
|
|
|
|
DWORD dwErrorControl,
|
|
|
|
|
LPSTR lpBinaryPathName,
|
|
|
|
|
LPSTR lpLoadOrderGroup,
|
|
|
|
|
LPDWORD lpdwTagId,
|
|
|
|
|
LPSTR lpDependencies,
|
|
|
|
|
DWORD dwDependSize,
|
|
|
|
|
LPSTR lpServiceStartName,
|
|
|
|
|
LPBYTE lpPassword,
|
|
|
|
|
DWORD dwPwSize,
|
|
|
|
|
LPSTR lpDisplayName)
|
|
|
|
|
{
|
|
|
|
|
UNIMPLEMENTED;
|
2005-12-25 14:45:30 +00:00
|
|
|
|
return ERROR_CALL_NOT_IMPLEMENTED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Function 24 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD RCreateServiceA(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle,
|
|
|
|
|
SC_RPC_HANDLE hSCManager,
|
|
|
|
|
LPSTR lpServiceName,
|
|
|
|
|
LPSTR lpDisplayName,
|
|
|
|
|
DWORD dwDesiredAccess,
|
|
|
|
|
DWORD dwServiceType,
|
|
|
|
|
DWORD dwStartType,
|
|
|
|
|
DWORD dwErrorControl,
|
|
|
|
|
LPSTR lpBinaryPathName,
|
|
|
|
|
LPSTR lpLoadOrderGroup,
|
|
|
|
|
LPDWORD lpdwTagId,
|
|
|
|
|
LPBYTE lpDependencies,
|
|
|
|
|
DWORD dwDependSize,
|
|
|
|
|
LPSTR lpServiceStartName,
|
|
|
|
|
LPBYTE lpPassword,
|
|
|
|
|
DWORD dwPwSize,
|
|
|
|
|
LPSC_RPC_HANDLE lpServiceHandle)
|
|
|
|
|
{
|
|
|
|
|
UNIMPLEMENTED;
|
2005-12-25 14:45:30 +00:00
|
|
|
|
return ERROR_CALL_NOT_IMPLEMENTED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Function 25 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD REnumDependentServicesA(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle,
|
|
|
|
|
SC_RPC_HANDLE hService,
|
|
|
|
|
DWORD dwServiceState,
|
|
|
|
|
LPBYTE lpServices,
|
|
|
|
|
DWORD cbBufSize,
|
|
|
|
|
LPBOUNDED_DWORD_256K pcbBytesNeeded,
|
|
|
|
|
LPBOUNDED_DWORD_256K lpServicesReturned)
|
|
|
|
|
{
|
|
|
|
|
UNIMPLEMENTED;
|
2006-01-01 12:00:13 +00:00
|
|
|
|
*pcbBytesNeeded = 0;
|
|
|
|
|
*lpServicesReturned = 0;
|
2005-12-25 14:45:30 +00:00
|
|
|
|
return ERROR_CALL_NOT_IMPLEMENTED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Function 26 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD REnumServicesStatusA(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle,
|
|
|
|
|
SC_RPC_HANDLE hSCManager,
|
|
|
|
|
DWORD dwServiceType,
|
|
|
|
|
DWORD dwServiceState,
|
|
|
|
|
LPBYTE lpBuffer,
|
|
|
|
|
DWORD dwBufSize,
|
|
|
|
|
LPBOUNDED_DWORD_256K pcbBytesNeeded,
|
|
|
|
|
LPBOUNDED_DWORD_256K lpServicesReturned,
|
|
|
|
|
LPBOUNDED_DWORD_256K lpResumeHandle)
|
|
|
|
|
{
|
|
|
|
|
UNIMPLEMENTED;
|
2005-12-25 14:45:30 +00:00
|
|
|
|
return ERROR_CALL_NOT_IMPLEMENTED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2005-07-31 12:11:56 +00:00
|
|
|
|
/* Function 27 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD ROpenSCManagerA(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle,
|
|
|
|
|
LPSTR lpMachineName,
|
|
|
|
|
LPSTR lpDatabaseName,
|
|
|
|
|
DWORD dwDesiredAccess,
|
|
|
|
|
LPSC_RPC_HANDLE lpScHandle)
|
2005-07-31 12:11:56 +00:00
|
|
|
|
{
|
2005-10-22 19:46:00 +00:00
|
|
|
|
UNICODE_STRING MachineName;
|
|
|
|
|
UNICODE_STRING DatabaseName;
|
|
|
|
|
DWORD dwError;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DPRINT("ROpenSCManagerA() called\n");
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-10-22 19:46:00 +00:00
|
|
|
|
if (lpMachineName)
|
|
|
|
|
RtlCreateUnicodeStringFromAsciiz(&MachineName,
|
|
|
|
|
lpMachineName);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-10-22 19:46:00 +00:00
|
|
|
|
if (lpDatabaseName)
|
|
|
|
|
RtlCreateUnicodeStringFromAsciiz(&DatabaseName,
|
|
|
|
|
lpDatabaseName);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2008-04-10 16:39:01 +00:00
|
|
|
|
dwError = ROpenSCManagerW(BindingHandle,
|
2005-10-22 19:46:00 +00:00
|
|
|
|
lpMachineName ? MachineName.Buffer : NULL,
|
|
|
|
|
lpDatabaseName ? DatabaseName.Buffer : NULL,
|
|
|
|
|
dwDesiredAccess,
|
2008-04-10 14:49:04 +00:00
|
|
|
|
lpScHandle);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-10-22 19:46:00 +00:00
|
|
|
|
if (lpMachineName)
|
|
|
|
|
RtlFreeUnicodeString(&MachineName);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-10-22 19:46:00 +00:00
|
|
|
|
if (lpDatabaseName)
|
|
|
|
|
RtlFreeUnicodeString(&DatabaseName);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-10-22 19:46:00 +00:00
|
|
|
|
return dwError;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Function 28 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD ROpenServiceA(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle,
|
|
|
|
|
SC_RPC_HANDLE hSCManager,
|
|
|
|
|
LPSTR lpServiceName,
|
|
|
|
|
DWORD dwDesiredAccess,
|
|
|
|
|
LPSC_RPC_HANDLE lpServiceHandle)
|
2005-07-31 12:11:56 +00:00
|
|
|
|
{
|
2005-10-22 19:46:00 +00:00
|
|
|
|
UNICODE_STRING ServiceName;
|
|
|
|
|
DWORD dwError;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DPRINT("ROpenServiceA() called\n");
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2008-08-29 10:34:23 +00:00
|
|
|
|
if (lpServiceName)
|
|
|
|
|
RtlCreateUnicodeStringFromAsciiz(&ServiceName,
|
|
|
|
|
lpServiceName);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2008-04-10 16:39:01 +00:00
|
|
|
|
dwError = ROpenServiceW(BindingHandle,
|
2005-10-22 19:46:00 +00:00
|
|
|
|
hSCManager,
|
|
|
|
|
ServiceName.Buffer,
|
|
|
|
|
dwDesiredAccess,
|
2008-04-10 14:49:04 +00:00
|
|
|
|
lpServiceHandle);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2008-08-29 10:34:23 +00:00
|
|
|
|
if (lpServiceName)
|
|
|
|
|
RtlFreeUnicodeString(&ServiceName);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
2005-10-22 19:46:00 +00:00
|
|
|
|
return dwError;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2005-12-25 14:45:30 +00:00
|
|
|
|
/* Function 29 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD RQueryServiceConfigA(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle,
|
|
|
|
|
SC_RPC_HANDLE hService,
|
2008-08-24 18:08:17 +00:00
|
|
|
|
LPBYTE lpBuf, //LPQUERY_SERVICE_CONFIGA lpServiceConfig,
|
2008-04-10 14:49:04 +00:00
|
|
|
|
DWORD cbBufSize,
|
|
|
|
|
LPBOUNDED_DWORD_8K pcbBytesNeeded)
|
2005-12-25 14:45:30 +00:00
|
|
|
|
{
|
2008-04-10 14:49:04 +00:00
|
|
|
|
UNIMPLEMENTED;
|
2005-12-25 14:45:30 +00:00
|
|
|
|
return ERROR_CALL_NOT_IMPLEMENTED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Function 30 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD RQueryServiceLockStatusA(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle,
|
|
|
|
|
SC_RPC_HANDLE hSCManager,
|
|
|
|
|
LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus,
|
|
|
|
|
DWORD cbBufSize,
|
|
|
|
|
LPBOUNDED_DWORD_4K pcbBytesNeeded)
|
2005-12-25 14:45:30 +00:00
|
|
|
|
{
|
2008-04-10 14:49:04 +00:00
|
|
|
|
UNIMPLEMENTED;
|
2005-12-25 14:45:30 +00:00
|
|
|
|
return ERROR_CALL_NOT_IMPLEMENTED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Function 31 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD RStartServiceA(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle,
|
|
|
|
|
SC_RPC_HANDLE hService,
|
|
|
|
|
DWORD argc,
|
|
|
|
|
LPSTRING_PTRSA argv)
|
2005-12-31 11:33:46 +00:00
|
|
|
|
{
|
2006-08-07 22:13:26 +00:00
|
|
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
|
|
|
PSERVICE_HANDLE hSvc;
|
|
|
|
|
PSERVICE lpService = NULL;
|
|
|
|
|
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DPRINT1("RStartServiceA() called\n");
|
2006-08-07 22:13:26 +00:00
|
|
|
|
|
|
|
|
|
if (ScmShutdown)
|
|
|
|
|
return ERROR_SHUTDOWN_IN_PROGRESS;
|
|
|
|
|
|
|
|
|
|
hSvc = (PSERVICE_HANDLE)hService;
|
2008-03-26 17:44:08 +00:00
|
|
|
|
if (!hSvc || hSvc->Handle.Tag != SERVICE_TAG)
|
2006-08-07 22:13:26 +00:00
|
|
|
|
{
|
|
|
|
|
DPRINT1("Invalid handle tag!\n");
|
|
|
|
|
return ERROR_INVALID_HANDLE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
|
|
|
|
|
SERVICE_START))
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
|
|
|
|
|
return ERROR_ACCESS_DENIED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lpService = hSvc->ServiceEntry;
|
|
|
|
|
if (lpService == NULL)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("lpService == NULL!\n");
|
|
|
|
|
return ERROR_INVALID_HANDLE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (lpService->dwStartType == SERVICE_DISABLED)
|
|
|
|
|
return ERROR_SERVICE_DISABLED;
|
|
|
|
|
|
|
|
|
|
if (lpService->bDeleted)
|
|
|
|
|
return ERROR_SERVICE_MARKED_FOR_DELETE;
|
|
|
|
|
|
|
|
|
|
/* FIXME: Convert argument vector to Unicode */
|
|
|
|
|
|
|
|
|
|
/* Start the service */
|
2008-04-10 14:49:04 +00:00
|
|
|
|
dwError = ScmStartService(lpService, 0, NULL);
|
2006-08-31 17:16:19 +00:00
|
|
|
|
|
|
|
|
|
/* FIXME: Free argument vector */
|
2006-08-07 22:13:26 +00:00
|
|
|
|
|
|
|
|
|
return dwError;
|
2005-12-31 11:33:46 +00:00
|
|
|
|
}
|
2005-12-25 14:45:30 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Function 32 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD RGetServiceDisplayNameA(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle,
|
|
|
|
|
SC_RPC_HANDLE hSCManager,
|
|
|
|
|
LPSTR lpServiceName,
|
|
|
|
|
LPSTR lpDisplayName,
|
|
|
|
|
LPBOUNDED_DWORD_4K lpcchBuffer)
|
2005-12-25 14:45:30 +00:00
|
|
|
|
{
|
2008-08-29 10:01:06 +00:00
|
|
|
|
// PMANAGER_HANDLE hManager;
|
|
|
|
|
PSERVICE lpService;
|
|
|
|
|
DWORD dwLength;
|
|
|
|
|
DWORD dwError;
|
|
|
|
|
LPWSTR lpServiceNameW;
|
|
|
|
|
|
|
|
|
|
DPRINT("RGetServiceDisplayNameA() called\n");
|
|
|
|
|
DPRINT("hSCManager = %p\n", hSCManager);
|
|
|
|
|
DPRINT("lpServiceName: %s\n", lpServiceName);
|
|
|
|
|
DPRINT("lpDisplayName: %p\n", lpDisplayName);
|
|
|
|
|
DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer);
|
|
|
|
|
|
|
|
|
|
// hManager = (PMANAGER_HANDLE)hSCManager;
|
|
|
|
|
// if (hManager->Handle.Tag != MANAGER_TAG)
|
|
|
|
|
// {
|
|
|
|
|
// DPRINT1("Invalid manager handle!\n");
|
|
|
|
|
// return ERROR_INVALID_HANDLE;
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
dwLength = strlen(lpServiceName) + 1;
|
|
|
|
|
lpServiceNameW = HeapAlloc(GetProcessHeap(),
|
|
|
|
|
HEAP_ZERO_MEMORY,
|
|
|
|
|
dwLength * sizeof(WCHAR));
|
|
|
|
|
if (!lpServiceNameW)
|
|
|
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
|
|
|
|
|
|
MultiByteToWideChar(CP_ACP,
|
|
|
|
|
0,
|
|
|
|
|
lpServiceName,
|
|
|
|
|
strlen(lpServiceName),
|
|
|
|
|
lpServiceNameW,
|
|
|
|
|
dwLength);
|
|
|
|
|
|
|
|
|
|
lpService = ScmGetServiceEntryByName(lpServiceNameW);
|
|
|
|
|
|
|
|
|
|
HeapFree(GetProcessHeap(), 0, lpServiceNameW);
|
|
|
|
|
|
|
|
|
|
if (lpService == NULL)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Could not find a service!\n");
|
|
|
|
|
|
|
|
|
|
/* If the service could not be found and lpcchBuffer is 0, windows
|
|
|
|
|
puts null in lpDisplayName and puts 1 in lpcchBuffer */
|
|
|
|
|
if (*lpcchBuffer == 0)
|
|
|
|
|
{
|
|
|
|
|
*lpcchBuffer = 1;
|
|
|
|
|
*lpDisplayName = '\0';
|
|
|
|
|
}
|
|
|
|
|
return ERROR_SERVICE_DOES_NOT_EXIST;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!lpService->lpDisplayName)
|
|
|
|
|
{
|
|
|
|
|
dwLength = wcslen(lpService->lpServiceName);
|
|
|
|
|
if (lpServiceName != NULL &&
|
|
|
|
|
*lpcchBuffer > dwLength)
|
|
|
|
|
{
|
|
|
|
|
WideCharToMultiByte(CP_ACP,
|
|
|
|
|
0,
|
|
|
|
|
lpService->lpServiceName,
|
|
|
|
|
wcslen(lpService->lpServiceName),
|
|
|
|
|
lpDisplayName,
|
|
|
|
|
*lpcchBuffer,
|
|
|
|
|
NULL,
|
|
|
|
|
NULL);
|
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
dwLength = wcslen(lpService->lpDisplayName);
|
|
|
|
|
if (lpDisplayName != NULL &&
|
|
|
|
|
*lpcchBuffer > dwLength)
|
|
|
|
|
{
|
|
|
|
|
WideCharToMultiByte(CP_ACP,
|
|
|
|
|
0,
|
|
|
|
|
lpService->lpDisplayName,
|
|
|
|
|
wcslen(lpService->lpDisplayName),
|
|
|
|
|
lpDisplayName,
|
|
|
|
|
*lpcchBuffer,
|
|
|
|
|
NULL,
|
|
|
|
|
NULL);
|
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dwError = (*lpcchBuffer > dwLength) ? ERROR_SUCCESS : ERROR_INSUFFICIENT_BUFFER;
|
|
|
|
|
|
|
|
|
|
*lpcchBuffer = dwLength * 2;
|
|
|
|
|
|
|
|
|
|
return dwError;
|
2005-12-25 14:45:30 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Function 33 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD RGetServiceKeyNameA(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle,
|
|
|
|
|
SC_RPC_HANDLE hSCManager,
|
|
|
|
|
LPSTR lpDisplayName,
|
2008-08-29 10:01:06 +00:00
|
|
|
|
LPSTR lpServiceName,
|
2008-04-10 14:49:04 +00:00
|
|
|
|
LPBOUNDED_DWORD_4K lpcchBuffer)
|
2005-12-25 14:45:30 +00:00
|
|
|
|
{
|
2008-08-29 10:01:06 +00:00
|
|
|
|
PSERVICE lpService;
|
|
|
|
|
DWORD dwLength;
|
|
|
|
|
DWORD dwError;
|
|
|
|
|
LPWSTR lpDisplayNameW;
|
|
|
|
|
|
|
|
|
|
DPRINT("RGetServiceKeyNameA() called\n");
|
|
|
|
|
DPRINT("hSCManager = %p\n", hSCManager);
|
|
|
|
|
DPRINT("lpDisplayName: %s\n", lpDisplayName);
|
|
|
|
|
DPRINT("lpServiceName: %p\n", lpServiceName);
|
|
|
|
|
DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer);
|
|
|
|
|
|
|
|
|
|
dwLength = strlen(lpDisplayName) + 1;
|
|
|
|
|
lpDisplayNameW = HeapAlloc(GetProcessHeap(),
|
|
|
|
|
HEAP_ZERO_MEMORY,
|
|
|
|
|
dwLength * sizeof(WCHAR));
|
|
|
|
|
if (!lpDisplayNameW)
|
|
|
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
|
|
|
|
|
|
MultiByteToWideChar(CP_ACP,
|
|
|
|
|
0,
|
|
|
|
|
lpDisplayName,
|
|
|
|
|
strlen(lpDisplayName),
|
|
|
|
|
lpDisplayNameW,
|
|
|
|
|
dwLength);
|
|
|
|
|
|
|
|
|
|
lpService = ScmGetServiceEntryByDisplayName(lpDisplayNameW);
|
|
|
|
|
|
|
|
|
|
HeapFree(GetProcessHeap(), 0, lpDisplayNameW);
|
|
|
|
|
|
|
|
|
|
if (lpService == NULL)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Could not find the service!\n");
|
|
|
|
|
|
|
|
|
|
/* If the service could not be found and lpcchBuffer is 0,
|
|
|
|
|
put null in lpDisplayName and puts 1 in lpcchBuffer, verified WINXP. */
|
|
|
|
|
if (*lpcchBuffer == 0)
|
|
|
|
|
{
|
|
|
|
|
*lpcchBuffer = 1;
|
|
|
|
|
*lpServiceName = '\0';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ERROR_SERVICE_DOES_NOT_EXIST;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dwLength = wcslen(lpService->lpServiceName);
|
|
|
|
|
if (lpService != NULL &&
|
|
|
|
|
*lpcchBuffer > dwLength)
|
|
|
|
|
{
|
|
|
|
|
WideCharToMultiByte(CP_ACP,
|
|
|
|
|
0,
|
|
|
|
|
lpService->lpServiceName,
|
|
|
|
|
wcslen(lpService->lpServiceName),
|
|
|
|
|
lpServiceName,
|
|
|
|
|
dwLength,
|
|
|
|
|
NULL,
|
|
|
|
|
NULL);
|
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dwError = (*lpcchBuffer > dwLength) ? ERROR_SUCCESS : ERROR_INSUFFICIENT_BUFFER;
|
|
|
|
|
|
|
|
|
|
*lpcchBuffer = dwLength * 2;
|
|
|
|
|
|
|
|
|
|
return dwError;
|
2005-12-25 14:45:30 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Function 34 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD RGetCurrentGroupStateW(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle)
|
2006-01-01 10:31:35 +00:00
|
|
|
|
{
|
2008-04-10 14:49:04 +00:00
|
|
|
|
UNIMPLEMENTED;
|
2006-01-01 10:31:35 +00:00
|
|
|
|
return ERROR_CALL_NOT_IMPLEMENTED;
|
|
|
|
|
}
|
2005-12-25 14:45:30 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Function 35 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD REnumServiceGroupW(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle,
|
|
|
|
|
SC_RPC_HANDLE hSCManager,
|
|
|
|
|
DWORD dwServiceType,
|
|
|
|
|
DWORD dwServiceState,
|
|
|
|
|
LPBYTE lpBuffer,
|
|
|
|
|
DWORD cbBufSize,
|
|
|
|
|
LPBOUNDED_DWORD_256K pcbBytesNeeded,
|
|
|
|
|
LPBOUNDED_DWORD_256K lpServicesReturned,
|
|
|
|
|
LPBOUNDED_DWORD_256K lpResumeIndex,
|
2008-05-18 15:23:52 +00:00
|
|
|
|
LPCWSTR pszGroupName)
|
2006-01-01 10:31:35 +00:00
|
|
|
|
{
|
2008-04-10 14:49:04 +00:00
|
|
|
|
UNIMPLEMENTED;
|
2006-01-01 10:31:35 +00:00
|
|
|
|
return ERROR_CALL_NOT_IMPLEMENTED;
|
|
|
|
|
}
|
2005-12-25 14:45:30 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Function 36 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD RChangeServiceConfig2A(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle,
|
|
|
|
|
SC_RPC_HANDLE hService,
|
|
|
|
|
SC_RPC_CONFIG_INFOA Info)
|
2006-01-01 10:31:35 +00:00
|
|
|
|
{
|
2008-04-10 14:49:04 +00:00
|
|
|
|
UNIMPLEMENTED;
|
2006-01-01 10:31:35 +00:00
|
|
|
|
return ERROR_CALL_NOT_IMPLEMENTED;
|
|
|
|
|
}
|
2005-12-25 14:45:30 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Function 37 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD RChangeServiceConfig2W(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle,
|
|
|
|
|
SC_RPC_HANDLE hService,
|
|
|
|
|
SC_RPC_CONFIG_INFOW Info)
|
2005-12-30 10:29:07 +00:00
|
|
|
|
{
|
2007-09-05 22:35:51 +00:00
|
|
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
|
|
|
PSERVICE_HANDLE hSvc;
|
|
|
|
|
PSERVICE lpService = NULL;
|
|
|
|
|
HKEY hServiceKey = NULL;
|
|
|
|
|
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DPRINT("RChangeServiceConfig2W() called\n");
|
2008-04-10 14:49:04 +00:00
|
|
|
|
DPRINT("dwInfoLevel = %lu\n", Info.dwInfoLevel);
|
2007-09-05 22:35:51 +00:00
|
|
|
|
|
|
|
|
|
if (ScmShutdown)
|
|
|
|
|
return ERROR_SHUTDOWN_IN_PROGRESS;
|
|
|
|
|
|
|
|
|
|
hSvc = (PSERVICE_HANDLE)hService;
|
2008-03-26 17:44:08 +00:00
|
|
|
|
if (!hSvc || hSvc->Handle.Tag != SERVICE_TAG)
|
2007-09-05 22:35:51 +00:00
|
|
|
|
{
|
|
|
|
|
DPRINT1("Invalid handle tag!\n");
|
|
|
|
|
return ERROR_INVALID_HANDLE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
|
|
|
|
|
SERVICE_CHANGE_CONFIG))
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
|
|
|
|
|
return ERROR_ACCESS_DENIED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lpService = hSvc->ServiceEntry;
|
|
|
|
|
if (lpService == NULL)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("lpService == NULL!\n");
|
|
|
|
|
return ERROR_INVALID_HANDLE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* FIXME: Lock database exclusively */
|
|
|
|
|
|
|
|
|
|
if (lpService->bDeleted)
|
|
|
|
|
{
|
|
|
|
|
/* FIXME: Unlock database */
|
|
|
|
|
DPRINT1("The service has already been marked for delete!\n");
|
|
|
|
|
return ERROR_SERVICE_MARKED_FOR_DELETE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Open the service key */
|
|
|
|
|
dwError = ScmOpenServiceKey(lpService->szServiceName,
|
|
|
|
|
KEY_SET_VALUE,
|
|
|
|
|
&hServiceKey);
|
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
|
goto done;
|
|
|
|
|
|
2008-04-10 14:49:04 +00:00
|
|
|
|
if (Info.dwInfoLevel & SERVICE_CONFIG_DESCRIPTION)
|
2007-09-05 22:35:51 +00:00
|
|
|
|
{
|
2007-09-07 10:55:16 +00:00
|
|
|
|
LPSERVICE_DESCRIPTIONW lpServiceDescription;
|
2007-09-05 22:35:51 +00:00
|
|
|
|
|
2008-04-10 14:49:04 +00:00
|
|
|
|
lpServiceDescription = (LPSERVICE_DESCRIPTIONW)&Info;
|
|
|
|
|
lpServiceDescription->lpDescription = (LPWSTR)(&Info + sizeof(LPSERVICE_DESCRIPTIONW));
|
2007-09-05 22:35:51 +00:00
|
|
|
|
|
2007-09-07 10:55:16 +00:00
|
|
|
|
if (lpServiceDescription != NULL &&
|
|
|
|
|
lpServiceDescription->lpDescription != NULL)
|
2007-09-05 22:35:51 +00:00
|
|
|
|
{
|
|
|
|
|
RegSetValueExW(hServiceKey,
|
|
|
|
|
L"Description",
|
|
|
|
|
0,
|
|
|
|
|
REG_SZ,
|
|
|
|
|
(LPBYTE)lpServiceDescription->lpDescription,
|
|
|
|
|
(wcslen(lpServiceDescription->lpDescription) + 1) * sizeof(WCHAR));
|
|
|
|
|
|
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
|
goto done;
|
|
|
|
|
}
|
|
|
|
|
}
|
2008-04-10 14:49:04 +00:00
|
|
|
|
else if (Info.dwInfoLevel & SERVICE_CONFIG_FAILURE_ACTIONS)
|
2007-09-05 22:35:51 +00:00
|
|
|
|
{
|
2008-04-10 14:49:04 +00:00
|
|
|
|
UNIMPLEMENTED;
|
2007-09-05 22:35:51 +00:00
|
|
|
|
dwError = ERROR_CALL_NOT_IMPLEMENTED;
|
|
|
|
|
goto done;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
done:
|
|
|
|
|
/* FIXME: Unlock database */
|
|
|
|
|
if (hServiceKey != NULL)
|
|
|
|
|
RegCloseKey(hServiceKey);
|
|
|
|
|
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DPRINT("RChangeServiceConfig2W() done (Error %lu)\n", dwError);
|
2007-09-05 22:35:51 +00:00
|
|
|
|
|
|
|
|
|
return dwError;
|
2005-12-30 10:29:07 +00:00
|
|
|
|
}
|
2005-12-25 14:45:30 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Function 38 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD RQueryServiceConfig2A(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle,
|
|
|
|
|
SC_RPC_HANDLE hService,
|
|
|
|
|
DWORD dwInfoLevel,
|
|
|
|
|
LPBYTE lpBuffer,
|
|
|
|
|
DWORD cbBufSize,
|
|
|
|
|
LPBOUNDED_DWORD_8K pcbBytesNeeded)
|
|
|
|
|
{
|
|
|
|
|
UNIMPLEMENTED;
|
2006-01-01 10:31:35 +00:00
|
|
|
|
return ERROR_CALL_NOT_IMPLEMENTED;
|
|
|
|
|
}
|
2005-12-25 14:45:30 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Function 39 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD RQueryServiceConfig2W(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle,
|
|
|
|
|
SC_RPC_HANDLE hService,
|
|
|
|
|
DWORD dwInfoLevel,
|
|
|
|
|
LPBYTE lpBuffer,
|
|
|
|
|
DWORD cbBufSize,
|
|
|
|
|
LPBOUNDED_DWORD_8K pcbBytesNeeded)
|
2006-01-01 10:31:35 +00:00
|
|
|
|
{
|
2007-09-05 22:35:51 +00:00
|
|
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
|
|
|
PSERVICE_HANDLE hSvc;
|
|
|
|
|
PSERVICE lpService = NULL;
|
|
|
|
|
HKEY hServiceKey = NULL;
|
|
|
|
|
DWORD dwRequiredSize;
|
|
|
|
|
LPWSTR lpDescription = NULL;
|
|
|
|
|
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DPRINT("RQueryServiceConfig2W() called\n");
|
2007-09-05 22:35:51 +00:00
|
|
|
|
|
|
|
|
|
if (ScmShutdown)
|
|
|
|
|
return ERROR_SHUTDOWN_IN_PROGRESS;
|
|
|
|
|
|
|
|
|
|
hSvc = (PSERVICE_HANDLE)hService;
|
2008-03-26 17:44:08 +00:00
|
|
|
|
if (!hSvc || hSvc->Handle.Tag != SERVICE_TAG)
|
2007-09-05 22:35:51 +00:00
|
|
|
|
{
|
|
|
|
|
DPRINT1("Invalid handle tag!\n");
|
|
|
|
|
return ERROR_INVALID_HANDLE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
|
|
|
|
|
SERVICE_QUERY_CONFIG))
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
|
|
|
|
|
return ERROR_ACCESS_DENIED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lpService = hSvc->ServiceEntry;
|
|
|
|
|
if (lpService == NULL)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("lpService == NULL!\n");
|
|
|
|
|
return ERROR_INVALID_HANDLE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* FIXME: Lock the service database shared */
|
|
|
|
|
|
|
|
|
|
dwError = ScmOpenServiceKey(lpService->lpServiceName,
|
|
|
|
|
KEY_READ,
|
|
|
|
|
&hServiceKey);
|
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
|
|
if (dwInfoLevel & SERVICE_CONFIG_DESCRIPTION)
|
|
|
|
|
{
|
|
|
|
|
LPSERVICE_DESCRIPTIONW lpServiceDescription = (LPSERVICE_DESCRIPTIONW)lpBuffer;
|
|
|
|
|
LPWSTR lpStr;
|
|
|
|
|
|
|
|
|
|
dwError = ScmReadString(hServiceKey,
|
|
|
|
|
L"Description",
|
|
|
|
|
&lpDescription);
|
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
|
|
dwRequiredSize = sizeof(SERVICE_DESCRIPTIONW) + ((wcslen(lpDescription) + 1) * sizeof(WCHAR));
|
|
|
|
|
|
|
|
|
|
if (cbBufSize < dwRequiredSize)
|
|
|
|
|
{
|
|
|
|
|
*pcbBytesNeeded = dwRequiredSize;
|
|
|
|
|
dwError = ERROR_INSUFFICIENT_BUFFER;
|
|
|
|
|
goto done;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
lpStr = (LPWSTR)(lpServiceDescription + 1);
|
|
|
|
|
wcscpy(lpStr, lpDescription);
|
|
|
|
|
lpServiceDescription->lpDescription = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceDescription);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (dwInfoLevel & SERVICE_CONFIG_FAILURE_ACTIONS)
|
|
|
|
|
{
|
2008-04-10 14:49:04 +00:00
|
|
|
|
UNIMPLEMENTED;
|
2007-09-05 22:35:51 +00:00
|
|
|
|
dwError = ERROR_CALL_NOT_IMPLEMENTED;
|
|
|
|
|
goto done;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
done:
|
|
|
|
|
if (lpDescription != NULL)
|
|
|
|
|
HeapFree(GetProcessHeap(), 0, lpDescription);
|
|
|
|
|
|
|
|
|
|
if (hServiceKey != NULL)
|
|
|
|
|
RegCloseKey(hServiceKey);
|
|
|
|
|
|
|
|
|
|
/* FIXME: Unlock database */
|
|
|
|
|
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError);
|
2007-09-05 22:35:51 +00:00
|
|
|
|
|
|
|
|
|
return dwError;
|
2006-01-01 10:31:35 +00:00
|
|
|
|
}
|
2005-12-25 14:45:30 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Function 40 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD RQueryServiceStatusEx(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle,
|
|
|
|
|
SC_RPC_HANDLE hService,
|
|
|
|
|
SC_STATUS_TYPE InfoLevel,
|
|
|
|
|
LPBYTE lpBuffer,
|
|
|
|
|
DWORD cbBufSize,
|
|
|
|
|
LPBOUNDED_DWORD_8K pcbBytesNeeded)
|
2005-12-25 14:45:30 +00:00
|
|
|
|
{
|
2005-12-25 21:19:33 +00:00
|
|
|
|
LPSERVICE_STATUS_PROCESS lpStatus;
|
|
|
|
|
PSERVICE_HANDLE hSvc;
|
|
|
|
|
PSERVICE lpService;
|
|
|
|
|
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DPRINT("RQueryServiceStatusEx() called\n");
|
2005-12-25 21:19:33 +00:00
|
|
|
|
|
|
|
|
|
if (ScmShutdown)
|
|
|
|
|
return ERROR_SHUTDOWN_IN_PROGRESS;
|
|
|
|
|
|
|
|
|
|
if (InfoLevel != SC_STATUS_PROCESS_INFO)
|
|
|
|
|
return ERROR_INVALID_LEVEL;
|
|
|
|
|
|
|
|
|
|
*pcbBytesNeeded = sizeof(SERVICE_STATUS_PROCESS);
|
|
|
|
|
|
|
|
|
|
if (cbBufSize < sizeof(SERVICE_STATUS_PROCESS))
|
|
|
|
|
return ERROR_INSUFFICIENT_BUFFER;
|
|
|
|
|
|
|
|
|
|
hSvc = (PSERVICE_HANDLE)hService;
|
2008-03-26 17:44:08 +00:00
|
|
|
|
if (!hSvc || hSvc->Handle.Tag != SERVICE_TAG)
|
2005-12-25 21:19:33 +00:00
|
|
|
|
{
|
|
|
|
|
DPRINT1("Invalid handle tag!\n");
|
|
|
|
|
return ERROR_INVALID_HANDLE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
|
|
|
|
|
SERVICE_QUERY_STATUS))
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
|
|
|
|
|
return ERROR_ACCESS_DENIED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lpService = hSvc->ServiceEntry;
|
|
|
|
|
if (lpService == NULL)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("lpService == NULL!\n");
|
|
|
|
|
return ERROR_INVALID_HANDLE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lpStatus = (LPSERVICE_STATUS_PROCESS)lpBuffer;
|
|
|
|
|
|
|
|
|
|
/* Return service status information */
|
|
|
|
|
RtlCopyMemory(lpStatus,
|
|
|
|
|
&lpService->Status,
|
|
|
|
|
sizeof(SERVICE_STATUS));
|
|
|
|
|
|
|
|
|
|
lpStatus->dwProcessId = lpService->ProcessId; /* FIXME */
|
|
|
|
|
lpStatus->dwServiceFlags = 0; /* FIXME */
|
|
|
|
|
|
|
|
|
|
return ERROR_SUCCESS;
|
2005-12-25 14:45:30 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Function 41 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD REnumServicesStatusExA(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle,
|
|
|
|
|
SC_RPC_HANDLE hSCManager,
|
|
|
|
|
SC_ENUM_TYPE InfoLevel,
|
|
|
|
|
DWORD dwServiceType,
|
|
|
|
|
DWORD dwServiceState,
|
|
|
|
|
LPBYTE lpBuffer,
|
|
|
|
|
DWORD cbBufSize,
|
|
|
|
|
LPBOUNDED_DWORD_256K pcbBytesNeeded,
|
|
|
|
|
LPBOUNDED_DWORD_256K lpServicesReturned,
|
|
|
|
|
LPBOUNDED_DWORD_256K lpResumeIndex,
|
2008-05-18 15:23:52 +00:00
|
|
|
|
LPCSTR pszGroupName)
|
2008-04-10 14:49:04 +00:00
|
|
|
|
{
|
|
|
|
|
UNIMPLEMENTED;
|
2006-01-01 10:31:35 +00:00
|
|
|
|
*pcbBytesNeeded = 0;
|
|
|
|
|
*lpServicesReturned = 0;
|
|
|
|
|
return ERROR_CALL_NOT_IMPLEMENTED;
|
|
|
|
|
}
|
2005-12-25 14:45:30 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Function 42 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD REnumServicesStatusExW(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle,
|
|
|
|
|
SC_RPC_HANDLE hSCManager,
|
|
|
|
|
SC_ENUM_TYPE InfoLevel,
|
|
|
|
|
DWORD dwServiceType,
|
|
|
|
|
DWORD dwServiceState,
|
|
|
|
|
LPBYTE lpBuffer,
|
|
|
|
|
DWORD cbBufSize,
|
|
|
|
|
LPBOUNDED_DWORD_256K pcbBytesNeeded,
|
|
|
|
|
LPBOUNDED_DWORD_256K lpServicesReturned,
|
|
|
|
|
LPBOUNDED_DWORD_256K lpResumeIndex,
|
2008-05-18 15:23:52 +00:00
|
|
|
|
LPCWSTR pszGroupName)
|
2005-12-26 15:06:46 +00:00
|
|
|
|
{
|
|
|
|
|
PMANAGER_HANDLE hManager;
|
|
|
|
|
PSERVICE lpService;
|
|
|
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
|
|
|
PLIST_ENTRY ServiceEntry;
|
|
|
|
|
PSERVICE CurrentService;
|
|
|
|
|
DWORD dwState;
|
|
|
|
|
DWORD dwRequiredSize;
|
|
|
|
|
DWORD dwServiceCount;
|
|
|
|
|
DWORD dwSize;
|
|
|
|
|
DWORD dwLastResumeCount;
|
|
|
|
|
LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr;
|
|
|
|
|
LPWSTR lpStringPtr;
|
|
|
|
|
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DPRINT("REnumServicesStatusExW() called\n");
|
2005-12-26 15:06:46 +00:00
|
|
|
|
|
|
|
|
|
if (ScmShutdown)
|
|
|
|
|
return ERROR_SHUTDOWN_IN_PROGRESS;
|
|
|
|
|
|
|
|
|
|
if (InfoLevel != SC_ENUM_PROCESS_INFO)
|
|
|
|
|
return ERROR_INVALID_LEVEL;
|
|
|
|
|
|
|
|
|
|
hManager = (PMANAGER_HANDLE)hSCManager;
|
2008-03-26 17:44:08 +00:00
|
|
|
|
if (!hManager || hManager->Handle.Tag != MANAGER_TAG)
|
2005-12-26 15:06:46 +00:00
|
|
|
|
{
|
|
|
|
|
DPRINT1("Invalid manager handle!\n");
|
|
|
|
|
return ERROR_INVALID_HANDLE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Check access rights */
|
|
|
|
|
if (!RtlAreAllAccessesGranted(hManager->Handle.DesiredAccess,
|
|
|
|
|
SC_MANAGER_ENUMERATE_SERVICE))
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Insufficient access rights! 0x%lx\n",
|
|
|
|
|
hManager->Handle.DesiredAccess);
|
|
|
|
|
return ERROR_ACCESS_DENIED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*pcbBytesNeeded = 0;
|
|
|
|
|
*lpServicesReturned = 0;
|
|
|
|
|
|
2008-04-10 14:49:04 +00:00
|
|
|
|
dwLastResumeCount = *lpResumeIndex;
|
2005-12-26 15:06:46 +00:00
|
|
|
|
|
|
|
|
|
/* Lock the service list shared */
|
|
|
|
|
|
|
|
|
|
lpService = ScmGetServiceEntryByResumeCount(dwLastResumeCount);
|
|
|
|
|
if (lpService == NULL)
|
|
|
|
|
{
|
|
|
|
|
dwError = ERROR_SUCCESS;
|
|
|
|
|
goto Done;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dwRequiredSize = 0;
|
|
|
|
|
dwServiceCount = 0;
|
|
|
|
|
|
|
|
|
|
for (ServiceEntry = &lpService->ServiceListEntry;
|
|
|
|
|
ServiceEntry != &ServiceListHead;
|
|
|
|
|
ServiceEntry = ServiceEntry->Flink)
|
|
|
|
|
{
|
|
|
|
|
CurrentService = CONTAINING_RECORD(ServiceEntry,
|
|
|
|
|
SERVICE,
|
|
|
|
|
ServiceListEntry);
|
|
|
|
|
|
|
|
|
|
if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
dwState = SERVICE_ACTIVE;
|
|
|
|
|
if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
|
|
|
|
|
dwState = SERVICE_INACTIVE;
|
|
|
|
|
|
|
|
|
|
if ((dwState & dwServiceState) == 0)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (pszGroupName)
|
|
|
|
|
{
|
2006-01-01 10:31:35 +00:00
|
|
|
|
if (*pszGroupName == 0)
|
|
|
|
|
{
|
|
|
|
|
if (CurrentService->lpGroup != NULL)
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if ((CurrentService->lpGroup == NULL) ||
|
|
|
|
|
_wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName))
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2005-12-26 15:06:46 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dwSize = sizeof(ENUM_SERVICE_STATUS_PROCESSW) +
|
|
|
|
|
((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
|
|
|
|
|
((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
|
|
|
|
|
|
2008-04-10 14:49:04 +00:00
|
|
|
|
if (dwRequiredSize + dwSize <= cbBufSize)
|
2005-12-26 15:06:46 +00:00
|
|
|
|
{
|
|
|
|
|
DPRINT("Service name: %S fit\n", CurrentService->lpServiceName);
|
|
|
|
|
dwRequiredSize += dwSize;
|
|
|
|
|
dwServiceCount++;
|
|
|
|
|
dwLastResumeCount = CurrentService->dwResumeCount;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
DPRINT("Service name: %S no fit\n", CurrentService->lpServiceName);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DPRINT("dwRequiredSize: %lu\n", dwRequiredSize);
|
|
|
|
|
DPRINT("dwServiceCount: %lu\n", dwServiceCount);
|
|
|
|
|
|
|
|
|
|
for (;
|
|
|
|
|
ServiceEntry != &ServiceListHead;
|
|
|
|
|
ServiceEntry = ServiceEntry->Flink)
|
|
|
|
|
{
|
|
|
|
|
CurrentService = CONTAINING_RECORD(ServiceEntry,
|
|
|
|
|
SERVICE,
|
|
|
|
|
ServiceListEntry);
|
|
|
|
|
|
|
|
|
|
if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
dwState = SERVICE_ACTIVE;
|
|
|
|
|
if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
|
|
|
|
|
dwState = SERVICE_INACTIVE;
|
|
|
|
|
|
|
|
|
|
if ((dwState & dwServiceState) == 0)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (pszGroupName)
|
|
|
|
|
{
|
2006-01-01 10:31:35 +00:00
|
|
|
|
if (*pszGroupName == 0)
|
|
|
|
|
{
|
|
|
|
|
if (CurrentService->lpGroup != NULL)
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if ((CurrentService->lpGroup == NULL) ||
|
|
|
|
|
_wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName))
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2005-12-26 15:06:46 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dwRequiredSize += (sizeof(ENUM_SERVICE_STATUS_PROCESSW) +
|
|
|
|
|
((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
|
|
|
|
|
((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR)));
|
|
|
|
|
|
|
|
|
|
dwError = ERROR_MORE_DATA;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize);
|
|
|
|
|
|
2008-04-10 14:49:04 +00:00
|
|
|
|
*lpResumeIndex = dwLastResumeCount;
|
2005-12-26 15:06:46 +00:00
|
|
|
|
*lpServicesReturned = dwServiceCount;
|
|
|
|
|
*pcbBytesNeeded = dwRequiredSize;
|
|
|
|
|
|
2008-04-10 14:49:04 +00:00
|
|
|
|
lpStatusPtr = (LPENUM_SERVICE_STATUS_PROCESSW)lpBuffer;
|
|
|
|
|
lpStringPtr = (LPWSTR)((ULONG_PTR)lpBuffer +
|
2005-12-26 15:06:46 +00:00
|
|
|
|
dwServiceCount * sizeof(ENUM_SERVICE_STATUS_PROCESSW));
|
|
|
|
|
|
|
|
|
|
dwRequiredSize = 0;
|
|
|
|
|
for (ServiceEntry = &lpService->ServiceListEntry;
|
|
|
|
|
ServiceEntry != &ServiceListHead;
|
|
|
|
|
ServiceEntry = ServiceEntry->Flink)
|
|
|
|
|
{
|
|
|
|
|
CurrentService = CONTAINING_RECORD(ServiceEntry,
|
|
|
|
|
SERVICE,
|
|
|
|
|
ServiceListEntry);
|
|
|
|
|
|
|
|
|
|
if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
dwState = SERVICE_ACTIVE;
|
|
|
|
|
if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
|
|
|
|
|
dwState = SERVICE_INACTIVE;
|
|
|
|
|
|
|
|
|
|
if ((dwState & dwServiceState) == 0)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (pszGroupName)
|
|
|
|
|
{
|
2006-01-01 10:31:35 +00:00
|
|
|
|
if (*pszGroupName == 0)
|
|
|
|
|
{
|
|
|
|
|
if (CurrentService->lpGroup != NULL)
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if ((CurrentService->lpGroup == NULL) ||
|
|
|
|
|
_wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName))
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2005-12-26 15:06:46 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dwSize = sizeof(ENUM_SERVICE_STATUS_PROCESSW) +
|
|
|
|
|
((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
|
|
|
|
|
((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
|
|
|
|
|
|
2008-04-10 14:49:04 +00:00
|
|
|
|
if (dwRequiredSize + dwSize <= cbBufSize)
|
2005-12-26 15:06:46 +00:00
|
|
|
|
{
|
|
|
|
|
/* Copy the service name */
|
|
|
|
|
wcscpy(lpStringPtr,
|
|
|
|
|
CurrentService->lpServiceName);
|
2008-04-10 14:49:04 +00:00
|
|
|
|
lpStatusPtr->lpServiceName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpBuffer);
|
2005-12-26 15:06:46 +00:00
|
|
|
|
lpStringPtr += (wcslen(CurrentService->lpServiceName) + 1);
|
|
|
|
|
|
|
|
|
|
/* Copy the display name */
|
|
|
|
|
wcscpy(lpStringPtr,
|
|
|
|
|
CurrentService->lpDisplayName);
|
2008-04-10 14:49:04 +00:00
|
|
|
|
lpStatusPtr->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpBuffer);
|
2005-12-26 15:06:46 +00:00
|
|
|
|
lpStringPtr += (wcslen(CurrentService->lpDisplayName) + 1);
|
|
|
|
|
|
|
|
|
|
/* Copy the status information */
|
|
|
|
|
memcpy(&lpStatusPtr->ServiceStatusProcess,
|
|
|
|
|
&CurrentService->Status,
|
|
|
|
|
sizeof(SERVICE_STATUS));
|
|
|
|
|
lpStatusPtr->ServiceStatusProcess.dwProcessId = CurrentService->ProcessId; /* FIXME */
|
|
|
|
|
lpStatusPtr->ServiceStatusProcess.dwServiceFlags = 0; /* FIXME */
|
|
|
|
|
|
|
|
|
|
lpStatusPtr++;
|
|
|
|
|
dwRequiredSize += dwSize;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Done:;
|
|
|
|
|
/* Unlock the service list */
|
|
|
|
|
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DPRINT("REnumServicesStatusExW() done (Error %lu)\n", dwError);
|
2005-12-26 15:06:46 +00:00
|
|
|
|
|
|
|
|
|
return dwError;
|
|
|
|
|
}
|
2005-12-25 14:45:30 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Function 43 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD RSendTSMessage(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle)
|
|
|
|
|
{
|
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
|
return ERROR_CALL_NOT_IMPLEMENTED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Function 44 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD RCreateServiceWOW64A(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle,
|
|
|
|
|
LPSTR lpServiceName,
|
|
|
|
|
LPSTR lpDisplayName,
|
|
|
|
|
DWORD dwDesiredAccess,
|
|
|
|
|
DWORD dwServiceType,
|
|
|
|
|
DWORD dwStartType,
|
|
|
|
|
DWORD dwErrorControl,
|
|
|
|
|
LPSTR lpBinaryPathName,
|
|
|
|
|
LPSTR lpLoadOrderGroup,
|
|
|
|
|
LPDWORD lpdwTagId,
|
|
|
|
|
LPBYTE lpDependencies,
|
|
|
|
|
DWORD dwDependSize,
|
|
|
|
|
LPSTR lpServiceStartName,
|
|
|
|
|
LPBYTE lpPassword,
|
|
|
|
|
DWORD dwPwSize,
|
|
|
|
|
LPSC_RPC_HANDLE lpServiceHandle)
|
|
|
|
|
{
|
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
|
return ERROR_CALL_NOT_IMPLEMENTED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Function 45 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD RCreateServiceWOW64W(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle,
|
|
|
|
|
LPWSTR lpServiceName,
|
|
|
|
|
LPWSTR lpDisplayName,
|
|
|
|
|
DWORD dwDesiredAccess,
|
|
|
|
|
DWORD dwServiceType,
|
|
|
|
|
DWORD dwStartType,
|
|
|
|
|
DWORD dwErrorControl,
|
|
|
|
|
LPWSTR lpBinaryPathName,
|
|
|
|
|
LPWSTR lpLoadOrderGroup,
|
|
|
|
|
LPDWORD lpdwTagId,
|
|
|
|
|
LPBYTE lpDependencies,
|
|
|
|
|
DWORD dwDependSize,
|
|
|
|
|
LPWSTR lpServiceStartName,
|
|
|
|
|
LPBYTE lpPassword,
|
|
|
|
|
DWORD dwPwSize,
|
|
|
|
|
LPSC_RPC_HANDLE lpServiceHandle)
|
|
|
|
|
{
|
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
|
return ERROR_CALL_NOT_IMPLEMENTED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Function 46 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD RQueryServiceTagInfo(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle)
|
|
|
|
|
{
|
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
|
return ERROR_CALL_NOT_IMPLEMENTED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Function 47 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD RNotifyServiceStatusChange(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle,
|
|
|
|
|
SC_RPC_HANDLE hService,
|
|
|
|
|
SC_RPC_NOTIFY_PARAMS NotifyParams,
|
|
|
|
|
GUID *pClientProcessGuid,
|
|
|
|
|
GUID *pSCMProcessGuid,
|
|
|
|
|
PBOOL pfCreateRemoteQueue,
|
|
|
|
|
LPSC_NOTIFY_RPC_HANDLE phNotify)
|
|
|
|
|
{
|
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
|
return ERROR_CALL_NOT_IMPLEMENTED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Function 48 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD RGetNotifyResults(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle,
|
|
|
|
|
SC_NOTIFY_RPC_HANDLE hNotify,
|
|
|
|
|
PSC_RPC_NOTIFY_PARAMS_LIST *ppNotifyParams)
|
|
|
|
|
{
|
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
|
return ERROR_CALL_NOT_IMPLEMENTED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Function 49 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD RCloseNotifyHandle(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle,
|
|
|
|
|
LPSC_NOTIFY_RPC_HANDLE phNotify,
|
|
|
|
|
PBOOL pfApcFired)
|
|
|
|
|
{
|
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
|
return ERROR_CALL_NOT_IMPLEMENTED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Function 50 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD RControlServiceExA(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle,
|
|
|
|
|
SC_RPC_HANDLE hService,
|
|
|
|
|
DWORD dwControl,
|
|
|
|
|
DWORD dwInfoLevel)
|
|
|
|
|
{
|
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
|
return ERROR_CALL_NOT_IMPLEMENTED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Function 51 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD RControlServiceExW(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle,
|
|
|
|
|
SC_RPC_HANDLE hService,
|
|
|
|
|
DWORD dwControl,
|
|
|
|
|
DWORD dwInfoLevel)
|
|
|
|
|
{
|
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
|
return ERROR_CALL_NOT_IMPLEMENTED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Function 52 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD RSendPnPMessage(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle)
|
|
|
|
|
{
|
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
|
return ERROR_CALL_NOT_IMPLEMENTED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Function 53 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD RValidatePnPService(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle)
|
|
|
|
|
{
|
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
|
return ERROR_CALL_NOT_IMPLEMENTED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Function 54 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD ROpenServiceStatusHandle(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle)
|
|
|
|
|
{
|
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
|
return ERROR_CALL_NOT_IMPLEMENTED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Function 55 */
|
2008-04-10 16:39:01 +00:00
|
|
|
|
DWORD RFunction55(
|
2008-04-10 14:49:04 +00:00
|
|
|
|
handle_t BindingHandle)
|
|
|
|
|
{
|
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
|
return ERROR_CALL_NOT_IMPLEMENTED;
|
|
|
|
|
}
|
2005-12-25 14:45:30 +00:00
|
|
|
|
|
|
|
|
|
|
2005-07-31 12:11:56 +00:00
|
|
|
|
void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len)
|
|
|
|
|
{
|
2005-10-22 19:46:00 +00:00
|
|
|
|
return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
|
|
|
|
|
{
|
2005-10-22 19:46:00 +00:00
|
|
|
|
HeapFree(GetProcessHeap(), 0, ptr);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
2008-04-10 14:49:04 +00:00
|
|
|
|
|
|
|
|
|
void __RPC_USER SC_RPC_HANDLE_rundown(SC_RPC_HANDLE hSCObject)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void __RPC_USER SC_RPC_LOCK_rundown(SC_RPC_LOCK Lock)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void __RPC_USER SC_NOTIFY_RPC_HANDLE_rundown(SC_NOTIFY_RPC_HANDLE hNotify)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2005-07-31 12:11:56 +00:00
|
|
|
|
/* EOF */
|