LoadLibraryA: Skip import resolution & DllMain for EXEs

This commit is contained in:
2025-11-11 21:22:00 -07:00
parent 4f666eefbd
commit f012b22101
7 changed files with 72 additions and 39 deletions

View File

@@ -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

View File

@@ -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;

View File

@@ -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
View File

@@ -0,0 +1,10 @@
#include "modules.h"
extern const wibo::ModuleStub lib_ws2 = {
(const char *[]){
"WS2_32",
nullptr,
},
nullptr,
nullptr,
};

View File

@@ -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;

View File

@@ -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;
};

View File

@@ -65,6 +65,7 @@ class Executable {
bool importsResolved = false;
bool importsResolving = false;
bool sectionsProtected = false;
bool isDll = false;
std::vector<SectionInfo> sections;
};