mirror of
https://github.com/decompals/wibo.git
synced 2025-10-15 14:45:12 +00:00
Some Atom function impls
This commit is contained in:
parent
ffdfa38591
commit
cf7ea70fac
@ -198,6 +198,18 @@ void *resolveByName(const char *name) {
|
||||
return (void *)kernel32::CreatePipe;
|
||||
|
||||
// winbase.h
|
||||
if (strcmp(name, "FindAtomA") == 0)
|
||||
return (void *)kernel32::FindAtomA;
|
||||
if (strcmp(name, "FindAtomW") == 0)
|
||||
return (void *)kernel32::FindAtomW;
|
||||
if (strcmp(name, "AddAtomA") == 0)
|
||||
return (void *)kernel32::AddAtomA;
|
||||
if (strcmp(name, "AddAtomW") == 0)
|
||||
return (void *)kernel32::AddAtomW;
|
||||
if (strcmp(name, "GetAtomNameA") == 0)
|
||||
return (void *)kernel32::GetAtomNameA;
|
||||
if (strcmp(name, "GetAtomNameW") == 0)
|
||||
return (void *)kernel32::GetAtomNameW;
|
||||
if (strcmp(name, "GlobalAlloc") == 0)
|
||||
return (void *)kernel32::GlobalAlloc;
|
||||
if (strcmp(name, "GlobalReAlloc") == 0)
|
||||
|
@ -15,7 +15,9 @@
|
||||
#include <filesystem>
|
||||
#include <limits>
|
||||
#include <mimalloc.h>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/statvfs.h>
|
||||
#include <system_error>
|
||||
@ -29,6 +31,141 @@ constexpr UINT GMEM_MODIFY = 0x0080;
|
||||
constexpr UINT LMEM_MOVEABLE = 0x0002;
|
||||
constexpr UINT LMEM_ZEROINIT = 0x0040;
|
||||
|
||||
constexpr ATOM kMinIntegerAtom = 0x0001;
|
||||
constexpr ATOM kMaxIntegerAtom = 0xBFFF;
|
||||
constexpr ATOM kMinStringAtom = 0xC000;
|
||||
constexpr ATOM kMaxStringAtom = 0xFFFF;
|
||||
|
||||
struct AtomData {
|
||||
uint16_t refCount = 0;
|
||||
std::string original;
|
||||
};
|
||||
|
||||
struct AtomTable {
|
||||
std::mutex mutex;
|
||||
std::unordered_map<std::string, ATOM> stringToAtom;
|
||||
std::unordered_map<ATOM, AtomData> atomToData;
|
||||
ATOM nextStringAtom = kMinStringAtom;
|
||||
};
|
||||
|
||||
AtomTable &localAtomTable() {
|
||||
static AtomTable table;
|
||||
return table;
|
||||
}
|
||||
|
||||
ATOM allocateStringAtomLocked(AtomTable &table) {
|
||||
constexpr unsigned int kRange = static_cast<unsigned int>(kMaxStringAtom - kMinStringAtom + 1);
|
||||
unsigned int startOffset = 0;
|
||||
if (table.nextStringAtom >= kMinStringAtom && table.nextStringAtom <= kMaxStringAtom) {
|
||||
startOffset = static_cast<unsigned int>(table.nextStringAtom - kMinStringAtom);
|
||||
}
|
||||
for (unsigned int i = 0; i < kRange; ++i) {
|
||||
unsigned int offset = (startOffset + i) % kRange;
|
||||
ATOM candidate = static_cast<ATOM>(kMinStringAtom + offset);
|
||||
if (table.atomToData.find(candidate) == table.atomToData.end()) {
|
||||
table.nextStringAtom = static_cast<ATOM>(candidate + 1);
|
||||
if (table.nextStringAtom > kMaxStringAtom) {
|
||||
table.nextStringAtom = kMinStringAtom;
|
||||
}
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool tryHandleIntegerAtomPointer(const void *ptr, ATOM &atomOut) {
|
||||
uintptr_t value = reinterpret_cast<uintptr_t>(ptr);
|
||||
if ((value >> 16) != 0) {
|
||||
return false;
|
||||
}
|
||||
ATOM maybeAtom = static_cast<ATOM>(value & 0xFFFFu);
|
||||
if (maybeAtom < kMinIntegerAtom || maybeAtom > kMaxIntegerAtom) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
atomOut = 0;
|
||||
return true;
|
||||
}
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
atomOut = maybeAtom;
|
||||
return true;
|
||||
}
|
||||
|
||||
ATOM findAtomByNormalizedKey(const std::string &normalizedKey) {
|
||||
auto &table = localAtomTable();
|
||||
std::lock_guard lk(table.mutex);
|
||||
auto it = table.stringToAtom.find(normalizedKey);
|
||||
if (it == table.stringToAtom.end()) {
|
||||
wibo::lastError = ERROR_FILE_NOT_FOUND;
|
||||
return 0;
|
||||
}
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return it->second;
|
||||
}
|
||||
|
||||
ATOM tryParseIntegerAtomString(const std::string &value, bool &handled) {
|
||||
handled = false;
|
||||
if (value.empty() || value[0] != '#') {
|
||||
return 0;
|
||||
}
|
||||
char *end = nullptr;
|
||||
unsigned long parsed = std::strtoul(value.c_str() + 1, &end, 10);
|
||||
if (end == value.c_str() + 1 || *end != '\0') {
|
||||
return 0;
|
||||
}
|
||||
handled = true;
|
||||
if (parsed < kMinIntegerAtom || parsed > kMaxIntegerAtom) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return 0;
|
||||
}
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return static_cast<ATOM>(parsed);
|
||||
}
|
||||
|
||||
ATOM findAtomByString(const std::string &value) {
|
||||
bool handledInteger = false;
|
||||
ATOM atom = tryParseIntegerAtomString(value, handledInteger);
|
||||
if (handledInteger) {
|
||||
return atom;
|
||||
}
|
||||
std::string normalized = stringToLower(value);
|
||||
return findAtomByNormalizedKey(normalized);
|
||||
}
|
||||
|
||||
ATOM addAtomByString(const std::string &value) {
|
||||
bool handledInteger = false;
|
||||
ATOM atom = tryParseIntegerAtomString(value, handledInteger);
|
||||
if (handledInteger) {
|
||||
return atom;
|
||||
}
|
||||
if (value.empty() || value.size() > 255) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return 0;
|
||||
}
|
||||
std::string normalized = stringToLower(value);
|
||||
auto &table = localAtomTable();
|
||||
std::lock_guard lk(table.mutex);
|
||||
auto existing = table.stringToAtom.find(normalized);
|
||||
if (existing != table.stringToAtom.end()) {
|
||||
auto dataIt = table.atomToData.find(existing->second);
|
||||
if (dataIt != table.atomToData.end() && dataIt->second.refCount < std::numeric_limits<uint16_t>::max()) {
|
||||
dataIt->second.refCount++;
|
||||
}
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return existing->second;
|
||||
}
|
||||
ATOM newAtom = allocateStringAtomLocked(table);
|
||||
if (newAtom == 0) {
|
||||
wibo::lastError = ERROR_NOT_ENOUGH_MEMORY;
|
||||
return 0;
|
||||
}
|
||||
AtomData data;
|
||||
data.refCount = 1;
|
||||
data.original = value;
|
||||
table.stringToAtom.emplace(std::move(normalized), newAtom);
|
||||
table.atomToData.emplace(newAtom, std::move(data));
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return newAtom;
|
||||
}
|
||||
|
||||
void *doAlloc(UINT dwBytes, bool zero) {
|
||||
if (dwBytes == 0) {
|
||||
dwBytes = 1;
|
||||
@ -165,6 +302,166 @@ const uint16_t kComputerNameWide[] = {u'C', u'O', u'M', u'P', u'N', u'A', u'M',
|
||||
|
||||
namespace kernel32 {
|
||||
|
||||
ATOM WIN_FUNC AddAtomA(LPCSTR lpString) {
|
||||
ATOM atom = 0;
|
||||
if (tryHandleIntegerAtomPointer(lpString, atom)) {
|
||||
DEBUG_LOG("AddAtomA(int:%u)\n", atom);
|
||||
return atom;
|
||||
}
|
||||
DEBUG_LOG("AddAtomA(%s)\n", lpString ? lpString : "<null>");
|
||||
if (!lpString) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return 0;
|
||||
}
|
||||
size_t len = strnlen(lpString, 256);
|
||||
if (len == 0 || len >= 256) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return 0;
|
||||
}
|
||||
std::string value(lpString, len);
|
||||
ATOM result = addAtomByString(value);
|
||||
DEBUG_LOG("AddAtomA -> %u (lastError=%u)\n", result, wibo::lastError);
|
||||
return result;
|
||||
}
|
||||
|
||||
ATOM WIN_FUNC AddAtomW(LPCWSTR lpString) {
|
||||
ATOM atom = 0;
|
||||
if (tryHandleIntegerAtomPointer(lpString, atom)) {
|
||||
DEBUG_LOG("AddAtomW(int:%u)\n", atom);
|
||||
return atom;
|
||||
}
|
||||
if (!lpString) {
|
||||
DEBUG_LOG("AddAtomW(<null>)\n");
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return 0;
|
||||
}
|
||||
size_t len = wstrnlen(reinterpret_cast<const uint16_t *>(lpString), 256);
|
||||
if (len == 0 || len >= 256) {
|
||||
DEBUG_LOG("AddAtomW(invalid length)\n");
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return 0;
|
||||
}
|
||||
std::string value = wideStringToString(reinterpret_cast<const uint16_t *>(lpString), static_cast<int>(len));
|
||||
DEBUG_LOG("AddAtomW(%s)\n", value.c_str());
|
||||
ATOM result = addAtomByString(value);
|
||||
DEBUG_LOG("AddAtomW -> %u (lastError=%u)\n", result, wibo::lastError);
|
||||
return result;
|
||||
}
|
||||
|
||||
ATOM WIN_FUNC FindAtomA(LPCSTR lpString) {
|
||||
ATOM atom = 0;
|
||||
if (tryHandleIntegerAtomPointer(lpString, atom)) {
|
||||
DEBUG_LOG("FindAtomA(int:%u)\n", atom);
|
||||
return atom;
|
||||
}
|
||||
DEBUG_LOG("FindAtomA(%s)\n", lpString ? lpString : "<null>");
|
||||
if (!lpString) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return 0;
|
||||
}
|
||||
size_t len = strnlen(lpString, 256);
|
||||
if (len == 0 || len >= 256) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return 0;
|
||||
}
|
||||
std::string value(lpString, len);
|
||||
ATOM result = findAtomByString(value);
|
||||
DEBUG_LOG("FindAtomA -> %u (lastError=%u)\n", result, wibo::lastError);
|
||||
return result;
|
||||
}
|
||||
|
||||
ATOM WIN_FUNC FindAtomW(LPCWSTR lpString) {
|
||||
ATOM atom = 0;
|
||||
if (tryHandleIntegerAtomPointer(lpString, atom)) {
|
||||
DEBUG_LOG("FindAtomW(int:%u)\n", atom);
|
||||
return atom;
|
||||
}
|
||||
if (!lpString) {
|
||||
DEBUG_LOG("FindAtomW(<null>)\n");
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return 0;
|
||||
}
|
||||
size_t len = wstrnlen(reinterpret_cast<const uint16_t *>(lpString), 256);
|
||||
if (len == 0 || len >= 256) {
|
||||
DEBUG_LOG("FindAtomW(invalid length)\n");
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return 0;
|
||||
}
|
||||
std::string value = wideStringToString(reinterpret_cast<const uint16_t *>(lpString), static_cast<int>(len));
|
||||
DEBUG_LOG("FindAtomW(%s)\n", value.c_str());
|
||||
ATOM result = findAtomByString(value);
|
||||
DEBUG_LOG("FindAtomW -> %u (lastError=%u)\n", result, wibo::lastError);
|
||||
return result;
|
||||
}
|
||||
|
||||
UINT WIN_FUNC GetAtomNameA(ATOM nAtom, LPSTR lpBuffer, int nSize) {
|
||||
DEBUG_LOG("GetAtomNameA(%u, %p, %d)\n", nAtom, lpBuffer, nSize);
|
||||
if (!lpBuffer || nSize <= 0) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return 0;
|
||||
}
|
||||
std::string value;
|
||||
if (nAtom >= kMinIntegerAtom && nAtom <= kMaxIntegerAtom) {
|
||||
value = '#';
|
||||
value += std::to_string(nAtom);
|
||||
} else {
|
||||
auto &table = localAtomTable();
|
||||
std::lock_guard lk(table.mutex);
|
||||
auto it = table.atomToData.find(nAtom);
|
||||
if (it == table.atomToData.end()) {
|
||||
wibo::lastError = ERROR_INVALID_HANDLE;
|
||||
return 0;
|
||||
}
|
||||
value = it->second.original;
|
||||
}
|
||||
if (value.size() + 1 > static_cast<size_t>(nSize)) {
|
||||
wibo::lastError = ERROR_INSUFFICIENT_BUFFER;
|
||||
return 0;
|
||||
}
|
||||
std::memcpy(lpBuffer, value.c_str(), value.size());
|
||||
lpBuffer[value.size()] = '\0';
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
UINT written = static_cast<UINT>(value.size());
|
||||
DEBUG_LOG("GetAtomNameA -> %u (lastError=%u)\n", written, wibo::lastError);
|
||||
return written;
|
||||
}
|
||||
|
||||
UINT WIN_FUNC GetAtomNameW(ATOM nAtom, LPWSTR lpBuffer, int nSize) {
|
||||
DEBUG_LOG("GetAtomNameW(%u, %p, %d)\n", nAtom, lpBuffer, nSize);
|
||||
if (!lpBuffer || nSize <= 0) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return 0;
|
||||
}
|
||||
std::string narrow;
|
||||
if (nAtom >= kMinIntegerAtom && nAtom <= kMaxIntegerAtom) {
|
||||
narrow = '#';
|
||||
narrow += std::to_string(nAtom);
|
||||
} else {
|
||||
auto &table = localAtomTable();
|
||||
std::lock_guard lk(table.mutex);
|
||||
auto it = table.atomToData.find(nAtom);
|
||||
if (it == table.atomToData.end()) {
|
||||
wibo::lastError = ERROR_INVALID_HANDLE;
|
||||
return 0;
|
||||
}
|
||||
narrow = it->second.original;
|
||||
}
|
||||
auto wide = stringToWideString(narrow.c_str(), narrow.size());
|
||||
size_t needed = wide.size();
|
||||
if (needed > static_cast<size_t>(nSize)) {
|
||||
wibo::lastError = ERROR_INSUFFICIENT_BUFFER;
|
||||
return 0;
|
||||
}
|
||||
std::memcpy(lpBuffer, wide.data(), needed * sizeof(uint16_t));
|
||||
if (needed > 0) {
|
||||
lpBuffer[needed - 1] = 0;
|
||||
}
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
UINT written = static_cast<UINT>(needed ? needed - 1 : 0);
|
||||
DEBUG_LOG("GetAtomNameW -> %u (lastError=%u)\n", written, wibo::lastError);
|
||||
return written;
|
||||
}
|
||||
|
||||
UINT WIN_FUNC SetHandleCount(UINT uNumber) {
|
||||
DEBUG_LOG("SetHandleCount(%u)\n", uNumber);
|
||||
(void)uNumber;
|
||||
|
@ -8,6 +8,12 @@ namespace kernel32 {
|
||||
|
||||
BOOL WIN_FUNC IsBadReadPtr(LPCVOID lp, UINT_PTR ucb);
|
||||
BOOL WIN_FUNC IsBadWritePtr(LPVOID lp, UINT_PTR ucb);
|
||||
ATOM WIN_FUNC FindAtomA(LPCSTR lpString);
|
||||
ATOM WIN_FUNC FindAtomW(LPCWSTR lpString);
|
||||
ATOM WIN_FUNC AddAtomA(LPCSTR lpString);
|
||||
ATOM WIN_FUNC AddAtomW(LPCWSTR lpString);
|
||||
UINT WIN_FUNC GetAtomNameA(ATOM nAtom, LPSTR lpBuffer, int nSize);
|
||||
UINT WIN_FUNC GetAtomNameW(ATOM nAtom, LPWSTR lpBuffer, int nSize);
|
||||
UINT WIN_FUNC SetHandleCount(UINT uNumber);
|
||||
DWORD WIN_FUNC FormatMessageA(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId, LPSTR lpBuffer,
|
||||
DWORD nSize, va_list *Arguments);
|
||||
|
@ -51,6 +51,7 @@ using FARPROC = void *;
|
||||
using WORD = uint16_t;
|
||||
using LPWORD = WORD *;
|
||||
using LANGID = WORD;
|
||||
using ATOM = uint16_t;
|
||||
using DWORD = uint32_t;
|
||||
using PDWORD = DWORD *;
|
||||
using LPDWORD = DWORD *;
|
||||
|
@ -68,7 +68,7 @@ HANDLE Handles::alloc(Pin<> obj, uint32_t grantedAccess, uint32_t flags) {
|
||||
}
|
||||
|
||||
Pin<> Handles::get(HANDLE h, HandleMeta *metaOut) {
|
||||
if (isPseudo(h)) {
|
||||
if (h == nullptr || isPseudo(h)) {
|
||||
return {}; // pseudo-handles have no entries
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user