mirror of
https://github.com/decompals/wibo.git
synced 2025-10-16 15:15:10 +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/handles.cpp
|
||||||
src/loader.cpp
|
src/loader.cpp
|
||||||
src/main.cpp
|
src/main.cpp
|
||||||
src/module_registry.cpp
|
src/modules.cpp
|
||||||
src/processes.cpp
|
src/processes.cpp
|
||||||
src/resources.cpp
|
src/resources.cpp
|
||||||
src/strutil.cpp
|
src/strutil.cpp
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
|
#include "modules.h"
|
||||||
|
|
||||||
#include "advapi32/processthreadsapi.h"
|
#include "advapi32/processthreadsapi.h"
|
||||||
#include "advapi32/securitybaseapi.h"
|
#include "advapi32/securitybaseapi.h"
|
||||||
#include "advapi32/winbase.h"
|
#include "advapi32/winbase.h"
|
||||||
#include "advapi32/wincrypt.h"
|
#include "advapi32/wincrypt.h"
|
||||||
#include "advapi32/winreg.h"
|
#include "advapi32/winreg.h"
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
@ -105,7 +106,7 @@ void *resolveByName(const char *name) {
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
wibo::Module lib_advapi32 = {
|
wibo::ModuleStub lib_advapi32 = {
|
||||||
(const char *[]){
|
(const char *[]){
|
||||||
"advapi32",
|
"advapi32",
|
||||||
nullptr,
|
nullptr,
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include "processthreadsapi.h"
|
#include "processthreadsapi.h"
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "context.h"
|
||||||
#include "errors.h"
|
#include "errors.h"
|
||||||
#include "handles.h"
|
#include "handles.h"
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include "securitybaseapi.h"
|
#include "securitybaseapi.h"
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "context.h"
|
||||||
#include "errors.h"
|
#include "errors.h"
|
||||||
#include "handles.h"
|
#include "handles.h"
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include "winbase.h"
|
#include "winbase.h"
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "context.h"
|
||||||
#include "errors.h"
|
#include "errors.h"
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#include "strutil.h"
|
#include "strutil.h"
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include "wincrypt.h"
|
#include "wincrypt.h"
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "context.h"
|
||||||
#include "errors.h"
|
#include "errors.h"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include "winreg.h"
|
#include "winreg.h"
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "context.h"
|
||||||
#include "errors.h"
|
#include "errors.h"
|
||||||
#include "handles.h"
|
#include "handles.h"
|
||||||
#include "strutil.h"
|
#include "strutil.h"
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "context.h"
|
||||||
#include "errors.h"
|
#include "errors.h"
|
||||||
|
#include "modules.h"
|
||||||
|
|
||||||
#include <sys/random.h>
|
#include <sys/random.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -72,7 +74,7 @@ static void *resolveByName(const char *name) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
wibo::Module lib_bcrypt = {
|
wibo::ModuleStub lib_bcrypt = {
|
||||||
(const char *[]){
|
(const char *[]){
|
||||||
"bcrypt",
|
"bcrypt",
|
||||||
nullptr,
|
nullptr,
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "context.h"
|
||||||
|
#include "modules.h"
|
||||||
|
|
||||||
#include <csignal>
|
#include <csignal>
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
@ -436,7 +438,7 @@ static void *resolveByName(const char *name) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
wibo::Module lib_crt = {
|
wibo::ModuleStub lib_crt = {
|
||||||
(const char *[]){
|
(const char *[]){
|
||||||
"api-ms-win-crt-heap-l1-1-0",
|
"api-ms-win-crt-heap-l1-1-0",
|
||||||
"api-ms-win-crt-locale-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/debugapi.h"
|
||||||
#include "kernel32/errhandlingapi.h"
|
#include "kernel32/errhandlingapi.h"
|
||||||
@ -600,7 +600,7 @@ void *resolveByName(const char *name) {
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
wibo::Module lib_kernel32 = {
|
wibo::ModuleStub lib_kernel32 = {
|
||||||
(const char *[]){
|
(const char *[]){
|
||||||
"kernel32",
|
"kernel32",
|
||||||
nullptr,
|
nullptr,
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include "debugapi.h"
|
#include "debugapi.h"
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "context.h"
|
||||||
#include "errors.h"
|
#include "errors.h"
|
||||||
|
|
||||||
namespace kernel32 {
|
namespace kernel32 {
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include "errhandlingapi.h"
|
#include "errhandlingapi.h"
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "context.h"
|
||||||
#include "errors.h"
|
#include "errors.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include "fibersapi.h"
|
#include "fibersapi.h"
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "context.h"
|
||||||
#include "errors.h"
|
#include "errors.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "access.h"
|
#include "access.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "context.h"
|
||||||
#include "errors.h"
|
#include "errors.h"
|
||||||
#include "files.h"
|
#include "files.h"
|
||||||
#include "handles.h"
|
#include "handles.h"
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "handleapi.h"
|
#include "handleapi.h"
|
||||||
|
|
||||||
|
#include "context.h"
|
||||||
#include "errors.h"
|
#include "errors.h"
|
||||||
#include "handles.h"
|
#include "handles.h"
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include "heapapi.h"
|
#include "heapapi.h"
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "context.h"
|
||||||
#include "errors.h"
|
#include "errors.h"
|
||||||
#include "handles.h"
|
#include "handles.h"
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include "interlockedapi.h"
|
#include "interlockedapi.h"
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "context.h"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "ioapiset.h"
|
#include "ioapiset.h"
|
||||||
|
|
||||||
|
#include "context.h"
|
||||||
#include "errors.h"
|
#include "errors.h"
|
||||||
#include "synchapi.h"
|
#include "synchapi.h"
|
||||||
|
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
#include "libloaderapi.h"
|
#include "libloaderapi.h"
|
||||||
|
|
||||||
|
#include "context.h"
|
||||||
#include "errors.h"
|
#include "errors.h"
|
||||||
#include "files.h"
|
#include "files.h"
|
||||||
|
#include "modules.h"
|
||||||
#include "resources.h"
|
#include "resources.h"
|
||||||
#include "strutil.h"
|
#include "strutil.h"
|
||||||
|
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
#include "memoryapi.h"
|
#include "memoryapi.h"
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "context.h"
|
||||||
#include "errors.h"
|
#include "errors.h"
|
||||||
#include "handles.h"
|
#include "handles.h"
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
#include "modules.h"
|
||||||
#include "strutil.h"
|
#include "strutil.h"
|
||||||
|
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
|
@ -1,14 +1,11 @@
|
|||||||
#include "namedpipeapi.h"
|
#include "namedpipeapi.h"
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "context.h"
|
||||||
#include "errors.h"
|
#include "errors.h"
|
||||||
#include "fileapi.h"
|
|
||||||
#include "files.h"
|
|
||||||
#include "handles.h"
|
#include "handles.h"
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
#include <cerrno>
|
|
||||||
#include <cstdio>
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "processenv.h"
|
#include "processenv.h"
|
||||||
|
|
||||||
|
#include "context.h"
|
||||||
#include "errors.h"
|
#include "errors.h"
|
||||||
#include "files.h"
|
#include "files.h"
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
#include "processthreadsapi.h"
|
#include "processthreadsapi.h"
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "context.h"
|
||||||
#include "errors.h"
|
#include "errors.h"
|
||||||
#include "files.h"
|
#include "files.h"
|
||||||
#include "handles.h"
|
#include "handles.h"
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
#include "modules.h"
|
||||||
#include "processes.h"
|
#include "processes.h"
|
||||||
#include "strutil.h"
|
#include "strutil.h"
|
||||||
#include "timeutil.h"
|
#include "timeutil.h"
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include "profileapi.h"
|
#include "profileapi.h"
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "context.h"
|
||||||
#include "errors.h"
|
#include "errors.h"
|
||||||
|
|
||||||
namespace kernel32 {
|
namespace kernel32 {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "stringapiset.h"
|
#include "stringapiset.h"
|
||||||
|
|
||||||
|
#include "context.h"
|
||||||
#include "errors.h"
|
#include "errors.h"
|
||||||
#include "strutil.h"
|
#include "strutil.h"
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "synchapi.h"
|
#include "synchapi.h"
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "context.h"
|
||||||
#include "errors.h"
|
#include "errors.h"
|
||||||
#include "handles.h"
|
#include "handles.h"
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include "sysinfoapi.h"
|
#include "sysinfoapi.h"
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "context.h"
|
||||||
#include "errors.h"
|
#include "errors.h"
|
||||||
#include "timeutil.h"
|
#include "timeutil.h"
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "timezoneapi.h"
|
#include "timezoneapi.h"
|
||||||
|
|
||||||
|
#include "context.h"
|
||||||
#include "errors.h"
|
#include "errors.h"
|
||||||
#include "timeutil.h"
|
#include "timeutil.h"
|
||||||
|
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
#include "winbase.h"
|
#include "winbase.h"
|
||||||
|
|
||||||
|
#include "context.h"
|
||||||
#include "errors.h"
|
#include "errors.h"
|
||||||
#include "files.h"
|
#include "files.h"
|
||||||
#include "handles.h"
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
#include "modules.h"
|
||||||
#include "strutil.h"
|
#include "strutil.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@ -13,16 +14,15 @@
|
|||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <fstream>
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <mimalloc.h>
|
#include <mimalloc.h>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
|
||||||
#include <vector>
|
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/statvfs.h>
|
#include <sys/statvfs.h>
|
||||||
#include <system_error>
|
#include <system_error>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
@ -317,6 +317,7 @@ ActivationContext *currentActivationContext() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void ensureDefaultActivationContext() {
|
void ensureDefaultActivationContext() {
|
||||||
static std::once_flag initFlag;
|
static std::once_flag initFlag;
|
||||||
std::call_once(initFlag, [] {
|
std::call_once(initFlag, [] {
|
||||||
@ -331,48 +332,10 @@ void ensureDefaultActivationContext() {
|
|||||||
entry.dllData.PathSegmentOffset = 0;
|
entry.dllData.PathSegmentOffset = 0;
|
||||||
ctx->dllRedirections.emplace_back(std::move(entry));
|
ctx->dllRedirections.emplace_back(std::move(entry));
|
||||||
};
|
};
|
||||||
addDll("msvcr80.dll");
|
for (const auto &[key, module] : wibo::allLoadedModules()) {
|
||||||
addDll("msvcp80.dll");
|
if (!module->moduleStub) {
|
||||||
addDll("mfc80.dll");
|
addDll(module->normalizedName);
|
||||||
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());
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -643,15 +606,15 @@ BOOL WIN_FUNC FindActCtxSectionStringA(DWORD dwFlags, const GUID *lpExtensionGui
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
const uint16_t *widePtr = wideStorage.empty() ? nullptr : wideStorage.data();
|
const uint16_t *widePtr = wideStorage.empty() ? nullptr : wideStorage.data();
|
||||||
return FindActCtxSectionStringW(dwFlags, lpExtensionGuid, ulSectionId,
|
return FindActCtxSectionStringW(dwFlags, lpExtensionGuid, ulSectionId, reinterpret_cast<LPCWSTR>(widePtr),
|
||||||
reinterpret_cast<LPCWSTR>(widePtr), ReturnedData);
|
ReturnedData);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL WIN_FUNC FindActCtxSectionStringW(DWORD dwFlags, const GUID *lpExtensionGuid, ULONG ulSectionId,
|
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();
|
std::string lookup = lpStringToFind ? wideStringToString(lpStringToFind) : std::string();
|
||||||
DEBUG_LOG("FindActCtxSectionStringW(%#x, %p, %u, %s, %p)\n", dwFlags, lpExtensionGuid, ulSectionId,
|
DEBUG_LOG("FindActCtxSectionStringW(%#x, %p, %u, %s, %p)\n", dwFlags, lpExtensionGuid, ulSectionId, lookup.c_str(),
|
||||||
lookup.c_str(), ReturnedData);
|
ReturnedData);
|
||||||
|
|
||||||
if (lpExtensionGuid) {
|
if (lpExtensionGuid) {
|
||||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||||
@ -701,8 +664,6 @@ BOOL WIN_FUNC FindActCtxSectionStringW(DWORD dwFlags, const GUID *lpExtensionGui
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
ensureVc80ManifestOnDisk(*matchedEntry);
|
|
||||||
|
|
||||||
ReturnedData->lpData = const_cast<ACTIVATION_CONTEXT_DATA_DLL_REDIRECTION *>(&matchedEntry->dllData);
|
ReturnedData->lpData = const_cast<ACTIVATION_CONTEXT_DATA_DLL_REDIRECTION *>(&matchedEntry->dllData);
|
||||||
ReturnedData->ulLength = matchedEntry->dllData.Size;
|
ReturnedData->ulLength = matchedEntry->dllData.Size;
|
||||||
ReturnedData->lpSectionBase = const_cast<ACTIVATION_CONTEXT_DATA_DLL_REDIRECTION *>(&matchedEntry->dllData);
|
ReturnedData->lpSectionBase = const_cast<ACTIVATION_CONTEXT_DATA_DLL_REDIRECTION *>(&matchedEntry->dllData);
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
#include "wincon.h"
|
#include "wincon.h"
|
||||||
|
|
||||||
|
#include "context.h"
|
||||||
#include "errors.h"
|
#include "errors.h"
|
||||||
#include "files.h"
|
#include "files.h"
|
||||||
|
#include "handles.h"
|
||||||
#include "strutil.h"
|
#include "strutil.h"
|
||||||
|
|
||||||
#include <cstdio>
|
|
||||||
|
|
||||||
namespace kernel32 {
|
namespace kernel32 {
|
||||||
|
|
||||||
BOOL WIN_FUNC GetConsoleMode(HANDLE hConsoleHandle, LPDWORD lpMode) {
|
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);
|
auto file = wibo::handles().getAs<FileObject>(hConsoleOutput);
|
||||||
if (file->fd == STDOUT_FILENO || file->fd == STDERR_FILENO) {
|
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());
|
dprintf(file->fd, "%s", str.c_str());
|
||||||
if (lpNumberOfCharsWritten) {
|
if (lpNumberOfCharsWritten) {
|
||||||
*lpNumberOfCharsWritten = nNumberOfCharsToWrite;
|
*lpNumberOfCharsWritten = nNumberOfCharsToWrite;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "winnls.h"
|
#include "winnls.h"
|
||||||
|
|
||||||
|
#include "context.h"
|
||||||
#include "errors.h"
|
#include "errors.h"
|
||||||
#include "strutil.h"
|
#include "strutil.h"
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "winnt.h"
|
#include "winnt.h"
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "context.h"
|
||||||
|
|
||||||
namespace kernel32 {
|
namespace kernel32 {
|
||||||
|
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
#include "wow64apiset.h"
|
#include "wow64apiset.h"
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "kernel32/internal.h"
|
#include "context.h"
|
||||||
#include "errors.h"
|
#include "errors.h"
|
||||||
#include "handles.h"
|
#include "handles.h"
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
namespace kernel32 {
|
namespace kernel32 {
|
||||||
|
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "context.h"
|
||||||
|
#include "modules.h"
|
||||||
|
|
||||||
namespace lmgr {
|
namespace lmgr {
|
||||||
int WIN_ENTRY lp_checkout(int a, int b, const char* c, const char* d, int e, const char* f, int* out) {
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
wibo::Module lib_lmgr = {
|
wibo::ModuleStub lib_lmgr = {
|
||||||
(const char *[]){
|
(const char *[]){
|
||||||
"lmgr11",
|
"lmgr11",
|
||||||
"lmgr326b",
|
"lmgr326b",
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "context.h"
|
||||||
|
#include "modules.h"
|
||||||
|
|
||||||
namespace mscoree {
|
namespace mscoree {
|
||||||
|
|
||||||
@ -16,7 +18,7 @@ static void *resolveByName(const char *name) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
wibo::Module lib_mscoree = {
|
wibo::ModuleStub lib_mscoree = {
|
||||||
(const char *[]){
|
(const char *[]){
|
||||||
"mscoree",
|
"mscoree",
|
||||||
nullptr,
|
nullptr,
|
||||||
|
@ -1,46 +1,50 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "context.h"
|
||||||
|
#include "files.h"
|
||||||
#include "kernel32/internal.h"
|
#include "kernel32/internal.h"
|
||||||
|
#include "modules.h"
|
||||||
|
#include "processes.h"
|
||||||
|
#include "strutil.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <cctype>
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
#include <climits>
|
#include <climits>
|
||||||
#include <clocale>
|
#include <clocale>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cctype>
|
#include <csignal>
|
||||||
#include <float.h>
|
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <csignal>
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <ctime>
|
||||||
#include <cwchar>
|
#include <cwchar>
|
||||||
#include <cwctype>
|
#include <cwctype>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
#include <float.h>
|
||||||
|
#include <math.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <ctime>
|
#include <spawn.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <strings.h>
|
#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/stat.h>
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/time.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
|
#ifndef O_BINARY
|
||||||
#define O_BINARY 0
|
#define O_BINARY 0
|
||||||
#endif
|
#endif
|
||||||
#include "files.h"
|
|
||||||
#include "processes.h"
|
|
||||||
#include "strutil.h"
|
|
||||||
|
|
||||||
typedef void (*_PVFV)();
|
typedef void (*_PVFV)();
|
||||||
typedef int (*_PIFV)();
|
typedef int (*_PIFV)();
|
||||||
@ -3218,7 +3222,7 @@ static void *resolveByName(const char *name) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
wibo::Module lib_msvcrt = {
|
wibo::ModuleStub lib_msvcrt = {
|
||||||
(const char *[]){
|
(const char *[]){
|
||||||
"msvcrt",
|
"msvcrt",
|
||||||
"msvcrt40",
|
"msvcrt40",
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "kernel32/internal.h"
|
#include "context.h"
|
||||||
#include "errors.h"
|
#include "errors.h"
|
||||||
#include "files.h"
|
#include "files.h"
|
||||||
#include "handles.h"
|
#include "handles.h"
|
||||||
|
#include "kernel32/internal.h"
|
||||||
#include "kernel32/processthreadsapi.h"
|
#include "kernel32/processthreadsapi.h"
|
||||||
|
#include "modules.h"
|
||||||
#include "processes.h"
|
#include "processes.h"
|
||||||
#include "strutil.h"
|
#include "strutil.h"
|
||||||
|
|
||||||
@ -408,7 +410,7 @@ static void *resolveByName(const char *name) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
wibo::Module lib_ntdll = {
|
wibo::ModuleStub lib_ntdll = {
|
||||||
(const char *[]){
|
(const char *[]){
|
||||||
"ntdll",
|
"ntdll",
|
||||||
nullptr,
|
nullptr,
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "context.h"
|
||||||
|
#include "modules.h"
|
||||||
|
|
||||||
namespace ole32 {
|
namespace ole32 {
|
||||||
int WIN_FUNC CoInitialize(void *pvReserved) {
|
int WIN_FUNC CoInitialize(void *pvReserved) {
|
||||||
@ -37,7 +39,7 @@ static void *resolveByName(const char *name) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
wibo::Module lib_ole32 = {
|
wibo::ModuleStub lib_ole32 = {
|
||||||
(const char *[]){
|
(const char *[]){
|
||||||
"ole32",
|
"ole32",
|
||||||
nullptr,
|
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 "common.h"
|
||||||
|
#include "context.h"
|
||||||
|
#include "modules.h"
|
||||||
|
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
@ -283,7 +285,7 @@ void *resolveByName(const char *name) {
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
wibo::Module lib_rpcrt4 = {
|
wibo::ModuleStub lib_rpcrt4 = {
|
||||||
(const char *[]){"rpcrt4", nullptr},
|
(const char *[]){"rpcrt4", nullptr},
|
||||||
resolveByName,
|
resolveByName,
|
||||||
nullptr,
|
nullptr,
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "context.h"
|
||||||
#include "errors.h"
|
#include "errors.h"
|
||||||
#include "strutil.h"
|
#include "modules.h"
|
||||||
|
#include "resources.h"
|
||||||
|
|
||||||
namespace user32 {
|
namespace user32 {
|
||||||
constexpr uint32_t RT_STRING_ID = 6;
|
constexpr uint32_t RT_STRING_ID = 6;
|
||||||
@ -186,7 +188,7 @@ static void *resolveByName(const char *name) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
wibo::Module lib_user32 = {
|
wibo::ModuleStub lib_user32 = {
|
||||||
(const char *[]){
|
(const char *[]){
|
||||||
"user32",
|
"user32",
|
||||||
nullptr,
|
nullptr,
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "context.h"
|
||||||
|
#include "modules.h"
|
||||||
|
|
||||||
namespace vcruntime {
|
namespace vcruntime {
|
||||||
|
|
||||||
@ -36,7 +38,7 @@ static void *resolveByName(const char *name) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
wibo::Module lib_vcruntime = {
|
wibo::ModuleStub lib_vcruntime = {
|
||||||
(const char *[]){
|
(const char *[]){
|
||||||
"vcruntime140",
|
"vcruntime140",
|
||||||
nullptr,
|
nullptr,
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "context.h"
|
||||||
#include "errors.h"
|
#include "errors.h"
|
||||||
#include "files.h"
|
#include "files.h"
|
||||||
|
#include "modules.h"
|
||||||
#include "resources.h"
|
#include "resources.h"
|
||||||
#include "strutil.h"
|
#include "strutil.h"
|
||||||
|
|
||||||
@ -14,13 +16,9 @@ namespace {
|
|||||||
|
|
||||||
constexpr uint32_t RT_VERSION = 16;
|
constexpr uint32_t RT_VERSION = 16;
|
||||||
|
|
||||||
static uint16_t readU16(const uint8_t *ptr) {
|
static uint16_t readU16(const uint8_t *ptr) { return static_cast<uint16_t>(ptr[0] | (ptr[1] << 8)); }
|
||||||
return static_cast<uint16_t>(ptr[0] | (ptr[1] << 8));
|
|
||||||
}
|
|
||||||
|
|
||||||
static size_t align4(size_t offset) {
|
static size_t align4(size_t offset) { return (offset + 3u) & ~static_cast<size_t>(3u); }
|
||||||
return (offset + 3u) & ~static_cast<size_t>(3u);
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::string narrowKey(const std::u16string &key) {
|
static std::string narrowKey(const std::u16string &key) {
|
||||||
std::string result;
|
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);
|
cursor = block + sizeof(uint16_t) * 3 + (out.key.size() + 1) * sizeof(uint16_t);
|
||||||
if (cursor > end) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,8 +77,8 @@ static bool parseVersionBlock(const uint8_t *block, size_t available, VersionBlo
|
|||||||
|
|
||||||
uint32_t valueBytes = 0;
|
uint32_t valueBytes = 0;
|
||||||
if (valueLength) {
|
if (valueLength) {
|
||||||
valueBytes = type == 1 ? static_cast<uint32_t>(valueLength) * sizeof(uint16_t)
|
valueBytes =
|
||||||
: static_cast<uint32_t>(valueLength);
|
type == 1 ? static_cast<uint32_t>(valueLength) * sizeof(uint16_t) : static_cast<uint32_t>(valueLength);
|
||||||
if (cursor + valueBytes > end) {
|
if (cursor + valueBytes > end) {
|
||||||
DEBUG_LOG("value beyond block: bytes=%u remaining=%zu\n", valueBytes, static_cast<size_t>(end - cursor));
|
DEBUG_LOG("value beyond block: bytes=%u remaining=%zu\n", valueBytes, static_cast<size_t>(end - cursor));
|
||||||
return false;
|
return false;
|
||||||
@ -100,12 +99,8 @@ static bool parseVersionBlock(const uint8_t *block, size_t available, VersionBlo
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool queryVersionBlock(const uint8_t *block, size_t available,
|
static bool queryVersionBlock(const uint8_t *block, size_t available, const std::vector<std::string> &segments,
|
||||||
const std::vector<std::string> &segments,
|
size_t depth, const uint8_t **outPtr, uint32_t *outLen, uint16_t *outType) {
|
||||||
size_t depth,
|
|
||||||
const uint8_t **outPtr,
|
|
||||||
uint32_t *outLen,
|
|
||||||
uint16_t *outType) {
|
|
||||||
VersionBlockView view;
|
VersionBlockView view;
|
||||||
if (!parseVersionBlock(block, available, view))
|
if (!parseVersionBlock(block, available, view))
|
||||||
return false;
|
return false;
|
||||||
@ -217,9 +212,10 @@ unsigned int WIN_FUNC GetFileVersionInfoSizeA(const char *lptstrFilename, unsign
|
|||||||
return static_cast<unsigned int>(buffer.size());
|
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();
|
HOST_CONTEXT_GUARD();
|
||||||
(void) dwHandle;
|
(void)dwHandle;
|
||||||
DEBUG_LOG("GetFileVersionInfoA(%s, %u, %p)\n", lptstrFilename, dwLen, lpData);
|
DEBUG_LOG("GetFileVersionInfoA(%s, %u, %p)\n", lptstrFilename, dwLen, lpData);
|
||||||
if (!lpData || dwLen == 0) {
|
if (!lpData || dwLen == 0) {
|
||||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||||
@ -243,7 +239,8 @@ unsigned int WIN_FUNC GetFileVersionInfoA(const char *lptstrFilename, unsigned i
|
|||||||
return 1;
|
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)
|
if (!pBlock)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -280,7 +277,8 @@ static unsigned int VerQueryValueImpl(const void *pBlock, const std::string &sub
|
|||||||
return 1;
|
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();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("VerQueryValueA(%p, %s, %p, %p)\n", pBlock, lpSubBlock ? lpSubBlock : "(null)", lplpBuffer, puLen);
|
DEBUG_LOG("VerQueryValueA(%p, %s, %p, %p)\n", pBlock, lpSubBlock ? lpSubBlock : "(null)", lplpBuffer, puLen);
|
||||||
if (!lpSubBlock)
|
if (!lpSubBlock)
|
||||||
@ -295,14 +293,16 @@ unsigned int WIN_FUNC GetFileVersionInfoSizeW(const uint16_t *lptstrFilename, un
|
|||||||
return GetFileVersionInfoSizeA(narrow.c_str(), lpdwHandle);
|
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();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("GetFileVersionInfoW -> ");
|
DEBUG_LOG("GetFileVersionInfoW -> ");
|
||||||
auto narrow = wideStringToString(lptstrFilename);
|
auto narrow = wideStringToString(lptstrFilename);
|
||||||
return GetFileVersionInfoA(narrow.c_str(), dwHandle, dwLen, lpData);
|
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();
|
HOST_CONTEXT_GUARD();
|
||||||
if (!lpSubBlock)
|
if (!lpSubBlock)
|
||||||
return 0;
|
return 0;
|
||||||
@ -314,16 +314,22 @@ unsigned int WIN_FUNC VerQueryValueW(const void *pBlock, const uint16_t *lpSubBl
|
|||||||
} // namespace version
|
} // namespace version
|
||||||
|
|
||||||
static void *resolveByName(const char *name) {
|
static void *resolveByName(const char *name) {
|
||||||
if (strcmp(name, "GetFileVersionInfoSizeA") == 0) return (void *) version::GetFileVersionInfoSizeA;
|
if (strcmp(name, "GetFileVersionInfoSizeA") == 0)
|
||||||
if (strcmp(name, "GetFileVersionInfoA") == 0) return (void *) version::GetFileVersionInfoA;
|
return (void *)version::GetFileVersionInfoSizeA;
|
||||||
if (strcmp(name, "VerQueryValueA") == 0) return (void *) version::VerQueryValueA;
|
if (strcmp(name, "GetFileVersionInfoA") == 0)
|
||||||
if (strcmp(name, "GetFileVersionInfoSizeW") == 0) return (void *) version::GetFileVersionInfoSizeW;
|
return (void *)version::GetFileVersionInfoA;
|
||||||
if (strcmp(name, "GetFileVersionInfoW") == 0) return (void *) version::GetFileVersionInfoW;
|
if (strcmp(name, "VerQueryValueA") == 0)
|
||||||
if (strcmp(name, "VerQueryValueW") == 0) return (void *) version::VerQueryValueW;
|
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;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
wibo::Module lib_version = {
|
wibo::ModuleStub lib_version = {
|
||||||
(const char *[]){
|
(const char *[]){
|
||||||
"version",
|
"version",
|
||||||
nullptr,
|
nullptr,
|
||||||
|
187
src/common.h
187
src/common.h
@ -6,13 +6,9 @@
|
|||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <memory>
|
|
||||||
#include <optional>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <unordered_map>
|
|
||||||
#include <utility>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
// On Windows, the incoming stack is aligned to a 4 byte boundary.
|
// On Windows, the incoming stack is aligned to a 4 byte boundary.
|
||||||
@ -240,10 +236,11 @@ struct TIB {
|
|||||||
uint16_t hostFsSelector;
|
uint16_t hostFsSelector;
|
||||||
uint16_t hostGsSelector;
|
uint16_t hostGsSelector;
|
||||||
uint8_t hostSegmentsValid;
|
uint8_t hostSegmentsValid;
|
||||||
uint8_t hostSegmentsPadding[5];
|
uint8_t padding[3];
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace wibo {
|
namespace wibo {
|
||||||
|
|
||||||
extern thread_local uint32_t lastError;
|
extern thread_local uint32_t lastError;
|
||||||
extern char **argv;
|
extern char **argv;
|
||||||
extern int argc;
|
extern int argc;
|
||||||
@ -257,185 +254,13 @@ extern uint16_t tibSelector;
|
|||||||
extern int tibEntryNumber;
|
extern int tibEntryNumber;
|
||||||
extern PEB *processPeb;
|
extern PEB *processPeb;
|
||||||
|
|
||||||
|
TIB *allocateTib();
|
||||||
|
void destroyTib(TIB *tib);
|
||||||
|
void initializeTibStackInfo(TIB *tib);
|
||||||
|
bool installTibForCurrentThread(TIB *tib);
|
||||||
void setThreadTibForHost(TIB *tib);
|
void setThreadTibForHost(TIB *tib);
|
||||||
TIB *getThreadTibForHost();
|
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, ...);
|
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
|
} // namespace wibo
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#include "common.h"
|
#include "context.h"
|
||||||
|
|
||||||
#include <cstddef>
|
#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 "common.h"
|
||||||
#include "errors.h"
|
#include "errors.h"
|
||||||
|
#include "modules.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <errno.h>
|
|
||||||
#include <memory>
|
|
||||||
#include <strings.h>
|
#include <strings.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
@ -291,7 +291,8 @@ bool wibo::Executable::loadPE(FILE *file, bool exec) {
|
|||||||
|
|
||||||
size_t sectionSpan = std::max(section.virtualSize, section.sizeOfRawData);
|
size_t sectionSpan = std::max(section.virtualSize, section.sizeOfRawData);
|
||||||
if (sectionSpan != 0) {
|
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) +
|
uintptr_t sectionEnd = alignUp(imageBaseAddr + static_cast<uintptr_t>(section.virtualAddress) +
|
||||||
static_cast<uintptr_t>(sectionSpan),
|
static_cast<uintptr_t>(sectionSpan),
|
||||||
pageSizeValue);
|
pageSizeValue);
|
||||||
@ -305,9 +306,8 @@ bool wibo::Executable::loadPE(FILE *file, bool exec) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::sort(sections.begin(), sections.end(), [](const SectionInfo &lhs, const SectionInfo &rhs) {
|
std::sort(sections.begin(), sections.end(),
|
||||||
return lhs.base < rhs.base;
|
[](const SectionInfo &lhs, const SectionInfo &rhs) { return lhs.base < rhs.base; });
|
||||||
});
|
|
||||||
|
|
||||||
if (exec && relocationDelta != 0) {
|
if (exec && relocationDelta != 0) {
|
||||||
if (relocationDirectoryRVA == 0 || relocationDirectorySize == 0) {
|
if (relocationDirectoryRVA == 0 || relocationDirectorySize == 0) {
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "context.h"
|
||||||
#include "files.h"
|
#include "files.h"
|
||||||
|
#include "modules.h"
|
||||||
#include "processes.h"
|
#include "processes.h"
|
||||||
#include "strutil.h"
|
#include "strutil.h"
|
||||||
|
|
||||||
#include <asm/ldt.h>
|
#include <asm/ldt.h>
|
||||||
#include <charconv>
|
#include <charconv>
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
|
#include "modules.h"
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "context.h"
|
||||||
#include "errors.h"
|
#include "errors.h"
|
||||||
#include "files.h"
|
#include "files.h"
|
||||||
#include "strutil.h"
|
#include "strutil.h"
|
||||||
@ -17,19 +20,19 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
extern const wibo::Module lib_advapi32;
|
extern const wibo::ModuleStub lib_advapi32;
|
||||||
extern const wibo::Module lib_bcrypt;
|
extern const wibo::ModuleStub lib_bcrypt;
|
||||||
extern const wibo::Module lib_crt;
|
extern const wibo::ModuleStub lib_crt;
|
||||||
extern const wibo::Module lib_kernel32;
|
extern const wibo::ModuleStub lib_kernel32;
|
||||||
extern const wibo::Module lib_lmgr;
|
extern const wibo::ModuleStub lib_lmgr;
|
||||||
extern const wibo::Module lib_mscoree;
|
extern const wibo::ModuleStub lib_mscoree;
|
||||||
extern const wibo::Module lib_msvcrt;
|
extern const wibo::ModuleStub lib_msvcrt;
|
||||||
extern const wibo::Module lib_ntdll;
|
extern const wibo::ModuleStub lib_ntdll;
|
||||||
extern const wibo::Module lib_rpcrt4;
|
extern const wibo::ModuleStub lib_rpcrt4;
|
||||||
extern const wibo::Module lib_ole32;
|
extern const wibo::ModuleStub lib_ole32;
|
||||||
extern const wibo::Module lib_user32;
|
extern const wibo::ModuleStub lib_user32;
|
||||||
extern const wibo::Module lib_vcruntime;
|
extern const wibo::ModuleStub lib_vcruntime;
|
||||||
extern const wibo::Module lib_version;
|
extern const wibo::ModuleStub lib_version;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
@ -118,16 +121,14 @@ StubFuncType resolveMissingFuncOrdinal(const char *dllName, uint16_t ordinal) {
|
|||||||
return resolveMissingFuncName(dllName, buf);
|
return resolveMissingFuncName(dllName, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
using ModulePtr = std::unique_ptr<wibo::ModuleInfo>;
|
|
||||||
|
|
||||||
struct ModuleRegistry {
|
struct ModuleRegistry {
|
||||||
std::recursive_mutex mutex;
|
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::unordered_map<std::string, wibo::ModuleInfo *> modulesByAlias;
|
||||||
std::optional<std::filesystem::path> dllDirectory;
|
std::optional<std::filesystem::path> dllDirectory;
|
||||||
bool initialized = false;
|
bool initialized = false;
|
||||||
std::unordered_map<void *, wibo::ModuleInfo *> onExitTables;
|
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_map<std::string, wibo::ModuleInfo *> builtinAliasMap;
|
||||||
std::unordered_set<std::string> pinnedAliases;
|
std::unordered_set<std::string> pinnedAliases;
|
||||||
std::unordered_set<wibo::ModuleInfo *> pinnedModules;
|
std::unordered_set<wibo::ModuleInfo *> pinnedModules;
|
||||||
@ -150,18 +151,18 @@ struct LockedRegistry {
|
|||||||
ModuleRegistry &operator*() const { return *reg; }
|
ModuleRegistry &operator*() const { return *reg; }
|
||||||
};
|
};
|
||||||
|
|
||||||
void registerBuiltinModule(ModuleRegistry ®, const wibo::Module *module);
|
void registerBuiltinModule(ModuleRegistry ®, const wibo::ModuleStub *module);
|
||||||
|
|
||||||
LockedRegistry registry() {
|
LockedRegistry registry() {
|
||||||
static ModuleRegistry reg;
|
static ModuleRegistry reg;
|
||||||
std::unique_lock guard(reg.mutex);
|
std::unique_lock guard(reg.mutex);
|
||||||
if (!reg.initialized) {
|
if (!reg.initialized) {
|
||||||
reg.initialized = true;
|
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_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,
|
&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);
|
registerBuiltinModule(reg, *module);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -365,18 +366,18 @@ void registerAlias(ModuleRegistry ®, const std::string &alias, wibo::ModuleIn
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Prefer externally loaded modules over built-ins when both are present.
|
// 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;
|
reg.modulesByAlias[alias] = info;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void registerBuiltinModule(ModuleRegistry ®, const wibo::Module *module) {
|
void registerBuiltinModule(ModuleRegistry ®, const wibo::ModuleStub *module) {
|
||||||
if (!module) {
|
if (!module) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ModulePtr entry = std::make_unique<wibo::ModuleInfo>();
|
wibo::ModulePtr entry = std::make_shared<wibo::ModuleInfo>();
|
||||||
entry->handle = entry.get();
|
entry->handle = entry.get();
|
||||||
entry->module = module;
|
entry->moduleStub = module;
|
||||||
entry->refCount = UINT_MAX;
|
entry->refCount = UINT_MAX;
|
||||||
entry->originalName = module->names[0] ? module->names[0] : "";
|
entry->originalName = module->names[0] ? module->names[0] : "";
|
||||||
entry->normalizedName = normalizedBaseKey(parseModuleName(entry->originalName));
|
entry->normalizedName = normalizedBaseKey(parseModuleName(entry->originalName));
|
||||||
@ -520,7 +521,7 @@ bool shouldDeliverThreadNotifications(const wibo::ModuleInfo &info) {
|
|||||||
if (&info == wibo::mainModule) {
|
if (&info == wibo::mainModule) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (info.module != nullptr) {
|
if (info.moduleStub != nullptr) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!info.executable) {
|
if (!info.executable) {
|
||||||
@ -536,7 +537,7 @@ bool shouldDeliverThreadNotifications(const wibo::ModuleInfo &info) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ensureExportsInitialized(wibo::ModuleInfo &info) {
|
void ensureExportsInitialized(wibo::ModuleInfo &info) {
|
||||||
if (info.module || info.exportsInitialized)
|
if (info.moduleStub || info.exportsInitialized)
|
||||||
return;
|
return;
|
||||||
if (!info.executable)
|
if (!info.executable)
|
||||||
return;
|
return;
|
||||||
@ -604,7 +605,7 @@ ModuleInfo *registerProcessModule(std::unique_ptr<Executable> executable, std::f
|
|||||||
|
|
||||||
ModulePtr info = std::make_unique<ModuleInfo>();
|
ModulePtr info = std::make_unique<ModuleInfo>();
|
||||||
info->handle = executable->imageBase; // Use image base as handle for main module
|
info->handle = executable->imageBase; // Use image base as handle for main module
|
||||||
info->module = nullptr;
|
info->moduleStub = nullptr;
|
||||||
info->originalName = std::move(originalName);
|
info->originalName = std::move(originalName);
|
||||||
info->normalizedName = std::move(normalizedName);
|
info->normalizedName = std::move(normalizedName);
|
||||||
info->resolvedPath = std::move(resolvedPath);
|
info->resolvedPath = std::move(resolvedPath);
|
||||||
@ -655,7 +656,7 @@ void shutdownModuleRegistry() {
|
|||||||
auto reg = registry();
|
auto reg = registry();
|
||||||
for (auto &pair : reg->modulesByKey) {
|
for (auto &pair : reg->modulesByKey) {
|
||||||
ModuleInfo *info = pair.second.get();
|
ModuleInfo *info = pair.second.get();
|
||||||
if (!info || info->module) {
|
if (!info || info->moduleStub) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
runPendingOnExit(*info);
|
runPendingOnExit(*info);
|
||||||
@ -877,7 +878,7 @@ ModuleInfo *loadModule(const char *dllName) {
|
|||||||
|
|
||||||
ModulePtr info = std::make_unique<ModuleInfo>();
|
ModulePtr info = std::make_unique<ModuleInfo>();
|
||||||
info->handle = info.get();
|
info->handle = info.get();
|
||||||
info->module = nullptr;
|
info->moduleStub = nullptr;
|
||||||
info->originalName = requested;
|
info->originalName = requested;
|
||||||
info->normalizedName = normalizedBaseKey(parsed);
|
info->normalizedName = normalizedBaseKey(parsed);
|
||||||
info->resolvedPath = files::canonicalPath(path);
|
info->resolvedPath = files::canonicalPath(path);
|
||||||
@ -940,8 +941,8 @@ ModuleInfo *loadModule(const char *dllName) {
|
|||||||
existing = findByAlias(*reg, normalizeAlias(requested));
|
existing = findByAlias(*reg, normalizeAlias(requested));
|
||||||
}
|
}
|
||||||
if (existing) {
|
if (existing) {
|
||||||
DEBUG_LOG(" found existing module alias %s (builtin=%d)\n", alias.c_str(), existing->module != nullptr);
|
DEBUG_LOG(" found existing module alias %s (builtin=%d)\n", alias.c_str(), existing->moduleStub != nullptr);
|
||||||
if (existing->module == nullptr) {
|
if (existing->moduleStub == nullptr) {
|
||||||
if (existing->refCount != UINT_MAX) {
|
if (existing->refCount != UINT_MAX) {
|
||||||
existing->refCount++;
|
existing->refCount++;
|
||||||
}
|
}
|
||||||
@ -986,7 +987,7 @@ ModuleInfo *loadModule(const char *dllName) {
|
|||||||
builtin = builtinIt->second;
|
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());
|
DEBUG_LOG(" falling back to builtin module %s\n", builtin->originalName.c_str());
|
||||||
lastError = (diskError != ERROR_SUCCESS) ? diskError : ERROR_SUCCESS;
|
lastError = (diskError != ERROR_SUCCESS) ? diskError : ERROR_SUCCESS;
|
||||||
return builtin;
|
return builtin;
|
||||||
@ -1032,14 +1033,14 @@ void *resolveFuncByName(ModuleInfo *info, const char *funcName) {
|
|||||||
if (!info) {
|
if (!info) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
if (info->module && info->module->byName) {
|
if (info->moduleStub && info->moduleStub->byName) {
|
||||||
void *func = info->module->byName(funcName);
|
void *func = info->moduleStub->byName(funcName);
|
||||||
if (func) {
|
if (func) {
|
||||||
return func;
|
return func;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ensureExportsInitialized(*info);
|
ensureExportsInitialized(*info);
|
||||||
if (!info->module) {
|
if (!info->moduleStub) {
|
||||||
auto it = info->exportNameToOrdinal.find(funcName);
|
auto it = info->exportNameToOrdinal.find(funcName);
|
||||||
if (it != info->exportNameToOrdinal.end()) {
|
if (it != info->exportNameToOrdinal.end()) {
|
||||||
return resolveFuncByOrdinal(info, it->second);
|
return resolveFuncByOrdinal(info, it->second);
|
||||||
@ -1052,13 +1053,13 @@ void *resolveFuncByOrdinal(ModuleInfo *info, uint16_t ordinal) {
|
|||||||
if (!info) {
|
if (!info) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
if (info->module && info->module->byOrdinal) {
|
if (info->moduleStub && info->moduleStub->byOrdinal) {
|
||||||
void *func = info->module->byOrdinal(ordinal);
|
void *func = info->moduleStub->byOrdinal(ordinal);
|
||||||
if (func) {
|
if (func) {
|
||||||
return func;
|
return func;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!info->module) {
|
if (!info->moduleStub) {
|
||||||
ensureExportsInitialized(*info);
|
ensureExportsInitialized(*info);
|
||||||
if (!info->exportsByOrdinal.empty() && ordinal >= info->exportOrdinalBase) {
|
if (!info->exportsByOrdinal.empty() && ordinal >= info->exportOrdinalBase) {
|
||||||
auto index = static_cast<size_t>(ordinal - info->exportOrdinalBase);
|
auto index = static_cast<size_t>(ordinal - info->exportOrdinalBase);
|
||||||
@ -1109,4 +1110,9 @@ Executable *executableFromModule(HMODULE module) {
|
|||||||
return info->executable.get();
|
return info->executable.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unordered_map<std::string, ModulePtr> allLoadedModules() {
|
||||||
|
auto reg = registry();
|
||||||
|
return reg->modulesByKey;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace wibo
|
} // 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 "resources.h"
|
||||||
#include "errors.h"
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "errors.h"
|
||||||
|
#include "modules.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
@ -1,12 +1,44 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace wibo {
|
namespace wibo {
|
||||||
|
|
||||||
struct Executable;
|
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);
|
bool resourceEntryBelongsToExecutable(const Executable &exe, const ImageResourceDataEntry *entry);
|
||||||
ResourceIdentifier resourceIdentifierFromAnsi(const char *id);
|
ResourceIdentifier resourceIdentifierFromAnsi(const char *id);
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include "strutil.h"
|
#include "strutil.h"
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user