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

@@ -1,5 +1,7 @@
#include "common.h"
#include <vector>
typedef void (*_PVFV)();
typedef int (*_PIFV)();
@@ -19,6 +21,8 @@ namespace crt {
int _commode = 0;
std::vector<_PVFV> atexitFuncs;
void WIN_ENTRY _initterm(const _PVFV *ppfn, const _PVFV *end) {
do {
if (_PVFV pfn = *++ppfn) {
@@ -48,7 +52,8 @@ int WIN_ENTRY _set_fmode(int mode) {
int *WIN_ENTRY __p__commode() { return &_commode; }
int WIN_ENTRY _crt_atexit(void (*func)()) {
DEBUG_LOG("STUB: _crt_atexit(%p)\n", func);
DEBUG_LOG("_crt_atexit(%p)\n", func);
atexitFuncs.push_back(func);
return 0;
}
@@ -85,6 +90,15 @@ int *WIN_ENTRY __p___argc() { return &wibo::argc; }
size_t WIN_ENTRY strlen(const char *str) { return ::strlen(str); }
void WIN_ENTRY exit(int status) {
DEBUG_LOG("exit(%i)\n", status);
for (auto it = atexitFuncs.rbegin(); it != atexitFuncs.rend(); ++it) {
DEBUG_LOG("Calling atexit function %p\n", *it);
(*it)();
}
::exit(status);
}
} // namespace crt
static void *resolveByName(const char *name) {
@@ -118,6 +132,8 @@ static void *resolveByName(const char *name) {
return (void *)crt::__p___argc;
if (strcmp(name, "strlen") == 0)
return (void *)crt::strlen;
if (strcmp(name, "exit") == 0)
return (void *)crt::exit;
return nullptr;
}