mirror of
https://github.com/decompals/wibo.git
synced 2025-12-16 16:37:12 +00:00
LoadLibraryA: Skip import resolution & DllMain for EXEs
This commit is contained in:
@@ -196,6 +196,7 @@ add_executable(wibo
|
||||
dll/user32.cpp
|
||||
dll/vcruntime.cpp
|
||||
dll/version.cpp
|
||||
dll/ws2.cpp
|
||||
src/access.cpp
|
||||
src/async_io.cpp
|
||||
src/errors.cpp
|
||||
|
||||
@@ -153,7 +153,7 @@ DWORD WINAPI GetModuleFileNameW(HMODULE hModule, LPWSTR lpFilename, DWORD nSize)
|
||||
|
||||
HRSRC WINAPI FindResourceA(HMODULE hModule, LPCSTR lpName, LPCSTR lpType) {
|
||||
HOST_CONTEXT_GUARD();
|
||||
DEBUG_LOG("FindResourceA %p %p %p\n", hModule, lpName, lpType);
|
||||
DEBUG_LOG("FindResourceA(%p, %s, %s)\n", hModule, lpName, lpType);
|
||||
auto type = wibo::resourceIdentifierFromAnsi(lpType);
|
||||
auto name = wibo::resourceIdentifierFromAnsi(lpName);
|
||||
return findResourceInternal(hModule, type, name, std::nullopt);
|
||||
@@ -161,7 +161,7 @@ HRSRC WINAPI FindResourceA(HMODULE hModule, LPCSTR lpName, LPCSTR lpType) {
|
||||
|
||||
HRSRC WINAPI FindResourceExA(HMODULE hModule, LPCSTR lpType, LPCSTR lpName, WORD wLanguage) {
|
||||
HOST_CONTEXT_GUARD();
|
||||
DEBUG_LOG("FindResourceExA %p %p %p %u\n", hModule, lpName, lpType, wLanguage);
|
||||
DEBUG_LOG("FindResourceExA(%p, %s, %s, %u)\n", hModule, lpName, lpType, wLanguage);
|
||||
auto type = wibo::resourceIdentifierFromAnsi(lpType);
|
||||
auto name = wibo::resourceIdentifierFromAnsi(lpName);
|
||||
return findResourceInternal(hModule, type, name, wLanguage);
|
||||
@@ -169,7 +169,7 @@ HRSRC WINAPI FindResourceExA(HMODULE hModule, LPCSTR lpType, LPCSTR lpName, WORD
|
||||
|
||||
HRSRC WINAPI FindResourceW(HMODULE hModule, LPCWSTR lpName, LPCWSTR lpType) {
|
||||
HOST_CONTEXT_GUARD();
|
||||
DEBUG_LOG("FindResourceW %p\n", hModule);
|
||||
DEBUG_LOG("FindResourceW(%p, %p, %p)\n", hModule, lpName, lpType);
|
||||
auto type = wibo::resourceIdentifierFromWide(lpType);
|
||||
auto name = wibo::resourceIdentifierFromWide(lpName);
|
||||
return findResourceInternal(hModule, type, name, std::nullopt);
|
||||
@@ -177,7 +177,7 @@ HRSRC WINAPI FindResourceW(HMODULE hModule, LPCWSTR lpName, LPCWSTR lpType) {
|
||||
|
||||
HRSRC WINAPI FindResourceExW(HMODULE hModule, LPCWSTR lpType, LPCWSTR lpName, WORD wLanguage) {
|
||||
HOST_CONTEXT_GUARD();
|
||||
DEBUG_LOG("FindResourceExW %p %u\n", hModule, wLanguage);
|
||||
DEBUG_LOG("FindResourceExW(%p, %p, %p, %u)\n", hModule, lpName, lpType, wLanguage);
|
||||
auto type = wibo::resourceIdentifierFromWide(lpType);
|
||||
auto name = wibo::resourceIdentifierFromWide(lpName);
|
||||
return findResourceInternal(hModule, type, name, wLanguage);
|
||||
@@ -185,7 +185,7 @@ HRSRC WINAPI FindResourceExW(HMODULE hModule, LPCWSTR lpType, LPCWSTR lpName, WO
|
||||
|
||||
HGLOBAL WINAPI LoadResource(HMODULE hModule, HRSRC hResInfo) {
|
||||
HOST_CONTEXT_GUARD();
|
||||
DEBUG_LOG("LoadResource %p %p\n", hModule, hResInfo);
|
||||
DEBUG_LOG("LoadResource(%p, %p)\n", hModule, hResInfo);
|
||||
if (!hResInfo) {
|
||||
setLastError(ERROR_RESOURCE_DATA_NOT_FOUND);
|
||||
return GUEST_NULL;
|
||||
|
||||
@@ -1125,10 +1125,12 @@ BOOL WINAPI InitOnceBeginInitialize(LPINIT_ONCE lpInitOnce, DWORD dwFlags, PBOOL
|
||||
HOST_CONTEXT_GUARD();
|
||||
DEBUG_LOG("InitOnceBeginInitialize(%p, %u, %p, %p)\n", lpInitOnce, dwFlags, fPending, lpContext);
|
||||
if (!lpInitOnce) {
|
||||
DEBUG_LOG("-> ERROR_INVALID_PARAMETER\n");
|
||||
setLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
if (dwFlags & ~(INIT_ONCE_CHECK_ONLY | INIT_ONCE_ASYNC)) {
|
||||
DEBUG_LOG("-> ERROR_INVALID_PARAMETER\n");
|
||||
setLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
@@ -1137,6 +1139,7 @@ BOOL WINAPI InitOnceBeginInitialize(LPINIT_ONCE lpInitOnce, DWORD dwFlags, PBOOL
|
||||
|
||||
if (dwFlags & INIT_ONCE_CHECK_ONLY) {
|
||||
if (dwFlags & INIT_ONCE_ASYNC) {
|
||||
DEBUG_LOG("-> ERROR_INVALID_PARAMETER\n");
|
||||
setLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
@@ -1145,6 +1148,7 @@ BOOL WINAPI InitOnceBeginInitialize(LPINIT_ONCE lpInitOnce, DWORD dwFlags, PBOOL
|
||||
if (fPending) {
|
||||
*fPending = TRUE;
|
||||
}
|
||||
DEBUG_LOG("-> ERROR_GEN_FAILURE\n");
|
||||
setLastError(ERROR_GEN_FAILURE);
|
||||
return FALSE;
|
||||
}
|
||||
@@ -1186,6 +1190,7 @@ BOOL WINAPI InitOnceBeginInitialize(LPINIT_ONCE lpInitOnce, DWORD dwFlags, PBOOL
|
||||
}
|
||||
case 1: { // synchronous initialization in progress
|
||||
if (dwFlags & INIT_ONCE_ASYNC) {
|
||||
DEBUG_LOG("-> ERROR_INVALID_PARAMETER\n");
|
||||
setLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
@@ -1222,6 +1227,7 @@ BOOL WINAPI InitOnceBeginInitialize(LPINIT_ONCE lpInitOnce, DWORD dwFlags, PBOOL
|
||||
}
|
||||
case 3: { // async pending
|
||||
if (!(dwFlags & INIT_ONCE_ASYNC)) {
|
||||
DEBUG_LOG("-> ERROR_INVALID_PARAMETER\n");
|
||||
setLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
@@ -1240,20 +1246,24 @@ BOOL WINAPI InitOnceComplete(LPINIT_ONCE lpInitOnce, DWORD dwFlags, LPVOID lpCon
|
||||
HOST_CONTEXT_GUARD();
|
||||
DEBUG_LOG("InitOnceComplete(%p, %u, %p)\n", lpInitOnce, dwFlags, lpContext);
|
||||
if (!lpInitOnce) {
|
||||
DEBUG_LOG("-> ERROR_INVALID_PARAMETER\n");
|
||||
setLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
if (dwFlags & ~(INIT_ONCE_ASYNC | INIT_ONCE_INIT_FAILED)) {
|
||||
DEBUG_LOG("-> ERROR_INVALID_PARAMETER\n");
|
||||
setLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
const bool markFailed = (dwFlags & INIT_ONCE_INIT_FAILED) != 0;
|
||||
if (markFailed) {
|
||||
if (lpContext) {
|
||||
DEBUG_LOG("-> ERROR_INVALID_PARAMETER\n");
|
||||
setLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
if (dwFlags & INIT_ONCE_ASYNC) {
|
||||
DEBUG_LOG("-> ERROR_INVALID_PARAMETER\n");
|
||||
setLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
@@ -1261,6 +1271,7 @@ BOOL WINAPI InitOnceComplete(LPINIT_ONCE lpInitOnce, DWORD dwFlags, LPVOID lpCon
|
||||
|
||||
const GUEST_PTR contextValue = static_cast<GUEST_PTR>(reinterpret_cast<uintptr_t>(lpContext));
|
||||
if (!markFailed && (contextValue & kInitOnceReservedMask)) {
|
||||
DEBUG_LOG("-> ERROR_INVALID_PARAMETER\n");
|
||||
setLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
@@ -1274,6 +1285,7 @@ BOOL WINAPI InitOnceComplete(LPINIT_ONCE lpInitOnce, DWORD dwFlags, LPVOID lpCon
|
||||
case 1: {
|
||||
auto syncState = getInitOnceState(lpInitOnce);
|
||||
if (!syncState) {
|
||||
DEBUG_LOG("-> ERROR_GEN_FAILURE\n");
|
||||
setLastError(ERROR_GEN_FAILURE);
|
||||
return FALSE;
|
||||
}
|
||||
@@ -1292,6 +1304,7 @@ BOOL WINAPI InitOnceComplete(LPINIT_ONCE lpInitOnce, DWORD dwFlags, LPVOID lpCon
|
||||
}
|
||||
case 3:
|
||||
if (!(dwFlags & INIT_ONCE_ASYNC)) {
|
||||
DEBUG_LOG("-> ERROR_INVALID_PARAMETER\n");
|
||||
setLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
@@ -1300,6 +1313,7 @@ BOOL WINAPI InitOnceComplete(LPINIT_ONCE lpInitOnce, DWORD dwFlags, LPVOID lpCon
|
||||
}
|
||||
return TRUE;
|
||||
default:
|
||||
DEBUG_LOG("-> ERROR_GEN_FAILURE\n");
|
||||
setLastError(ERROR_GEN_FAILURE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
10
dll/ws2.cpp
Normal file
10
dll/ws2.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#include "modules.h"
|
||||
|
||||
extern const wibo::ModuleStub lib_ws2 = {
|
||||
(const char *[]){
|
||||
"WS2_32",
|
||||
nullptr,
|
||||
},
|
||||
nullptr,
|
||||
nullptr,
|
||||
};
|
||||
@@ -19,6 +19,8 @@
|
||||
#include <unistd.h>
|
||||
#include <variant>
|
||||
|
||||
constexpr uint16_t IMAGE_FILE_DLL = 0x2000;
|
||||
|
||||
struct PEHeader {
|
||||
uint8_t magic[4]; // "PE\0\0"
|
||||
uint16_t machine;
|
||||
@@ -372,6 +374,7 @@ bool loadPEFromSource(wibo::Executable &executable, const PeInputView &source, b
|
||||
DEBUG_LOG("loadPE: unreasonable section count %u\n", header.numberOfSections);
|
||||
return false;
|
||||
}
|
||||
executable.isDll = !!(header.characteristics & IMAGE_FILE_DLL);
|
||||
|
||||
constexpr size_t kOptionalHeaderMinimumSize = offsetof(PE32Header, reserved) + sizeof(PEImageDataDirectory);
|
||||
if (header.sizeOfOptionalHeader < kOptionalHeaderMinimumSize) {
|
||||
@@ -440,9 +443,10 @@ bool loadPEFromSource(wibo::Executable &executable, const PeInputView &source, b
|
||||
initialProtect, MEM_IMAGE);
|
||||
}
|
||||
if (allocStatus != wibo::heap::VmStatus::Success) {
|
||||
DEBUG_LOG("Image mapping failed (status=%u)\n", static_cast<unsigned>(allocStatus));
|
||||
DEBUG_LOG("loadPE: mapping failed (status=%u)\n", static_cast<unsigned>(allocStatus));
|
||||
return false;
|
||||
}
|
||||
DEBUG_LOG("loadPE: mapping succeeded (base=%p, size=%zu)\n", allocatedBase, allocationSize);
|
||||
|
||||
std::unique_ptr<void, ImageMemoryDeleter> imageGuard(allocatedBase);
|
||||
executable.imageBase = allocatedBase;
|
||||
|
||||
@@ -40,6 +40,7 @@ extern const wibo::ModuleStub lib_ole32;
|
||||
extern const wibo::ModuleStub lib_user32;
|
||||
extern const wibo::ModuleStub lib_vcruntime;
|
||||
extern const wibo::ModuleStub lib_version;
|
||||
extern const wibo::ModuleStub lib_ws2;
|
||||
|
||||
// setup.S
|
||||
template <size_t Index> void stubThunk();
|
||||
@@ -186,7 +187,7 @@ LockedRegistry registry() {
|
||||
reg.initialized = true;
|
||||
const wibo::ModuleStub *builtins[] = {
|
||||
&lib_advapi32, &lib_bcrypt, &lib_kernel32, &lib_lmgr, &lib_mscoree, &lib_ntdll,
|
||||
&lib_ole32, &lib_rpcrt4, &lib_user32, &lib_vcruntime, &lib_version,
|
||||
&lib_ole32, &lib_rpcrt4, &lib_user32, &lib_vcruntime, &lib_version, &lib_ws2,
|
||||
#if WIBO_HAS_MSVCRT
|
||||
&lib_msvcrt,
|
||||
#endif
|
||||
@@ -1173,39 +1174,41 @@ static ModuleInfo *loadModuleInternal(const std::string &dllName) {
|
||||
ModuleInfo *raw = info.get();
|
||||
reg->modulesByKey[key] = std::move(info);
|
||||
registerExternalModuleAliases(*reg, dllName, raw->resolvedPath, raw);
|
||||
reg.lock.unlock();
|
||||
ensureExportsInitialized(*raw);
|
||||
if (!raw->executable->resolveImports()) {
|
||||
DEBUG_LOG(" resolveImports failed for %s\n", raw->originalName.c_str());
|
||||
reg.lock.lock();
|
||||
reg->modulesByKey.erase(key);
|
||||
diskError = kernel32::getLastError();
|
||||
return nullptr;
|
||||
}
|
||||
if (!initializeModuleTls(*raw)) {
|
||||
DEBUG_LOG(" initializeModuleTls failed for %s\n", raw->originalName.c_str());
|
||||
reg.lock.lock();
|
||||
reg->modulesByKey.erase(key);
|
||||
diskError = kernel32::getLastError();
|
||||
return nullptr;
|
||||
}
|
||||
reg.lock.lock();
|
||||
if (!callDllMain(*raw, DLL_PROCESS_ATTACH, nullptr)) {
|
||||
DEBUG_LOG(" DllMain failed for %s\n", raw->originalName.c_str());
|
||||
releaseModuleTls(*raw);
|
||||
// runPendingOnExit(*raw);
|
||||
for (auto it = reg->modulesByAlias.begin(); it != reg->modulesByAlias.end();) {
|
||||
if (it->second == raw) {
|
||||
it = reg->modulesByAlias.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
if (raw->executable->isDll) {
|
||||
reg.lock.unlock();
|
||||
ensureExportsInitialized(*raw);
|
||||
if (!raw->executable->resolveImports()) {
|
||||
DEBUG_LOG(" resolveImports failed for %s\n", raw->originalName.c_str());
|
||||
reg.lock.lock();
|
||||
reg->modulesByKey.erase(key);
|
||||
diskError = kernel32::getLastError();
|
||||
return nullptr;
|
||||
}
|
||||
if (!initializeModuleTls(*raw)) {
|
||||
DEBUG_LOG(" initializeModuleTls failed for %s\n", raw->originalName.c_str());
|
||||
reg.lock.lock();
|
||||
reg->modulesByKey.erase(key);
|
||||
diskError = kernel32::getLastError();
|
||||
return nullptr;
|
||||
}
|
||||
reg.lock.lock();
|
||||
if (!callDllMain(*raw, DLL_PROCESS_ATTACH, nullptr)) {
|
||||
DEBUG_LOG(" DllMain failed for %s\n", raw->originalName.c_str());
|
||||
releaseModuleTls(*raw);
|
||||
// runPendingOnExit(*raw);
|
||||
for (auto it = reg->modulesByAlias.begin(); it != reg->modulesByAlias.end();) {
|
||||
if (it->second == raw) {
|
||||
it = reg->modulesByAlias.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
reg->pinnedModules.erase(raw);
|
||||
reg->modulesByKey.erase(key);
|
||||
diskError = ERROR_DLL_INIT_FAILED;
|
||||
kernel32::setLastError(ERROR_DLL_INIT_FAILED);
|
||||
return nullptr;
|
||||
}
|
||||
reg->pinnedModules.erase(raw);
|
||||
reg->modulesByKey.erase(key);
|
||||
diskError = ERROR_DLL_INIT_FAILED;
|
||||
kernel32::setLastError(ERROR_DLL_INIT_FAILED);
|
||||
return nullptr;
|
||||
}
|
||||
return raw;
|
||||
};
|
||||
|
||||
@@ -65,6 +65,7 @@ class Executable {
|
||||
bool importsResolved = false;
|
||||
bool importsResolving = false;
|
||||
bool sectionsProtected = false;
|
||||
bool isDll = false;
|
||||
std::vector<SectionInfo> sections;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user