Fix TlsGetValue & more (#48)

`TlsGetValue` disambiguates 0 and an error by relying on `GetLastError`. Depending on the program state, `GetLastError` could be non-0, even though `TlsGetValue` succeeded. Resolve this by always setting `wibo::lastError`. This matches the behavior described by the documentation.

Additionally, when reading resources, later versions of mwcc and mwld call `GetModuleHandleA` with the program path, and then call `LoadStringA` on that handle. Support this behavior by _actually_ loading the PE at the path passed in to `GetModuleHandleA`, instead of assuming it's the current program.

(This is especially useful because sjiswrap relies on overriding `GetModuleFileNameA`, so the wrapped program reads its own resources, rather than sjiswrap's.)

Other small changes:
- Add ms-win-crt `exit` & run atexit funcs
- Implements vcruntime `memmove`
- Implements kernel32 `GetModuleFileNameA`
This commit is contained in:
2023-10-01 23:56:35 -04:00
committed by GitHub
parent 8a6aacb82d
commit c4de05946d
7 changed files with 145 additions and 31 deletions

View File

@@ -31,7 +31,7 @@ void wibo::debug_log(const char *fmt, ...) {
vfprintf(stderr, fmt, args);
}
va_end(args);
}
@@ -110,11 +110,6 @@ const wibo::Module * wibo::modules[] = {
nullptr,
};
struct ModuleInfo {
std::string name;
const wibo::Module* module = nullptr;
};
HMODULE wibo::loadModule(const char *dllName) {
auto *result = new ModuleInfo;
result->name = dllName;
@@ -151,6 +146,32 @@ void *wibo::resolveFuncByOrdinal(HMODULE module, uint16_t ordinal) {
return resolveMissingFuncOrdinal(info->name.c_str(), ordinal);
}
wibo::Executable *wibo::executableFromModule(HMODULE module) {
if (wibo::isMainModule(module)) {
return wibo::mainModule;
}
auto info = static_cast<wibo::ModuleInfo *>(module);
if (!info->executable) {
DEBUG_LOG("wibo::executableFromModule: loading %s\n", info->name.c_str());
auto executable = std::make_unique<wibo::Executable>();
const auto path = files::pathFromWindows(info->name.c_str());
FILE *f = fopen(path.c_str(), "rb");
if (!f) {
perror("wibo::executableFromModule");
return nullptr;
}
bool result = executable->loadPE(f, false);
fclose(f);
if (!result) {
DEBUG_LOG("wibo::executableFromModule: failed to load %s\n", path.c_str());
return nullptr;
}
info->executable = std::move(executable);
}
return info->executable.get();
}
struct UNICODE_STRING {
unsigned short Length;
unsigned short MaximumLength;
@@ -295,7 +316,7 @@ int main(int argc, char **argv) {
return 1;
}
exec.loadPE(f);
exec.loadPE(f, true);
fclose(f);
// 32-bit windows only reserves the lowest 2GB of memory for use by a process (https://www.tenouk.com/WinVirtualAddressSpace.html)