#pragma once #include #include #include #include namespace montauk::abi::UserMemory { static constexpr uint64_t USER_SPACE_END = 0x0000800000000000ULL; inline bool IsUserPtr(uint64_t addr) { return addr == 0 || addr < USER_SPACE_END; } inline bool ValidUserPtr(uint64_t addr) { return addr != 0 && addr < USER_SPACE_END; } inline uint64_t CurrentPml4() { auto* proc = Sched::GetCurrentProcessPtr(); return proc ? proc->pml4Phys : 0; } inline bool Range(uint64_t addr, uint64_t size, bool requireWrite = false) { if (size == 0) return true; if (!ValidUserPtr(addr)) return false; if (addr + size < addr) return false; if (addr + size > USER_SPACE_END) return false; uint64_t pml4Phys = CurrentPml4(); if (pml4Phys == 0) return false; return Memory::VMM::Paging::IsUserRangeAccessible(pml4Phys, addr, size, requireWrite); } inline bool OptionalRange(uint64_t addr, uint64_t size, bool requireWrite = false) { return addr == 0 || Range(addr, size, requireWrite); } template inline bool Readable(uint64_t addr) { return Range(addr, sizeof(T), false); } template inline bool Writable(uint64_t addr) { return Range(addr, sizeof(T), true); } inline bool String(uint64_t addr, uint64_t maxLen) { if (!ValidUserPtr(addr) || maxLen == 0) return false; uint64_t pml4Phys = CurrentPml4(); if (pml4Phys == 0) return false; const char* str = (const char*)addr; for (uint64_t i = 0; i < maxLen; i++) { if (!Memory::VMM::Paging::IsUserRangeAccessible(pml4Phys, addr + i, 1, false)) { return false; } if (str[i] == '\0') return true; } return false; } }