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
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
Reference in new issue
Block a user