More msvcrt (WIP quality) and various fixes

This commit is contained in:
Luke Street 2025-09-29 20:07:19 -06:00
parent f09e6a3986
commit 9dd65bc70a
9 changed files with 1466 additions and 108 deletions

View File

@ -19,7 +19,18 @@
// force_align_arg_pointer will realign the stack to match GCC's 16 byte alignment.
#define WIN_ENTRY __attribute__((force_align_arg_pointer, callee_pop_aggregate_return(0)))
#define WIN_FUNC WIN_ENTRY __attribute__((stdcall))
#define DEBUG_LOG(...) wibo::debug_log(__VA_ARGS__)
#define DEBUG_LOG(...) \
do { \
if (wibo::debugEnabled) { \
wibo::debug_log(__VA_ARGS__); \
} \
} while (0)
#ifndef NDEBUG
#define VERBOSE_LOG(...) DEBUG_LOG(__VA_ARGS__)
#else
#define VERBOSE_LOG(...) ((void)0)
#endif
typedef void *HANDLE;
typedef void *HMODULE;

View File

@ -286,18 +286,18 @@ namespace {
namespace advapi32 {
unsigned int WIN_FUNC RegOpenKeyExA(void *hKey, const char *lpSubKey, unsigned int ulOptions, void *samDesired, void **phkResult) {
DEBUG_LOG("RegOpenKeyExA(key=%p, subkey=%s, ...)\n", hKey, lpSubKey);
DEBUG_LOG("STUB: RegOpenKeyExA(%p, %s, ...)\n", hKey, lpSubKey);
return 1; // screw them for now
}
BOOL WIN_FUNC CryptReleaseContext(void* hProv, unsigned int dwFlags) {
DEBUG_LOG("STUB: CryptReleaseContext %p %u\n", hProv, dwFlags);
DEBUG_LOG("STUB: CryptReleaseContext(%p, %u)\n", hProv, dwFlags);
return TRUE;
}
BOOL WIN_FUNC CryptAcquireContextW(void **phProv, const uint16_t *pszContainer, const uint16_t *pszProvider,
unsigned int dwProvType, unsigned int dwFlags) {
DEBUG_LOG("STUB: CryptAcquireContextW(%p)\n", phProv);
DEBUG_LOG("STUB: CryptAcquireContextW(%p, %p, %p, %u, %u)\n", phProv, pszContainer, pszProvider, dwProvType, dwFlags);
// to quote the guy above me: screw them for now
static int lmao = 42;
@ -310,7 +310,7 @@ namespace advapi32 {
}
BOOL WIN_FUNC CryptGenRandom(void* hProv, unsigned int dwLen, unsigned char* pbBuffer){
DEBUG_LOG("STUB: CryptGenRandom(%p)\n", hProv);
DEBUG_LOG("CryptGenRandom(%p)\n", hProv);
if (!pbBuffer || dwLen == 0) return FALSE;
ssize_t ret = getrandom(pbBuffer, dwLen, 0);
@ -322,7 +322,7 @@ namespace advapi32 {
}
BOOL WIN_FUNC CryptCreateHash(void* hProv, unsigned int Algid, void* hKey, unsigned int dwFlags, void** phHash) {
DEBUG_LOG("CryptCreateHash(Algid=0x%x)\n", Algid);
DEBUG_LOG("CryptCreateHash(%p, %u, %p, %u, %p)\n", hProv, Algid, hKey, dwFlags, phHash);
(void)hProv;
if (!phHash) {
wibo::lastError = ERROR_INVALID_PARAMETER;
@ -351,7 +351,7 @@ namespace advapi32 {
}
BOOL WIN_FUNC CryptHashData(void* hHash, const unsigned char* pbData, unsigned int dwDataLen, unsigned int dwFlags) {
DEBUG_LOG("CryptHashData(%p, %u bytes)\n", hHash, dwDataLen);
DEBUG_LOG("CryptHashData(%p, %p, %u, %u)\n", hHash, pbData, dwDataLen, dwFlags);
if (!hHash || (dwDataLen && !pbData) || dwFlags != 0) {
wibo::lastError = ERROR_INVALID_PARAMETER;
return FALSE;
@ -367,7 +367,7 @@ namespace advapi32 {
}
BOOL WIN_FUNC CryptGetHashParam(void* hHash, unsigned int dwParam, unsigned char* pbData, unsigned int* pdwDataLen, unsigned int dwFlags) {
DEBUG_LOG("CryptGetHashParam(%p, param=0x%x)\n", hHash, dwParam);
DEBUG_LOG("CryptGetHashParam(%p, %u, %p, %p, %u)\n", hHash, dwParam, pbData, pdwDataLen, dwFlags);
if (!hHash || !pdwDataLen || dwFlags != 0) {
wibo::lastError = ERROR_INVALID_PARAMETER;
return FALSE;
@ -458,7 +458,7 @@ namespace advapi32 {
}
BOOL WIN_FUNC OpenProcessToken(HANDLE ProcessHandle, DWORD DesiredAccess, HANDLE *TokenHandle) {
DEBUG_LOG("OpenProcessToken(process=%p, access=0x%x)\n", ProcessHandle, DesiredAccess);
DEBUG_LOG("OpenProcessToken(%p, %u, %p)\n", ProcessHandle, DesiredAccess, TokenHandle);
if (!TokenHandle) {
wibo::lastError = ERROR_INVALID_PARAMETER;
return FALSE;
@ -480,7 +480,8 @@ namespace advapi32 {
}
BOOL WIN_FUNC GetTokenInformation(HANDLE TokenHandle, unsigned int TokenInformationClass, void *TokenInformation, unsigned int TokenInformationLength, unsigned int *ReturnLength) {
DEBUG_LOG("GetTokenInformation(%p, class=%u, len=%u)\n", TokenHandle, TokenInformationClass, TokenInformationLength);
DEBUG_LOG("GetTokenInformation(%p, %u, %p, %u, %p)\n", TokenHandle, TokenInformationClass, TokenInformation,
TokenInformationLength, ReturnLength);
if (!ReturnLength) {
wibo::lastError = ERROR_INVALID_PARAMETER;
return FALSE;
@ -547,10 +548,11 @@ namespace advapi32 {
}
BOOL WIN_FUNC LookupAccountSidW(const uint16_t *lpSystemName, const void *sidPointer, uint16_t *Name,
unsigned long *cchName, uint16_t *ReferencedDomainName,
unsigned long *cchReferencedDomainName, SID_NAME_USE *peUse) {
unsigned long *cchName, uint16_t *ReferencedDomainName,
unsigned long *cchReferencedDomainName, SID_NAME_USE *peUse) {
std::string systemName = lpSystemName ? wideStringToString(lpSystemName) : std::string("(null)");
DEBUG_LOG("LookupAccountSidW(system=%s, sid=%p)\n", systemName.c_str(), sidPointer);
DEBUG_LOG("LookupAccountSidW(%s, %p, %p, %p, %p, %p, %p)\n", systemName.c_str(), sidPointer, Name, cchName,
ReferencedDomainName, cchReferencedDomainName, peUse);
(void) lpSystemName; // Only local lookup supported
if (!sidPointer || !cchName || !cchReferencedDomainName || !peUse) {
wibo::lastError = ERROR_INVALID_PARAMETER;

View File

@ -40,16 +40,20 @@ std::vector<_PVFV> atexitFuncs;
_invalid_parameter_handler invalidParameterHandler = nullptr;
void WIN_ENTRY _initterm(const _PVFV *ppfn, const _PVFV *end) {
DEBUG_LOG("_initterm(%p, %p)\n", ppfn, end);
do {
if (_PVFV pfn = *++ppfn) {
DEBUG_LOG("-> calling %p\n", pfn);
pfn();
}
} while (ppfn < end);
}
int WIN_ENTRY _initterm_e(const _PIFV *ppfn, const _PIFV *end) {
DEBUG_LOG("_initterm_e(%p, %p)\n", ppfn, end);
do {
if (_PIFV pfn = *++ppfn) {
DEBUG_LOG("-> calling %p\n", pfn);
if (int err = pfn())
return err;
}
@ -66,9 +70,15 @@ int WIN_ENTRY _set_fmode(int mode) {
return 0;
}
int *WIN_ENTRY __p__commode() { return &_commode; }
int *WIN_ENTRY __p__commode() {
DEBUG_LOG("__p__commode()\n");
return &_commode;
}
int *WIN_ENTRY __p__fmode() { return &_fmode; }
int *WIN_ENTRY __p__fmode() {
DEBUG_LOG("__p__fmode()\n");
return &_fmode;
}
int WIN_ENTRY _crt_atexit(void (*func)()) {
DEBUG_LOG("_crt_atexit(%p)\n", func);
@ -108,37 +118,85 @@ int WIN_ENTRY _set_new_mode(int newhandlermode) {
return 0;
}
char **WIN_ENTRY _get_initial_narrow_environment() { return environ; }
char **WIN_ENTRY _get_initial_narrow_environment() {
DEBUG_LOG("_get_initial_narrow_environment()\n");
return environ;
}
char ***WIN_ENTRY __p__environ() { return &environ; }
char ***WIN_ENTRY __p__environ() {
DEBUG_LOG("__p__environ()\n");
return &environ;
}
char ***WIN_ENTRY __p___argv() { return &wibo::argv; }
char ***WIN_ENTRY __p___argv() {
DEBUG_LOG("__p___argv()\n");
return &wibo::argv;
}
int *WIN_ENTRY __p___argc() { return &wibo::argc; }
int *WIN_ENTRY __p___argc() {
DEBUG_LOG("__p___argc()\n");
return &wibo::argc;
}
size_t WIN_ENTRY strlen(const char *str) { return ::strlen(str); }
size_t WIN_ENTRY strlen(const char *str) {
VERBOSE_LOG("strlen(%p)\n", str);
return ::strlen(str);
}
int WIN_ENTRY strcmp(const char *lhs, const char *rhs) { return ::strcmp(lhs, rhs); }
int WIN_ENTRY strcmp(const char *lhs, const char *rhs) {
VERBOSE_LOG("strcmp(%p, %p)\n", lhs, rhs);
return ::strcmp(lhs, rhs);
}
int WIN_ENTRY strncmp(const char *lhs, const char *rhs, size_t count) { return ::strncmp(lhs, rhs, count); }
int WIN_ENTRY strncmp(const char *lhs, const char *rhs, size_t count) {
VERBOSE_LOG("strncmp(%p, %p, %zu)\n", lhs, rhs, count);
return ::strncmp(lhs, rhs, count);
}
char *WIN_ENTRY strcpy(char *dest, const char *src) { return ::strcpy(dest, src); }
char *WIN_ENTRY strcpy(char *dest, const char *src) {
VERBOSE_LOG("strcpy(%p, %p)\n", dest, src);
return ::strcpy(dest, src);
}
void *WIN_ENTRY malloc(size_t size) { return ::malloc(size); }
void *WIN_ENTRY malloc(size_t size) {
VERBOSE_LOG("malloc(%zu)\n", size);
return ::malloc(size);
}
void *WIN_ENTRY calloc(size_t count, size_t size) { return ::calloc(count, size); }
void *WIN_ENTRY calloc(size_t count, size_t size) {
VERBOSE_LOG("calloc(%zu, %zu)\n", count, size);
return ::calloc(count, size);
}
void *WIN_ENTRY realloc(void *ptr, size_t newSize) { return ::realloc(ptr, newSize); }
void *WIN_ENTRY realloc(void *ptr, size_t newSize) {
VERBOSE_LOG("realloc(%p, %zu)\n", ptr, newSize);
return ::realloc(ptr, newSize);
}
void WIN_ENTRY free(void *ptr) { ::free(ptr); }
void WIN_ENTRY free(void *ptr) {
VERBOSE_LOG("free(%p)\n", ptr);
::free(ptr);
}
void *WIN_ENTRY memcpy(void *dest, const void *src, size_t count) { return std::memcpy(dest, src, count); }
void *WIN_ENTRY memcpy(void *dest, const void *src, size_t count) {
VERBOSE_LOG("memcpy(%p, %p, %zu)\n", dest, src, count);
return std::memcpy(dest, src, count);
}
void *WIN_ENTRY memmove(void *dest, const void *src, size_t count) { return std::memmove(dest, src, count); }
void *WIN_ENTRY memmove(void *dest, const void *src, size_t count) {
VERBOSE_LOG("memmove(%p, %p, %zu)\n", dest, src, count);
return std::memmove(dest, src, count);
}
void *WIN_ENTRY memset(void *dest, int ch, size_t count) { return std::memset(dest, ch, count); }
void *WIN_ENTRY memset(void *dest, int ch, size_t count) {
VERBOSE_LOG("memset(%p, %i, %zu)\n", dest, ch, count);
return std::memset(dest, ch, count);
}
int WIN_ENTRY memcmp(const void *lhs, const void *rhs, size_t count) { return std::memcmp(lhs, rhs, count); }
int WIN_ENTRY memcmp(const void *lhs, const void *rhs, size_t count) {
VERBOSE_LOG("memcmp(%p, %p, %zu)\n", lhs, rhs, count);
return std::memcmp(lhs, rhs, count);
}
int WIN_ENTRY __setusermatherr(void *handler) {
DEBUG_LOG("STUB: __setusermatherr(%p)\n", handler);
@ -192,9 +250,13 @@ void WIN_ENTRY abort(void) {
using signal_handler = void (*)(int);
signal_handler WIN_ENTRY signal(int signum, signal_handler handler) { return std::signal(signum, handler); }
signal_handler WIN_ENTRY signal(int signum, signal_handler handler) {
DEBUG_LOG("signal(%i, %p)\n", signum, handler);
return std::signal(signum, handler);
}
void *WIN_ENTRY __acrt_iob_func(unsigned int index) {
DEBUG_LOG("__acrt_iob_func(%u)\n", index);
if (index == 0)
return stdin;
if (index == 1)
@ -204,13 +266,15 @@ void *WIN_ENTRY __acrt_iob_func(unsigned int index) {
return nullptr;
}
int WIN_ENTRY __stdio_common_vfprintf(unsigned long long /*options*/, FILE *stream, const char *format,
void * /*locale*/, va_list args) {
int WIN_ENTRY __stdio_common_vfprintf(unsigned long long options, FILE *stream, const char *format, void *locale,
va_list args) {
DEBUG_LOG("__stdio_common_vfprintf(%llu, %p, %s, %p, %p)\n", options, stream, format, locale, args);
return vfprintf(stream, format, args);
}
int WIN_ENTRY __stdio_common_vsprintf(unsigned long long /*options*/, char *buffer, size_t len, const char *format,
void * /*locale*/, va_list args) {
int WIN_ENTRY __stdio_common_vsprintf(unsigned long long options, char *buffer, size_t len, const char *format,
void *locale, va_list args) {
DEBUG_LOG("__stdio_common_vsprintf(%llu, %p, %zu, %s, %p, ...)\n", options, buffer, len, format, locale);
if (!buffer || !format)
return -1;
int result = vsnprintf(buffer, len, format, args);

View File

@ -495,7 +495,7 @@ namespace kernel32 {
}
BOOL WIN_FUNC Wow64DisableWow64FsRedirection(void **OldValue) {
DEBUG_LOG("Wow64DisableWow64FsRedirection\n");
DEBUG_LOG("STUB: Wow64DisableWow64FsRedirection\n");
if (OldValue) {
*OldValue = nullptr;
}
@ -504,7 +504,7 @@ namespace kernel32 {
}
BOOL WIN_FUNC Wow64RevertWow64FsRedirection(void *OldValue) {
DEBUG_LOG("Wow64RevertWow64FsRedirection\n");
DEBUG_LOG("STUB: Wow64RevertWow64FsRedirection\n");
(void) OldValue;
wibo::lastError = ERROR_SUCCESS;
return TRUE;
@ -523,6 +523,7 @@ namespace kernel32 {
// @brief returns a pseudo handle to the current process
void *WIN_FUNC GetCurrentProcess() {
DEBUG_LOG("STUB: GetCurrentProcess() -> %p\n", (void *) 0xFFFFFFFF);
// pseudo handle is always returned, and is -1 (a special constant)
return (void *) 0xFFFFFFFF;
}
@ -530,15 +531,14 @@ namespace kernel32 {
// @brief DWORD (unsigned int) returns a process identifier of the calling process.
unsigned int WIN_FUNC GetCurrentProcessId() {
uint32_t pid = getpid();
DEBUG_LOG("Current processID is: %d\n", pid);
DEBUG_LOG("GetCurrentProcessId() -> %d\n", pid);
return pid;
}
unsigned int WIN_FUNC GetCurrentThreadId() {
pthread_t thread_id;
thread_id = pthread_self();
DEBUG_LOG("Current thread ID is: %lu\n", thread_id);
DEBUG_LOG("GetCurrentThreadId() -> %lu\n", thread_id);
// Cast thread_id to unsigned int to fit a DWORD
unsigned int u_thread_id = (unsigned int) thread_id;
@ -547,7 +547,7 @@ namespace kernel32 {
}
void WIN_FUNC ExitProcess(unsigned int uExitCode) {
DEBUG_LOG("ExitProcess %d\n", uExitCode);
DEBUG_LOG("ExitProcess(%u)\n", uExitCode);
exit(uExitCode);
}
@ -680,9 +680,12 @@ namespace kernel32 {
lpProcessInformation
);
std::string application = lpApplicationName ? lpApplicationName : "";
bool useSearchPath = lpApplicationName == nullptr;
std::string application;
std::vector<std::string> arguments = processes::splitCommandLine(lpCommandLine);
if (application.empty()) {
if (lpApplicationName) {
application = lpApplicationName;
} else {
if (arguments.empty()) {
wibo::lastError = ERROR_FILE_NOT_FOUND;
return 0;
@ -692,8 +695,13 @@ namespace kernel32 {
if (arguments.empty()) {
arguments.push_back(application);
}
DEBUG_LOG(" -> args:");
for (const auto &arg : arguments) {
DEBUG_LOG(" '%s'", arg.c_str());
}
DEBUG_LOG("\n");
auto resolved = processes::resolveExecutable(application, true);
auto resolved = processes::resolveExecutable(application, useSearchPath);
if (!resolved) {
wibo::lastError = ERROR_FILE_NOT_FOUND;
return 0;

View File

@ -2,13 +2,13 @@
namespace lmgr {
int WIN_ENTRY lp_checkout(int a, int b, const char* c, const char* d, int e, const char* f, int* out) {
DEBUG_LOG("lp_checkout %d %d %s %s %d %s\n", a, b, c, d, e, f);
DEBUG_LOG("lp_checkout(%d, %d, %s, %s, %d, %s)\n", a, b, c, d, e, f);
*out = 1234;
return 0;
}
int WIN_ENTRY lp_checkin() {
DEBUG_LOG("lp_checkin\n");
DEBUG_LOG("lp_checkin()\n");
return 0;
}
}

View File

@ -1,14 +1,17 @@
#include "common.h"
namespace mscoree {
void WIN_FUNC CorExitProcess(int exitCode) {
exit(exitCode);
}
void WIN_FUNC CorExitProcess(int exitCode) {
DEBUG_LOG("CorExitProcess(%i)\n", exitCode);
exit(exitCode);
}
} // namespace mscoree
static void *resolveByName(const char *name) {
if (strcmp(name, "CorExitProcess") == 0) return (void *) mscoree::CorExitProcess;
if (strcmp(name, "CorExitProcess") == 0)
return (void *)mscoree::CorExitProcess;
return nullptr;
}

File diff suppressed because it is too large Load Diff

View File

@ -69,7 +69,7 @@ namespace files {
}
// Remove the drive letter
if (str.rfind("z:/", 0) == 0 || str.rfind("Z:/", 0) == 0) {
if (str.rfind("z:/", 0) == 0 || str.rfind("Z:/", 0) == 0 || str.rfind("c:/", 0) == 0 || str.rfind("C:/", 0) == 0) {
str.erase(0, 2);
}

View File

@ -112,6 +112,9 @@ namespace processes {
static std::vector<std::filesystem::path> buildSearchDirectories() {
std::vector<std::filesystem::path> dirs;
if (wibo::guestExecutablePath.has_parent_path()) {
dirs.push_back(wibo::guestExecutablePath.parent_path());
}
dirs.push_back(std::filesystem::current_path());
if (const char *envPath = std::getenv("PATH")) {
auto parsed = parseHostPath(envPath);
@ -198,6 +201,15 @@ namespace processes {
}
nativeArgs.push_back(nullptr);
DEBUG_LOG("Spawning process: %s, args: [", wibo::executableName.c_str());
for (size_t i = 0; i < storage.size(); ++i) {
if (i != 0) {
DEBUG_LOG(", ");
}
DEBUG_LOG("'%s'", storage[i].c_str());
}
DEBUG_LOG("]\n");
posix_spawn_file_actions_t actions;
posix_spawn_file_actions_init(&actions);