mirror of
https://github.com/decompals/wibo.git
synced 2025-12-12 14:46:09 +00:00
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:
@@ -250,14 +250,14 @@ namespace kernel32 {
|
||||
|
||||
unsigned int WIN_FUNC WaitForSingleObject(void *hHandle, unsigned int dwMilliseconds) {
|
||||
DEBUG_LOG("WaitForSingleObject (%u)\n", dwMilliseconds);
|
||||
|
||||
|
||||
// TODO - wait on other objects?
|
||||
|
||||
// TODO: wait for less than forever
|
||||
assert(dwMilliseconds == 0xffffffff);
|
||||
assert(dwMilliseconds == 0xffffffff);
|
||||
|
||||
processes::Process* process = processes::processFromHandle(hHandle, false);
|
||||
|
||||
|
||||
int status;
|
||||
waitpid(process->pid, &status, 0);
|
||||
|
||||
@@ -268,7 +268,7 @@ namespace kernel32 {
|
||||
// Specific exit codes don't really map onto any of these situations - we just know it's bad.
|
||||
// Specify a non-zero exit code to alert our parent process something's gone wrong.
|
||||
DEBUG_LOG("WaitForSingleObject: Child process exited abnormally - returning exit code 1.");
|
||||
process->exitCode = 1;
|
||||
process->exitCode = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -366,30 +366,42 @@ namespace kernel32 {
|
||||
}
|
||||
}
|
||||
DEBUG_LOG("...returning nothing\n");
|
||||
return 0xFFFFFFFF;
|
||||
wibo::lastError = 1;
|
||||
return 0xFFFFFFFF; // TLS_OUT_OF_INDEXES
|
||||
}
|
||||
|
||||
unsigned int WIN_FUNC TlsFree(unsigned int dwTlsIndex) {
|
||||
DEBUG_LOG("TlsFree(%u)\n", dwTlsIndex);
|
||||
if (dwTlsIndex >= 0 && dwTlsIndex < MAX_TLS_VALUES && tlsValuesUsed[dwTlsIndex]) {
|
||||
tlsValuesUsed[dwTlsIndex] = false;
|
||||
return 1;
|
||||
} else {
|
||||
wibo::lastError = 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void *WIN_FUNC TlsGetValue(unsigned int dwTlsIndex) {
|
||||
// DEBUG_LOG("TlsGetValue(%u)\n", dwTlsIndex);
|
||||
if (dwTlsIndex >= 0 && dwTlsIndex < MAX_TLS_VALUES && tlsValuesUsed[dwTlsIndex])
|
||||
return tlsValues[dwTlsIndex];
|
||||
else
|
||||
return 0;
|
||||
// DEBUG_LOG("TlsGetValue(%u)", dwTlsIndex);
|
||||
void *result = nullptr;
|
||||
if (dwTlsIndex >= 0 && dwTlsIndex < MAX_TLS_VALUES && tlsValuesUsed[dwTlsIndex]) {
|
||||
result = tlsValues[dwTlsIndex];
|
||||
// See https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-TlsGetValue#return-value
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
} else {
|
||||
wibo::lastError = 1;
|
||||
}
|
||||
// DEBUG_LOG(" -> %p\n", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
unsigned int WIN_FUNC TlsSetValue(unsigned int dwTlsIndex, void *lpTlsValue) {
|
||||
// DEBUG_LOG("TlsSetValue(%u, %p)\n", dwTlsIndex, lpTlsValue);
|
||||
if (dwTlsIndex >= 0 && dwTlsIndex < MAX_TLS_VALUES && tlsValuesUsed[dwTlsIndex]) {
|
||||
tlsValues[dwTlsIndex] = lpTlsValue;
|
||||
return 1;
|
||||
} else {
|
||||
wibo::lastError = 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -1303,16 +1315,42 @@ namespace kernel32 {
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int WIN_FUNC GetModuleFileNameA(void* hModule, char* lpFilename, unsigned int nSize) {
|
||||
DWORD WIN_FUNC GetModuleFileNameA(HMODULE hModule, LPSTR lpFilename, DWORD nSize) {
|
||||
DEBUG_LOG("GetModuleFileNameA (hModule=%p, nSize=%i)\n", hModule, nSize);
|
||||
if (lpFilename == nullptr) {
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return 0;
|
||||
}
|
||||
|
||||
*lpFilename = 0; // just NUL terminate
|
||||
std::string path;
|
||||
if (wibo::isMainModule(hModule)) {
|
||||
const auto exePath = files::pathFromWindows(wibo::argv[0]);
|
||||
const auto absPath = std::filesystem::absolute(exePath);
|
||||
path = files::pathToWindows(absPath);
|
||||
} else {
|
||||
path = static_cast<wibo::ModuleInfo *>(hModule)->name;
|
||||
}
|
||||
const size_t len = path.size();
|
||||
if (nSize == 0) {
|
||||
wibo::lastError = ERROR_INSUFFICIENT_BUFFER;
|
||||
return 0;
|
||||
}
|
||||
|
||||
wibo::lastError = 0;
|
||||
return 0;
|
||||
const size_t copyLen = std::min(len, nSize - 1);
|
||||
memcpy(lpFilename, path.c_str(), copyLen);
|
||||
if (copyLen < nSize) {
|
||||
lpFilename[copyLen] = 0;
|
||||
}
|
||||
if (copyLen < len) {
|
||||
wibo::lastError = ERROR_INSUFFICIENT_BUFFER;
|
||||
return nSize;
|
||||
}
|
||||
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
return copyLen;
|
||||
}
|
||||
|
||||
unsigned int WIN_FUNC GetModuleFileNameW(void* hModule, uint16_t* lpFilename, unsigned int nSize) {
|
||||
DWORD WIN_FUNC GetModuleFileNameW(HMODULE hModule, LPWSTR lpFilename, DWORD nSize) {
|
||||
DEBUG_LOG("GetModuleFileNameW (hModule=%p, nSize=%i)\n", hModule, nSize);
|
||||
|
||||
*lpFilename = 0; // just NUL terminate
|
||||
|
||||
Reference in New Issue
Block a user