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

+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;