implement generic I/O async request object to replace file-specific async requests, refactor lwIP network stack to dispatch requests through IRPs with cancellation support, add cancellation polling to lwIP accept and receive operations using LwipSocketWaitRecvNetbuf and LwipSocketWaitAccept, introduce NetSubmitSocketIrp for routing socket operations via device IRPs, track network IRP statistics with SYS_NET_IRP_STATS, add process module lock spinlock and reference counting for process modules, implement dynamic module loading and unloading via user module handles, add POSIX dynamic loader APIs including dlopen, dlsym, dlerror, and dlclose, introduce PosixStart entry point for posix applications, add new native smoke tests for net IRPs.

This commit is contained in:
maksw committed 2026-06-27 10:37:53 +02:00
1 parent ed3d065abd
commit 1f5477cf66
32 files changed
+3713 -551

No files matched your search

@@ -0,0 +1,156 @@
// User-mode smoke test for public dynamic module loading.
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include <ntlite/syscall.h>
// Prints one NUL-terminated string to the kernel console.
static void print(const char* s) {
SYS_WRITE_CONSOLE_REQUEST req = { SysSvFromCstr(s) };
SysWriteConsole(&req);
}
// Prints one unsigned integer.
static void print_u64(uint64_t v) {
char buf[32];
int i = 0;
if (v == 0) {
print("0");
return;
}
while (v && i < (int)sizeof(buf)) {
buf[i++] = (char)('0' + (v % 10));
v /= 10;
}
while (i--) {
char c = buf[i];
SYS_WRITE_CONSOLE_REQUEST req = { SysSvFromParts(&c, 1) };
SysWriteConsole(&req);
}
}
// Terminates the current process.
static void exit_now(int32_t code) {
for (;;) SysExitProcess(code);
}
// Fails the test with one message.
static void fail(const char* message) {
print("module_load_smoke: ");
print(message);
print("\n");
exit_now(1);
}
// Fails the test with one status value.
static void fail_status(const char* what, uint32_t status) {
print("module_load_smoke: ");
print(what);
print(" status=");
print_u64(status);
print("\n");
exit_now(1);
}
// Checks whether one public module snapshot has the expected shape.
static void check_module_info(const SYS_MODULE_INFO* info) {
if (!info) fail("null module info");
if (info->Size != sizeof(*info)) fail("module info size mismatch");
if (info->Version != SYS_MODULE_INFO_VERSION) fail("module info version mismatch");
if (info->Base == 0 || info->ImageSize == 0) fail("module has empty mapping");
if ((info->Flags & SYS_MODULE_FLAG_PUBLIC_REF) == 0) fail("module missing public reference flag");
if (info->PublicRefCount == 0 || info->TotalRefCount == 0) fail("module reference counts missing");
if (strcmp(info->Name, "posix.dll") != 0) fail("module name mismatch");
}
// Returns whether the current module list contains the specified base address.
static int module_list_contains(uintptr_t base) {
size_t count = 0;
uint32_t status = SysGetModuleList(0, 0, &count);
if (status != STATUS_SUCCESS) fail_status("query module count", status);
if (count == 0) return 0;
if (count > 32) fail("module count unexpectedly large");
SYS_MODULE_INFO modules[32];
memset(modules, 0, sizeof(modules));
status = SysGetModuleList(modules, count, &count);
if (status != STATUS_SUCCESS) fail_status("query module list", status);
for (size_t i = 0; i < count; i++) {
if (modules[i].Base == base)
return 1;
}
return 0;
}
// Verifies export lookup through a module handle.
static void check_export_lookup(void) {
uint32_t handle = 0;
SYS_LOAD_MODULE_REQUEST req;
memset(&req, 0, sizeof(req));
req.Size = sizeof(req);
req.Path = SysSvFromCstr("syscall.dll");
req.ModuleHandleOut = &handle;
uint32_t status = SysLoadModule(&req);
if (status != STATUS_SUCCESS) fail_status("load syscall.dll", status);
if (handle == 0) fail("syscall load returned null handle");
uintptr_t address = 0;
SYS_GET_MODULE_EXPORT_REQUEST exportReq;
memset(&exportReq, 0, sizeof(exportReq));
exportReq.Size = sizeof(exportReq);
exportReq.ModuleHandle = handle;
exportReq.Name = SysSvFromCstr("SysGetCurrentPid");
exportReq.AddressOut = &address;
status = SysGetModuleExport(&exportReq);
if (status != STATUS_SUCCESS) fail_status("lookup SysGetCurrentPid", status);
if (address == 0) fail("export address is zero");
status = SysUnloadModule(handle);
if (status != STATUS_SUCCESS) fail_status("unload syscall.dll handle", status);
}
// Runs the public dynamic module loader smoke test.
int main(void) {
print("module_load_smoke: start\n");
check_export_lookup();
uint32_t handle = 0;
SYS_MODULE_INFO info;
memset(&info, 0, sizeof(info));
SYS_LOAD_MODULE_REQUEST req;
memset(&req, 0, sizeof(req));
req.Size = sizeof(req);
req.Path = SysSvFromCstr("posix.dll");
req.ModuleHandleOut = &handle;
req.InfoOut = &info;
uint32_t status = SysLoadModule(&req);
if (status != STATUS_SUCCESS) fail_status("load posix.dll", status);
if (handle == 0) fail("load returned null handle");
check_module_info(&info);
if (!module_list_contains(info.Base)) fail("loaded module absent from list");
SYS_MODULE_INFO byHandle;
memset(&byHandle, 0, sizeof(byHandle));
status = SysGetModuleInfo(handle, &byHandle);
if (status != STATUS_SUCCESS) fail_status("get module info", status);
check_module_info(&byHandle);
if (byHandle.Base != info.Base) fail("module handle base mismatch");
status = SysUnloadModule(handle);
if (status != STATUS_SUCCESS) fail_status("unload module", status);
memset(&byHandle, 0, sizeof(byHandle));
status = SysGetModuleInfo(handle, &byHandle);
if (status != STATUS_INVALID_HANDLE) fail_status("query unloaded handle", status);
print("module_load_smoke: PASS\n");
exit_now(0);
return 0;
}