Files
nt-lite/code/kernel/ke_system_service.c
T

93 lines
3.4 KiB
C

// Kernel well-known system-service registry. This file intentionally owns only numeric service discovery.
#include <kernel/ke_system_service.h>
#include <kernel/ke_port.h>
#include <kernel/ke_spinlock.h>
#include <kernel/ob_object.h>
#include <ntlite/security.h>
static SPINLOCK gSystemServiceLock = SPINLOCK_INIT;
static PORT* gSystemServices[SYS_SERVICE_MAX + 1u];
// Returns whether one numeric service identifier is valid for the current ABI.
static bool KiSystemServiceIdValid(SYS_SERVICE_ID serviceId) {
return serviceId > SYS_SERVICE_INVALID && serviceId <= SYS_SERVICE_MAX;
}
// Returns the security claim that authorizes publication of one well-known service.
SYS_SERVICE_CLAIMS KeSystemServiceRequiredClaim(SYS_SERVICE_ID serviceId) {
switch (serviceId) {
case SYS_SERVICE_RESOURCE:
return SYS_SERVICE_CLAIM_RESOURCE;
default:
return 0;
}
}
// Registers one weak listener reference without creating a string or pathname namespace.
KSTATUS KeSystemServiceRegister(SYS_SERVICE_ID serviceId, PORT* listener) {
if (!KiSystemServiceIdValid(serviceId) || !listener || !KePortIsListener(listener))
return NTLSTATUS_INVALID_PARAMETER;
uintptr_t flags = KeAcquireSpinlock(&gSystemServiceLock);
if (gSystemServices[serviceId]) {
KeReleaseSpinlock(&gSystemServiceLock, flags);
return NTLSTATUS_ALREADY_EXISTS;
}
gSystemServices[serviceId] = listener;
KeReleaseSpinlock(&gSystemServiceLock, flags);
return NTLSTATUS_SUCCESS;
}
// Removes one registration only when the caller still names the registered listener object.
KSTATUS KeSystemServiceUnregister(SYS_SERVICE_ID serviceId, PORT* listener) {
if (!KiSystemServiceIdValid(serviceId) || !listener || !KePortIsListener(listener))
return NTLSTATUS_INVALID_PARAMETER;
uintptr_t flags = KeAcquireSpinlock(&gSystemServiceLock);
if (!gSystemServices[serviceId]) {
KeReleaseSpinlock(&gSystemServiceLock, flags);
return NTLSTATUS_NOT_FOUND;
}
if (gSystemServices[serviceId] != listener) {
KeReleaseSpinlock(&gSystemServiceLock, flags);
return NTLSTATUS_ACCESS_DENIED;
}
gSystemServices[serviceId] = (PORT*)0;
KeReleaseSpinlock(&gSystemServiceLock, flags);
return NTLSTATUS_SUCCESS;
}
// References one currently registered listener for a connect operation.
KSTATUS KeSystemServiceReference(SYS_SERVICE_ID serviceId, PORT** listenerOut) {
if (!listenerOut)
return NTLSTATUS_INVALID_PARAMETER;
*listenerOut = (PORT*)0;
if (!KiSystemServiceIdValid(serviceId))
return NTLSTATUS_INVALID_PARAMETER;
uintptr_t flags = KeAcquireSpinlock(&gSystemServiceLock);
PORT* listener = gSystemServices[serviceId];
if (!listener || !ObTryReferenceObject((OBJECT*)listener)) {
KeReleaseSpinlock(&gSystemServiceLock, flags);
return NTLSTATUS_NOT_FOUND;
}
KeReleaseSpinlock(&gSystemServiceLock, flags);
*listenerOut = listener;
return NTLSTATUS_SUCCESS;
}
// Removes any weak registration whose listener is entering terminal object destruction.
void KeSystemServiceUnregisterListener(PORT* listener) {
if (!listener)
return;
uintptr_t flags = KeAcquireSpinlock(&gSystemServiceLock);
for (SYS_SERVICE_ID id = 1; id <= SYS_SERVICE_MAX; ++id) {
if (gSystemServices[id] == listener)
gSystemServices[id] = (PORT*)0;
}
KeReleaseSpinlock(&gSystemServiceLock, flags);
}