replace ad hoc driver loading with a proper driver manager, new DDK, new PnP manager with device matching, asynchronous startup, resource ownership and removal, add shared PCI capability helpers, replace typed, rigid services with a proper service manager, implement proper system shutdown and restart, shutting down unloads drivers and shuts down services, add simple power button, remove heavyweight boot self-tests and SMP stress runs, add monotonic timestamps to kernel debug output, fruitless USB and PS/2 fixes, make test builds opt in.

This commit is contained in:
maksw committed 2026-10-26 10:08:03 +01:00
1 parent c0ad63c27f
commit d36f19509c
160 files changed
+6563 -7366

No files matched your search

+43
View File
@@ -112,6 +112,37 @@ static KSTATUS RssrvConsoleWrite(RSSRV_CONSOLE_STATE* console,
return status;
}
// Writes one positioned status line, retaining the console cursor under the
// same RSSRV session lock so ordinary writers keep their cursor position.
static KSTATUS RssrvConsoleWriteAt(RSSRV_CONSOLE_STATE* console,
int32_t x, int32_t y, const char* data,
uint32_t length, uint32_t* writtenOut) {
if (writtenOut) *writtenOut = 0;
if (!console || !data || x < 0 || y < 0 || length > NTL_CONSOLE_WRITE_MAX - 8u)
return NTLSTATUS_INVALID_PARAMETER;
for (uint32_t i = 0; i < length; ++i)
if ((uint8_t)data[i] > 0x7fu || (uint8_t)data[i] < 0x20u)
return NTLSTATUS_INVALID_PARAMETER;
KSTATUS status = RssrvConsoleLock(console);
if (!KSUCCESS(status)) return status;
SYS_CONSOLE_INFO original;
memset(&original, 0, sizeof(original));
status = RssrvDisplayQueryConsoleInfo(console->Display, &original);
if (KSUCCESS(status))
status = RssrvDisplaySetConsoleCursor(console->Display, x, y);
if (KSUCCESS(status)) {
status = RssrvDisplayWriteConsole(console->Display, data, length);
if (KSUCCESS(status) && length) RssrvConsoleChangedLocked(console);
KSTATUS restore = RssrvDisplaySetConsoleCursor(console->Display,
(int32_t)original.CursorX,
(int32_t)original.CursorY);
if (KSUCCESS(status)) status = restore;
}
RssrvConsoleUnlock(console);
if (KSUCCESS(status) && writtenOut) *writtenOut = length;
return status;
}
// Queries dimensions from the backing display and snapshots RSSRV's console generation.
static KSTATUS RssrvConsoleQueryInfo(RSSRV_CONSOLE_STATE* console, NTL_CONSOLE_INFO* infoOut) {
if (!console || !infoOut) return NTLSTATUS_INVALID_PARAMETER;
@@ -297,6 +328,18 @@ static void RssrvConsoleSessionThread(uintptr_t argument) {
(void)RssrvConsoleReply(endpoint, info.MessageId, request.Operation,
status, written, 0, 0);
break;
case NTL_CONSOLE_OP_WRITE_AT:
if (request.Data.WriteAt.Length > NTL_CONSOLE_WRITE_MAX - 8u) {
status = NTLSTATUS_INVALID_PARAMETER;
} else {
status = RssrvConsoleWriteAt(console, request.Data.WriteAt.X,
request.Data.WriteAt.Y,
request.Data.WriteAt.Data,
request.Data.WriteAt.Length, &written);
}
(void)RssrvConsoleReply(endpoint, info.MessageId, request.Operation,
status, written, 0, 0);
break;
case NTL_CONSOLE_OP_QUERY_INFO:
status = RssrvConsoleQueryInfo(console, &consoleInfo);
(void)RssrvConsoleReply(endpoint, info.MessageId, request.Operation,
@@ -0,0 +1,17 @@
// Exact-path namespace publication policy. A scoped capability can bind or unbind one name.
#pragma once
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include <ntlite/resource.h>
static inline bool RssrvScopeAllows(const char* scope, uint32_t operation,
const char* path, uint32_t pathLength) {
if (!scope) return true; // Unscoped administrator; separately issued by RSSRV.
return path &&
(operation == NTL_RESOURCE_OP_BIND || operation == NTL_RESOURCE_OP_UNBIND) &&
strlen(scope) == (size_t)pathLength && memcmp(scope, path, pathLength) == 0;
}
+111
View File
@@ -2,6 +2,7 @@
#include <stdbool.h>
#include "rssrv_internal.h"
#include "publication_scope.h"
#include <stdlib.h>
#include <string.h>
@@ -9,6 +10,7 @@ typedef struct RSSRV_SESSION {
RSSRV_RESOURCE_SERVICE* Service;
SYS_HANDLE Endpoint;
bool Administrative;
const char* ScopePath;
} RSSRV_SESSION;
// Replies with one fixed resource-protocol reply and no handle transfer.
@@ -248,10 +250,16 @@ static KSTATUS RssrvHandleBind(RSSRV_RESOURCE_SERVICE* service,
return KSUCCESS(replyStatus) ? bindStatus : replyStatus;
}
// Allocates one durable, exact-path publication listener owned by RSSRV.
static KSTATUS RssrvCreatePublisher(RSSRV_RESOURCE_SERVICE* service,
const char* path, uint32_t length,
SYS_HANDLE* listenerOut);
// Dispatches one received resource request and returns whether a received handle was consumed.
static uint32_t RssrvDispatchRequest(RSSRV_RESOURCE_SERVICE* service,
SYS_HANDLE endpoint,
uint32_t administrative,
const char* scopePath,
const uint8_t* payload,
uint32_t payloadLength,
const SYS_PORT_MESSAGE_INFO* info,
@@ -281,6 +289,53 @@ static uint32_t RssrvDispatchRequest(RSSRV_RESOURCE_SERVICE* service,
return 0;
}
// A scoped listener can only publish or withdraw its exact delegated path.
if (!RssrvScopeAllows(scopePath, operation, path, request.PathLength)) {
(void)RssrvReplyStatus(endpoint, info->MessageId, operation,
NTLSTATUS_ACCESS_DENIED, NTL_RESOURCE_KIND_INVALID);
return 0;
}
if (operation == NTL_RESOURCE_OP_CREATE_PUBLISHER) {
if (!administrative || scopePath || request.Flags != NTL_RESOURCE_FLAG_NONE ||
request.AuxLength || info->HandleCount || request.Rights || request.ExportRights ||
request.Kind != NTL_RESOURCE_KIND_INVALID ||
RssrvVolumesOwnPath(path, request.PathLength) || request.PathLength > RSSRV_PUBLICATION_PATH_MAX) {
(void)RssrvReplyStatus(endpoint, info->MessageId, operation,
NTLSTATUS_ACCESS_DENIED, NTL_RESOURCE_KIND_INVALID);
return 0;
}
SYS_HANDLE publisher = SYS_HANDLE_INVALID;
status = RssrvCreatePublisher(service, path, request.PathLength, &publisher);
if (!KSUCCESS(status)) {
(void)RssrvReplyStatus(endpoint, info->MessageId, operation,
status, NTL_RESOURCE_KIND_INVALID);
return 0;
}
NTL_RESOURCE_REPLY reply = {0};
reply.Size = sizeof(reply);
reply.Version = NTL_RESOURCE_PROTOCOL_VERSION;
reply.Operation = operation;
reply.Status = NTLSTATUS_SUCCESS;
SYS_PORT_HANDLE_TRANSFER transfer = {0};
transfer.Handle = publisher;
transfer.DesiredRights = SYS_RIGHT_QUERY | SYS_RIGHT_DUPLICATE |
SYS_RIGHT_TRANSFER | SYS_PORT_RIGHT_CONNECT;
SYS_REPLY_PORT_REQUEST out = {0};
out.Size = sizeof(out);
out.EndpointHandle = endpoint;
out.MessageId = info->MessageId;
out.Payload = &reply;
out.PayloadLength = sizeof(reply);
out.Handles = &transfer;
out.HandleCount = 1u;
status = SysReplyPort(&out);
if (!KSUCCESS(status))
(void)RssrvReplyStatus(endpoint, info->MessageId, operation,
status, NTL_RESOURCE_KIND_INVALID);
return 0;
}
switch (operation) {
case NTL_RESOURCE_OP_LOOKUP:
if (request.Flags != NTL_RESOURCE_FLAG_NONE || request.AuxLength != 0 || info->HandleCount != 0 ||
@@ -408,6 +463,7 @@ static void RssrvSessionThread(uintptr_t argument) {
RSSRV_RESOURCE_SERVICE* service = session->Service;
SYS_HANDLE endpoint = session->Endpoint;
uint32_t administrative = session->Administrative;
const char* scopePath = session->ScopePath;
RssrvSetCurrentThreadName(administrative ? "rssrv.session.admin" : "rssrv.session.public");
free(session);
@@ -440,6 +496,7 @@ static void RssrvSessionThread(uintptr_t argument) {
consumed = RssrvDispatchRequest(service,
endpoint,
administrative,
scopePath,
payload,
info.PayloadLength,
&info,
@@ -449,6 +506,10 @@ static void RssrvSessionThread(uintptr_t argument) {
}
}
// A scoped publisher owns the binding for the lifetime of its connected
// session. Release it on abrupt disconnect as well as graceful unbind.
if (scopePath)
(void)RssrvNamespaceUnbind(service->Namespace, scopePath, (uint32_t)strlen(scopePath));
(void)SysCloseHandle(endpoint);
SysExitThread(0);
}
@@ -483,6 +544,7 @@ static void RssrvListenerThread(uintptr_t argument) {
session->Service = worker->Service;
session->Endpoint = endpoint;
session->Administrative = worker->Administrative;
session->ScopePath = worker->ScopePath[0] ? worker->ScopePath : NULL;
SYS_CREATE_THREAD_REQUEST create;
memset(&create, 0, sizeof(create));
@@ -532,6 +594,53 @@ static KSTATUS RssrvStartListenerWorker(RSSRV_RESOURCE_SERVICE* service,
return SysCreateThread(&create);
}
// Reuses a per-path authority across service generations and never broadens its scope.
static KSTATUS RssrvCreatePublisher(RSSRV_RESOURCE_SERVICE* service,
const char* path, uint32_t length,
SYS_HANDLE* listenerOut) {
if (!service || !path || !listenerOut || !length ||
length > RSSRV_PUBLICATION_PATH_MAX) return NTLSTATUS_INVALID_PARAMETER;
KSTATUS status = SysWait(service->ScopeMutex, SYS_WAIT_FLAG_NONE);
if (!KSUCCESS(status)) return status;
for (uint32_t i = 0; i < service->ScopeCount; ++i) {
RSSRV_LISTENER_WORKER* worker = &service->ScopeWorkers[i];
if (strlen(worker->ScopePath) == length &&
memcmp(worker->ScopePath, path, length) == 0) {
*listenerOut = worker->Listener;
(void)SysReleaseMutex(service->ScopeMutex);
return NTLSTATUS_SUCCESS;
}
}
if (service->ScopeCount >= RSSRV_PUBLICATION_SCOPE_MAX) {
(void)SysReleaseMutex(service->ScopeMutex);
return NTLSTATUS_LIMIT_REACHED;
}
RSSRV_LISTENER_WORKER* worker = &service->ScopeWorkers[service->ScopeCount];
memset(worker, 0, sizeof(*worker));
memcpy(worker->ScopePath, path, length);
worker->ScopePath[length] = '\0';
status = RssrvCreateListener(&worker->Listener);
if (KSUCCESS(status))
status = RssrvStartListenerWorker(service, worker, worker->Listener, 1u);
if (!KSUCCESS(status)) {
if (worker->Listener != SYS_HANDLE_INVALID) (void)SysCloseHandle(worker->Listener);
memset(worker, 0, sizeof(*worker));
(void)SysReleaseMutex(service->ScopeMutex);
return status;
}
++service->ScopeCount;
*listenerOut = worker->Listener;
(void)SysReleaseMutex(service->ScopeMutex);
return NTLSTATUS_SUCCESS;
}
// Issues a publisher restricted to one RSSRV-owned namespace path.
KSTATUS RssrvResourceCreatePublisher(RSSRV_RESOURCE_SERVICE* service,
const char* path, SYS_HANDLE* listenerOut) {
if (!path) return NTLSTATUS_INVALID_PARAMETER;
return RssrvCreatePublisher(service, path, (uint32_t)strlen(path), listenerOut);
}
// Initializes the public/admin resource protocol component around existing namespace state.
KSTATUS RssrvResourceInitialize(RSSRV_RESOURCE_SERVICE* service,
RSSRV_NAMESPACE* namespaceState) {
@@ -539,6 +648,8 @@ KSTATUS RssrvResourceInitialize(RSSRV_RESOURCE_SERVICE* service,
return NTLSTATUS_INVALID_PARAMETER;
memset(service, 0, sizeof(*service));
service->Namespace = namespaceState;
KSTATUS lockStatus = SysCreateMutex(&service->ScopeMutex);
if (!KSUCCESS(lockStatus)) return lockStatus;
service->PublicListener = SYS_HANDLE_INVALID;
service->AdminListener = SYS_HANDLE_INVALID;
service->PublicWorker.Listener = SYS_HANDLE_INVALID;
+47 -29
View File
@@ -2,10 +2,13 @@
#include "rssrv_internal.h"
#include <ntlite/exception.h>
#include <ntlite/desktop.h>
#include <ntlite/posix_service.h>
#include <ntlite/service.h>
#include <ntlite/service_control.h>
#include <ntlite/syscall.h>
#include <stdint.h>
#include <ntlite/bootstrap_capabilities.h>
#include <string.h>
static RSSRV_STATE gRssrv;
@@ -37,12 +40,14 @@ static KSTATUS RssrvAcceptControl(SYS_HANDLE controlListener, SYS_HANDLE* endpoi
return SysAcceptPort(&accept);
}
// Sends service readiness and delegates init-only namespace and DWM-session bootstrap capabilities.
// Exports only the capabilities consumed by dependent services. Init treats
// the names as opaque; RSSRV owns the underlying namespace policies.
static KSTATUS RssrvSendReady(SYS_HANDLE controlEndpoint,
const RSSRV_RESOURCE_SERVICE* resource,
const RSSRV_SESSION_STATE* session) {
if (!resource || !session || resource->AdminListener == SYS_HANDLE_INVALID ||
session->DwmListener == SYS_HANDLE_INVALID)
const RSSRV_SESSION_STATE* session,
SYS_HANDLE desktopPublisher,
SYS_HANDLE posixPublisher) {
if (!session || session->DwmListener == SYS_HANDLE_INVALID ||
desktopPublisher == SYS_HANDLE_INVALID || posixPublisher == SYS_HANDLE_INVALID)
return NTLSTATUS_INVALID_PARAMETER;
NTL_SERVICE_CONTROL_MESSAGE message;
@@ -50,18 +55,23 @@ static KSTATUS RssrvSendReady(SYS_HANDLE controlEndpoint,
message.Size = sizeof(message);
message.Version = NTL_SERVICE_CONTROL_VERSION;
message.Operation = NTL_SERVICE_CONTROL_READY;
message.ExportCount = 2u;
message.ExportCount = 3u;
message.Status = NTLSTATUS_SUCCESS;
if (!NtlServiceControlNameExport(&message, 0u, "session-control") ||
!NtlServiceControlNameExport(&message, 1u, "desktop-publisher") ||
!NtlServiceControlNameExport(&message, 2u, "posix-publisher"))
return NTLSTATUS_FAILURE;
SYS_PORT_HANDLE_TRANSFER transfers[2];
SYS_PORT_HANDLE_TRANSFER transfers[3];
memset(transfers, 0, sizeof(transfers));
transfers[0].Handle = resource->AdminListener;
transfers[0].DesiredRights = SYS_RIGHT_QUERY | SYS_PORT_RIGHT_CONNECT;
transfers[0].Flags = SYS_PORT_TRANSFER_FLAG_NONE;
transfers[1].Handle = session->DwmListener;
// Init must transfer this private listener once more into DWM. DWM itself receives only connect/query rights.
transfers[1].DesiredRights = SYS_RIGHT_DUPLICATE | SYS_RIGHT_TRANSFER | SYS_RIGHT_QUERY | SYS_PORT_RIGHT_CONNECT;
transfers[1].Flags = SYS_PORT_TRANSFER_FLAG_NONE;
transfers[0].Handle = session->DwmListener;
transfers[1].Handle = desktopPublisher;
transfers[2].Handle = posixPublisher;
for (uint32_t i = 0; i < 3u; ++i) {
transfers[i].DesiredRights = SYS_RIGHT_DUPLICATE | SYS_RIGHT_TRANSFER |
SYS_RIGHT_QUERY | SYS_PORT_RIGHT_CONNECT;
transfers[i].Flags = SYS_PORT_TRANSFER_FLAG_NONE;
}
SYS_SEND_PORT_REQUEST send;
memset(&send, 0, sizeof(send));
@@ -71,7 +81,7 @@ static KSTATUS RssrvSendReady(SYS_HANDLE controlEndpoint,
send.Payload = &message;
send.PayloadLength = sizeof(message);
send.Handles = transfers;
send.HandleCount = 2u;
send.HandleCount = 3u;
send.TimeoutMilliseconds = SYS_PORT_TIMEOUT_INFINITE;
return SysSendPort(&send);
}
@@ -99,8 +109,7 @@ static void RssrvControlLoop(SYS_HANDLE controlEndpoint) {
return;
if (info.Type != SYS_PORT_MESSAGE_NOTIFICATION || info.HandleCount != 0 ||
info.PayloadLength != sizeof(message) || message.Size != sizeof(message) ||
message.Version != NTL_SERVICE_CONTROL_VERSION || message.ExportCount != 0 ||
message.Reserved[0] != 0 || message.Reserved[1] != 0 || message.Reserved[2] != 0)
!NtlServiceControlValid(&message, NTL_SERVICE_CONTROL_STOP, 0u))
continue;
if (message.Operation == NTL_SERVICE_CONTROL_STOP)
return;
@@ -154,19 +163,19 @@ void _start(void) {
memset(&security, 0, sizeof(security));
security.Size = sizeof(security);
status = SysQuerySecurityContext(SYS_SECURITY_CONTEXT_CURRENT, &security);
if (!KSUCCESS(status) || security.EffectivePrivileges != SYS_PRIV_SYSTEM_SERVICE_REGISTER ||
security.DelegablePrivileges != 0 || security.ServiceClaims != SYS_SERVICE_CLAIM_RESOURCE ||
security.DelegableServiceClaims != 0)
if (!KSUCCESS(status) || security.EffectivePrivileges != 0 ||
security.DelegablePrivileges != 0)
RssrvExit(2);
SYS_HANDLE systemVolume = SysGetStartupCapability(SYS_STARTUP_CAP_SYSTEM_VOLUME_NAMESPACE);
SYS_HANDLE controlListener = SysGetStartupCapability(SYS_STARTUP_CAP_SERVICE_CONTROL);
SYS_HANDLE volumeManager = SysGetStartupCapability(SYS_STARTUP_CAP_VOLUME_MANAGER);
SYS_HANDLE inputManager = SysGetStartupCapability(SYS_STARTUP_CAP_INPUT_MANAGER);
SYS_HANDLE displayManager = SysGetStartupCapability(SYS_STARTUP_CAP_DISPLAY_MANAGER);
SYS_HANDLE systemVolume = SysGetStartupCapability(NTL_BOOT_CAP_NAMESPACE_ROOT);
SYS_HANDLE controlListener = SysGetStartupCapability("service.control");
SYS_HANDLE volumeManager = SysGetStartupCapability(NTL_BOOT_CAP_VOLUME_MANAGER);
SYS_HANDLE inputManager = SysGetStartupCapability(NTL_BOOT_CAP_INPUT_MANAGER);
SYS_HANDLE displayManager = SysGetStartupCapability(NTL_BOOT_CAP_DISPLAY_POLICY);
SYS_HANDLE registrationAuthority = SysGetStartupCapability(NTL_BOOT_CAP_RESOURCE_REGISTRATION);
if (systemVolume == SYS_HANDLE_INVALID || controlListener == SYS_HANDLE_INVALID ||
volumeManager == SYS_HANDLE_INVALID || inputManager == SYS_HANDLE_INVALID ||
displayManager == SYS_HANDLE_INVALID)
displayManager == SYS_HANDLE_INVALID || registrationAuthority == SYS_HANDLE_INVALID)
RssrvExit(3);
uint32_t systemVolumeId = 0;
@@ -232,13 +241,22 @@ void _start(void) {
status = RssrvVolumesStartWorker(&gRssrv.Volumes);
if (!KSUCCESS(status)) RssrvExit(11);
status = SysRegisterSystemService(SYS_SERVICE_RESOURCE, gRssrv.Resource.PublicListener);
status = SysRegisterSystemService(registrationAuthority, gRssrv.Resource.PublicListener);
if (!KSUCCESS(status)) RssrvExit(12);
status = RssrvSendReady(controlEndpoint, &gRssrv.Resource, &gRssrv.Session);
SYS_HANDLE desktopPublisher = SYS_HANDLE_INVALID;
SYS_HANDLE posixPublisher = SYS_HANDLE_INVALID;
status = RssrvResourceCreatePublisher(&gRssrv.Resource, NTL_DESKTOP_SERVICE_PATH,
&desktopPublisher);
if (!KSUCCESS(status)) RssrvExit(13);
status = RssrvResourceCreatePublisher(&gRssrv.Resource, NTL_POSIX_SERVICE_PATH,
&posixPublisher);
if (!KSUCCESS(status)) RssrvExit(13);
status = RssrvSendReady(controlEndpoint, &gRssrv.Session,
desktopPublisher, posixPublisher);
if (!KSUCCESS(status)) RssrvExit(13);
RssrvControlLoop(controlEndpoint);
(void)SysUnregisterSystemService(SYS_SERVICE_RESOURCE, gRssrv.Resource.PublicListener);
(void)SysUnregisterSystemService(registrationAuthority, gRssrv.Resource.PublicListener);
(void)SysDisconnectPort(controlEndpoint);
(void)SysCloseHandle(controlEndpoint);
RssrvExit(0);
+8
View File
@@ -10,6 +10,8 @@
#include <stdbool.h>
#define RSSRV_LISTENER_BACKLOG 16u
#define RSSRV_PUBLICATION_SCOPE_MAX 32u
#define RSSRV_PUBLICATION_PATH_MAX 127u
#define RSSRV_SYMBOLIC_LINK_MAX_DEPTH 16u
#define RSSRV_VOLUME_PATH_CAPACITY 48u
#define RSSRV_INPUT_KEY_QUEUE_SIZE 256u
@@ -137,6 +139,7 @@ typedef struct RSSRV_LISTENER_WORKER {
RSSRV_RESOURCE_SERVICE* Service;
SYS_HANDLE Listener;
bool Administrative;
char ScopePath[RSSRV_PUBLICATION_PATH_MAX + 1u];
} RSSRV_LISTENER_WORKER;
struct RSSRV_RESOURCE_SERVICE {
@@ -145,6 +148,9 @@ struct RSSRV_RESOURCE_SERVICE {
SYS_HANDLE AdminListener;
RSSRV_LISTENER_WORKER PublicWorker;
RSSRV_LISTENER_WORKER AdminWorker;
SYS_HANDLE ScopeMutex;
uint32_t ScopeCount;
RSSRV_LISTENER_WORKER ScopeWorkers[RSSRV_PUBLICATION_SCOPE_MAX];
};
typedef struct RSSRV_STATE {
@@ -305,3 +311,5 @@ KSTATUS RssrvResourceInitialize(RSSRV_RESOURCE_SERVICE* service,
// Creates the resource listeners and starts their accept workers.
KSTATUS RssrvResourceStart(RSSRV_RESOURCE_SERVICE* service);
KSTATUS RssrvResourceCreatePublisher(RSSRV_RESOURCE_SERVICE* service,
const char* path, SYS_HANDLE* listenerOut);