mirror of
https://github.com/decompals/wibo.git
synced 2025-10-15 14:45:12 +00:00
DLL fixes; impl GetSystemInfo, __dllonexit, and more
This commit is contained in:
parent
a17a3c5413
commit
042a43ced1
1
common.h
1
common.h
@ -26,6 +26,7 @@ typedef void *HMODULE;
|
||||
typedef void *PVOID;
|
||||
typedef void *LPVOID;
|
||||
typedef void *FARPROC;
|
||||
typedef uint16_t WORD;
|
||||
typedef uint32_t DWORD;
|
||||
typedef DWORD *PDWORD;
|
||||
typedef DWORD *LPDWORD;
|
||||
|
122
dll/kernel32.cpp
122
dll/kernel32.cpp
@ -7,6 +7,7 @@
|
||||
#include <climits>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <ctype.h>
|
||||
#include <filesystem>
|
||||
#include <fnmatch.h>
|
||||
@ -21,9 +22,46 @@
|
||||
#include <sys/statvfs.h>
|
||||
#include <sys/wait.h>
|
||||
#include <spawn.h>
|
||||
#include <unistd.h>
|
||||
#include <vector>
|
||||
#include <fcntl.h>
|
||||
|
||||
namespace {
|
||||
using DWORD_PTR = uintptr_t;
|
||||
|
||||
constexpr WORD PROCESSOR_ARCHITECTURE_INTEL = 0;
|
||||
constexpr WORD PROCESSOR_ARCHITECTURE_ARM = 5;
|
||||
constexpr WORD PROCESSOR_ARCHITECTURE_IA64 = 6;
|
||||
constexpr WORD PROCESSOR_ARCHITECTURE_AMD64 = 9;
|
||||
constexpr WORD PROCESSOR_ARCHITECTURE_ARM64 = 12;
|
||||
constexpr WORD PROCESSOR_ARCHITECTURE_UNKNOWN = 0xFFFF;
|
||||
|
||||
constexpr DWORD PROCESSOR_INTEL_386 = 386;
|
||||
constexpr DWORD PROCESSOR_INTEL_486 = 486;
|
||||
constexpr DWORD PROCESSOR_INTEL_PENTIUM = 586;
|
||||
constexpr DWORD PROCESSOR_INTEL_IA64 = 2200;
|
||||
constexpr DWORD PROCESSOR_AMD_X8664 = 8664;
|
||||
|
||||
struct SYSTEM_INFO {
|
||||
union {
|
||||
DWORD dwOemId;
|
||||
struct {
|
||||
WORD wProcessorArchitecture;
|
||||
WORD wReserved;
|
||||
};
|
||||
};
|
||||
DWORD dwPageSize;
|
||||
LPVOID lpMinimumApplicationAddress;
|
||||
LPVOID lpMaximumApplicationAddress;
|
||||
DWORD_PTR dwActiveProcessorMask;
|
||||
DWORD dwNumberOfProcessors;
|
||||
DWORD dwProcessorType;
|
||||
DWORD dwAllocationGranularity;
|
||||
WORD wProcessorLevel;
|
||||
WORD wProcessorRevision;
|
||||
};
|
||||
}
|
||||
|
||||
typedef union _RTL_RUN_ONCE {
|
||||
PVOID Ptr;
|
||||
} RTL_RUN_ONCE, *PRTL_RUN_ONCE;
|
||||
@ -177,6 +215,88 @@ namespace kernel32 {
|
||||
return 1; // success in retrieval
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC DisableThreadLibraryCalls(HMODULE hLibModule) {
|
||||
DEBUG_LOG("DisableThreadLibraryCalls(%p)\n", hLibModule);
|
||||
(void)hLibModule;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void WIN_FUNC GetSystemInfo(SYSTEM_INFO *lpSystemInfo) {
|
||||
DEBUG_LOG("GetSystemInfo\n");
|
||||
if (!lpSystemInfo) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::memset(lpSystemInfo, 0, sizeof(*lpSystemInfo));
|
||||
|
||||
WORD architecture = PROCESSOR_ARCHITECTURE_UNKNOWN;
|
||||
DWORD processorType = 0;
|
||||
WORD processorLevel = 0;
|
||||
|
||||
#if defined(__x86_64__) || defined(_M_X64)
|
||||
architecture = PROCESSOR_ARCHITECTURE_AMD64;
|
||||
processorType = PROCESSOR_AMD_X8664;
|
||||
processorLevel = 6;
|
||||
#elif defined(__i386__) || defined(_M_IX86)
|
||||
architecture = PROCESSOR_ARCHITECTURE_INTEL;
|
||||
processorType = PROCESSOR_INTEL_PENTIUM;
|
||||
processorLevel = 6;
|
||||
#elif defined(__aarch64__)
|
||||
architecture = PROCESSOR_ARCHITECTURE_ARM64;
|
||||
processorType = 0;
|
||||
processorLevel = 8;
|
||||
#elif defined(__arm__)
|
||||
architecture = PROCESSOR_ARCHITECTURE_ARM;
|
||||
processorType = 0;
|
||||
processorLevel = 7;
|
||||
#else
|
||||
architecture = PROCESSOR_ARCHITECTURE_UNKNOWN;
|
||||
processorType = 0;
|
||||
processorLevel = 0;
|
||||
#endif
|
||||
|
||||
lpSystemInfo->wProcessorArchitecture = architecture;
|
||||
lpSystemInfo->wReserved = 0;
|
||||
lpSystemInfo->dwOemId = lpSystemInfo->wProcessorArchitecture;
|
||||
lpSystemInfo->dwProcessorType = processorType;
|
||||
lpSystemInfo->wProcessorLevel = processorLevel;
|
||||
lpSystemInfo->wProcessorRevision = 0;
|
||||
|
||||
long pageSize = sysconf(_SC_PAGESIZE);
|
||||
if (pageSize <= 0) {
|
||||
pageSize = 4096;
|
||||
}
|
||||
lpSystemInfo->dwPageSize = static_cast<DWORD>(pageSize);
|
||||
|
||||
lpSystemInfo->lpMinimumApplicationAddress = reinterpret_cast<LPVOID>(0x00010000);
|
||||
if (sizeof(void *) == 4) {
|
||||
lpSystemInfo->lpMaximumApplicationAddress = reinterpret_cast<LPVOID>(0x7FFEFFFF);
|
||||
} else {
|
||||
lpSystemInfo->lpMaximumApplicationAddress = reinterpret_cast<LPVOID>(0x00007FFFFFFEFFFFull);
|
||||
}
|
||||
|
||||
unsigned int cpuCount = 1;
|
||||
long reported = sysconf(_SC_NPROCESSORS_ONLN);
|
||||
if (reported > 0) {
|
||||
cpuCount = static_cast<unsigned int>(reported);
|
||||
}
|
||||
lpSystemInfo->dwNumberOfProcessors = cpuCount;
|
||||
|
||||
unsigned int maskWidth = static_cast<unsigned int>(sizeof(DWORD_PTR) * 8);
|
||||
DWORD_PTR mask;
|
||||
if (cpuCount >= maskWidth) {
|
||||
mask = static_cast<DWORD_PTR>(~static_cast<DWORD_PTR>(0));
|
||||
} else {
|
||||
mask = (static_cast<DWORD_PTR>(1) << cpuCount) - 1;
|
||||
}
|
||||
if (mask == 0) {
|
||||
mask = 1;
|
||||
}
|
||||
lpSystemInfo->dwActiveProcessorMask = mask;
|
||||
|
||||
lpSystemInfo->dwAllocationGranularity = 0x10000;
|
||||
}
|
||||
|
||||
struct PROCESS_INFORMATION {
|
||||
HANDLE hProcess;
|
||||
HANDLE hThread;
|
||||
@ -2764,6 +2884,7 @@ static void *resolveByName(const char *name) {
|
||||
if (strcmp(name, "GetDiskFreeSpaceExW") == 0) return (void*) kernel32::GetDiskFreeSpaceExW;
|
||||
|
||||
// sysinfoapi.h
|
||||
if (strcmp(name, "GetSystemInfo") == 0) return (void *) kernel32::GetSystemInfo;
|
||||
if (strcmp(name, "GetSystemTime") == 0) return (void *) kernel32::GetSystemTime;
|
||||
if (strcmp(name, "GetLocalTime") == 0) return (void *) kernel32::GetLocalTime;
|
||||
if (strcmp(name, "GetSystemTimeAsFileTime") == 0) return (void *) kernel32::GetSystemTimeAsFileTime;
|
||||
@ -2788,6 +2909,7 @@ static void *resolveByName(const char *name) {
|
||||
if (strcmp(name, "SizeofResource") == 0) return (void *) kernel32::SizeofResource;
|
||||
if (strcmp(name, "LoadLibraryA") == 0) return (void *) kernel32::LoadLibraryA;
|
||||
if (strcmp(name, "LoadLibraryExW") == 0) return (void *) kernel32::LoadLibraryExW;
|
||||
if (strcmp(name, "DisableThreadLibraryCalls") == 0) return (void *) kernel32::DisableThreadLibraryCalls;
|
||||
if (strcmp(name, "FreeLibrary") == 0) return (void *) kernel32::FreeLibrary;
|
||||
if (strcmp(name, "GetProcAddress") == 0) return (void *) kernel32::GetProcAddress;
|
||||
|
||||
|
129
dll/msvcrt.cpp
129
dll/msvcrt.cpp
@ -1,5 +1,6 @@
|
||||
#include "common.h"
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cerrno>
|
||||
#include <climits>
|
||||
#include <clocale>
|
||||
@ -11,6 +12,7 @@
|
||||
#include <cwchar>
|
||||
#include <cwctype>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
@ -20,6 +22,7 @@
|
||||
|
||||
typedef void (*_PVFV)();
|
||||
typedef int (*_PIFV)();
|
||||
using _onexit_t = _PIFV;
|
||||
|
||||
namespace msvcrt {
|
||||
int _commode;
|
||||
@ -29,6 +32,40 @@ namespace msvcrt {
|
||||
uint16_t* _wpgmptr;
|
||||
|
||||
namespace {
|
||||
struct DllOnExitTable {
|
||||
_PVFV **pbegin;
|
||||
_PVFV **pend;
|
||||
std::vector<_PVFV> callbacks;
|
||||
bool registered;
|
||||
};
|
||||
|
||||
constexpr size_t LOCK_TABLE_SIZE = 64;
|
||||
std::array<std::recursive_mutex, LOCK_TABLE_SIZE> &lockTable() {
|
||||
static std::array<std::recursive_mutex, LOCK_TABLE_SIZE> table;
|
||||
return table;
|
||||
}
|
||||
|
||||
std::vector<DllOnExitTable> &dllOnExitTables() {
|
||||
static std::vector<DllOnExitTable> tables;
|
||||
return tables;
|
||||
}
|
||||
|
||||
std::mutex &dllOnExitMutex() {
|
||||
static std::mutex mutex;
|
||||
return mutex;
|
||||
}
|
||||
|
||||
DllOnExitTable &ensureDllOnExitTable(_PVFV **pbegin, _PVFV **pend) {
|
||||
auto &tables = dllOnExitTables();
|
||||
for (auto &table : tables) {
|
||||
if (table.pbegin == pbegin && table.pend == pend) {
|
||||
return table;
|
||||
}
|
||||
}
|
||||
tables.push_back(DllOnExitTable{pbegin, pend, {}, false});
|
||||
return tables.back();
|
||||
}
|
||||
|
||||
template <typename CharT>
|
||||
struct StringListStorage {
|
||||
std::vector<std::unique_ptr<CharT[]>> strings;
|
||||
@ -336,10 +373,96 @@ namespace msvcrt {
|
||||
return std::malloc(size);
|
||||
}
|
||||
|
||||
void* WIN_ENTRY _malloc_crt(size_t size) {
|
||||
return std::malloc(size);
|
||||
}
|
||||
|
||||
void WIN_ENTRY _lock(int locknum) {
|
||||
if (locknum < 0 || static_cast<size_t>(locknum) >= LOCK_TABLE_SIZE) {
|
||||
DEBUG_LOG("_lock: unsupported lock %d\n", locknum);
|
||||
return;
|
||||
}
|
||||
lockTable()[static_cast<size_t>(locknum)].lock();
|
||||
}
|
||||
|
||||
void WIN_ENTRY _unlock(int locknum) {
|
||||
if (locknum < 0 || static_cast<size_t>(locknum) >= LOCK_TABLE_SIZE) {
|
||||
DEBUG_LOG("_unlock: unsupported lock %d\n", locknum);
|
||||
return;
|
||||
}
|
||||
lockTable()[static_cast<size_t>(locknum)].unlock();
|
||||
}
|
||||
|
||||
_onexit_t WIN_ENTRY __dllonexit(_onexit_t func, _PVFV **pbegin, _PVFV **pend) {
|
||||
if (!pbegin || !pend) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> guard(dllOnExitMutex());
|
||||
auto &table = ensureDllOnExitTable(pbegin, pend);
|
||||
if (!table.registered) {
|
||||
wibo::registerOnExitTable(reinterpret_cast<void *>(pbegin));
|
||||
table.registered = true;
|
||||
}
|
||||
|
||||
if (func) {
|
||||
auto callback = reinterpret_cast<_PVFV>(func);
|
||||
table.callbacks.push_back(callback);
|
||||
wibo::addOnExitFunction(reinterpret_cast<void *>(pbegin), reinterpret_cast<void (*)()>(callback));
|
||||
}
|
||||
|
||||
if (table.callbacks.empty()) {
|
||||
*pbegin = nullptr;
|
||||
*pend = nullptr;
|
||||
} else {
|
||||
_PVFV *dataPtr = table.callbacks.data();
|
||||
*pbegin = dataPtr;
|
||||
*pend = dataPtr + table.callbacks.size();
|
||||
}
|
||||
|
||||
return reinterpret_cast<_onexit_t>(func);
|
||||
}
|
||||
|
||||
void WIN_ENTRY free(void* ptr){
|
||||
std::free(ptr);
|
||||
}
|
||||
|
||||
static uint16_t toLower(uint16_t ch) {
|
||||
if (ch >= 'A' && ch <= 'Z') {
|
||||
return static_cast<uint16_t>(ch + ('a' - 'A'));
|
||||
}
|
||||
wchar_t wide = static_cast<wchar_t>(ch);
|
||||
wchar_t lowered = std::towlower(wide);
|
||||
if (lowered < 0 || lowered > 0xFFFF) {
|
||||
return ch;
|
||||
}
|
||||
return static_cast<uint16_t>(lowered);
|
||||
}
|
||||
|
||||
int WIN_ENTRY _wcsicmp(const uint16_t *lhs, const uint16_t *rhs) {
|
||||
if (lhs == rhs) {
|
||||
return 0;
|
||||
}
|
||||
if (!lhs) {
|
||||
return -1;
|
||||
}
|
||||
if (!rhs) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (*lhs && *rhs) {
|
||||
uint16_t a = toLower(*lhs++);
|
||||
uint16_t b = toLower(*rhs++);
|
||||
if (a != b) {
|
||||
return static_cast<int>(a) - static_cast<int>(b);
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t a = toLower(*lhs);
|
||||
uint16_t b = toLower(*rhs);
|
||||
return static_cast<int>(a) - static_cast<int>(b);
|
||||
}
|
||||
|
||||
int WIN_ENTRY _get_wpgmptr(uint16_t** pValue){
|
||||
DEBUG_LOG("_get_wpgmptr(%p)\n", pValue);
|
||||
if(!pValue) return 22;
|
||||
@ -760,8 +883,12 @@ static void *resolveByName(const char *name) {
|
||||
if (strcmp(name, "strcmp") == 0) return (void *)msvcrt::strcmp;
|
||||
if (strcmp(name, "strncmp") == 0) return (void *)msvcrt::strncmp;
|
||||
if (strcmp(name, "malloc") == 0) return (void*)msvcrt::malloc;
|
||||
if (strcmp(name, "_malloc_crt") == 0) return (void*)msvcrt::malloc;
|
||||
if (strcmp(name, "_malloc_crt") == 0) return (void*)msvcrt::_malloc_crt;
|
||||
if (strcmp(name, "_lock") == 0) return (void*)msvcrt::_lock;
|
||||
if (strcmp(name, "_unlock") == 0) return (void*)msvcrt::_unlock;
|
||||
if (strcmp(name, "__dllonexit") == 0) return (void*)msvcrt::__dllonexit;
|
||||
if (strcmp(name, "free") == 0) return (void*)msvcrt::free;
|
||||
if (strcmp(name, "_wcsicmp") == 0) return (void*)msvcrt::_wcsicmp;
|
||||
if (strcmp(name, "_get_wpgmptr") == 0) return (void*)msvcrt::_get_wpgmptr;
|
||||
if (strcmp(name, "_wsplitpath_s") == 0) return (void*)msvcrt::_wsplitpath_s;
|
||||
if (strcmp(name, "wcscat_s") == 0) return (void*)msvcrt::wcscat_s;
|
||||
|
@ -292,7 +292,7 @@ bool wibo::Executable::loadPE(FILE *file, bool exec) {
|
||||
++dir;
|
||||
}
|
||||
|
||||
entryPoint = fromRVA<void>(header32.addressOfEntryPoint);
|
||||
entryPoint = header32.addressOfEntryPoint ? fromRVA<void>(header32.addressOfEntryPoint) : nullptr;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user