📄 rpcserver.c
字号:
/*
*/
/* 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
{
DWORD Tag;
DWORD RefCount;
DWORD DesiredAccess;
} SCMGR_HANDLE;
typedef struct _MANAGER_HANDLE
{
SCMGR_HANDLE Handle;
/* FIXME: Insert more data here */
WCHAR DatabaseName[1];
} MANAGER_HANDLE, *PMANAGER_HANDLE;
typedef struct _SERVICE_HANDLE
{
SCMGR_HANDLE Handle;
DWORD DesiredAccess;
PSERVICE ServiceEntry;
/* FIXME: Insert more data here */
} 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)
{
RPC_STATUS Status;
DPRINT("ScmStartRpcServer() called");
Status = RpcServerUseProtseqEpW(L"ncacn_np",
10,
L"\\pipe\\ntsvcs",
NULL);
if (Status != RPC_S_OK)
{
DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status);
return;
}
Status = RpcServerRegisterIf(svcctl_ServerIfHandle,
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;
}
DPRINT("ScmStartRpcServer() done");
}
static DWORD
ScmCreateManagerHandle(LPWSTR lpDatabaseName,
SC_HANDLE *Handle)
{
PMANAGER_HANDLE Ptr;
if (lpDatabaseName == NULL)
lpDatabaseName = SERVICES_ACTIVE_DATABASEW;
Ptr = (MANAGER_HANDLE*) HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
sizeof(MANAGER_HANDLE) + wcslen(lpDatabaseName) * sizeof(WCHAR));
if (Ptr == NULL)
return ERROR_NOT_ENOUGH_MEMORY;
Ptr->Handle.Tag = MANAGER_TAG;
Ptr->Handle.RefCount = 1;
/* FIXME: initialize more data here */
wcscpy(Ptr->DatabaseName, lpDatabaseName);
*Handle = (SC_HANDLE)Ptr;
return ERROR_SUCCESS;
}
static DWORD
ScmCreateServiceHandle(PSERVICE lpServiceEntry,
SC_HANDLE *Handle)
{
PSERVICE_HANDLE Ptr;
Ptr = (SERVICE_HANDLE*) HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
sizeof(SERVICE_HANDLE));
if (Ptr == NULL)
return ERROR_NOT_ENOUGH_MEMORY;
Ptr->Handle.Tag = SERVICE_TAG;
Ptr->Handle.RefCount = 1;
/* FIXME: initialize more data here */
Ptr->ServiceEntry = lpServiceEntry;
*Handle = (SC_HANDLE)Ptr;
return ERROR_SUCCESS;
}
static DWORD
ScmCheckAccess(SC_HANDLE Handle,
DWORD dwDesiredAccess)
{
PMANAGER_HANDLE hMgr;
hMgr = (PMANAGER_HANDLE)Handle;
if (hMgr->Handle.Tag == MANAGER_TAG)
{
RtlMapGenericMask(&dwDesiredAccess,
&ScmManagerMapping);
hMgr->Handle.DesiredAccess = dwDesiredAccess;
return ERROR_SUCCESS;
}
else if (hMgr->Handle.Tag == SERVICE_TAG)
{
RtlMapGenericMask(&dwDesiredAccess,
&ScmServiceMapping);
hMgr->Handle.DesiredAccess = dwDesiredAccess;
return ERROR_SUCCESS;
}
return ERROR_INVALID_HANDLE;
}
DWORD
ScmAssignNewTag(PSERVICE lpService)
{
/* FIXME */
DPRINT("Assigning new tag to service %S\n", lpService->lpServiceName);
lpService->dwTag = 0;
return ERROR_SUCCESS;
}
/* Function 0 */
unsigned long
ScmrCloseServiceHandle(handle_t BindingHandle,
unsigned int hScObject)
{
PMANAGER_HANDLE hManager;
DPRINT("ScmrCloseServiceHandle() called\n");
DPRINT("hScObject = %X\n", hScObject);
if (hScObject == 0)
return ERROR_INVALID_HANDLE;
hManager = (PMANAGER_HANDLE)hScObject;
if (hManager->Handle.Tag == MANAGER_TAG)
{
DPRINT("Found manager handle\n");
hManager->Handle.RefCount--;
if (hManager->Handle.RefCount == 0)
{
/* FIXME: add cleanup code */
HeapFree(GetProcessHeap(), 0, hManager);
}
DPRINT("ScmrCloseServiceHandle() done\n");
return ERROR_SUCCESS;
}
else if (hManager->Handle.Tag == SERVICE_TAG)
{
DPRINT("Found service handle\n");
hManager->Handle.RefCount--;
if (hManager->Handle.RefCount == 0)
{
/* FIXME: add cleanup code */
HeapFree(GetProcessHeap(), 0, hManager);
}
DPRINT("ScmrCloseServiceHandle() done\n");
return ERROR_SUCCESS;
}
DPRINT1("Invalid handle tag (Tag %lx)\n", hManager->Handle.Tag);
return ERROR_INVALID_HANDLE;
}
/* Function 1 */
unsigned long
ScmrControlService(handle_t BindingHandle,
unsigned int hService,
unsigned long dwControl,
LPSERVICE_STATUS lpServiceStatus)
{
PSERVICE_HANDLE hSvc;
PSERVICE lpService;
ACCESS_MASK DesiredAccess;
DWORD dwError = ERROR_SUCCESS;
DPRINT("ScmrControlService() called\n");
if (ScmShutdown)
return ERROR_SHUTDOWN_IN_PROGRESS;
/* Check the service handle */
hSvc = (PSERVICE_HANDLE)hService;
if (hSvc->Handle.Tag != SERVICE_TAG)
{
DPRINT1("Invalid handle tag!\n");
return ERROR_INVALID_HANDLE;
}
/* 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;
}
if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
DesiredAccess))
return ERROR_ACCESS_DENIED;
/* Check the service entry point */
lpService = hSvc->ServiceEntry;
if (lpService == NULL)
{
DPRINT1("lpService == NULL!\n");
return ERROR_INVALID_HANDLE;
}
if (lpService->Status.dwServiceType & SERVICE_DRIVER)
{
/* Send control code to the driver */
dwError = ScmControlDriver(lpService,
dwControl,
lpServiceStatus);
}
else
{
/* Send control code to the service */
dwError = ScmControlService(lpService,
dwControl,
lpServiceStatus);
}
/* Return service status information */
RtlCopyMemory(lpServiceStatus,
&lpService->Status,
sizeof(SERVICE_STATUS));
return dwError;
}
/* Function 2 */
unsigned long
ScmrDeleteService(handle_t BindingHandle,
unsigned int hService)
{
PSERVICE_HANDLE hSvc;
PSERVICE lpService;
DWORD dwError;
DPRINT("ScmrDeleteService() called\n");
if (ScmShutdown)
return ERROR_SHUTDOWN_IN_PROGRESS;
hSvc = (PSERVICE_HANDLE)hService;
if (hSvc->Handle.Tag != SERVICE_TAG)
return ERROR_INVALID_HANDLE;
if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
STANDARD_RIGHTS_REQUIRED))
return ERROR_ACCESS_DENIED;
lpService = hSvc->ServiceEntry;
if (lpService == NULL)
{
DPRINT1("lpService == NULL!\n");
return ERROR_INVALID_HANDLE;
}
/* FIXME: Acquire service database lock exclusively */
if (lpService->bDeleted)
{
DPRINT1("The service has already been marked for delete!\n");
return ERROR_SERVICE_MARKED_FOR_DELETE;
}
/* Mark service for delete */
lpService->bDeleted = TRUE;
dwError = ScmMarkServiceForDelete(lpService);
/* FIXME: Release service database lock */
DPRINT("ScmrDeleteService() done\n");
return dwError;
}
/* Function 3 */
unsigned long
ScmrLockServiceDatabase(handle_t BindingHandle,
unsigned int hSCManager,
unsigned int *hLock)
{
PMANAGER_HANDLE hMgr;
DPRINT("ScmrLockServiceDatabase() called\n");
*hLock = 0;
hMgr = (PMANAGER_HANDLE)hSCManager;
if (hMgr->Handle.Tag != MANAGER_TAG)
return ERROR_INVALID_HANDLE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -