mirror of
https://github.com/decompals/wibo.git
synced 2025-10-15 14:45:12 +00:00
Reorg headers, module_registry -> modules, remove ActCtx msvcr80.dll hack
This commit is contained in:
parent
b87fb5e472
commit
0d76e541c1
@ -80,7 +80,7 @@ add_executable(wibo
|
||||
src/handles.cpp
|
||||
src/loader.cpp
|
||||
src/main.cpp
|
||||
src/module_registry.cpp
|
||||
src/modules.cpp
|
||||
src/processes.cpp
|
||||
src/resources.cpp
|
||||
src/strutil.cpp
|
||||
|
@ -1,9 +1,10 @@
|
||||
#include "modules.h"
|
||||
|
||||
#include "advapi32/processthreadsapi.h"
|
||||
#include "advapi32/securitybaseapi.h"
|
||||
#include "advapi32/winbase.h"
|
||||
#include "advapi32/wincrypt.h"
|
||||
#include "advapi32/winreg.h"
|
||||
#include "common.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
@ -105,7 +106,7 @@ void *resolveByName(const char *name) {
|
||||
|
||||
} // namespace
|
||||
|
||||
wibo::Module lib_advapi32 = {
|
||||
wibo::ModuleStub lib_advapi32 = {
|
||||
(const char *[]){
|
||||
"advapi32",
|
||||
nullptr,
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "processthreadsapi.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "context.h"
|
||||
#include "errors.h"
|
||||
#include "handles.h"
|
||||
#include "internal.h"
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "securitybaseapi.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "context.h"
|
||||
#include "errors.h"
|
||||
#include "handles.h"
|
||||
#include "internal.h"
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "winbase.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "context.h"
|
||||
#include "errors.h"
|
||||
#include "internal.h"
|
||||
#include "strutil.h"
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "wincrypt.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "context.h"
|
||||
#include "errors.h"
|
||||
|
||||
#include <cstring>
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "winreg.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "context.h"
|
||||
#include "errors.h"
|
||||
#include "handles.h"
|
||||
#include "strutil.h"
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "common.h"
|
||||
#include "context.h"
|
||||
#include "errors.h"
|
||||
#include "modules.h"
|
||||
|
||||
#include <sys/random.h>
|
||||
#include <vector>
|
||||
@ -72,7 +74,7 @@ static void *resolveByName(const char *name) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
wibo::Module lib_bcrypt = {
|
||||
wibo::ModuleStub lib_bcrypt = {
|
||||
(const char *[]){
|
||||
"bcrypt",
|
||||
nullptr,
|
||||
|
@ -1,4 +1,6 @@
|
||||
#include "common.h"
|
||||
#include "context.h"
|
||||
#include "modules.h"
|
||||
|
||||
#include <csignal>
|
||||
#include <cstdarg>
|
||||
@ -436,7 +438,7 @@ static void *resolveByName(const char *name) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
wibo::Module lib_crt = {
|
||||
wibo::ModuleStub lib_crt = {
|
||||
(const char *[]){
|
||||
"api-ms-win-crt-heap-l1-1-0",
|
||||
"api-ms-win-crt-locale-l1-1-0",
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "common.h"
|
||||
#include "modules.h"
|
||||
|
||||
#include "kernel32/debugapi.h"
|
||||
#include "kernel32/errhandlingapi.h"
|
||||
@ -600,7 +600,7 @@ void *resolveByName(const char *name) {
|
||||
|
||||
} // namespace
|
||||
|
||||
wibo::Module lib_kernel32 = {
|
||||
wibo::ModuleStub lib_kernel32 = {
|
||||
(const char *[]){
|
||||
"kernel32",
|
||||
nullptr,
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "debugapi.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "context.h"
|
||||
#include "errors.h"
|
||||
|
||||
namespace kernel32 {
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "errhandlingapi.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "context.h"
|
||||
#include "errors.h"
|
||||
|
||||
namespace {
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "fibersapi.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "context.h"
|
||||
#include "errors.h"
|
||||
|
||||
namespace {
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include "access.h"
|
||||
#include "common.h"
|
||||
#include "context.h"
|
||||
#include "errors.h"
|
||||
#include "files.h"
|
||||
#include "handles.h"
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "handleapi.h"
|
||||
|
||||
#include "context.h"
|
||||
#include "errors.h"
|
||||
#include "handles.h"
|
||||
#include "internal.h"
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "heapapi.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "context.h"
|
||||
#include "errors.h"
|
||||
#include "handles.h"
|
||||
#include "internal.h"
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "interlockedapi.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "context.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "ioapiset.h"
|
||||
|
||||
#include "context.h"
|
||||
#include "errors.h"
|
||||
#include "synchapi.h"
|
||||
|
||||
|
@ -1,7 +1,9 @@
|
||||
#include "libloaderapi.h"
|
||||
|
||||
#include "context.h"
|
||||
#include "errors.h"
|
||||
#include "files.h"
|
||||
#include "modules.h"
|
||||
#include "resources.h"
|
||||
#include "strutil.h"
|
||||
|
||||
|
@ -1,8 +1,11 @@
|
||||
#include "memoryapi.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "context.h"
|
||||
#include "errors.h"
|
||||
#include "handles.h"
|
||||
#include "internal.h"
|
||||
#include "modules.h"
|
||||
#include "strutil.h"
|
||||
|
||||
#include <cerrno>
|
||||
|
@ -1,14 +1,11 @@
|
||||
#include "namedpipeapi.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "context.h"
|
||||
#include "errors.h"
|
||||
#include "fileapi.h"
|
||||
#include "files.h"
|
||||
#include "handles.h"
|
||||
#include "internal.h"
|
||||
|
||||
#include <cerrno>
|
||||
#include <cstdio>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "processenv.h"
|
||||
|
||||
#include "context.h"
|
||||
#include "errors.h"
|
||||
#include "files.h"
|
||||
#include "internal.h"
|
||||
|
@ -1,9 +1,12 @@
|
||||
#include "processthreadsapi.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "context.h"
|
||||
#include "errors.h"
|
||||
#include "files.h"
|
||||
#include "handles.h"
|
||||
#include "internal.h"
|
||||
#include "modules.h"
|
||||
#include "processes.h"
|
||||
#include "strutil.h"
|
||||
#include "timeutil.h"
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "profileapi.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "context.h"
|
||||
#include "errors.h"
|
||||
|
||||
namespace kernel32 {
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "stringapiset.h"
|
||||
|
||||
#include "context.h"
|
||||
#include "errors.h"
|
||||
#include "strutil.h"
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "synchapi.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "context.h"
|
||||
#include "errors.h"
|
||||
#include "handles.h"
|
||||
#include "internal.h"
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "sysinfoapi.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "context.h"
|
||||
#include "errors.h"
|
||||
#include "timeutil.h"
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "timezoneapi.h"
|
||||
|
||||
#include "context.h"
|
||||
#include "errors.h"
|
||||
#include "timeutil.h"
|
||||
|
||||
|
@ -1,9 +1,10 @@
|
||||
#include "winbase.h"
|
||||
|
||||
#include "context.h"
|
||||
#include "errors.h"
|
||||
#include "files.h"
|
||||
#include "handles.h"
|
||||
#include "internal.h"
|
||||
#include "modules.h"
|
||||
#include "strutil.h"
|
||||
|
||||
#include <algorithm>
|
||||
@ -13,16 +14,15 @@
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <limits>
|
||||
#include <mimalloc.h>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/statvfs.h>
|
||||
#include <system_error>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace {
|
||||
|
||||
@ -317,6 +317,7 @@ ActivationContext *currentActivationContext() {
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void ensureDefaultActivationContext() {
|
||||
static std::once_flag initFlag;
|
||||
std::call_once(initFlag, [] {
|
||||
@ -331,48 +332,10 @@ void ensureDefaultActivationContext() {
|
||||
entry.dllData.PathSegmentOffset = 0;
|
||||
ctx->dllRedirections.emplace_back(std::move(entry));
|
||||
};
|
||||
addDll("msvcr80.dll");
|
||||
addDll("msvcp80.dll");
|
||||
addDll("mfc80.dll");
|
||||
addDll("mfc80u.dll");
|
||||
addDll("msvcrt.dll");
|
||||
});
|
||||
}
|
||||
|
||||
constexpr const char kVc80ManifestName[] = "Microsoft.VC80.CRT.manifest";
|
||||
|
||||
void ensureVc80ManifestOnDisk(const DllRedirectionEntry &entry) {
|
||||
static std::once_flag manifestOnce;
|
||||
if (entry.nameLower != "msvcr80.dll") {
|
||||
return;
|
||||
}
|
||||
std::call_once(manifestOnce, [] {
|
||||
wibo::ModuleInfo *module = wibo::findLoadedModule("msvcr80.dll");
|
||||
if (!module || module->resolvedPath.empty()) {
|
||||
DEBUG_LOG("VC80 manifest: module not yet loaded, skipping creation\n");
|
||||
return;
|
||||
}
|
||||
std::filesystem::path manifestPath = module->resolvedPath.parent_path() / kVc80ManifestName;
|
||||
std::error_code ec;
|
||||
if (std::filesystem::exists(manifestPath, ec)) {
|
||||
return;
|
||||
}
|
||||
constexpr const char kManifestContents[] =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n"
|
||||
"<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">\n"
|
||||
" <assemblyIdentity type=\"win32\" name=\"Microsoft.VC80.CRT\" version=\"8.0.50727.762\" processorArchitecture=\"x86\" publicKeyToken=\"1fc8b3b9a1e18e3b\"/>\n"
|
||||
" <file name=\"msvcr80.dll\"/>\n"
|
||||
" <file name=\"msvcp80.dll\"/>\n"
|
||||
" <file name=\"msvcm80.dll\"/>\n"
|
||||
"</assembly>\n";
|
||||
std::ofstream out(manifestPath, std::ios::binary);
|
||||
if (!out) {
|
||||
DEBUG_LOG("VC80 manifest: failed to create %s\n", manifestPath.string().c_str());
|
||||
return;
|
||||
}
|
||||
out.write(kManifestContents, sizeof(kManifestContents) - 1);
|
||||
if (!out) {
|
||||
DEBUG_LOG("VC80 manifest: write error for %s\n", manifestPath.string().c_str());
|
||||
for (const auto &[key, module] : wibo::allLoadedModules()) {
|
||||
if (!module->moduleStub) {
|
||||
addDll(module->normalizedName);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -631,7 +594,7 @@ BOOL WIN_FUNC SetDllDirectoryA(LPCSTR lpPathName) {
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC FindActCtxSectionStringA(DWORD dwFlags, const GUID *lpExtensionGuid, ULONG ulSectionId,
|
||||
LPCSTR lpStringToFind, PACTCTX_SECTION_KEYED_DATA ReturnedData) {
|
||||
LPCSTR lpStringToFind, PACTCTX_SECTION_KEYED_DATA ReturnedData) {
|
||||
DEBUG_LOG("FindActCtxSectionStringA(%#x, %p, %u, %s, %p)\n", dwFlags, lpExtensionGuid, ulSectionId,
|
||||
lpStringToFind ? lpStringToFind : "<null>", ReturnedData);
|
||||
std::vector<uint16_t> wideStorage;
|
||||
@ -643,15 +606,15 @@ BOOL WIN_FUNC FindActCtxSectionStringA(DWORD dwFlags, const GUID *lpExtensionGui
|
||||
}
|
||||
}
|
||||
const uint16_t *widePtr = wideStorage.empty() ? nullptr : wideStorage.data();
|
||||
return FindActCtxSectionStringW(dwFlags, lpExtensionGuid, ulSectionId,
|
||||
reinterpret_cast<LPCWSTR>(widePtr), ReturnedData);
|
||||
return FindActCtxSectionStringW(dwFlags, lpExtensionGuid, ulSectionId, reinterpret_cast<LPCWSTR>(widePtr),
|
||||
ReturnedData);
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC FindActCtxSectionStringW(DWORD dwFlags, const GUID *lpExtensionGuid, ULONG ulSectionId,
|
||||
LPCWSTR lpStringToFind, PACTCTX_SECTION_KEYED_DATA ReturnedData) {
|
||||
LPCWSTR lpStringToFind, PACTCTX_SECTION_KEYED_DATA ReturnedData) {
|
||||
std::string lookup = lpStringToFind ? wideStringToString(lpStringToFind) : std::string();
|
||||
DEBUG_LOG("FindActCtxSectionStringW(%#x, %p, %u, %s, %p)\n", dwFlags, lpExtensionGuid, ulSectionId,
|
||||
lookup.c_str(), ReturnedData);
|
||||
DEBUG_LOG("FindActCtxSectionStringW(%#x, %p, %u, %s, %p)\n", dwFlags, lpExtensionGuid, ulSectionId, lookup.c_str(),
|
||||
ReturnedData);
|
||||
|
||||
if (lpExtensionGuid) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
@ -701,8 +664,6 @@ BOOL WIN_FUNC FindActCtxSectionStringW(DWORD dwFlags, const GUID *lpExtensionGui
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ensureVc80ManifestOnDisk(*matchedEntry);
|
||||
|
||||
ReturnedData->lpData = const_cast<ACTIVATION_CONTEXT_DATA_DLL_REDIRECTION *>(&matchedEntry->dllData);
|
||||
ReturnedData->ulLength = matchedEntry->dllData.Size;
|
||||
ReturnedData->lpSectionBase = const_cast<ACTIVATION_CONTEXT_DATA_DLL_REDIRECTION *>(&matchedEntry->dllData);
|
||||
|
@ -1,11 +1,11 @@
|
||||
#include "wincon.h"
|
||||
|
||||
#include "context.h"
|
||||
#include "errors.h"
|
||||
#include "files.h"
|
||||
#include "handles.h"
|
||||
#include "strutil.h"
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
namespace kernel32 {
|
||||
|
||||
BOOL WIN_FUNC GetConsoleMode(HANDLE hConsoleHandle, LPDWORD lpMode) {
|
||||
@ -83,7 +83,7 @@ BOOL WIN_FUNC WriteConsoleW(HANDLE hConsoleOutput, LPCVOID lpBuffer, DWORD nNumb
|
||||
|
||||
auto file = wibo::handles().getAs<FileObject>(hConsoleOutput);
|
||||
if (file->fd == STDOUT_FILENO || file->fd == STDERR_FILENO) {
|
||||
auto str = wideStringToString(static_cast<const uint16_t *>(lpBuffer), nNumberOfCharsToWrite);
|
||||
auto str = wideStringToString(static_cast<const uint16_t *>(lpBuffer), static_cast<int>(nNumberOfCharsToWrite));
|
||||
dprintf(file->fd, "%s", str.c_str());
|
||||
if (lpNumberOfCharsWritten) {
|
||||
*lpNumberOfCharsWritten = nNumberOfCharsToWrite;
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "winnls.h"
|
||||
|
||||
#include "context.h"
|
||||
#include "errors.h"
|
||||
#include "strutil.h"
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "winnt.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "context.h"
|
||||
|
||||
namespace kernel32 {
|
||||
|
||||
|
@ -1,8 +1,10 @@
|
||||
#include "wow64apiset.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "kernel32/internal.h"
|
||||
#include "context.h"
|
||||
#include "errors.h"
|
||||
#include "handles.h"
|
||||
#include "internal.h"
|
||||
|
||||
namespace kernel32 {
|
||||
|
||||
|
@ -1,4 +1,6 @@
|
||||
#include "common.h"
|
||||
#include "context.h"
|
||||
#include "modules.h"
|
||||
|
||||
namespace lmgr {
|
||||
int WIN_ENTRY lp_checkout(int a, int b, const char* c, const char* d, int e, const char* f, int* out) {
|
||||
@ -25,7 +27,7 @@ static void *resolveByOrdinal(uint16_t ordinal) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
wibo::Module lib_lmgr = {
|
||||
wibo::ModuleStub lib_lmgr = {
|
||||
(const char *[]){
|
||||
"lmgr11",
|
||||
"lmgr326b",
|
||||
|
@ -1,4 +1,6 @@
|
||||
#include "common.h"
|
||||
#include "context.h"
|
||||
#include "modules.h"
|
||||
|
||||
namespace mscoree {
|
||||
|
||||
@ -16,7 +18,7 @@ static void *resolveByName(const char *name) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
wibo::Module lib_mscoree = {
|
||||
wibo::ModuleStub lib_mscoree = {
|
||||
(const char *[]){
|
||||
"mscoree",
|
||||
nullptr,
|
||||
|
@ -1,46 +1,50 @@
|
||||
#include "common.h"
|
||||
#include "context.h"
|
||||
#include "files.h"
|
||||
#include "kernel32/internal.h"
|
||||
#include "modules.h"
|
||||
#include "processes.h"
|
||||
#include "strutil.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cctype>
|
||||
#include <cerrno>
|
||||
#include <climits>
|
||||
#include <clocale>
|
||||
#include <cmath>
|
||||
#include <cctype>
|
||||
#include <float.h>
|
||||
#include <csignal>
|
||||
#include <cstdarg>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <csignal>
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
#include <cwchar>
|
||||
#include <cwctype>
|
||||
#include <fcntl.h>
|
||||
#include <filesystem>
|
||||
#include <float.h>
|
||||
#include <math.h>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <ctime>
|
||||
#include <spawn.h>
|
||||
#include <string>
|
||||
#include <strings.h>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
#include <unistd.h>
|
||||
#include <vector>
|
||||
#include <spawn.h>
|
||||
#include <sys/wait.h>
|
||||
#include <math.h>
|
||||
#include <utime.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <type_traits>
|
||||
#include <unistd.h>
|
||||
#include <unordered_map>
|
||||
#include <utime.h>
|
||||
#include <vector>
|
||||
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
#include "files.h"
|
||||
#include "processes.h"
|
||||
#include "strutil.h"
|
||||
|
||||
typedef void (*_PVFV)();
|
||||
typedef int (*_PIFV)();
|
||||
@ -3218,7 +3222,7 @@ static void *resolveByName(const char *name) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
wibo::Module lib_msvcrt = {
|
||||
wibo::ModuleStub lib_msvcrt = {
|
||||
(const char *[]){
|
||||
"msvcrt",
|
||||
"msvcrt40",
|
||||
|
@ -1,9 +1,11 @@
|
||||
#include "common.h"
|
||||
#include "kernel32/internal.h"
|
||||
#include "context.h"
|
||||
#include "errors.h"
|
||||
#include "files.h"
|
||||
#include "handles.h"
|
||||
#include "kernel32/internal.h"
|
||||
#include "kernel32/processthreadsapi.h"
|
||||
#include "modules.h"
|
||||
#include "processes.h"
|
||||
#include "strutil.h"
|
||||
|
||||
@ -408,7 +410,7 @@ static void *resolveByName(const char *name) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
wibo::Module lib_ntdll = {
|
||||
wibo::ModuleStub lib_ntdll = {
|
||||
(const char *[]){
|
||||
"ntdll",
|
||||
nullptr,
|
||||
|
@ -1,4 +1,6 @@
|
||||
#include "common.h"
|
||||
#include "context.h"
|
||||
#include "modules.h"
|
||||
|
||||
namespace ole32 {
|
||||
int WIN_FUNC CoInitialize(void *pvReserved) {
|
||||
@ -37,7 +39,7 @@ static void *resolveByName(const char *name) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
wibo::Module lib_ole32 = {
|
||||
wibo::ModuleStub lib_ole32 = {
|
||||
(const char *[]){
|
||||
"ole32",
|
||||
nullptr,
|
||||
|
@ -1,68 +0,0 @@
|
||||
#include "common.h"
|
||||
#include "errors.h"
|
||||
#include "handles.h"
|
||||
|
||||
namespace psapi {
|
||||
BOOL WIN_FUNC EnumProcessModules(HANDLE hProcess, HMODULE *lphModule, DWORD cb, DWORD *lpcbNeeded) {
|
||||
HOST_CONTEXT_GUARD();
|
||||
DEBUG_LOG("EnumProcessModules(%p, %p, %u, %p)\n", hProcess, lphModule, cb, lpcbNeeded);
|
||||
|
||||
bool recognizedHandle = false;
|
||||
if (hProcess == (HANDLE)0xFFFFFFFF) {
|
||||
recognizedHandle = true;
|
||||
} else {
|
||||
auto data = handles::dataFromHandle(hProcess, false);
|
||||
recognizedHandle = (data.type == handles::TYPE_PROCESS);
|
||||
}
|
||||
if (!recognizedHandle) {
|
||||
wibo::lastError = ERROR_ACCESS_DENIED;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
HMODULE currentModule = wibo::mainModule ? wibo::mainModule->handle : nullptr;
|
||||
DWORD required = currentModule ? sizeof(HMODULE) : 0;
|
||||
if (lpcbNeeded) {
|
||||
*lpcbNeeded = required;
|
||||
}
|
||||
|
||||
if (required == 0) {
|
||||
wibo::lastError = ERROR_INVALID_HANDLE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!lphModule || cb < required) {
|
||||
wibo::lastError = ERROR_INSUFFICIENT_BUFFER;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
lphModule[0] = currentModule;
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
} // namespace psapi
|
||||
|
||||
static void *resolveByName(const char *name) {
|
||||
if (strcmp(name, "EnumProcessModules") == 0)
|
||||
return (void *)psapi::EnumProcessModules;
|
||||
if (strcmp(name, "K32EnumProcessModules") == 0)
|
||||
return (void *)psapi::EnumProcessModules;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void *resolveByOrdinal(uint16_t ordinal) {
|
||||
switch (ordinal) {
|
||||
case 4: // EnumProcessModules
|
||||
return (void *)psapi::EnumProcessModules;
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
wibo::Module lib_psapi = {
|
||||
(const char *[]){
|
||||
"psapi",
|
||||
nullptr,
|
||||
},
|
||||
resolveByName,
|
||||
resolveByOrdinal,
|
||||
};
|
@ -1,4 +1,6 @@
|
||||
#include "common.h"
|
||||
#include "context.h"
|
||||
#include "modules.h"
|
||||
|
||||
#include <cstdarg>
|
||||
#include <cstdlib>
|
||||
@ -283,7 +285,7 @@ void *resolveByName(const char *name) {
|
||||
|
||||
} // namespace
|
||||
|
||||
wibo::Module lib_rpcrt4 = {
|
||||
wibo::ModuleStub lib_rpcrt4 = {
|
||||
(const char *[]){"rpcrt4", nullptr},
|
||||
resolveByName,
|
||||
nullptr,
|
||||
|
@ -1,6 +1,8 @@
|
||||
#include "common.h"
|
||||
#include "context.h"
|
||||
#include "errors.h"
|
||||
#include "strutil.h"
|
||||
#include "modules.h"
|
||||
#include "resources.h"
|
||||
|
||||
namespace user32 {
|
||||
constexpr uint32_t RT_STRING_ID = 6;
|
||||
@ -186,7 +188,7 @@ static void *resolveByName(const char *name) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
wibo::Module lib_user32 = {
|
||||
wibo::ModuleStub lib_user32 = {
|
||||
(const char *[]){
|
||||
"user32",
|
||||
nullptr,
|
||||
|
@ -1,4 +1,6 @@
|
||||
#include "common.h"
|
||||
#include "context.h"
|
||||
#include "modules.h"
|
||||
|
||||
namespace vcruntime {
|
||||
|
||||
@ -36,7 +38,7 @@ static void *resolveByName(const char *name) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
wibo::Module lib_vcruntime = {
|
||||
wibo::ModuleStub lib_vcruntime = {
|
||||
(const char *[]){
|
||||
"vcruntime140",
|
||||
nullptr,
|
||||
|
@ -1,6 +1,8 @@
|
||||
#include "common.h"
|
||||
#include "context.h"
|
||||
#include "errors.h"
|
||||
#include "files.h"
|
||||
#include "modules.h"
|
||||
#include "resources.h"
|
||||
#include "strutil.h"
|
||||
|
||||
@ -14,13 +16,9 @@ namespace {
|
||||
|
||||
constexpr uint32_t RT_VERSION = 16;
|
||||
|
||||
static uint16_t readU16(const uint8_t *ptr) {
|
||||
return static_cast<uint16_t>(ptr[0] | (ptr[1] << 8));
|
||||
}
|
||||
static uint16_t readU16(const uint8_t *ptr) { return static_cast<uint16_t>(ptr[0] | (ptr[1] << 8)); }
|
||||
|
||||
static size_t align4(size_t offset) {
|
||||
return (offset + 3u) & ~static_cast<size_t>(3u);
|
||||
}
|
||||
static size_t align4(size_t offset) { return (offset + 3u) & ~static_cast<size_t>(3u); }
|
||||
|
||||
static std::string narrowKey(const std::u16string &key) {
|
||||
std::string result;
|
||||
@ -70,7 +68,8 @@ static bool parseVersionBlock(const uint8_t *block, size_t available, VersionBlo
|
||||
|
||||
cursor = block + sizeof(uint16_t) * 3 + (out.key.size() + 1) * sizeof(uint16_t);
|
||||
if (cursor > end) {
|
||||
DEBUG_LOG("key cursor beyond block: cursor=%zu end=%zu\n", static_cast<size_t>(cursor - block), static_cast<size_t>(end - block));
|
||||
DEBUG_LOG("key cursor beyond block: cursor=%zu end=%zu\n", static_cast<size_t>(cursor - block),
|
||||
static_cast<size_t>(end - block));
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -78,8 +77,8 @@ static bool parseVersionBlock(const uint8_t *block, size_t available, VersionBlo
|
||||
|
||||
uint32_t valueBytes = 0;
|
||||
if (valueLength) {
|
||||
valueBytes = type == 1 ? static_cast<uint32_t>(valueLength) * sizeof(uint16_t)
|
||||
: static_cast<uint32_t>(valueLength);
|
||||
valueBytes =
|
||||
type == 1 ? static_cast<uint32_t>(valueLength) * sizeof(uint16_t) : static_cast<uint32_t>(valueLength);
|
||||
if (cursor + valueBytes > end) {
|
||||
DEBUG_LOG("value beyond block: bytes=%u remaining=%zu\n", valueBytes, static_cast<size_t>(end - cursor));
|
||||
return false;
|
||||
@ -100,12 +99,8 @@ static bool parseVersionBlock(const uint8_t *block, size_t available, VersionBlo
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool queryVersionBlock(const uint8_t *block, size_t available,
|
||||
const std::vector<std::string> &segments,
|
||||
size_t depth,
|
||||
const uint8_t **outPtr,
|
||||
uint32_t *outLen,
|
||||
uint16_t *outType) {
|
||||
static bool queryVersionBlock(const uint8_t *block, size_t available, const std::vector<std::string> &segments,
|
||||
size_t depth, const uint8_t **outPtr, uint32_t *outLen, uint16_t *outType) {
|
||||
VersionBlockView view;
|
||||
if (!parseVersionBlock(block, available, view))
|
||||
return false;
|
||||
@ -217,9 +212,10 @@ unsigned int WIN_FUNC GetFileVersionInfoSizeA(const char *lptstrFilename, unsign
|
||||
return static_cast<unsigned int>(buffer.size());
|
||||
}
|
||||
|
||||
unsigned int WIN_FUNC GetFileVersionInfoA(const char *lptstrFilename, unsigned int dwHandle, unsigned int dwLen, void *lpData) {
|
||||
unsigned int WIN_FUNC GetFileVersionInfoA(const char *lptstrFilename, unsigned int dwHandle, unsigned int dwLen,
|
||||
void *lpData) {
|
||||
HOST_CONTEXT_GUARD();
|
||||
(void) dwHandle;
|
||||
(void)dwHandle;
|
||||
DEBUG_LOG("GetFileVersionInfoA(%s, %u, %p)\n", lptstrFilename, dwLen, lpData);
|
||||
if (!lpData || dwLen == 0) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
@ -243,7 +239,8 @@ unsigned int WIN_FUNC GetFileVersionInfoA(const char *lptstrFilename, unsigned i
|
||||
return 1;
|
||||
}
|
||||
|
||||
static unsigned int VerQueryValueImpl(const void *pBlock, const std::string &subBlock, void **lplpBuffer, unsigned int *puLen) {
|
||||
static unsigned int VerQueryValueImpl(const void *pBlock, const std::string &subBlock, void **lplpBuffer,
|
||||
unsigned int *puLen) {
|
||||
if (!pBlock)
|
||||
return 0;
|
||||
|
||||
@ -280,7 +277,8 @@ static unsigned int VerQueryValueImpl(const void *pBlock, const std::string &sub
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned int WIN_FUNC VerQueryValueA(const void *pBlock, const char *lpSubBlock, void **lplpBuffer, unsigned int *puLen) {
|
||||
unsigned int WIN_FUNC VerQueryValueA(const void *pBlock, const char *lpSubBlock, void **lplpBuffer,
|
||||
unsigned int *puLen) {
|
||||
HOST_CONTEXT_GUARD();
|
||||
DEBUG_LOG("VerQueryValueA(%p, %s, %p, %p)\n", pBlock, lpSubBlock ? lpSubBlock : "(null)", lplpBuffer, puLen);
|
||||
if (!lpSubBlock)
|
||||
@ -295,14 +293,16 @@ unsigned int WIN_FUNC GetFileVersionInfoSizeW(const uint16_t *lptstrFilename, un
|
||||
return GetFileVersionInfoSizeA(narrow.c_str(), lpdwHandle);
|
||||
}
|
||||
|
||||
unsigned int WIN_FUNC GetFileVersionInfoW(const uint16_t *lptstrFilename, unsigned int dwHandle, unsigned int dwLen, void *lpData) {
|
||||
unsigned int WIN_FUNC GetFileVersionInfoW(const uint16_t *lptstrFilename, unsigned int dwHandle, unsigned int dwLen,
|
||||
void *lpData) {
|
||||
HOST_CONTEXT_GUARD();
|
||||
DEBUG_LOG("GetFileVersionInfoW -> ");
|
||||
auto narrow = wideStringToString(lptstrFilename);
|
||||
return GetFileVersionInfoA(narrow.c_str(), dwHandle, dwLen, lpData);
|
||||
}
|
||||
|
||||
unsigned int WIN_FUNC VerQueryValueW(const void *pBlock, const uint16_t *lpSubBlock, void **lplpBuffer, unsigned int *puLen) {
|
||||
unsigned int WIN_FUNC VerQueryValueW(const void *pBlock, const uint16_t *lpSubBlock, void **lplpBuffer,
|
||||
unsigned int *puLen) {
|
||||
HOST_CONTEXT_GUARD();
|
||||
if (!lpSubBlock)
|
||||
return 0;
|
||||
@ -314,16 +314,22 @@ unsigned int WIN_FUNC VerQueryValueW(const void *pBlock, const uint16_t *lpSubBl
|
||||
} // namespace version
|
||||
|
||||
static void *resolveByName(const char *name) {
|
||||
if (strcmp(name, "GetFileVersionInfoSizeA") == 0) return (void *) version::GetFileVersionInfoSizeA;
|
||||
if (strcmp(name, "GetFileVersionInfoA") == 0) return (void *) version::GetFileVersionInfoA;
|
||||
if (strcmp(name, "VerQueryValueA") == 0) return (void *) version::VerQueryValueA;
|
||||
if (strcmp(name, "GetFileVersionInfoSizeW") == 0) return (void *) version::GetFileVersionInfoSizeW;
|
||||
if (strcmp(name, "GetFileVersionInfoW") == 0) return (void *) version::GetFileVersionInfoW;
|
||||
if (strcmp(name, "VerQueryValueW") == 0) return (void *) version::VerQueryValueW;
|
||||
if (strcmp(name, "GetFileVersionInfoSizeA") == 0)
|
||||
return (void *)version::GetFileVersionInfoSizeA;
|
||||
if (strcmp(name, "GetFileVersionInfoA") == 0)
|
||||
return (void *)version::GetFileVersionInfoA;
|
||||
if (strcmp(name, "VerQueryValueA") == 0)
|
||||
return (void *)version::VerQueryValueA;
|
||||
if (strcmp(name, "GetFileVersionInfoSizeW") == 0)
|
||||
return (void *)version::GetFileVersionInfoSizeW;
|
||||
if (strcmp(name, "GetFileVersionInfoW") == 0)
|
||||
return (void *)version::GetFileVersionInfoW;
|
||||
if (strcmp(name, "VerQueryValueW") == 0)
|
||||
return (void *)version::VerQueryValueW;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
wibo::Module lib_version = {
|
||||
wibo::ModuleStub lib_version = {
|
||||
(const char *[]){
|
||||
"version",
|
||||
nullptr,
|
||||
|
187
src/common.h
187
src/common.h
@ -6,13 +6,9 @@
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <filesystem>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
// On Windows, the incoming stack is aligned to a 4 byte boundary.
|
||||
@ -240,10 +236,11 @@ struct TIB {
|
||||
uint16_t hostFsSelector;
|
||||
uint16_t hostGsSelector;
|
||||
uint8_t hostSegmentsValid;
|
||||
uint8_t hostSegmentsPadding[5];
|
||||
uint8_t padding[3];
|
||||
};
|
||||
|
||||
namespace wibo {
|
||||
|
||||
extern thread_local uint32_t lastError;
|
||||
extern char **argv;
|
||||
extern int argc;
|
||||
@ -257,185 +254,13 @@ extern uint16_t tibSelector;
|
||||
extern int tibEntryNumber;
|
||||
extern PEB *processPeb;
|
||||
|
||||
TIB *allocateTib();
|
||||
void destroyTib(TIB *tib);
|
||||
void initializeTibStackInfo(TIB *tib);
|
||||
bool installTibForCurrentThread(TIB *tib);
|
||||
void setThreadTibForHost(TIB *tib);
|
||||
TIB *getThreadTibForHost();
|
||||
|
||||
class HostContextGuard {
|
||||
public:
|
||||
HostContextGuard();
|
||||
~HostContextGuard();
|
||||
HostContextGuard(const HostContextGuard &) = delete;
|
||||
HostContextGuard &operator=(const HostContextGuard &) = delete;
|
||||
|
||||
private:
|
||||
uint16_t previousFs_;
|
||||
uint16_t previousGs_;
|
||||
bool restore_;
|
||||
};
|
||||
|
||||
class GuestContextGuard {
|
||||
public:
|
||||
explicit GuestContextGuard(TIB *tib);
|
||||
~GuestContextGuard();
|
||||
GuestContextGuard(const GuestContextGuard &) = delete;
|
||||
GuestContextGuard &operator=(const GuestContextGuard &) = delete;
|
||||
|
||||
private:
|
||||
uint16_t previousFs_;
|
||||
uint16_t previousGs_;
|
||||
bool applied_;
|
||||
};
|
||||
|
||||
#define HOST_CONTEXT_GUARD() wibo::HostContextGuard _wiboHostContextGuard
|
||||
#define GUEST_CONTEXT_GUARD(tibPtr) wibo::GuestContextGuard _wiboGuestContextGuard(tibPtr)
|
||||
|
||||
TIB *allocateTib();
|
||||
void initializeTibStackInfo(TIB *tib);
|
||||
bool installTibForCurrentThread(TIB *tib);
|
||||
void destroyTib(TIB *tib);
|
||||
|
||||
void debug_log(const char *fmt, ...);
|
||||
|
||||
using ResolveByName = void *(*)(const char *);
|
||||
using ResolveByOrdinal = void *(*)(uint16_t);
|
||||
struct Module {
|
||||
const char **names;
|
||||
ResolveByName byName;
|
||||
ResolveByOrdinal byOrdinal;
|
||||
};
|
||||
struct ModuleInfo;
|
||||
void initializeModuleRegistry();
|
||||
void shutdownModuleRegistry();
|
||||
ModuleInfo *moduleInfoFromHandle(HMODULE module);
|
||||
void setDllDirectoryOverride(const std::filesystem::path &path);
|
||||
void clearDllDirectoryOverride();
|
||||
std::optional<std::filesystem::path> dllDirectoryOverride();
|
||||
ModuleInfo *findLoadedModule(const char *name);
|
||||
void registerOnExitTable(void *table);
|
||||
void addOnExitFunction(void *table, void (*func)());
|
||||
void executeOnExitTable(void *table);
|
||||
void runPendingOnExit(ModuleInfo &info);
|
||||
void notifyDllThreadAttach();
|
||||
void notifyDllThreadDetach();
|
||||
BOOL disableThreadNotifications(ModuleInfo *info);
|
||||
|
||||
ModuleInfo *loadModule(const char *name);
|
||||
void freeModule(ModuleInfo *info);
|
||||
void *resolveFuncByName(ModuleInfo *info, const char *funcName);
|
||||
void *resolveFuncByOrdinal(ModuleInfo *info, uint16_t ordinal);
|
||||
void *resolveMissingImportByName(const char *dllName, const char *funcName);
|
||||
void *resolveMissingImportByOrdinal(const char *dllName, uint16_t ordinal);
|
||||
|
||||
struct ResourceIdentifier {
|
||||
ResourceIdentifier() : isString(false), id(0) {}
|
||||
static ResourceIdentifier fromID(uint32_t value) {
|
||||
ResourceIdentifier ident;
|
||||
ident.isString = false;
|
||||
ident.id = value;
|
||||
return ident;
|
||||
}
|
||||
static ResourceIdentifier fromString(std::u16string value) {
|
||||
ResourceIdentifier ident;
|
||||
ident.isString = true;
|
||||
ident.name = std::move(value);
|
||||
return ident;
|
||||
}
|
||||
bool isString;
|
||||
uint32_t id;
|
||||
std::u16string name;
|
||||
};
|
||||
|
||||
struct ResourceLocation {
|
||||
const void *dataEntry = nullptr;
|
||||
const void *data = nullptr;
|
||||
uint32_t size = 0;
|
||||
uint16_t language = 0;
|
||||
};
|
||||
|
||||
struct ImageResourceDataEntry {
|
||||
uint32_t offsetToData;
|
||||
uint32_t size;
|
||||
uint32_t codePage;
|
||||
uint32_t reserved;
|
||||
};
|
||||
|
||||
struct Executable {
|
||||
Executable() = default;
|
||||
~Executable();
|
||||
bool loadPE(FILE *file, bool exec);
|
||||
bool resolveImports();
|
||||
|
||||
struct SectionInfo {
|
||||
uintptr_t base = 0;
|
||||
size_t size = 0;
|
||||
DWORD protect = PAGE_NOACCESS;
|
||||
DWORD characteristics = 0;
|
||||
};
|
||||
|
||||
void *imageBase = nullptr;
|
||||
size_t imageSize = 0;
|
||||
void *entryPoint = nullptr;
|
||||
void *rsrcBase = nullptr;
|
||||
uint32_t rsrcSize = 0;
|
||||
uintptr_t preferredImageBase = 0;
|
||||
intptr_t relocationDelta = 0;
|
||||
uint32_t exportDirectoryRVA = 0;
|
||||
uint32_t exportDirectorySize = 0;
|
||||
uint32_t relocationDirectoryRVA = 0;
|
||||
uint32_t relocationDirectorySize = 0;
|
||||
uint32_t importDirectoryRVA = 0;
|
||||
uint32_t importDirectorySize = 0;
|
||||
uint32_t delayImportDirectoryRVA = 0;
|
||||
uint32_t delayImportDirectorySize = 0;
|
||||
bool execMapped = false;
|
||||
bool importsResolved = false;
|
||||
bool importsResolving = false;
|
||||
std::vector<SectionInfo> sections;
|
||||
|
||||
bool findResource(const ResourceIdentifier &type, const ResourceIdentifier &name, std::optional<uint16_t> language,
|
||||
ResourceLocation &out) const;
|
||||
template <typename T> T *fromRVA(uintptr_t rva) const { return (T *)(rva + (uint8_t *)imageBase); }
|
||||
template <typename T> T *fromRVA(T *rva) const { return fromRVA<T>((uintptr_t)rva); }
|
||||
};
|
||||
|
||||
extern ModuleInfo *mainModule;
|
||||
struct ModuleInfo {
|
||||
// Windows-style handle to the module. For the main module, this is the image base.
|
||||
// For other modules, this is a pointer to the ModuleInfo structure.
|
||||
HMODULE handle;
|
||||
// Original name used to load the module
|
||||
std::string originalName;
|
||||
// Normalized module name
|
||||
std::string normalizedName;
|
||||
// Full path to the loaded module
|
||||
std::filesystem::path resolvedPath;
|
||||
// Pointer to the built-in module, nullptr if loaded from file
|
||||
const wibo::Module *module = nullptr;
|
||||
// Loaded PE executable
|
||||
std::unique_ptr<wibo::Executable> executable;
|
||||
// Reference count, or UINT_MAX for built-in modules
|
||||
unsigned int refCount = 0;
|
||||
bool processAttachCalled = false;
|
||||
bool processAttachSucceeded = false;
|
||||
bool threadNotificationsEnabled = true;
|
||||
uint32_t exportOrdinalBase = 0;
|
||||
std::vector<void *> exportsByOrdinal;
|
||||
std::unordered_map<std::string, uint16_t> exportNameToOrdinal;
|
||||
bool exportsInitialized = false;
|
||||
std::vector<void *> onExitFunctions;
|
||||
};
|
||||
|
||||
ModuleInfo *registerProcessModule(std::unique_ptr<Executable> executable, std::filesystem::path resolvedPath,
|
||||
std::string originalName);
|
||||
Executable *executableFromModule(HMODULE module);
|
||||
ModuleInfo *moduleInfoFromAddress(void *addr);
|
||||
|
||||
/**
|
||||
* HMODULE will be `nullptr` or `mainModule->imageBase` if it's the main module,
|
||||
* otherwise it will be a pointer to a `wibo::ModuleInfo`.
|
||||
*/
|
||||
inline bool isMainModule(HMODULE hModule) {
|
||||
return hModule == nullptr || hModule == reinterpret_cast<HMODULE>(mainModule) ||
|
||||
(mainModule && mainModule->executable && hModule == mainModule->executable->imageBase);
|
||||
}
|
||||
} // namespace wibo
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "common.h"
|
||||
#include "context.h"
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
|
36
src/context.h
Normal file
36
src/context.h
Normal file
@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
|
||||
namespace wibo {
|
||||
|
||||
class HostContextGuard {
|
||||
public:
|
||||
HostContextGuard();
|
||||
~HostContextGuard();
|
||||
HostContextGuard(const HostContextGuard &) = delete;
|
||||
HostContextGuard &operator=(const HostContextGuard &) = delete;
|
||||
|
||||
private:
|
||||
uint16_t previousFs_;
|
||||
uint16_t previousGs_;
|
||||
bool restore_;
|
||||
};
|
||||
|
||||
class GuestContextGuard {
|
||||
public:
|
||||
explicit GuestContextGuard(TIB *tib);
|
||||
~GuestContextGuard();
|
||||
GuestContextGuard(const GuestContextGuard &) = delete;
|
||||
GuestContextGuard &operator=(const GuestContextGuard &) = delete;
|
||||
|
||||
private:
|
||||
uint16_t previousFs_;
|
||||
uint16_t previousGs_;
|
||||
bool applied_;
|
||||
};
|
||||
|
||||
} // namespace wibo
|
||||
|
||||
#define HOST_CONTEXT_GUARD() wibo::HostContextGuard _wiboHostContextGuard
|
||||
#define GUEST_CONTEXT_GUARD(tibPtr) wibo::GuestContextGuard _wiboGuestContextGuard(tibPtr)
|
@ -1,9 +1,9 @@
|
||||
#include "common.h"
|
||||
#include "errors.h"
|
||||
#include "modules.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <errno.h>
|
||||
#include <memory>
|
||||
#include <strings.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/syscall.h>
|
||||
@ -291,10 +291,11 @@ bool wibo::Executable::loadPE(FILE *file, bool exec) {
|
||||
|
||||
size_t sectionSpan = std::max(section.virtualSize, section.sizeOfRawData);
|
||||
if (sectionSpan != 0) {
|
||||
uintptr_t sectionStart = alignDown(imageBaseAddr + static_cast<uintptr_t>(section.virtualAddress), pageSizeValue);
|
||||
uintptr_t sectionStart =
|
||||
alignDown(imageBaseAddr + static_cast<uintptr_t>(section.virtualAddress), pageSizeValue);
|
||||
uintptr_t sectionEnd = alignUp(imageBaseAddr + static_cast<uintptr_t>(section.virtualAddress) +
|
||||
static_cast<uintptr_t>(sectionSpan),
|
||||
pageSizeValue);
|
||||
static_cast<uintptr_t>(sectionSpan),
|
||||
pageSizeValue);
|
||||
if (sectionEnd > sectionStart) {
|
||||
Executable::SectionInfo sectionInfo{};
|
||||
sectionInfo.base = sectionStart;
|
||||
@ -305,9 +306,8 @@ bool wibo::Executable::loadPE(FILE *file, bool exec) {
|
||||
}
|
||||
}
|
||||
}
|
||||
std::sort(sections.begin(), sections.end(), [](const SectionInfo &lhs, const SectionInfo &rhs) {
|
||||
return lhs.base < rhs.base;
|
||||
});
|
||||
std::sort(sections.begin(), sections.end(),
|
||||
[](const SectionInfo &lhs, const SectionInfo &rhs) { return lhs.base < rhs.base; });
|
||||
|
||||
if (exec && relocationDelta != 0) {
|
||||
if (relocationDirectoryRVA == 0 || relocationDirectorySize == 0) {
|
||||
|
@ -1,7 +1,10 @@
|
||||
#include "common.h"
|
||||
#include "context.h"
|
||||
#include "files.h"
|
||||
#include "modules.h"
|
||||
#include "processes.h"
|
||||
#include "strutil.h"
|
||||
|
||||
#include <asm/ldt.h>
|
||||
#include <charconv>
|
||||
#include <cstdarg>
|
||||
|
@ -1,4 +1,7 @@
|
||||
#include "modules.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "context.h"
|
||||
#include "errors.h"
|
||||
#include "files.h"
|
||||
#include "strutil.h"
|
||||
@ -17,19 +20,19 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
extern const wibo::Module lib_advapi32;
|
||||
extern const wibo::Module lib_bcrypt;
|
||||
extern const wibo::Module lib_crt;
|
||||
extern const wibo::Module lib_kernel32;
|
||||
extern const wibo::Module lib_lmgr;
|
||||
extern const wibo::Module lib_mscoree;
|
||||
extern const wibo::Module lib_msvcrt;
|
||||
extern const wibo::Module lib_ntdll;
|
||||
extern const wibo::Module lib_rpcrt4;
|
||||
extern const wibo::Module lib_ole32;
|
||||
extern const wibo::Module lib_user32;
|
||||
extern const wibo::Module lib_vcruntime;
|
||||
extern const wibo::Module lib_version;
|
||||
extern const wibo::ModuleStub lib_advapi32;
|
||||
extern const wibo::ModuleStub lib_bcrypt;
|
||||
extern const wibo::ModuleStub lib_crt;
|
||||
extern const wibo::ModuleStub lib_kernel32;
|
||||
extern const wibo::ModuleStub lib_lmgr;
|
||||
extern const wibo::ModuleStub lib_mscoree;
|
||||
extern const wibo::ModuleStub lib_msvcrt;
|
||||
extern const wibo::ModuleStub lib_ntdll;
|
||||
extern const wibo::ModuleStub lib_rpcrt4;
|
||||
extern const wibo::ModuleStub lib_ole32;
|
||||
extern const wibo::ModuleStub lib_user32;
|
||||
extern const wibo::ModuleStub lib_vcruntime;
|
||||
extern const wibo::ModuleStub lib_version;
|
||||
|
||||
namespace {
|
||||
|
||||
@ -118,16 +121,14 @@ StubFuncType resolveMissingFuncOrdinal(const char *dllName, uint16_t ordinal) {
|
||||
return resolveMissingFuncName(dllName, buf);
|
||||
}
|
||||
|
||||
using ModulePtr = std::unique_ptr<wibo::ModuleInfo>;
|
||||
|
||||
struct ModuleRegistry {
|
||||
std::recursive_mutex mutex;
|
||||
std::unordered_map<std::string, ModulePtr> modulesByKey;
|
||||
std::unordered_map<std::string, wibo::ModulePtr> modulesByKey;
|
||||
std::unordered_map<std::string, wibo::ModuleInfo *> modulesByAlias;
|
||||
std::optional<std::filesystem::path> dllDirectory;
|
||||
bool initialized = false;
|
||||
std::unordered_map<void *, wibo::ModuleInfo *> onExitTables;
|
||||
std::unordered_map<const wibo::Module *, std::vector<std::string>> builtinAliasLists;
|
||||
std::unordered_map<const wibo::ModuleStub *, std::vector<std::string>> builtinAliasLists;
|
||||
std::unordered_map<std::string, wibo::ModuleInfo *> builtinAliasMap;
|
||||
std::unordered_set<std::string> pinnedAliases;
|
||||
std::unordered_set<wibo::ModuleInfo *> pinnedModules;
|
||||
@ -150,18 +151,18 @@ struct LockedRegistry {
|
||||
ModuleRegistry &operator*() const { return *reg; }
|
||||
};
|
||||
|
||||
void registerBuiltinModule(ModuleRegistry ®, const wibo::Module *module);
|
||||
void registerBuiltinModule(ModuleRegistry ®, const wibo::ModuleStub *module);
|
||||
|
||||
LockedRegistry registry() {
|
||||
static ModuleRegistry reg;
|
||||
std::unique_lock guard(reg.mutex);
|
||||
if (!reg.initialized) {
|
||||
reg.initialized = true;
|
||||
const wibo::Module *builtins[] = {
|
||||
const wibo::ModuleStub *builtins[] = {
|
||||
&lib_advapi32, &lib_bcrypt, &lib_crt, &lib_kernel32, &lib_lmgr, &lib_mscoree, &lib_msvcrt,
|
||||
&lib_ntdll, &lib_ole32, &lib_rpcrt4, &lib_user32, &lib_vcruntime, &lib_version, nullptr,
|
||||
};
|
||||
for (const wibo::Module **module = builtins; *module; ++module) {
|
||||
for (const wibo::ModuleStub **module = builtins; *module; ++module) {
|
||||
registerBuiltinModule(reg, *module);
|
||||
}
|
||||
}
|
||||
@ -365,18 +366,18 @@ void registerAlias(ModuleRegistry ®, const std::string &alias, wibo::ModuleIn
|
||||
return;
|
||||
}
|
||||
// Prefer externally loaded modules over built-ins when both are present.
|
||||
if (it->second && it->second->module != nullptr && info->module == nullptr) {
|
||||
if (it->second && it->second->moduleStub != nullptr && info->moduleStub == nullptr) {
|
||||
reg.modulesByAlias[alias] = info;
|
||||
}
|
||||
}
|
||||
|
||||
void registerBuiltinModule(ModuleRegistry ®, const wibo::Module *module) {
|
||||
void registerBuiltinModule(ModuleRegistry ®, const wibo::ModuleStub *module) {
|
||||
if (!module) {
|
||||
return;
|
||||
}
|
||||
ModulePtr entry = std::make_unique<wibo::ModuleInfo>();
|
||||
wibo::ModulePtr entry = std::make_shared<wibo::ModuleInfo>();
|
||||
entry->handle = entry.get();
|
||||
entry->module = module;
|
||||
entry->moduleStub = module;
|
||||
entry->refCount = UINT_MAX;
|
||||
entry->originalName = module->names[0] ? module->names[0] : "";
|
||||
entry->normalizedName = normalizedBaseKey(parseModuleName(entry->originalName));
|
||||
@ -520,7 +521,7 @@ bool shouldDeliverThreadNotifications(const wibo::ModuleInfo &info) {
|
||||
if (&info == wibo::mainModule) {
|
||||
return false;
|
||||
}
|
||||
if (info.module != nullptr) {
|
||||
if (info.moduleStub != nullptr) {
|
||||
return false;
|
||||
}
|
||||
if (!info.executable) {
|
||||
@ -536,7 +537,7 @@ bool shouldDeliverThreadNotifications(const wibo::ModuleInfo &info) {
|
||||
}
|
||||
|
||||
void ensureExportsInitialized(wibo::ModuleInfo &info) {
|
||||
if (info.module || info.exportsInitialized)
|
||||
if (info.moduleStub || info.exportsInitialized)
|
||||
return;
|
||||
if (!info.executable)
|
||||
return;
|
||||
@ -604,7 +605,7 @@ ModuleInfo *registerProcessModule(std::unique_ptr<Executable> executable, std::f
|
||||
|
||||
ModulePtr info = std::make_unique<ModuleInfo>();
|
||||
info->handle = executable->imageBase; // Use image base as handle for main module
|
||||
info->module = nullptr;
|
||||
info->moduleStub = nullptr;
|
||||
info->originalName = std::move(originalName);
|
||||
info->normalizedName = std::move(normalizedName);
|
||||
info->resolvedPath = std::move(resolvedPath);
|
||||
@ -655,7 +656,7 @@ void shutdownModuleRegistry() {
|
||||
auto reg = registry();
|
||||
for (auto &pair : reg->modulesByKey) {
|
||||
ModuleInfo *info = pair.second.get();
|
||||
if (!info || info->module) {
|
||||
if (!info || info->moduleStub) {
|
||||
continue;
|
||||
}
|
||||
runPendingOnExit(*info);
|
||||
@ -877,7 +878,7 @@ ModuleInfo *loadModule(const char *dllName) {
|
||||
|
||||
ModulePtr info = std::make_unique<ModuleInfo>();
|
||||
info->handle = info.get();
|
||||
info->module = nullptr;
|
||||
info->moduleStub = nullptr;
|
||||
info->originalName = requested;
|
||||
info->normalizedName = normalizedBaseKey(parsed);
|
||||
info->resolvedPath = files::canonicalPath(path);
|
||||
@ -940,8 +941,8 @@ ModuleInfo *loadModule(const char *dllName) {
|
||||
existing = findByAlias(*reg, normalizeAlias(requested));
|
||||
}
|
||||
if (existing) {
|
||||
DEBUG_LOG(" found existing module alias %s (builtin=%d)\n", alias.c_str(), existing->module != nullptr);
|
||||
if (existing->module == nullptr) {
|
||||
DEBUG_LOG(" found existing module alias %s (builtin=%d)\n", alias.c_str(), existing->moduleStub != nullptr);
|
||||
if (existing->moduleStub == nullptr) {
|
||||
if (existing->refCount != UINT_MAX) {
|
||||
existing->refCount++;
|
||||
}
|
||||
@ -986,7 +987,7 @@ ModuleInfo *loadModule(const char *dllName) {
|
||||
builtin = builtinIt->second;
|
||||
}
|
||||
}
|
||||
if (builtin && builtin->module != nullptr) {
|
||||
if (builtin && builtin->moduleStub != nullptr) {
|
||||
DEBUG_LOG(" falling back to builtin module %s\n", builtin->originalName.c_str());
|
||||
lastError = (diskError != ERROR_SUCCESS) ? diskError : ERROR_SUCCESS;
|
||||
return builtin;
|
||||
@ -1032,14 +1033,14 @@ void *resolveFuncByName(ModuleInfo *info, const char *funcName) {
|
||||
if (!info) {
|
||||
return nullptr;
|
||||
}
|
||||
if (info->module && info->module->byName) {
|
||||
void *func = info->module->byName(funcName);
|
||||
if (info->moduleStub && info->moduleStub->byName) {
|
||||
void *func = info->moduleStub->byName(funcName);
|
||||
if (func) {
|
||||
return func;
|
||||
}
|
||||
}
|
||||
ensureExportsInitialized(*info);
|
||||
if (!info->module) {
|
||||
if (!info->moduleStub) {
|
||||
auto it = info->exportNameToOrdinal.find(funcName);
|
||||
if (it != info->exportNameToOrdinal.end()) {
|
||||
return resolveFuncByOrdinal(info, it->second);
|
||||
@ -1052,13 +1053,13 @@ void *resolveFuncByOrdinal(ModuleInfo *info, uint16_t ordinal) {
|
||||
if (!info) {
|
||||
return nullptr;
|
||||
}
|
||||
if (info->module && info->module->byOrdinal) {
|
||||
void *func = info->module->byOrdinal(ordinal);
|
||||
if (info->moduleStub && info->moduleStub->byOrdinal) {
|
||||
void *func = info->moduleStub->byOrdinal(ordinal);
|
||||
if (func) {
|
||||
return func;
|
||||
}
|
||||
}
|
||||
if (!info->module) {
|
||||
if (!info->moduleStub) {
|
||||
ensureExportsInitialized(*info);
|
||||
if (!info->exportsByOrdinal.empty() && ordinal >= info->exportOrdinalBase) {
|
||||
auto index = static_cast<size_t>(ordinal - info->exportOrdinalBase);
|
||||
@ -1109,4 +1110,9 @@ Executable *executableFromModule(HMODULE module) {
|
||||
return info->executable.get();
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, ModulePtr> allLoadedModules() {
|
||||
auto reg = registry();
|
||||
return reg->modulesByKey;
|
||||
}
|
||||
|
||||
} // namespace wibo
|
129
src/modules.h
Normal file
129
src/modules.h
Normal file
@ -0,0 +1,129 @@
|
||||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include <optional>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace wibo {
|
||||
|
||||
using ResolveByName = void *(*)(const char *);
|
||||
using ResolveByOrdinal = void *(*)(uint16_t);
|
||||
|
||||
struct ResourceIdentifier;
|
||||
struct ResourceLocation;
|
||||
|
||||
struct ModuleStub {
|
||||
const char **names;
|
||||
ResolveByName byName;
|
||||
ResolveByOrdinal byOrdinal;
|
||||
};
|
||||
|
||||
class Executable {
|
||||
public:
|
||||
struct SectionInfo {
|
||||
uintptr_t base = 0;
|
||||
size_t size = 0;
|
||||
DWORD protect = PAGE_NOACCESS;
|
||||
DWORD characteristics = 0;
|
||||
};
|
||||
|
||||
Executable() = default;
|
||||
~Executable();
|
||||
|
||||
bool loadPE(FILE *file, bool exec);
|
||||
bool resolveImports();
|
||||
bool findResource(const ResourceIdentifier &type, const ResourceIdentifier &name, std::optional<uint16_t> language,
|
||||
ResourceLocation &out) const;
|
||||
|
||||
template <typename T> T *fromRVA(uintptr_t rva) const { return (T *)(rva + (uint8_t *)imageBase); }
|
||||
template <typename T> T *fromRVA(T *rva) const { return fromRVA<T>((uintptr_t)rva); }
|
||||
|
||||
void *imageBase = nullptr;
|
||||
size_t imageSize = 0;
|
||||
void *entryPoint = nullptr;
|
||||
void *rsrcBase = nullptr;
|
||||
uint32_t rsrcSize = 0;
|
||||
uintptr_t preferredImageBase = 0;
|
||||
intptr_t relocationDelta = 0;
|
||||
uint32_t exportDirectoryRVA = 0;
|
||||
uint32_t exportDirectorySize = 0;
|
||||
uint32_t relocationDirectoryRVA = 0;
|
||||
uint32_t relocationDirectorySize = 0;
|
||||
uint32_t importDirectoryRVA = 0;
|
||||
uint32_t importDirectorySize = 0;
|
||||
uint32_t delayImportDirectoryRVA = 0;
|
||||
uint32_t delayImportDirectorySize = 0;
|
||||
bool execMapped = false;
|
||||
bool importsResolved = false;
|
||||
bool importsResolving = false;
|
||||
std::vector<SectionInfo> sections;
|
||||
};
|
||||
|
||||
struct ModuleInfo {
|
||||
// Windows-style handle to the module. For the main module, this is the image base.
|
||||
// For other modules, this is a pointer to the ModuleInfo structure.
|
||||
HMODULE handle;
|
||||
// Original name used to load the module
|
||||
std::string originalName;
|
||||
// Normalized module name
|
||||
std::string normalizedName;
|
||||
// Full path to the loaded module
|
||||
std::filesystem::path resolvedPath;
|
||||
// Pointer to the built-in module, nullptr if loaded from file
|
||||
const wibo::ModuleStub *moduleStub = nullptr;
|
||||
// Loaded PE executable
|
||||
std::unique_ptr<wibo::Executable> executable;
|
||||
// Reference count, or UINT_MAX for built-in modules
|
||||
unsigned int refCount = 0;
|
||||
bool processAttachCalled = false;
|
||||
bool processAttachSucceeded = false;
|
||||
bool threadNotificationsEnabled = true;
|
||||
uint32_t exportOrdinalBase = 0;
|
||||
std::vector<void *> exportsByOrdinal;
|
||||
std::unordered_map<std::string, uint16_t> exportNameToOrdinal;
|
||||
bool exportsInitialized = false;
|
||||
std::vector<void *> onExitFunctions;
|
||||
};
|
||||
extern ModuleInfo *mainModule;
|
||||
|
||||
using ModulePtr = std::shared_ptr<wibo::ModuleInfo>;
|
||||
|
||||
void initializeModuleRegistry();
|
||||
void shutdownModuleRegistry();
|
||||
ModuleInfo *moduleInfoFromHandle(HMODULE module);
|
||||
void setDllDirectoryOverride(const std::filesystem::path &path);
|
||||
void clearDllDirectoryOverride();
|
||||
std::optional<std::filesystem::path> dllDirectoryOverride();
|
||||
ModuleInfo *findLoadedModule(const char *name);
|
||||
void registerOnExitTable(void *table);
|
||||
void addOnExitFunction(void *table, void (*func)());
|
||||
void executeOnExitTable(void *table);
|
||||
void runPendingOnExit(ModuleInfo &info);
|
||||
void notifyDllThreadAttach();
|
||||
void notifyDllThreadDetach();
|
||||
BOOL disableThreadNotifications(ModuleInfo *info);
|
||||
std::unordered_map<std::string, ModulePtr> allLoadedModules();
|
||||
|
||||
ModuleInfo *loadModule(const char *name);
|
||||
void freeModule(ModuleInfo *info);
|
||||
void *resolveFuncByName(ModuleInfo *info, const char *funcName);
|
||||
void *resolveFuncByOrdinal(ModuleInfo *info, uint16_t ordinal);
|
||||
void *resolveMissingImportByName(const char *dllName, const char *funcName);
|
||||
void *resolveMissingImportByOrdinal(const char *dllName, uint16_t ordinal);
|
||||
|
||||
ModuleInfo *registerProcessModule(std::unique_ptr<Executable> executable, std::filesystem::path resolvedPath,
|
||||
std::string originalName);
|
||||
Executable *executableFromModule(HMODULE module);
|
||||
ModuleInfo *moduleInfoFromAddress(void *addr);
|
||||
|
||||
/**
|
||||
* HMODULE will be `nullptr` or `mainModule->imageBase` if it's the main module,
|
||||
* otherwise it will be a pointer to a `wibo::ModuleInfo`.
|
||||
*/
|
||||
inline bool isMainModule(HMODULE hModule) {
|
||||
return hModule == nullptr || hModule == reinterpret_cast<HMODULE>(mainModule) ||
|
||||
(mainModule && mainModule->executable && hModule == mainModule->executable->imageBase);
|
||||
}
|
||||
|
||||
} // namespace wibo
|
@ -1,6 +1,8 @@
|
||||
#include "resources.h"
|
||||
#include "errors.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "errors.h"
|
||||
#include "modules.h"
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -1,12 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
namespace wibo {
|
||||
|
||||
struct Executable;
|
||||
struct ImageResourceDataEntry;
|
||||
struct ResourceIdentifier;
|
||||
|
||||
struct ResourceIdentifier {
|
||||
ResourceIdentifier() : isString(false), id(0) {}
|
||||
static ResourceIdentifier fromID(uint32_t value) {
|
||||
ResourceIdentifier ident;
|
||||
ident.isString = false;
|
||||
ident.id = value;
|
||||
return ident;
|
||||
}
|
||||
static ResourceIdentifier fromString(std::u16string value) {
|
||||
ResourceIdentifier ident;
|
||||
ident.isString = true;
|
||||
ident.name = std::move(value);
|
||||
return ident;
|
||||
}
|
||||
bool isString;
|
||||
uint32_t id;
|
||||
std::u16string name;
|
||||
};
|
||||
|
||||
struct ResourceLocation {
|
||||
const void *dataEntry = nullptr;
|
||||
const void *data = nullptr;
|
||||
uint32_t size = 0;
|
||||
uint16_t language = 0;
|
||||
};
|
||||
|
||||
struct ImageResourceDataEntry {
|
||||
uint32_t offsetToData;
|
||||
uint32_t size;
|
||||
uint32_t codePage;
|
||||
uint32_t reserved;
|
||||
};
|
||||
|
||||
bool resourceEntryBelongsToExecutable(const Executable &exe, const ImageResourceDataEntry *entry);
|
||||
ResourceIdentifier resourceIdentifierFromAnsi(const char *id);
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "strutil.h"
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <cstdint>
|
||||
|
Loading…
x
Reference in New Issue
Block a user