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:
1 parent
c0ad63c27f
commit
d36f19509c
160 files changed
+6563
-7366
No files matched your search
@@ -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;
|
||||
|
||||
Reference in new issue
Block a user