// Native resource namespace service. RSSRV owns global names and transfers capabilities; it is not a file data path. #include #include #include #include #include #include #include #include #include #define RSSRV_LISTENER_BACKLOG 16u // One namespace binding. Path storage follows the fixed header in the same allocation. typedef struct RSSRV_ENTRY { struct RSSRV_ENTRY* Next; SYS_HANDLE Handle; uint32_t Kind; SYS_RIGHTS ExportRights; uint32_t PathLength; char Path[1]; } RSSRV_ENTRY; typedef struct RSSRV_SESSION { SYS_HANDLE Endpoint; uint32_t Administrative; } RSSRV_SESSION; typedef struct RSSRV_LISTENER_WORKER { SYS_HANDLE Listener; uint32_t Administrative; } RSSRV_LISTENER_WORKER; typedef struct RSSRV_VOLUME_PUBLICATION { struct RSSRV_VOLUME_PUBLICATION* Next; uint32_t InstanceId; uint32_t NamespaceId; uint32_t PathLength; char Path[48]; } RSSRV_VOLUME_PUBLICATION; static SYS_HANDLE gNamespaceMutex = SYS_HANDLE_INVALID; static RSSRV_ENTRY* gNamespace = (RSSRV_ENTRY*)0; static SYS_HANDLE gPublicListener = SYS_HANDLE_INVALID; static SYS_HANDLE gAdminListener = SYS_HANDLE_INVALID; static RSSRV_LISTENER_WORKER gPublicWorker; static RSSRV_LISTENER_WORKER gAdminWorker; static RSSRV_VOLUME_PUBLICATION* gPublishedVolumes = (RSSRV_VOLUME_PUBLICATION*)0; static uint32_t gNextHarddiskVolumeId = 1u; // Exits without depending on a compiler runtime return path. static void RssrvExit(int code) { for (;;) SysExitProcess(code); } // Acquires the namespace mutex. static KSTATUS RssrvLockNamespace(void) { return SysWait(gNamespaceMutex, SYS_WAIT_FLAG_NONE); } // Releases the namespace mutex. static void RssrvUnlockNamespace(void) { (void)SysReleaseMutex(gNamespaceMutex); } // Validates one canonical absolute native resource path. static KSTATUS RssrvValidatePath(const char* path, uint32_t length) { if (!path || length < 2 || length > NTL_RESOURCE_PATH_MAX || path[0] != '/' || path[length - 1] == '/') return NTLSTATUS_INVALID_PARAMETER; uint32_t componentStart = 1; for (uint32_t i = 1; i <= length; ++i) { if (i < length) { char c = path[i]; if (c == '\\' || c == '\0') return NTLSTATUS_INVALID_PARAMETER; if (c != '/') continue; } uint32_t componentLength = i - componentStart; if (componentLength == 0 || (componentLength == 1 && path[componentStart] == '.') || (componentLength == 2 && path[componentStart] == '.' && path[componentStart + 1] == '.')) return NTLSTATUS_INVALID_PARAMETER; componentStart = i + 1; } return NTLSTATUS_SUCCESS; } // Returns whether a path belongs to the RSSRV-owned automatic mounted-volume naming family. static int RssrvIsManagedVolumePath(const char* path, uint32_t length) { static const char prefix[] = "/Device/HarddiskVolume"; uint32_t prefixLength = (uint32_t)(sizeof(prefix) - 1u); return path && length >= prefixLength && memcmp(path, prefix, prefixLength) == 0; } // Finds one exact binding while the namespace mutex is held. static RSSRV_ENTRY* RssrvFindLocked(const char* path, uint32_t length, RSSRV_ENTRY*** linkOut) { RSSRV_ENTRY** link = &gNamespace; while (*link) { RSSRV_ENTRY* entry = *link; if (entry->PathLength == length && memcmp(entry->Path, path, length) == 0) { if (linkOut) *linkOut = link; return entry; } link = &entry->Next; } if (linkOut) *linkOut = link; return (RSSRV_ENTRY*)0; } // Finds the longest namespace binding that is an exact component prefix of path. static RSSRV_ENTRY* RssrvFindPrefixLocked(const char* path, uint32_t length) { RSSRV_ENTRY* best = (RSSRV_ENTRY*)0; for (RSSRV_ENTRY* entry = gNamespace; entry; entry = entry->Next) { if (entry->PathLength > length) continue; if (memcmp(entry->Path, path, entry->PathLength) != 0) continue; if (entry->PathLength != length && path[entry->PathLength] != '/') continue; if (!best || entry->PathLength > best->PathLength) best = entry; } return best; } // Takes ownership of one handle and binds it to a new exact resource name. static KSTATUS RssrvBindOwned(const char* path, uint32_t length, uint32_t kind, SYS_HANDLE handle, SYS_RIGHTS exportRights) { if (kind == NTL_RESOURCE_KIND_INVALID || handle == SYS_HANDLE_INVALID || !exportRights) return NTLSTATUS_INVALID_PARAMETER; KSTATUS status = RssrvValidatePath(path, length); if (!KSUCCESS(status)) return status; size_t bytes = offsetof(RSSRV_ENTRY, Path) + (size_t)length + 1u; RSSRV_ENTRY* entry = (RSSRV_ENTRY*)malloc(bytes); if (!entry) return NTLSTATUS_NO_MEMORY; memset(entry, 0, bytes); entry->Handle = handle; entry->Kind = kind; entry->ExportRights = exportRights; entry->PathLength = length; memcpy(entry->Path, path, length); entry->Path[length] = '\0'; status = RssrvLockNamespace(); if (!KSUCCESS(status)) { free(entry); return status; } if (RssrvFindLocked(path, length, (RSSRV_ENTRY***)0)) { RssrvUnlockNamespace(); free(entry); return NTLSTATUS_OBJECT_NAME_COLLISION; } entry->Next = gNamespace; gNamespace = entry; RssrvUnlockNamespace(); return NTLSTATUS_SUCCESS; } // Removes one binding and closes the namespace's retained handle. static KSTATUS RssrvUnbind(const char* path, uint32_t length) { KSTATUS status = RssrvValidatePath(path, length); if (!KSUCCESS(status)) return status; status = RssrvLockNamespace(); if (!KSUCCESS(status)) return status; RSSRV_ENTRY** link = (RSSRV_ENTRY**)0; RSSRV_ENTRY* entry = RssrvFindLocked(path, length, &link); if (!entry) { RssrvUnlockNamespace(); return NTLSTATUS_NOT_FOUND; } *link = entry->Next; RssrvUnlockNamespace(); (void)SysCloseHandle(entry->Handle); free(entry); return NTLSTATUS_SUCCESS; } // Finds one published mounted volume by kernel instance identity. static RSSRV_VOLUME_PUBLICATION* RssrvFindPublishedVolume(uint32_t instanceId) { for (RSSRV_VOLUME_PUBLICATION* publication = gPublishedVolumes; publication; publication = publication->Next) { if (publication->InstanceId == instanceId) return publication; } return (RSSRV_VOLUME_PUBLICATION*)0; } // Returns whether one kernel volume instance is present in the current manager snapshot. static int RssrvSnapshotContainsVolume(const SYS_VOLUME_INFO* volumes, uint32_t count, uint32_t instanceId) { for (uint32_t i = 0; i < count; ++i) { if (volumes[i].InstanceId == instanceId) return 1; } return 0; } // Builds one RSSRV-local /Device/HarddiskVolumeN name without introducing a formatting-runtime dependency. static KSTATUS RssrvBuildHarddiskVolumePath(uint32_t namespaceId, char* path, uint32_t capacity, uint32_t* lengthOut) { static const char prefix[] = "/Device/HarddiskVolume"; if (!namespaceId || !path || !lengthOut) return NTLSTATUS_INVALID_PARAMETER; uint32_t prefixLength = (uint32_t)(sizeof(prefix) - 1u); char digits[10]; uint32_t digitCount = 0; uint32_t value = namespaceId; do { digits[digitCount++] = (char)('0' + (value % 10u)); value /= 10u; } while (value && digitCount < (uint32_t)sizeof(digits)); if (prefixLength + digitCount + 1u > capacity) return NTLSTATUS_BUFFER_TOO_SMALL; memcpy(path, prefix, prefixLength); for (uint32_t i = 0; i < digitCount; ++i) path[prefixLength + i] = digits[digitCount - 1u - i]; path[prefixLength + digitCount] = '\0'; *lengthOut = prefixLength + digitCount; return NTLSTATUS_SUCCESS; } // Takes a stable manager snapshot, growing the userspace buffer if the mounted-volume count changes. static KSTATUS RssrvQueryVolumes(SYS_HANDLE manager, SYS_VOLUME_INFO** volumesOut, uint32_t* countOut, uint64_t* generationOut) { if (!volumesOut || !countOut || !generationOut) return NTLSTATUS_INVALID_PARAMETER; *volumesOut = (SYS_VOLUME_INFO*)0; *countOut = 0; *generationOut = 0; SYS_VOLUME_INFO* volumes = (SYS_VOLUME_INFO*)0; uint32_t capacity = 0; for (;;) { uint32_t count = 0; uint64_t generation = 0; SYS_QUERY_VOLUMES_REQUEST query; memset(&query, 0, sizeof(query)); query.Size = sizeof(query); query.ManagerHandle = manager; query.Flags = SYS_VOLUME_QUERY_FLAG_NONE; query.Capacity = capacity; query.Volumes = volumes; query.CountOut = &count; query.GenerationOut = &generation; KSTATUS status = SysQueryVolumes(&query); if (status == NTLSTATUS_BUFFER_TOO_SMALL) { if (volumes) free(volumes); volumes = (SYS_VOLUME_INFO*)0; capacity = count; if (capacity) { volumes = (SYS_VOLUME_INFO*)malloc((size_t)capacity * sizeof(*volumes)); if (!volumes) return NTLSTATUS_NO_MEMORY; memset(volumes, 0, (size_t)capacity * sizeof(*volumes)); } continue; } if (!KSUCCESS(status)) { if (volumes) free(volumes); return status; } for (uint32_t i = 0; i < count; ++i) { if (volumes[i].Size != sizeof(SYS_VOLUME_INFO) || volumes[i].Version != SYS_VOLUME_ENUM_VERSION || !volumes[i].InstanceId || volumes[i].Flags != 0) { if (volumes) free(volumes); return NTLSTATUS_INVALID_PARAMETER; } } *volumesOut = volumes; *countOut = count; *generationOut = generation; return NTLSTATUS_SUCCESS; } } // Reconciles the RSSRV object namespace with the kernel's mounted-volume snapshot. static KSTATUS RssrvSyncVolumes(SYS_HANDLE manager, uint64_t* generationOut) { if (!generationOut) return NTLSTATUS_INVALID_PARAMETER; SYS_VOLUME_INFO* volumes = (SYS_VOLUME_INFO*)0; uint32_t count = 0; uint64_t generation = 0; KSTATUS status = RssrvQueryVolumes(manager, &volumes, &count, &generation); if (!KSUCCESS(status)) return status; RSSRV_VOLUME_PUBLICATION** link = &gPublishedVolumes; while (*link) { RSSRV_VOLUME_PUBLICATION* publication = *link; if (RssrvSnapshotContainsVolume(volumes, count, publication->InstanceId)) { link = &publication->Next; continue; } status = RssrvUnbind(publication->Path, publication->PathLength); if (!KSUCCESS(status) && status != NTLSTATUS_NOT_FOUND) { free(volumes); return status; } *link = publication->Next; free(publication); } for (uint32_t i = 0; i < count; ++i) { if (RssrvFindPublishedVolume(volumes[i].InstanceId)) continue; SYS_HANDLE volume = SYS_HANDLE_INVALID; status = SysOpenVolume(manager, volumes[i].InstanceId, SYS_RIGHT_QUERY | SYS_RIGHT_TRANSFER | SYS_VOLUME_RIGHT_OPEN | SYS_VOLUME_RIGHT_MODIFY, &volume); if (status == NTLSTATUS_NOT_FOUND || status == NTLSTATUS_OBJECT_DEAD) continue; if (!KSUCCESS(status)) { free(volumes); return status; } RSSRV_VOLUME_PUBLICATION* publication = (RSSRV_VOLUME_PUBLICATION*)malloc(sizeof(*publication)); if (!publication) { (void)SysCloseHandle(volume); free(volumes); return NTLSTATUS_NO_MEMORY; } memset(publication, 0, sizeof(*publication)); publication->InstanceId = volumes[i].InstanceId; publication->NamespaceId = gNextHarddiskVolumeId; status = RssrvBuildHarddiskVolumePath(publication->NamespaceId, publication->Path, (uint32_t)sizeof(publication->Path), &publication->PathLength); if (!KSUCCESS(status)) { free(publication); (void)SysCloseHandle(volume); free(volumes); return status; } status = RssrvBindOwned(publication->Path, publication->PathLength, NTL_RESOURCE_KIND_VOLUME, volume, SYS_RIGHT_QUERY | SYS_VOLUME_RIGHT_OPEN | SYS_VOLUME_RIGHT_MODIFY); if (!KSUCCESS(status)) { free(publication); (void)SysCloseHandle(volume); free(volumes); return status; } publication->Next = gPublishedVolumes; gPublishedVolumes = publication; gNextHarddiskVolumeId++; if (!gNextHarddiskVolumeId) { free(volumes); return NTLSTATUS_LIMIT_REACHED; } } if (volumes) free(volumes); *generationOut = generation; return NTLSTATUS_SUCCESS; } // Keeps automatic /Device/HarddiskVolumeN bindings synchronized with mounted IO_VOLUME instances. static void RssrvVolumeWorker(uintptr_t argument) { SYS_HANDLE manager = (SYS_HANDLE)argument; for (;;) { uint64_t generation = 0; KSTATUS status = RssrvSyncVolumes(manager, &generation); if (!KSUCCESS(status)) RssrvExit(12); status = SysWaitVolumeChange(manager, generation, SYS_WAIT_TIMEOUT_INFINITE); if (!KSUCCESS(status)) RssrvExit(12); } } // Starts the mounted-volume namespace publication worker. static KSTATUS RssrvStartVolumeWorker(SYS_HANDLE manager) { uint32_t threadId = 0; SYS_CREATE_THREAD_REQUEST create; memset(&create, 0, sizeof(create)); create.Size = sizeof(create); create.Entry = (uintptr_t)RssrvVolumeWorker; create.Argument = (uintptr_t)manager; create.Priority = 1; create.Flags = SYS_CREATE_THREAD_FLAG_NONE; create.ThreadIdOut = &threadId; return SysCreateThread(&create); } // Replies with one fixed resource-protocol reply and no handle transfer. static KSTATUS RssrvReplyStatus(SYS_HANDLE endpoint, uint32_t messageId, uint32_t operation, KSTATUS status, uint32_t kind) { NTL_RESOURCE_REPLY reply; memset(&reply, 0, sizeof(reply)); reply.Size = sizeof(reply); reply.Version = NTL_RESOURCE_PROTOCOL_VERSION; reply.Operation = operation; reply.Flags = NTL_RESOURCE_FLAG_NONE; reply.Status = status; reply.Kind = kind; SYS_REPLY_PORT_REQUEST request; memset(&request, 0, sizeof(request)); request.Size = sizeof(request); request.EndpointHandle = endpoint; request.MessageId = messageId; request.Flags = SYS_PORT_FLAG_NONE; request.Payload = &reply; request.PayloadLength = sizeof(reply); return SysReplyPort(&request); } // Handles one lookup while retaining the namespace mutex through capability transfer. static KSTATUS RssrvHandleLookup(SYS_HANDLE endpoint, uint32_t messageId, const NTL_RESOURCE_REQUEST* request, const char* path) { if (!request->Rights) return RssrvReplyStatus(endpoint, messageId, request->Operation, NTLSTATUS_INVALID_PARAMETER, NTL_RESOURCE_KIND_INVALID); KSTATUS status = RssrvLockNamespace(); if (!KSUCCESS(status)) return RssrvReplyStatus(endpoint, messageId, request->Operation, status, NTL_RESOURCE_KIND_INVALID); RSSRV_ENTRY* entry = RssrvFindLocked(path, request->PathLength, (RSSRV_ENTRY***)0); if (!entry) { RssrvUnlockNamespace(); return RssrvReplyStatus(endpoint, messageId, request->Operation, NTLSTATUS_NOT_FOUND, NTL_RESOURCE_KIND_INVALID); } uint32_t kind = entry->Kind; NTL_RESOURCE_REPLY reply; memset(&reply, 0, sizeof(reply)); reply.Size = sizeof(reply); reply.Version = NTL_RESOURCE_PROTOCOL_VERSION; reply.Operation = NTL_RESOURCE_OP_LOOKUP; reply.Status = NTLSTATUS_SUCCESS; reply.Kind = kind; SYS_PORT_HANDLE_TRANSFER transfer; transfer.Handle = entry->Handle; if ((request->Rights & ~entry->ExportRights) != 0) { RssrvUnlockNamespace(); return RssrvReplyStatus(endpoint, messageId, request->Operation, NTLSTATUS_ACCESS_DENIED, kind); } transfer.DesiredRights = request->Rights; transfer.Flags = SYS_PORT_TRANSFER_FLAG_NONE; SYS_REPLY_PORT_REQUEST out; memset(&out, 0, sizeof(out)); out.Size = sizeof(out); out.EndpointHandle = endpoint; out.MessageId = messageId; out.Flags = SYS_PORT_FLAG_NONE; out.Payload = &reply; out.PayloadLength = sizeof(reply); out.Handles = &transfer; out.HandleCount = 1; status = SysReplyPort(&out); RssrvUnlockNamespace(); // A rights mismatch leaves the synchronous call pending, so return the precise error without a handle. if (!KSUCCESS(status)) return RssrvReplyStatus(endpoint, messageId, request->Operation, status, kind); return NTLSTATUS_SUCCESS; } // Resolves the longest bound resource prefix and transfers traversal authority. static KSTATUS RssrvHandleResolve(SYS_HANDLE endpoint, uint32_t messageId, const NTL_RESOURCE_REQUEST* request, const char* path) { if ((request->Flags & ~NTL_RESOURCE_RESOLVE_FLAG_MODIFY) != 0) return RssrvReplyStatus(endpoint, messageId, request->Operation, NTLSTATUS_INVALID_PARAMETER, NTL_RESOURCE_KIND_INVALID); KSTATUS status = RssrvLockNamespace(); if (!KSUCCESS(status)) return RssrvReplyStatus(endpoint, messageId, request->Operation, status, NTL_RESOURCE_KIND_INVALID); RSSRV_ENTRY* entry = RssrvFindPrefixLocked(path, request->PathLength); if (!entry) { RssrvUnlockNamespace(); return RssrvReplyStatus(endpoint, messageId, request->Operation, NTLSTATUS_NOT_FOUND, NTL_RESOURCE_KIND_INVALID); } SYS_RIGHTS desiredRights = 0; if (entry->Kind == NTL_RESOURCE_KIND_VOLUME) { desiredRights = SYS_VOLUME_RIGHT_OPEN; if (request->Flags & NTL_RESOURCE_RESOLVE_FLAG_MODIFY) desiredRights |= SYS_VOLUME_RIGHT_MODIFY; } else if (entry->Kind == NTL_RESOURCE_KIND_DIRECTORY) { desiredRights = SYS_DIR_RIGHT_OPEN; if (request->Flags & NTL_RESOURCE_RESOLVE_FLAG_MODIFY) desiredRights |= SYS_DIR_RIGHT_MODIFY; } else { uint32_t kind = entry->Kind; RssrvUnlockNamespace(); return RssrvReplyStatus(endpoint, messageId, request->Operation, NTLSTATUS_NOT_SUPPORTED, kind); } if ((desiredRights & ~entry->ExportRights) != 0) { uint32_t kind = entry->Kind; RssrvUnlockNamespace(); return RssrvReplyStatus(endpoint, messageId, request->Operation, NTLSTATUS_ACCESS_DENIED, kind); } uint32_t kind = entry->Kind; NTL_RESOURCE_REPLY reply; memset(&reply, 0, sizeof(reply)); reply.Size = sizeof(reply); reply.Version = NTL_RESOURCE_PROTOCOL_VERSION; reply.Operation = NTL_RESOURCE_OP_RESOLVE; reply.Flags = request->Flags; reply.Status = NTLSTATUS_SUCCESS; reply.Kind = kind; reply.ResolvedLength = entry->PathLength; SYS_PORT_HANDLE_TRANSFER transfer; transfer.Handle = entry->Handle; transfer.DesiredRights = desiredRights; transfer.Flags = SYS_PORT_TRANSFER_FLAG_NONE; SYS_REPLY_PORT_REQUEST out; memset(&out, 0, sizeof(out)); out.Size = sizeof(out); out.EndpointHandle = endpoint; out.MessageId = messageId; out.Flags = SYS_PORT_FLAG_NONE; out.Payload = &reply; out.PayloadLength = sizeof(reply); out.Handles = &transfer; out.HandleCount = 1; status = SysReplyPort(&out); RssrvUnlockNamespace(); if (!KSUCCESS(status)) return RssrvReplyStatus(endpoint, messageId, request->Operation, status, kind); return NTLSTATUS_SUCCESS; } // Handles one metadata query. static KSTATUS RssrvHandleQuery(SYS_HANDLE endpoint, uint32_t messageId, const NTL_RESOURCE_REQUEST* request, const char* path) { KSTATUS status = RssrvLockNamespace(); if (!KSUCCESS(status)) return RssrvReplyStatus(endpoint, messageId, request->Operation, status, NTL_RESOURCE_KIND_INVALID); RSSRV_ENTRY* entry = RssrvFindLocked(path, request->PathLength, (RSSRV_ENTRY***)0); uint32_t found = entry != (RSSRV_ENTRY*)0; uint32_t kind = found ? entry->Kind : NTL_RESOURCE_KIND_INVALID; RssrvUnlockNamespace(); return RssrvReplyStatus(endpoint, messageId, request->Operation, found ? NTLSTATUS_SUCCESS : NTLSTATUS_NOT_FOUND, kind); } // Handles one administrative bind. On success the namespace takes ownership of receivedHandle. static KSTATUS RssrvHandleBind(SYS_HANDLE endpoint, uint32_t messageId, const NTL_RESOURCE_REQUEST* request, const char* path, uint32_t administrative, SYS_HANDLE receivedHandle, uint32_t* consumedOut) { if (!consumedOut) return NTLSTATUS_INVALID_PARAMETER; *consumedOut = 0; if (!administrative || RssrvIsManagedVolumePath(path, request->PathLength)) return RssrvReplyStatus(endpoint, messageId, request->Operation, NTLSTATUS_ACCESS_DENIED, NTL_RESOURCE_KIND_INVALID); KSTATUS bindStatus = RssrvBindOwned(path, request->PathLength, request->Kind, receivedHandle, request->ExportRights); if (KSUCCESS(bindStatus)) *consumedOut = 1; KSTATUS replyStatus = RssrvReplyStatus(endpoint, messageId, request->Operation, bindStatus, KSUCCESS(bindStatus) ? request->Kind : NTL_RESOURCE_KIND_INVALID); return KSUCCESS(replyStatus) ? bindStatus : replyStatus; } // Dispatches one received resource request and returns whether a received handle was consumed. static uint32_t RssrvDispatchRequest(SYS_HANDLE endpoint, uint32_t administrative, const uint8_t* payload, uint32_t payloadLength, const SYS_PORT_MESSAGE_INFO* info, SYS_HANDLE receivedHandle) { uint32_t operation = 0; if (payloadLength < sizeof(NTL_RESOURCE_REQUEST)) { (void)RssrvReplyStatus(endpoint, info->MessageId, operation, NTLSTATUS_INVALID_PARAMETER, NTL_RESOURCE_KIND_INVALID); return 0; } NTL_RESOURCE_REQUEST request; memcpy(&request, payload, sizeof(request)); operation = request.Operation; if (request.Size != sizeof(request) || request.Version != NTL_RESOURCE_PROTOCOL_VERSION || request.PathLength == 0 || payloadLength != sizeof(request) + request.PathLength) { (void)RssrvReplyStatus(endpoint, info->MessageId, operation, NTLSTATUS_INVALID_PARAMETER, NTL_RESOURCE_KIND_INVALID); return 0; } const char* path = (const char*)(payload + sizeof(request)); KSTATUS status = RssrvValidatePath(path, request.PathLength); 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 || info->HandleCount != 0 || request.ExportRights != 0 || request.Kind != NTL_RESOURCE_KIND_INVALID) { (void)RssrvReplyStatus(endpoint, info->MessageId, operation, NTLSTATUS_INVALID_PARAMETER, NTL_RESOURCE_KIND_INVALID); return 0; } (void)RssrvHandleLookup(endpoint, info->MessageId, &request, path); return 0; case NTL_RESOURCE_OP_QUERY: if (request.Flags != NTL_RESOURCE_FLAG_NONE || info->HandleCount != 0 || request.Rights != 0 || request.ExportRights != 0 || request.Kind != NTL_RESOURCE_KIND_INVALID) { (void)RssrvReplyStatus(endpoint, info->MessageId, operation, NTLSTATUS_INVALID_PARAMETER, NTL_RESOURCE_KIND_INVALID); return 0; } (void)RssrvHandleQuery(endpoint, info->MessageId, &request, path); return 0; case NTL_RESOURCE_OP_RESOLVE: if (info->HandleCount != 0 || request.Rights != 0 || request.ExportRights != 0 || request.Kind != NTL_RESOURCE_KIND_INVALID || (request.Flags & ~NTL_RESOURCE_RESOLVE_FLAG_MODIFY) != 0) { (void)RssrvReplyStatus(endpoint, info->MessageId, operation, NTLSTATUS_INVALID_PARAMETER, NTL_RESOURCE_KIND_INVALID); return 0; } (void)RssrvHandleResolve(endpoint, info->MessageId, &request, path); return 0; case NTL_RESOURCE_OP_BIND: if (request.Flags != NTL_RESOURCE_FLAG_NONE || info->HandleCount != 1 || !(request.Rights & SYS_RIGHT_TRANSFER) || request.ExportRights == 0 || (request.ExportRights & ~request.Rights) != 0 || request.Kind == NTL_RESOURCE_KIND_INVALID || receivedHandle == SYS_HANDLE_INVALID) { (void)RssrvReplyStatus(endpoint, info->MessageId, operation, NTLSTATUS_INVALID_PARAMETER, NTL_RESOURCE_KIND_INVALID); return 0; } { uint32_t consumed = 0; (void)RssrvHandleBind(endpoint, info->MessageId, &request, path, administrative, receivedHandle, &consumed); return consumed; } case NTL_RESOURCE_OP_UNBIND: if (request.Flags != NTL_RESOURCE_FLAG_NONE || info->HandleCount != 0 || request.Rights != 0 || request.ExportRights != 0 || request.Kind != NTL_RESOURCE_KIND_INVALID) { (void)RssrvReplyStatus(endpoint, info->MessageId, operation, NTLSTATUS_INVALID_PARAMETER, NTL_RESOURCE_KIND_INVALID); return 0; } status = administrative && !RssrvIsManagedVolumePath(path, request.PathLength) ? RssrvUnbind(path, request.PathLength) : NTLSTATUS_ACCESS_DENIED; (void)RssrvReplyStatus(endpoint, info->MessageId, operation, status, NTL_RESOURCE_KIND_INVALID); return 0; default: (void)RssrvReplyStatus(endpoint, info->MessageId, operation, NTLSTATUS_NOT_SUPPORTED, NTL_RESOURCE_KIND_INVALID); return 0; } } // Serves one connected resource session until the peer disconnects. static void RssrvSessionThread(uintptr_t argument) { RSSRV_SESSION* session = (RSSRV_SESSION*)argument; if (!session) { SysExitThread(1); return; } SYS_HANDLE endpoint = session->Endpoint; uint32_t administrative = session->Administrative; free(session); uint8_t payload[SYS_PORT_MAX_INLINE_BYTES]; SYS_HANDLE handles[SYS_PORT_MAX_TRANSFER_HANDLES]; for (;;) { memset(handles, 0, sizeof(handles)); SYS_PORT_MESSAGE_INFO info; memset(&info, 0, sizeof(info)); info.Size = sizeof(info); SYS_RECEIVE_PORT_REQUEST receive; memset(&receive, 0, sizeof(receive)); receive.Size = sizeof(receive); receive.EndpointHandle = endpoint; receive.Flags = SYS_PORT_FLAG_NONE; receive.Payload = payload; receive.PayloadCapacity = sizeof(payload); receive.HandlesOut = handles; receive.HandleCapacity = SYS_PORT_MAX_TRANSFER_HANDLES; receive.InfoOut = &info; receive.TimeoutMilliseconds = SYS_PORT_TIMEOUT_INFINITE; KSTATUS status = SysReceivePort(&receive); if (status == NTLSTATUS_PORT_DISCONNECTED) break; if (!KSUCCESS(status)) break; uint32_t consumed = 0; if (info.Type == SYS_PORT_MESSAGE_REQUEST) consumed = RssrvDispatchRequest(endpoint, administrative, payload, info.PayloadLength, &info, info.HandleCount == 1 ? handles[0] : SYS_HANDLE_INVALID); for (uint32_t i = consumed ? 1u : 0u; i < info.HandleCount; ++i) { if (handles[i] != SYS_HANDLE_INVALID) (void)SysCloseHandle(handles[i]); } } (void)SysCloseHandle(endpoint); SysExitThread(0); } // Accepts sessions from one listener and gives every connection its own worker thread. static void RssrvListenerThread(uintptr_t argument) { RSSRV_LISTENER_WORKER* worker = (RSSRV_LISTENER_WORKER*)argument; if (!worker) { SysExitThread(1); return; } for (;;) { SYS_HANDLE endpoint = SYS_HANDLE_INVALID; SYS_ACCEPT_PORT_REQUEST accept; memset(&accept, 0, sizeof(accept)); accept.Size = sizeof(accept); accept.ListenerHandle = worker->Listener; accept.Flags = SYS_PORT_ACCEPT_FLAG_NONE; accept.TimeoutMilliseconds = SYS_PORT_TIMEOUT_INFINITE; accept.EndpointHandleOut = &endpoint; KSTATUS status = SysAcceptPort(&accept); if (!KSUCCESS(status)) break; RSSRV_SESSION* session = (RSSRV_SESSION*)malloc(sizeof(*session)); if (!session) { (void)SysDisconnectPort(endpoint); (void)SysCloseHandle(endpoint); continue; } session->Endpoint = endpoint; session->Administrative = worker->Administrative; uint32_t threadId = 0; SYS_CREATE_THREAD_REQUEST create; memset(&create, 0, sizeof(create)); create.Size = sizeof(create); create.Entry = (uintptr_t)RssrvSessionThread; create.Argument = (uintptr_t)session; create.Priority = 1; create.Flags = SYS_CREATE_THREAD_FLAG_NONE; create.ThreadIdOut = &threadId; status = SysCreateThread(&create); if (!KSUCCESS(status)) { free(session); (void)SysDisconnectPort(endpoint); (void)SysCloseHandle(endpoint); } } SysExitThread(0); } // Starts one resource listener worker thread. static KSTATUS RssrvStartListenerWorker(RSSRV_LISTENER_WORKER* worker, SYS_HANDLE listener, uint32_t administrative) { worker->Listener = listener; worker->Administrative = administrative; uint32_t threadId = 0; SYS_CREATE_THREAD_REQUEST create; memset(&create, 0, sizeof(create)); create.Size = sizeof(create); create.Entry = (uintptr_t)RssrvListenerThread; create.Argument = (uintptr_t)worker; create.Priority = 1; create.Flags = SYS_CREATE_THREAD_FLAG_NONE; create.ThreadIdOut = &threadId; return SysCreateThread(&create); } // Creates one listener using the service's bounded default backlog. static KSTATUS RssrvCreateListener(SYS_HANDLE* listenerOut) { SYS_CREATE_PORT_REQUEST create; memset(&create, 0, sizeof(create)); create.Size = sizeof(create); create.Flags = SYS_PORT_FLAG_NONE; create.Backlog = RSSRV_LISTENER_BACKLOG; create.HandleOut = listenerOut; return SysCreatePort(&create); } // Accepts the one private service-manager control connection. static KSTATUS RssrvAcceptControl(SYS_HANDLE controlListener, SYS_HANDLE* endpointOut) { SYS_ACCEPT_PORT_REQUEST accept; memset(&accept, 0, sizeof(accept)); accept.Size = sizeof(accept); accept.ListenerHandle = controlListener; accept.Flags = SYS_PORT_ACCEPT_FLAG_NONE; accept.TimeoutMilliseconds = SYS_PORT_TIMEOUT_INFINITE; accept.EndpointHandleOut = endpointOut; return SysAcceptPort(&accept); } // Sends service readiness and delegates the private administrative resource listener to init. static KSTATUS RssrvSendReady(SYS_HANDLE controlEndpoint) { NTL_SERVICE_CONTROL_MESSAGE message; memset(&message, 0, sizeof(message)); message.Size = sizeof(message); message.Version = NTL_SERVICE_CONTROL_VERSION; message.Operation = NTL_SERVICE_CONTROL_READY; message.Flags = NTL_SERVICE_READY_FLAG_RESOURCE_ADMIN_LISTENER; message.Status = NTLSTATUS_SUCCESS; SYS_PORT_HANDLE_TRANSFER transfer; transfer.Handle = gAdminListener; transfer.DesiredRights = SYS_RIGHT_QUERY | SYS_PORT_RIGHT_CONNECT; transfer.Flags = SYS_PORT_TRANSFER_FLAG_NONE; SYS_SEND_PORT_REQUEST send; memset(&send, 0, sizeof(send)); send.Size = sizeof(send); send.EndpointHandle = controlEndpoint; send.Flags = SYS_PORT_FLAG_NONE; send.Payload = &message; send.PayloadLength = sizeof(message); send.Handles = &transfer; send.HandleCount = 1; send.TimeoutMilliseconds = SYS_PORT_TIMEOUT_INFINITE; return SysSendPort(&send); } // Waits for the service manager's stop notification or control-port disconnect. static void RssrvControlLoop(SYS_HANDLE controlEndpoint) { for (;;) { NTL_SERVICE_CONTROL_MESSAGE message; SYS_PORT_MESSAGE_INFO info; memset(&message, 0, sizeof(message)); memset(&info, 0, sizeof(info)); info.Size = sizeof(info); SYS_RECEIVE_PORT_REQUEST receive; memset(&receive, 0, sizeof(receive)); receive.Size = sizeof(receive); receive.EndpointHandle = controlEndpoint; receive.Payload = &message; receive.PayloadCapacity = sizeof(message); receive.InfoOut = &info; receive.TimeoutMilliseconds = SYS_PORT_TIMEOUT_INFINITE; KSTATUS status = SysReceivePort(&receive); if (status == NTLSTATUS_PORT_DISCONNECTED) return; if (!KSUCCESS(status)) 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) continue; if (message.Operation == NTL_SERVICE_CONTROL_STOP) return; } } // Starts RSSRV and owns the global native resource namespace until init requests shutdown. void _start(void) { KSTATUS status = NtlInitializeExceptionRuntime(); if (!KSUCCESS(status)) RssrvExit(1); SYS_SECURITY_CONTEXT_INFO security; 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) 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); if (systemVolume == SYS_HANDLE_INVALID || controlListener == SYS_HANDLE_INVALID || volumeManager == SYS_HANDLE_INVALID) RssrvExit(3); status = SysCreateMutex(&gNamespaceMutex); if (!KSUCCESS(status)) RssrvExit(3); // RSSRV takes ownership of its startup system-volume handle as the first namespace binding. static const char systemRoot[] = "/SystemRoot"; status = RssrvBindOwned(systemRoot, sizeof(systemRoot) - 1, NTL_RESOURCE_KIND_VOLUME, systemVolume, SYS_RIGHT_QUERY | SYS_VOLUME_RIGHT_OPEN | SYS_VOLUME_RIGHT_MODIFY); if (!KSUCCESS(status)) RssrvExit(4); SYS_HANDLE controlEndpoint = SYS_HANDLE_INVALID; status = RssrvAcceptControl(controlListener, &controlEndpoint); (void)SysCloseHandle(controlListener); if (!KSUCCESS(status)) RssrvExit(5); status = RssrvCreateListener(&gPublicListener); if (!KSUCCESS(status)) RssrvExit(6); status = RssrvCreateListener(&gAdminListener); if (!KSUCCESS(status)) RssrvExit(7); status = RssrvStartListenerWorker(&gPublicWorker, gPublicListener, 0); if (!KSUCCESS(status)) RssrvExit(8); status = RssrvStartListenerWorker(&gAdminWorker, gAdminListener, 1); if (!KSUCCESS(status)) RssrvExit(9); uint64_t volumeGeneration = 0; status = RssrvSyncVolumes(volumeManager, &volumeGeneration); if (!KSUCCESS(status)) RssrvExit(10); status = RssrvStartVolumeWorker(volumeManager); if (!KSUCCESS(status)) RssrvExit(11); status = SysRegisterSystemService(SYS_SERVICE_RESOURCE, gPublicListener); if (!KSUCCESS(status)) RssrvExit(12); status = RssrvSendReady(controlEndpoint); if (!KSUCCESS(status)) RssrvExit(13); RssrvControlLoop(controlEndpoint); (void)SysUnregisterSystemService(SYS_SERVICE_RESOURCE, gPublicListener); (void)SysDisconnectPort(controlEndpoint); (void)SysCloseHandle(controlEndpoint); RssrvExit(0); }