From 52cdd7c811b5f900dde49d27434bcc78bc36c234 Mon Sep 17 00:00:00 2001 From: Luke Street Date: Fri, 31 Oct 2025 00:45:32 -0600 Subject: [PATCH] Fully functional guest<->host trampolines --- CMakeLists.txt | 12 +- dll/advapi32.cpp | 2 +- dll/advapi32/processthreadsapi.cpp | 2 +- dll/advapi32/processthreadsapi.h | 2 +- dll/advapi32/securitybaseapi.cpp | 36 +- dll/advapi32/securitybaseapi.h | 36 +- dll/advapi32/winbase.cpp | 10 +- dll/advapi32/winbase.h | 10 +- dll/advapi32/wincrypt.cpp | 14 +- dll/advapi32/wincrypt.h | 14 +- dll/advapi32/winreg.cpp | 18 +- dll/advapi32/winreg.h | 18 +- dll/bcrypt.cpp | 2 +- dll/crt.cpp | 264 +++-------- dll/crt.h | 76 +++ dll/kernel32.cpp | 6 +- dll/kernel32.h | 29 ++ dll/kernel32/errhandlingapi.cpp | 28 +- dll/kernel32/errhandlingapi.h | 4 +- dll/kernel32/fibersapi.h | 2 +- dll/kernel32/fileapi.cpp | 34 +- dll/kernel32/processthreadsapi.cpp | 53 +-- dll/kernel32/processthreadsapi.h | 2 +- dll/kernel32/profileapi.cpp | 4 +- dll/kernel32/winbase.cpp | 15 +- dll/kernel32/wincon.h | 2 +- dll/kernel32/winnls.h | 2 +- dll/lmgr.cpp | 32 +- dll/lmgr.h | 10 + dll/mscoree.cpp | 14 +- dll/mscoree.h | 9 + dll/msvcrt.cpp | 735 ++++++++++------------------- dll/msvcrt.h | 234 +++++++++ dll/ntdll.cpp | 94 ++-- dll/ntdll.h | 49 ++ dll/ole32.cpp | 24 +- dll/ole32.h | 11 + dll/rpcrt4.cpp | 73 +-- dll/rpcrt4.h | 39 ++ dll/user32.cpp | 36 +- dll/user32.h | 15 + dll/vcruntime.cpp | 24 +- dll/vcruntime.h | 12 + dll/version.cpp | 36 +- dll/version.h | 14 + src/common.h | 5 +- src/context.cpp | 65 --- src/context.h | 36 +- src/entry.h | 7 + src/main.cpp | 152 +----- src/modules.cpp | 54 +-- src/modules.h | 8 +- src/tls.cpp | 4 +- src/types.h | 173 ++++--- test/test_findfile.c | 2 + tools/gen_trampolines.py | 507 +++++++++++++++++--- 56 files changed, 1683 insertions(+), 1488 deletions(-) create mode 100644 dll/crt.h create mode 100644 dll/kernel32.h create mode 100644 dll/lmgr.h create mode 100644 dll/mscoree.h create mode 100644 dll/msvcrt.h create mode 100644 dll/ntdll.h create mode 100644 dll/ole32.h create mode 100644 dll/rpcrt4.h create mode 100644 dll/user32.h create mode 100644 dll/vcruntime.h create mode 100644 dll/version.h delete mode 100644 src/context.cpp create mode 100644 src/entry.h diff --git a/CMakeLists.txt b/CMakeLists.txt index b818d28..79755fb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -170,7 +170,6 @@ add_executable(wibo src/access.cpp src/async_io.cpp src/async_io_epoll.cpp - src/context.cpp src/errors.cpp src/files.cpp src/handles.cpp @@ -260,6 +259,17 @@ wibo_codegen_module(NAME advapi32 HEADERS dll/advapi32/winreg.h ) wibo_codegen_module(NAME bcrypt HEADERS dll/bcrypt.h) +wibo_codegen_module(NAME entry HEADERS src/entry.h) +wibo_codegen_module(NAME crt HEADERS dll/crt.h) +wibo_codegen_module(NAME mscoree HEADERS dll/mscoree.h) +wibo_codegen_module(NAME msvcrt HEADERS dll/msvcrt.h) +wibo_codegen_module(NAME version HEADERS dll/version.h) +wibo_codegen_module(NAME rpcrt4 HEADERS dll/rpcrt4.h) +wibo_codegen_module(NAME vcruntime HEADERS dll/vcruntime.h) +wibo_codegen_module(NAME lmgr HEADERS dll/lmgr.h) +wibo_codegen_module(NAME ole32 HEADERS dll/ole32.h) +wibo_codegen_module(NAME user32 HEADERS dll/user32.h) +wibo_codegen_module(NAME ntdll HEADERS dll/ntdll.h) wibo_codegen_module(NAME kernel32 HEADERS dll/kernel32/debugapi.h dll/kernel32/errhandlingapi.h diff --git a/dll/advapi32.cpp b/dll/advapi32.cpp index ce68888..6f2d0c9 100644 --- a/dll/advapi32.cpp +++ b/dll/advapi32.cpp @@ -7,6 +7,6 @@ extern const wibo::ModuleStub lib_advapi32 = { "advapi32", nullptr, }, - advapi32_trampoline_by_name, + advapi32ThunkByName, nullptr, }; diff --git a/dll/advapi32/processthreadsapi.cpp b/dll/advapi32/processthreadsapi.cpp index caf1972..dd50225 100644 --- a/dll/advapi32/processthreadsapi.cpp +++ b/dll/advapi32/processthreadsapi.cpp @@ -10,7 +10,7 @@ namespace advapi32 { -BOOL WIN_FUNC OpenProcessToken(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle) { +BOOL WINAPI OpenProcessToken(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle) { HOST_CONTEXT_GUARD(); DEBUG_LOG("OpenProcessToken(%p, %u, %p)\n", ProcessHandle, DesiredAccess, TokenHandle); if (!TokenHandle) { diff --git a/dll/advapi32/processthreadsapi.h b/dll/advapi32/processthreadsapi.h index 6644b84..4f29e11 100644 --- a/dll/advapi32/processthreadsapi.h +++ b/dll/advapi32/processthreadsapi.h @@ -4,6 +4,6 @@ namespace advapi32 { -BOOL WIN_FUNC OpenProcessToken(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle); +BOOL WINAPI OpenProcessToken(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle); } // namespace advapi32 diff --git a/dll/advapi32/securitybaseapi.cpp b/dll/advapi32/securitybaseapi.cpp index 4ffe75c..c91bc6d 100644 --- a/dll/advapi32/securitybaseapi.cpp +++ b/dll/advapi32/securitybaseapi.cpp @@ -103,7 +103,7 @@ bool writeLocalSystemSid(Sid *sid) { namespace advapi32 { -BOOL WIN_FUNC InitializeAcl(PACL pAcl, DWORD nAclLength, DWORD dwAclRevision) { +BOOL WINAPI InitializeAcl(PACL pAcl, DWORD nAclLength, DWORD dwAclRevision) { HOST_CONTEXT_GUARD(); DEBUG_LOG("InitializeAcl(%p, %u, %u)\n", pAcl, nAclLength, dwAclRevision); if (!pAcl) { @@ -133,7 +133,7 @@ BOOL WIN_FUNC InitializeAcl(PACL pAcl, DWORD nAclLength, DWORD dwAclRevision) { return TRUE; } -BOOL WIN_FUNC AddAccessAllowedAce(PACL pAcl, DWORD dwAceRevision, DWORD AccessMask, PSID pSid) { +BOOL WINAPI AddAccessAllowedAce(PACL pAcl, DWORD dwAceRevision, DWORD AccessMask, PSID pSid) { HOST_CONTEXT_GUARD(); DEBUG_LOG("AddAccessAllowedAce(%p, %u, 0x%x, %p)\n", pAcl, dwAceRevision, AccessMask, pSid); if (!pAcl || !pSid) { @@ -202,7 +202,7 @@ BOOL WIN_FUNC AddAccessAllowedAce(PACL pAcl, DWORD dwAceRevision, DWORD AccessMa return TRUE; } -BOOL WIN_FUNC FindFirstFreeAce(PACL pAcl, LPVOID *pAce) { +BOOL WINAPI FindFirstFreeAce(PACL pAcl, LPVOID *pAce) { HOST_CONTEXT_GUARD(); DEBUG_LOG("FindFirstFreeAce(%p, %p)\n", pAcl, pAce); if (!pAce) { @@ -225,7 +225,7 @@ BOOL WIN_FUNC FindFirstFreeAce(PACL pAcl, LPVOID *pAce) { return TRUE; } -BOOL WIN_FUNC GetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR pSecurityDescriptor, LPBOOL lpbDaclPresent, PACL *pDacl, +BOOL WINAPI GetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR pSecurityDescriptor, LPBOOL lpbDaclPresent, PACL *pDacl, LPBOOL lpbDaclDefaulted) { HOST_CONTEXT_GUARD(); DEBUG_LOG("GetSecurityDescriptorDacl(%p, %p, %p, %p)\n", pSecurityDescriptor, lpbDaclPresent, pDacl, @@ -262,7 +262,7 @@ BOOL WIN_FUNC GetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR pSecurityDescriptor return TRUE; } -PSID_IDENTIFIER_AUTHORITY WIN_FUNC GetSidIdentifierAuthority(PSID pSid) { +PSID_IDENTIFIER_AUTHORITY WINAPI GetSidIdentifierAuthority(PSID pSid) { HOST_CONTEXT_GUARD(); DEBUG_LOG("GetSidIdentifierAuthority(%p)\n", pSid); if (!pSid) { @@ -277,7 +277,7 @@ PSID_IDENTIFIER_AUTHORITY WIN_FUNC GetSidIdentifierAuthority(PSID pSid) { return reinterpret_cast(&sid->IdentifierAuthority); } -PUCHAR WIN_FUNC GetSidSubAuthorityCount(PSID pSid) { +PUCHAR WINAPI GetSidSubAuthorityCount(PSID pSid) { HOST_CONTEXT_GUARD(); DEBUG_LOG("GetSidSubAuthorityCount(%p)\n", pSid); if (!pSid) { @@ -292,7 +292,7 @@ PUCHAR WIN_FUNC GetSidSubAuthorityCount(PSID pSid) { return &sid->SubAuthorityCount; } -PDWORD WIN_FUNC GetSidSubAuthority(PSID pSid, DWORD nSubAuthority) { +PDWORD WINAPI GetSidSubAuthority(PSID pSid, DWORD nSubAuthority) { HOST_CONTEXT_GUARD(); DEBUG_LOG("GetSidSubAuthority(%p, %u)\n", pSid, nSubAuthority); if (!pSid) { @@ -307,14 +307,14 @@ PDWORD WIN_FUNC GetSidSubAuthority(PSID pSid, DWORD nSubAuthority) { return &sid->SubAuthority[nSubAuthority]; } -BOOL WIN_FUNC ImpersonateLoggedOnUser(HANDLE hToken) { +BOOL WINAPI ImpersonateLoggedOnUser(HANDLE hToken) { HOST_CONTEXT_GUARD(); DEBUG_LOG("STUB: ImpersonateLoggedOnUser(%p)\n", hToken); (void)hToken; return TRUE; } -BOOL WIN_FUNC DuplicateTokenEx(HANDLE hExistingToken, DWORD dwDesiredAccess, void *lpTokenAttributes, +BOOL WINAPI DuplicateTokenEx(HANDLE hExistingToken, DWORD dwDesiredAccess, void *lpTokenAttributes, DWORD ImpersonationLevel, DWORD TokenType, PHANDLE phNewToken) { HOST_CONTEXT_GUARD(); DEBUG_LOG("DuplicateTokenEx(%p, 0x%x, %p, %u, %u, %p)\n", hExistingToken, dwDesiredAccess, lpTokenAttributes, @@ -337,7 +337,7 @@ BOOL WIN_FUNC DuplicateTokenEx(HANDLE hExistingToken, DWORD dwDesiredAccess, voi return TRUE; } -BOOL WIN_FUNC CopySid(DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid) { +BOOL WINAPI CopySid(DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid) { HOST_CONTEXT_GUARD(); DEBUG_LOG("CopySid(%u, %p, %p)\n", nDestinationSidLength, pDestinationSid, pSourceSid); if (!pDestinationSid || !pSourceSid) { @@ -354,7 +354,7 @@ BOOL WIN_FUNC CopySid(DWORD nDestinationSidLength, PSID pDestinationSid, PSID pS return TRUE; } -BOOL WIN_FUNC InitializeSid(PSID sid, PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority, BYTE nSubAuthorityCount) { +BOOL WINAPI InitializeSid(PSID sid, PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority, BYTE nSubAuthorityCount) { HOST_CONTEXT_GUARD(); DEBUG_LOG("InitializeSid(%p, %p, %u)\n", sid, pIdentifierAuthority, nSubAuthorityCount); if (!sid || !pIdentifierAuthority) { @@ -375,7 +375,7 @@ BOOL WIN_FUNC InitializeSid(PSID sid, PSID_IDENTIFIER_AUTHORITY pIdentifierAutho return TRUE; } -BOOL WIN_FUNC EqualSid(PSID pSid1, PSID pSid2) { +BOOL WINAPI EqualSid(PSID pSid1, PSID pSid2) { HOST_CONTEXT_GUARD(); DEBUG_LOG("EqualSid(%p, %p)\n", pSid1, pSid2); if (!pSid1 || !pSid2) { @@ -398,7 +398,7 @@ BOOL WIN_FUNC EqualSid(PSID pSid1, PSID pSid2) { return equal ? TRUE : FALSE; } -BOOL WIN_FUNC SetKernelObjectSecurity(HANDLE Handle, SECURITY_INFORMATION SecurityInformation, +BOOL WINAPI SetKernelObjectSecurity(HANDLE Handle, SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR SecurityDescriptor) { HOST_CONTEXT_GUARD(); DEBUG_LOG("STUB: SetKernelObjectSecurity(%p, 0x%x, %p)\n", Handle, SecurityInformation, SecurityDescriptor); @@ -415,7 +415,7 @@ BOOL WIN_FUNC SetKernelObjectSecurity(HANDLE Handle, SECURITY_INFORMATION Securi return TRUE; } -BOOL WIN_FUNC InitializeSecurityDescriptor(PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD dwRevision) { +BOOL WINAPI InitializeSecurityDescriptor(PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD dwRevision) { HOST_CONTEXT_GUARD(); DEBUG_LOG("InitializeSecurityDescriptor(%p, %u)\n", pSecurityDescriptor, dwRevision); if (!pSecurityDescriptor || dwRevision != SECURITY_DESCRIPTOR_REVISION) { @@ -432,7 +432,7 @@ BOOL WIN_FUNC InitializeSecurityDescriptor(PSECURITY_DESCRIPTOR pSecurityDescrip return TRUE; } -BOOL WIN_FUNC SetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR pSecurityDescriptor, BOOL bDaclPresent, PACL pDacl, +BOOL WINAPI SetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR pSecurityDescriptor, BOOL bDaclPresent, PACL pDacl, BOOL bDaclDefaulted) { HOST_CONTEXT_GUARD(); DEBUG_LOG("SetSecurityDescriptorDacl(%p, %u, %p, %u)\n", pSecurityDescriptor, bDaclPresent, pDacl, bDaclDefaulted); @@ -454,7 +454,7 @@ BOOL WIN_FUNC SetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR pSecurityDescriptor return TRUE; } -BOOL WIN_FUNC GetTokenInformation(HANDLE TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, +BOOL WINAPI GetTokenInformation(HANDLE TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, LPVOID TokenInformation, DWORD TokenInformationLength, LPDWORD ReturnLength) { HOST_CONTEXT_GUARD(); DEBUG_LOG("STUB: GetTokenInformation(%p, %u, %p, %u, %p)\n", TokenHandle, TokenInformationClass, TokenInformation, @@ -534,7 +534,7 @@ BOOL WIN_FUNC GetTokenInformation(HANDLE TokenHandle, TOKEN_INFORMATION_CLASS To return FALSE; } -BOOL WIN_FUNC AdjustTokenPrivileges(HANDLE TokenHandle, BOOL DisableAllPrivileges, PTOKEN_PRIVILEGES NewState, +BOOL WINAPI AdjustTokenPrivileges(HANDLE TokenHandle, BOOL DisableAllPrivileges, PTOKEN_PRIVILEGES NewState, DWORD BufferLength, PTOKEN_PRIVILEGES PreviousState, LPDWORD ReturnLength) { HOST_CONTEXT_GUARD(); DEBUG_LOG("AdjustTokenPrivileges(%p, %u, %p, %u, %p, %p)\n", TokenHandle, DisableAllPrivileges, NewState, @@ -548,7 +548,7 @@ BOOL WIN_FUNC AdjustTokenPrivileges(HANDLE TokenHandle, BOOL DisableAllPrivilege return TRUE; } -BOOL WIN_FUNC SetTokenInformation(HANDLE TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, +BOOL WINAPI SetTokenInformation(HANDLE TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, LPVOID TokenInformation, DWORD TokenInformationLength) { HOST_CONTEXT_GUARD(); DEBUG_LOG("STUB: SetTokenInformation(%p, %u, %p, %u)\n", TokenHandle, TokenInformationClass, TokenInformation, diff --git a/dll/advapi32/securitybaseapi.h b/dll/advapi32/securitybaseapi.h index 9446bbe..3cf9b8c 100644 --- a/dll/advapi32/securitybaseapi.h +++ b/dll/advapi32/securitybaseapi.h @@ -83,30 +83,30 @@ enum TOKEN_INFORMATION_CLASS : DWORD { namespace advapi32 { -BOOL WIN_FUNC InitializeAcl(PACL pAcl, DWORD nAclLength, DWORD dwAclRevision); -BOOL WIN_FUNC AddAccessAllowedAce(PACL pAcl, DWORD dwAceRevision, DWORD AccessMask, PSID pSid); -BOOL WIN_FUNC FindFirstFreeAce(PACL pAcl, LPVOID *pAce); -PSID_IDENTIFIER_AUTHORITY WIN_FUNC GetSidIdentifierAuthority(PSID pSid); -PUCHAR WIN_FUNC GetSidSubAuthorityCount(PSID pSid); -PDWORD WIN_FUNC GetSidSubAuthority(PSID pSid, DWORD nSubAuthority); -BOOL WIN_FUNC ImpersonateLoggedOnUser(HANDLE hToken); -BOOL WIN_FUNC DuplicateTokenEx(HANDLE hExistingToken, DWORD dwDesiredAccess, void *lpTokenAttributes, +BOOL WINAPI InitializeAcl(PACL pAcl, DWORD nAclLength, DWORD dwAclRevision); +BOOL WINAPI AddAccessAllowedAce(PACL pAcl, DWORD dwAceRevision, DWORD AccessMask, PSID pSid); +BOOL WINAPI FindFirstFreeAce(PACL pAcl, LPVOID *pAce); +PSID_IDENTIFIER_AUTHORITY WINAPI GetSidIdentifierAuthority(PSID pSid); +PUCHAR WINAPI GetSidSubAuthorityCount(PSID pSid); +PDWORD WINAPI GetSidSubAuthority(PSID pSid, DWORD nSubAuthority); +BOOL WINAPI ImpersonateLoggedOnUser(HANDLE hToken); +BOOL WINAPI DuplicateTokenEx(HANDLE hExistingToken, DWORD dwDesiredAccess, void *lpTokenAttributes, DWORD ImpersonationLevel, DWORD TokenType, PHANDLE phNewToken); -BOOL WIN_FUNC CopySid(DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid); -BOOL WIN_FUNC InitializeSid(PSID sid, PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority, BYTE nSubAuthorityCount); -BOOL WIN_FUNC EqualSid(PSID pSid1, PSID pSid2); -BOOL WIN_FUNC GetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR pSecurityDescriptor, LPBOOL lpbDaclPresent, PACL *pDacl, +BOOL WINAPI CopySid(DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid); +BOOL WINAPI InitializeSid(PSID sid, PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority, BYTE nSubAuthorityCount); +BOOL WINAPI EqualSid(PSID pSid1, PSID pSid2); +BOOL WINAPI GetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR pSecurityDescriptor, LPBOOL lpbDaclPresent, PACL *pDacl, LPBOOL lpbDaclDefaulted); -BOOL WIN_FUNC SetKernelObjectSecurity(HANDLE Handle, SECURITY_INFORMATION SecurityInformation, +BOOL WINAPI SetKernelObjectSecurity(HANDLE Handle, SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR SecurityDescriptor); -BOOL WIN_FUNC InitializeSecurityDescriptor(PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD dwRevision); -BOOL WIN_FUNC SetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR pSecurityDescriptor, BOOL bDaclPresent, PACL pDacl, +BOOL WINAPI InitializeSecurityDescriptor(PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD dwRevision); +BOOL WINAPI SetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR pSecurityDescriptor, BOOL bDaclPresent, PACL pDacl, BOOL bDaclDefaulted); -BOOL WIN_FUNC GetTokenInformation(HANDLE TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, +BOOL WINAPI GetTokenInformation(HANDLE TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, LPVOID TokenInformation, DWORD TokenInformationLength, LPDWORD ReturnLength); -BOOL WIN_FUNC AdjustTokenPrivileges(HANDLE TokenHandle, BOOL DisableAllPrivileges, PTOKEN_PRIVILEGES NewState, +BOOL WINAPI AdjustTokenPrivileges(HANDLE TokenHandle, BOOL DisableAllPrivileges, PTOKEN_PRIVILEGES NewState, DWORD BufferLength, PTOKEN_PRIVILEGES PreviousState, LPDWORD ReturnLength); -BOOL WIN_FUNC SetTokenInformation(HANDLE TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, +BOOL WINAPI SetTokenInformation(HANDLE TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, LPVOID TokenInformation, DWORD TokenInformationLength); } // namespace advapi32 diff --git a/dll/advapi32/winbase.cpp b/dll/advapi32/winbase.cpp index d384934..8b75562 100644 --- a/dll/advapi32/winbase.cpp +++ b/dll/advapi32/winbase.cpp @@ -84,7 +84,7 @@ LUID lookupOrGeneratePrivilegeLuid(const std::string &normalizedName) { namespace advapi32 { -BOOL WIN_FUNC LookupAccountSidW(LPCWSTR lpSystemName, PSID Sid, LPWSTR Name, LPDWORD cchName, +BOOL WINAPI LookupAccountSidW(LPCWSTR lpSystemName, PSID Sid, LPWSTR Name, LPDWORD cchName, LPWSTR ReferencedDomainName, LPDWORD cchReferencedDomainName, SID_NAME_USE *peUse) { HOST_CONTEXT_GUARD(); std::string systemName = lpSystemName ? wideStringToString(lpSystemName) : std::string("(null)"); @@ -115,7 +115,7 @@ BOOL WIN_FUNC LookupAccountSidW(LPCWSTR lpSystemName, PSID Sid, LPWSTR Name, LPD return TRUE; } -BOOL WIN_FUNC LookupPrivilegeValueA(LPCSTR lpSystemName, LPCSTR lpName, PLUID lpLuid) { +BOOL WINAPI LookupPrivilegeValueA(LPCSTR lpSystemName, LPCSTR lpName, PLUID lpLuid) { HOST_CONTEXT_GUARD(); DEBUG_LOG("LookupPrivilegeValueA(%s, %s, %p)\n", lpSystemName ? lpSystemName : "(null)", lpName ? lpName : "(null)", lpLuid); @@ -130,7 +130,7 @@ BOOL WIN_FUNC LookupPrivilegeValueA(LPCSTR lpSystemName, LPCSTR lpName, PLUID lp return TRUE; } -BOOL WIN_FUNC LookupPrivilegeValueW(LPCWSTR lpSystemName, LPCWSTR lpName, PLUID lpLuid) { +BOOL WINAPI LookupPrivilegeValueW(LPCWSTR lpSystemName, LPCWSTR lpName, PLUID lpLuid) { HOST_CONTEXT_GUARD(); DEBUG_LOG("LookupPrivilegeValueW(%p, %p, %p)\n", lpSystemName, lpName, lpLuid); (void)lpSystemName; // only local lookup supported @@ -145,7 +145,7 @@ BOOL WIN_FUNC LookupPrivilegeValueW(LPCWSTR lpSystemName, LPCWSTR lpName, PLUID return TRUE; } -BOOL WIN_FUNC GetUserNameA(LPSTR lpBuffer, LPDWORD pcbBuffer) { +BOOL WINAPI GetUserNameA(LPSTR lpBuffer, LPDWORD pcbBuffer) { HOST_CONTEXT_GUARD(); DEBUG_LOG("GetUserNameA(%p, %p)\n", lpBuffer, pcbBuffer); if (!pcbBuffer) { @@ -164,7 +164,7 @@ BOOL WIN_FUNC GetUserNameA(LPSTR lpBuffer, LPDWORD pcbBuffer) { return TRUE; } -BOOL WIN_FUNC GetUserNameW(LPWSTR lpBuffer, LPDWORD pcbBuffer) { +BOOL WINAPI GetUserNameW(LPWSTR lpBuffer, LPDWORD pcbBuffer) { HOST_CONTEXT_GUARD(); DEBUG_LOG("GetUserNameW(%p, %p)\n", lpBuffer, pcbBuffer); if (!pcbBuffer) { diff --git a/dll/advapi32/winbase.h b/dll/advapi32/winbase.h index de20e5f..4df329b 100644 --- a/dll/advapi32/winbase.h +++ b/dll/advapi32/winbase.h @@ -17,11 +17,11 @@ enum SID_NAME_USE : DWORD { namespace advapi32 { -BOOL WIN_FUNC LookupAccountSidW(LPCWSTR lpSystemName, PSID Sid, LPWSTR Name, LPDWORD cchName, +BOOL WINAPI LookupAccountSidW(LPCWSTR lpSystemName, PSID Sid, LPWSTR Name, LPDWORD cchName, LPWSTR ReferencedDomainName, LPDWORD cchReferencedDomainName, SID_NAME_USE *peUse); -BOOL WIN_FUNC LookupPrivilegeValueA(LPCSTR lpSystemName, LPCSTR lpName, PLUID lpLuid); -BOOL WIN_FUNC LookupPrivilegeValueW(LPCWSTR lpSystemName, LPCWSTR lpName, PLUID lpLuid); -BOOL WIN_FUNC GetUserNameA(LPSTR lpBuffer, LPDWORD pcbBuffer); -BOOL WIN_FUNC GetUserNameW(LPWSTR lpBuffer, LPDWORD pcbBuffer); +BOOL WINAPI LookupPrivilegeValueA(LPCSTR lpSystemName, LPCSTR lpName, PLUID lpLuid); +BOOL WINAPI LookupPrivilegeValueW(LPCWSTR lpSystemName, LPCWSTR lpName, PLUID lpLuid); +BOOL WINAPI GetUserNameA(LPSTR lpBuffer, LPDWORD pcbBuffer); +BOOL WINAPI GetUserNameW(LPWSTR lpBuffer, LPDWORD pcbBuffer); } // namespace advapi32 diff --git a/dll/advapi32/wincrypt.cpp b/dll/advapi32/wincrypt.cpp index 5cfb634..93b10e6 100644 --- a/dll/advapi32/wincrypt.cpp +++ b/dll/advapi32/wincrypt.cpp @@ -60,7 +60,7 @@ DWORD hashSizeForAlgid(ALG_ID algid) { namespace advapi32 { -BOOL WIN_FUNC CryptReleaseContext(HCRYPTPROV hProv, DWORD dwFlags) { +BOOL WINAPI CryptReleaseContext(HCRYPTPROV hProv, DWORD dwFlags) { HOST_CONTEXT_GUARD(); DEBUG_LOG("STUB: CryptReleaseContext(%p, %u)\n", reinterpret_cast(static_cast(hProv)), dwFlags); (void)hProv; @@ -68,7 +68,7 @@ BOOL WIN_FUNC CryptReleaseContext(HCRYPTPROV hProv, DWORD dwFlags) { return TRUE; } -BOOL WIN_FUNC CryptAcquireContextW(HCRYPTPROV *phProv, LPCWSTR pszContainer, LPCWSTR pszProvider, DWORD dwProvType, +BOOL WINAPI CryptAcquireContextW(HCRYPTPROV *phProv, LPCWSTR pszContainer, LPCWSTR pszProvider, DWORD dwProvType, DWORD dwFlags) { HOST_CONTEXT_GUARD(); DEBUG_LOG("STUB: CryptAcquireContextW(%p, %p, %p, %u, %u)\n", phProv, pszContainer, pszProvider, dwProvType, @@ -83,7 +83,7 @@ BOOL WIN_FUNC CryptAcquireContextW(HCRYPTPROV *phProv, LPCWSTR pszContainer, LPC return TRUE; } -BOOL WIN_FUNC CryptGenRandom(HCRYPTPROV hProv, DWORD dwLen, BYTE *pbBuffer) { +BOOL WINAPI CryptGenRandom(HCRYPTPROV hProv, DWORD dwLen, BYTE *pbBuffer) { HOST_CONTEXT_GUARD(); DEBUG_LOG("CryptGenRandom(%p)\n", reinterpret_cast(static_cast(hProv))); (void)hProv; @@ -101,7 +101,7 @@ BOOL WIN_FUNC CryptGenRandom(HCRYPTPROV hProv, DWORD dwLen, BYTE *pbBuffer) { return TRUE; } -BOOL WIN_FUNC CryptCreateHash(HCRYPTPROV hProv, ALG_ID Algid, HCRYPTKEY hKey, DWORD dwFlags, HCRYPTHASH *phHash) { +BOOL WINAPI CryptCreateHash(HCRYPTPROV hProv, ALG_ID Algid, HCRYPTKEY hKey, DWORD dwFlags, HCRYPTHASH *phHash) { HOST_CONTEXT_GUARD(); DEBUG_LOG("CryptCreateHash(%p, %u, %p, %u, %p)\n", reinterpret_cast(static_cast(hProv)), Algid, reinterpret_cast(static_cast(hKey)), dwFlags, phHash); @@ -133,7 +133,7 @@ BOOL WIN_FUNC CryptCreateHash(HCRYPTPROV hProv, ALG_ID Algid, HCRYPTKEY hKey, DW return TRUE; } -BOOL WIN_FUNC CryptHashData(HCRYPTHASH hHash, const BYTE *pbData, DWORD dwDataLen, DWORD dwFlags) { +BOOL WINAPI CryptHashData(HCRYPTHASH hHash, const BYTE *pbData, DWORD dwDataLen, DWORD dwFlags) { HOST_CONTEXT_GUARD(); DEBUG_LOG("CryptHashData(%p, %p, %u, %u)\n", reinterpret_cast(static_cast(hHash)), pbData, dwDataLen, dwFlags); @@ -156,7 +156,7 @@ BOOL WIN_FUNC CryptHashData(HCRYPTHASH hHash, const BYTE *pbData, DWORD dwDataLe return TRUE; } -BOOL WIN_FUNC CryptGetHashParam(HCRYPTHASH hHash, DWORD dwParam, BYTE *pbData, DWORD *pdwDataLen, DWORD dwFlags) { +BOOL WINAPI CryptGetHashParam(HCRYPTHASH hHash, DWORD dwParam, BYTE *pbData, DWORD *pdwDataLen, DWORD dwFlags) { HOST_CONTEXT_GUARD(); DEBUG_LOG("CryptGetHashParam(%p, %u, %p, %p, %u)\n", reinterpret_cast(static_cast(hHash)), dwParam, pbData, pdwDataLen, dwFlags); @@ -234,7 +234,7 @@ BOOL WIN_FUNC CryptGetHashParam(HCRYPTHASH hHash, DWORD dwParam, BYTE *pbData, D } } -BOOL WIN_FUNC CryptDestroyHash(HCRYPTHASH hHash) { +BOOL WINAPI CryptDestroyHash(HCRYPTHASH hHash) { HOST_CONTEXT_GUARD(); DEBUG_LOG("CryptDestroyHash(%p)\n", reinterpret_cast(static_cast(hHash))); auto *hash = hashObjectFromHandle(hHash); diff --git a/dll/advapi32/wincrypt.h b/dll/advapi32/wincrypt.h index b6b619f..d7ba5bf 100644 --- a/dll/advapi32/wincrypt.h +++ b/dll/advapi32/wincrypt.h @@ -16,13 +16,13 @@ constexpr DWORD HP_HASHSIZE = 0x00000004; namespace advapi32 { -BOOL WIN_FUNC CryptReleaseContext(HCRYPTPROV hProv, DWORD dwFlags); -BOOL WIN_FUNC CryptAcquireContextW(HCRYPTPROV *phProv, LPCWSTR pszContainer, LPCWSTR pszProvider, DWORD dwProvType, +BOOL WINAPI CryptReleaseContext(HCRYPTPROV hProv, DWORD dwFlags); +BOOL WINAPI CryptAcquireContextW(HCRYPTPROV *phProv, LPCWSTR pszContainer, LPCWSTR pszProvider, DWORD dwProvType, DWORD dwFlags); -BOOL WIN_FUNC CryptGenRandom(HCRYPTPROV hProv, DWORD dwLen, BYTE *pbBuffer); -BOOL WIN_FUNC CryptCreateHash(HCRYPTPROV hProv, ALG_ID Algid, HCRYPTKEY hKey, DWORD dwFlags, HCRYPTHASH *phHash); -BOOL WIN_FUNC CryptHashData(HCRYPTHASH hHash, const BYTE *pbData, DWORD dwDataLen, DWORD dwFlags); -BOOL WIN_FUNC CryptGetHashParam(HCRYPTHASH hHash, DWORD dwParam, BYTE *pbData, DWORD *pdwDataLen, DWORD dwFlags); -BOOL WIN_FUNC CryptDestroyHash(HCRYPTHASH hHash); +BOOL WINAPI CryptGenRandom(HCRYPTPROV hProv, DWORD dwLen, BYTE *pbBuffer); +BOOL WINAPI CryptCreateHash(HCRYPTPROV hProv, ALG_ID Algid, HCRYPTKEY hKey, DWORD dwFlags, HCRYPTHASH *phHash); +BOOL WINAPI CryptHashData(HCRYPTHASH hHash, const BYTE *pbData, DWORD dwDataLen, DWORD dwFlags); +BOOL WINAPI CryptGetHashParam(HCRYPTHASH hHash, DWORD dwParam, BYTE *pbData, DWORD *pdwDataLen, DWORD dwFlags); +BOOL WINAPI CryptDestroyHash(HCRYPTHASH hHash); } // namespace advapi32 diff --git a/dll/advapi32/winreg.cpp b/dll/advapi32/winreg.cpp index 114c680..4a309fa 100644 --- a/dll/advapi32/winreg.cpp +++ b/dll/advapi32/winreg.cpp @@ -125,7 +125,7 @@ bool isPredefinedKeyHandle(HKEY hKey) { namespace advapi32 { -LSTATUS WIN_FUNC RegCreateKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD Reserved, LPWSTR lpClass, DWORD dwOptions, +LSTATUS WINAPI RegCreateKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD Reserved, LPWSTR lpClass, DWORD dwOptions, REGSAM samDesired, void *lpSecurityAttributes, PHKEY phkResult, LPDWORD lpdwDisposition) { HOST_CONTEXT_GUARD(); @@ -192,7 +192,7 @@ LSTATUS WIN_FUNC RegCreateKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD Reserved, LP return ERROR_SUCCESS; } -LSTATUS WIN_FUNC RegCreateKeyExA(HKEY hKey, LPCSTR lpSubKey, DWORD Reserved, LPSTR lpClass, DWORD dwOptions, +LSTATUS WINAPI RegCreateKeyExA(HKEY hKey, LPCSTR lpSubKey, DWORD Reserved, LPSTR lpClass, DWORD dwOptions, REGSAM samDesired, void *lpSecurityAttributes, PHKEY phkResult, LPDWORD lpdwDisposition) { HOST_CONTEXT_GUARD(); @@ -212,7 +212,7 @@ LSTATUS WIN_FUNC RegCreateKeyExA(HKEY hKey, LPCSTR lpSubKey, DWORD Reserved, LPS lpSecurityAttributes, phkResult, lpdwDisposition); } -LSTATUS WIN_FUNC RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult) { +LSTATUS WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult) { HOST_CONTEXT_GUARD(); std::string subKeyString = lpSubKey ? wideStringToString(lpSubKey) : std::string("(null)"); DEBUG_LOG("RegOpenKeyExW(%p, %s, %u, 0x%x, %p)\n", hKey, subKeyString.c_str(), ulOptions, samDesired, phkResult); @@ -269,7 +269,7 @@ LSTATUS WIN_FUNC RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REG return ERROR_SUCCESS; } -LSTATUS WIN_FUNC RegOpenKeyExA(HKEY hKey, LPCSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult) { +LSTATUS WINAPI RegOpenKeyExA(HKEY hKey, LPCSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult) { HOST_CONTEXT_GUARD(); DEBUG_LOG("RegOpenKeyExA(%p, %s, %u, 0x%x, %p)\n", hKey, lpSubKey ? lpSubKey : "(null)", ulOptions, samDesired, phkResult); @@ -282,7 +282,7 @@ LSTATUS WIN_FUNC RegOpenKeyExA(HKEY hKey, LPCSTR lpSubKey, DWORD ulOptions, REGS return RegOpenKeyExW(hKey, widePtr, ulOptions, samDesired, phkResult); } -LSTATUS WIN_FUNC RegQueryValueExW(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, BYTE *lpData, +LSTATUS WINAPI RegQueryValueExW(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, BYTE *lpData, LPDWORD lpcbData) { HOST_CONTEXT_GUARD(); std::string valueName = lpValueName ? wideStringToString(lpValueName) : std::string("(default)"); @@ -304,7 +304,7 @@ LSTATUS WIN_FUNC RegQueryValueExW(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpRese return ERROR_FILE_NOT_FOUND; } -LSTATUS WIN_FUNC RegQueryValueExA(HKEY hKey, LPCSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, BYTE *lpData, +LSTATUS WINAPI RegQueryValueExA(HKEY hKey, LPCSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, BYTE *lpData, LPDWORD lpcbData) { HOST_CONTEXT_GUARD(); DEBUG_LOG("RegQueryValueExA(%p, %s, %p, %p, %p, %p)\n", hKey, lpValueName ? lpValueName : "(null)", lpReserved, @@ -317,7 +317,7 @@ LSTATUS WIN_FUNC RegQueryValueExA(HKEY hKey, LPCSTR lpValueName, LPDWORD lpReser lpReserved, lpType, lpData, lpcbData); } -LSTATUS WIN_FUNC RegEnumKeyExW(HKEY hKey, DWORD dwIndex, LPWSTR lpName, LPDWORD lpcchName, LPDWORD lpReserved, +LSTATUS WINAPI RegEnumKeyExW(HKEY hKey, DWORD dwIndex, LPWSTR lpName, LPDWORD lpcchName, LPDWORD lpReserved, LPWSTR lpClass, LPDWORD lpcchClass, FILETIME *lpftLastWriteTime) { HOST_CONTEXT_GUARD(); DEBUG_LOG("RegEnumKeyExW(%p, %u, %p, %p, %p, %p, %p, %p)\n", hKey, dwIndex, lpName, lpcchName, lpReserved, lpClass, @@ -345,7 +345,7 @@ LSTATUS WIN_FUNC RegEnumKeyExW(HKEY hKey, DWORD dwIndex, LPWSTR lpName, LPDWORD return ERROR_NO_MORE_ITEMS; } -LSTATUS WIN_FUNC RegEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpName, LPDWORD lpcchName, LPDWORD lpReserved, +LSTATUS WINAPI RegEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpName, LPDWORD lpcchName, LPDWORD lpReserved, LPSTR lpClass, LPDWORD lpcchClass, FILETIME *lpftLastWriteTime) { HOST_CONTEXT_GUARD(); DEBUG_LOG("RegEnumKeyExA(%p, %u, %p, %p, %p, %p, %p, %p)\n", hKey, dwIndex, lpName, lpcchName, lpReserved, lpClass, @@ -373,7 +373,7 @@ LSTATUS WIN_FUNC RegEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpName, LPDWORD l return ERROR_NO_MORE_ITEMS; } -LSTATUS WIN_FUNC RegCloseKey(HKEY hKey) { +LSTATUS WINAPI RegCloseKey(HKEY hKey) { HOST_CONTEXT_GUARD(); DEBUG_LOG("RegCloseKey(%p)\n", hKey); if (isPredefinedKeyHandle(hKey)) { diff --git a/dll/advapi32/winreg.h b/dll/advapi32/winreg.h index bec8b23..574fc7d 100644 --- a/dll/advapi32/winreg.h +++ b/dll/advapi32/winreg.h @@ -33,22 +33,22 @@ constexpr REGSAM KEY_WOW64_32KEY = 0x00000200; namespace advapi32 { -LSTATUS WIN_FUNC RegCreateKeyExA(HKEY hKey, LPCSTR lpSubKey, DWORD Reserved, LPSTR lpClass, DWORD dwOptions, +LSTATUS WINAPI RegCreateKeyExA(HKEY hKey, LPCSTR lpSubKey, DWORD Reserved, LPSTR lpClass, DWORD dwOptions, REGSAM samDesired, void *lpSecurityAttributes, PHKEY phkResult, LPDWORD lpdwDisposition); -LSTATUS WIN_FUNC RegCreateKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD Reserved, LPWSTR lpClass, DWORD dwOptions, +LSTATUS WINAPI RegCreateKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD Reserved, LPWSTR lpClass, DWORD dwOptions, REGSAM samDesired, void *lpSecurityAttributes, PHKEY phkResult, LPDWORD lpdwDisposition); -LSTATUS WIN_FUNC RegOpenKeyExA(HKEY hKey, LPCSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult); -LSTATUS WIN_FUNC RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult); -LSTATUS WIN_FUNC RegQueryValueExA(HKEY hKey, LPCSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, BYTE *lpData, +LSTATUS WINAPI RegOpenKeyExA(HKEY hKey, LPCSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult); +LSTATUS WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult); +LSTATUS WINAPI RegQueryValueExA(HKEY hKey, LPCSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, BYTE *lpData, LPDWORD lpcbData); -LSTATUS WIN_FUNC RegQueryValueExW(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, BYTE *lpData, +LSTATUS WINAPI RegQueryValueExW(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, BYTE *lpData, LPDWORD lpcbData); -LSTATUS WIN_FUNC RegEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpName, LPDWORD lpcchName, LPDWORD lpReserved, +LSTATUS WINAPI RegEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpName, LPDWORD lpcchName, LPDWORD lpReserved, LPSTR lpClass, LPDWORD lpcchClass, FILETIME *lpftLastWriteTime); -LSTATUS WIN_FUNC RegEnumKeyExW(HKEY hKey, DWORD dwIndex, LPWSTR lpName, LPDWORD lpcchName, LPDWORD lpReserved, +LSTATUS WINAPI RegEnumKeyExW(HKEY hKey, DWORD dwIndex, LPWSTR lpName, LPDWORD lpcchName, LPDWORD lpReserved, LPWSTR lpClass, LPDWORD lpcchClass, FILETIME *lpftLastWriteTime); -LSTATUS WIN_FUNC RegCloseKey(HKEY hKey); +LSTATUS WINAPI RegCloseKey(HKEY hKey); } // namespace advapi32 diff --git a/dll/bcrypt.cpp b/dll/bcrypt.cpp index a77836b..e27c99c 100644 --- a/dll/bcrypt.cpp +++ b/dll/bcrypt.cpp @@ -85,6 +85,6 @@ extern const wibo::ModuleStub lib_bcrypt = { "bcryptprimitives", nullptr, }, - bcrypt_trampoline_by_name, + bcryptThunkByName, nullptr, }; diff --git a/dll/crt.cpp b/dll/crt.cpp index 739d702..2f30444 100644 --- a/dll/crt.cpp +++ b/dll/crt.cpp @@ -1,5 +1,8 @@ +#include "crt.h" + #include "common.h" #include "context.h" +#include "crt_trampolines.h" #include "kernel32/internal.h" #include "modules.h" @@ -11,29 +14,6 @@ #include #include -typedef void (*_PVFV)(); -typedef int (*_PIFV)(); -typedef void (*_invalid_parameter_handler)(const uint16_t *, const uint16_t *, const uint16_t *, unsigned int, - uintptr_t); - -extern char **environ; - -namespace msvcrt { -int WIN_ENTRY puts(const char *str); -} - -typedef enum _crt_app_type { - _crt_unknown_app, - _crt_console_app, - _crt_gui_app, -} _crt_app_type; - -typedef enum _crt_argv_mode { - _crt_argv_no_arguments, - _crt_argv_unexpanded_arguments, - _crt_argv_expanded_arguments, -} _crt_argv_mode; - namespace crt { int _commode = 0; @@ -42,33 +22,24 @@ int _fmode = 0; std::vector<_PVFV> atexitFuncs; _invalid_parameter_handler invalidParameterHandler = nullptr; -void WIN_ENTRY _initterm(const _PVFV *ppfn, const _PVFV *end) { +void CDECL _initterm(const _PVFV *ppfn, const _PVFV *end) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_initterm(%p, %p)\n", ppfn, end); - auto *tib = wibo::getThreadTibForHost(); do { if (_PVFV pfn = *++ppfn) { DEBUG_LOG("-> calling %p\n", pfn); - { - GUEST_CONTEXT_GUARD(tib); - pfn(); - } + call__PVFV(pfn); } } while (ppfn < end); } -int WIN_ENTRY _initterm_e(const _PIFV *ppfn, const _PIFV *end) { +int CDECL _initterm_e(const _PIFV *ppfn, const _PIFV *end) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_initterm_e(%p, %p)\n", ppfn, end); - auto *tib = wibo::getThreadTibForHost(); do { if (_PIFV pfn = *++ppfn) { DEBUG_LOG("-> calling %p\n", pfn); - int err = 0; - { - GUEST_CONTEXT_GUARD(tib); - err = pfn(); - } + int err = call__PIFV(pfn); if (err) return err; } @@ -77,44 +48,44 @@ int WIN_ENTRY _initterm_e(const _PIFV *ppfn, const _PIFV *end) { return 0; } -void WIN_ENTRY _set_app_type(_crt_app_type type) { +void CDECL _set_app_type(_crt_app_type type) { HOST_CONTEXT_GUARD(); DEBUG_LOG("STUB: _set_app_type(%i)\n", type); } -int WIN_ENTRY _set_fmode(int mode) { +int CDECL _set_fmode(int mode) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_set_fmode(%i)\n", mode); _fmode = mode; return 0; } -int *WIN_ENTRY __p__commode() { +int *CDECL __p__commode() { HOST_CONTEXT_GUARD(); DEBUG_LOG("__p__commode()\n"); return &_commode; } -int *WIN_ENTRY __p__fmode() { +int *CDECL __p__fmode() { HOST_CONTEXT_GUARD(); DEBUG_LOG("__p__fmode()\n"); return &_fmode; } -int WIN_ENTRY _crt_atexit(void (*func)()) { +int CDECL _crt_atexit(void (*func)()) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_crt_atexit(%p)\n", func); atexitFuncs.push_back(func); return 0; } -int WIN_ENTRY _configure_narrow_argv(_crt_argv_mode mode) { +int CDECL _configure_narrow_argv(_crt_argv_mode mode) { HOST_CONTEXT_GUARD(); DEBUG_LOG("STUB: _configure_narrow_argv(%i)\n", mode); return 0; } -_invalid_parameter_handler WIN_ENTRY _set_invalid_parameter_handler(_invalid_parameter_handler newHandler) { +_invalid_parameter_handler CDECL _set_invalid_parameter_handler(_invalid_parameter_handler newHandler) { HOST_CONTEXT_GUARD(); DEBUG_LOG("STUB: _set_invalid_parameter_handler(%p)\n", newHandler); _invalid_parameter_handler oldHandler = invalidParameterHandler; @@ -122,213 +93,203 @@ _invalid_parameter_handler WIN_ENTRY _set_invalid_parameter_handler(_invalid_par return oldHandler; } -int WIN_ENTRY _controlfp_s(unsigned int *currentControl, unsigned int newControl, unsigned int mask) { +int CDECL _controlfp_s(unsigned int *currentControl, unsigned int newControl, unsigned int mask) { HOST_CONTEXT_GUARD(); DEBUG_LOG("STUB: _controlfp_s(%p, %u, %u)\n", currentControl, newControl, mask); return 0; } -int WIN_ENTRY _configthreadlocale(int per_thread_locale_type) { +int CDECL _configthreadlocale(int per_thread_locale_type) { HOST_CONTEXT_GUARD(); DEBUG_LOG("STUB: _configthreadlocale(%i)\n", per_thread_locale_type); return 0; } -int WIN_ENTRY _initialize_narrow_environment() { +int CDECL _initialize_narrow_environment() { HOST_CONTEXT_GUARD(); DEBUG_LOG("STUB: _initialize_narrow_environment()\n"); return 0; } -int WIN_ENTRY _set_new_mode(int newhandlermode) { +int CDECL _set_new_mode(int newhandlermode) { HOST_CONTEXT_GUARD(); DEBUG_LOG("STUB: _set_new_mode(%i)\n", newhandlermode); return 0; } -char **WIN_ENTRY _get_initial_narrow_environment() { +char **CDECL _get_initial_narrow_environment() { HOST_CONTEXT_GUARD(); DEBUG_LOG("_get_initial_narrow_environment()\n"); return environ; } -char ***WIN_ENTRY __p__environ() { +char ***CDECL __p__environ() { HOST_CONTEXT_GUARD(); DEBUG_LOG("__p__environ()\n"); return &environ; } -char ***WIN_ENTRY __p___argv() { +char ***CDECL __p___argv() { HOST_CONTEXT_GUARD(); DEBUG_LOG("__p___argv()\n"); return &wibo::argv; } -int *WIN_ENTRY __p___argc() { +int *CDECL __p___argc() { HOST_CONTEXT_GUARD(); DEBUG_LOG("__p___argc()\n"); return &wibo::argc; } -size_t WIN_ENTRY strlen(const char *str) { +SIZE_T CDECL strlen(const char *str) { HOST_CONTEXT_GUARD(); VERBOSE_LOG("strlen(%p)\n", str); return ::strlen(str); } -int WIN_ENTRY strcmp(const char *lhs, const char *rhs) { +int CDECL strcmp(const char *lhs, const char *rhs) { HOST_CONTEXT_GUARD(); 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) { +int CDECL strncmp(const char *lhs, const char *rhs, SIZE_T count) { HOST_CONTEXT_GUARD(); VERBOSE_LOG("strncmp(%p, %p, %zu)\n", lhs, rhs, count); return ::strncmp(lhs, rhs, count); } -char *WIN_ENTRY strcpy(char *dest, const char *src) { +char *CDECL strcpy(char *dest, const char *src) { HOST_CONTEXT_GUARD(); VERBOSE_LOG("strcpy(%p, %p)\n", dest, src); return ::strcpy(dest, src); } -char *WIN_ENTRY strncpy(char *dest, const char *src, size_t count) { +char *CDECL strncpy(char *dest, const char *src, SIZE_T count) { HOST_CONTEXT_GUARD(); VERBOSE_LOG("strncpy(%p, %p, %zu)\n", dest, src, count); return ::strncpy(dest, src, count); } -const char *WIN_ENTRY strrchr(const char *str, int ch) { +const char *CDECL strrchr(const char *str, int ch) { HOST_CONTEXT_GUARD(); VERBOSE_LOG("strrchr(%p, %i)\n", str, ch); return ::strrchr(str, ch); } -void *WIN_ENTRY malloc(size_t size) { +void *CDECL malloc(SIZE_T size) { HOST_CONTEXT_GUARD(); VERBOSE_LOG("malloc(%zu)\n", size); return ::malloc(size); } -void *WIN_ENTRY calloc(size_t count, size_t size) { +void *CDECL calloc(SIZE_T count, SIZE_T size) { HOST_CONTEXT_GUARD(); VERBOSE_LOG("calloc(%zu, %zu)\n", count, size); return ::calloc(count, size); } -void *WIN_ENTRY realloc(void *ptr, size_t newSize) { +void *CDECL realloc(void *ptr, SIZE_T newSize) { HOST_CONTEXT_GUARD(); VERBOSE_LOG("realloc(%p, %zu)\n", ptr, newSize); return ::realloc(ptr, newSize); } -void WIN_ENTRY free(void *ptr) { +void CDECL free(void *ptr) { HOST_CONTEXT_GUARD(); VERBOSE_LOG("free(%p)\n", ptr); ::free(ptr); } -void *WIN_ENTRY memcpy(void *dest, const void *src, size_t count) { +void *CDECL memcpy(void *dest, const void *src, SIZE_T count) { HOST_CONTEXT_GUARD(); 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) { +void *CDECL memmove(void *dest, const void *src, SIZE_T count) { HOST_CONTEXT_GUARD(); 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) { +void *CDECL memset(void *dest, int ch, SIZE_T count) { HOST_CONTEXT_GUARD(); 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) { +int CDECL memcmp(const void *lhs, const void *rhs, SIZE_T count) { HOST_CONTEXT_GUARD(); VERBOSE_LOG("memcmp(%p, %p, %zu)\n", lhs, rhs, count); return std::memcmp(lhs, rhs, count); } -int WIN_ENTRY __setusermatherr(void *handler) { +int CDECL __setusermatherr(void *handler) { HOST_CONTEXT_GUARD(); DEBUG_LOG("STUB: __setusermatherr(%p)\n", handler); return 0; } -int WIN_ENTRY _initialize_onexit_table(void *table) { +int CDECL _initialize_onexit_table(void *table) { HOST_CONTEXT_GUARD(); DEBUG_LOG("STUB: _initialize_onexit_table(%p)\n", table); wibo::registerOnExitTable(table); return 0; } -int WIN_ENTRY _register_onexit_function(void *table, void (*func)()) { +int CDECL _register_onexit_function(void *table, void (*func)()) { HOST_CONTEXT_GUARD(); DEBUG_LOG("STUB: _register_onexit_function(%p, %p)\n", table, func); wibo::addOnExitFunction(table, func); return 0; } -int WIN_ENTRY _execute_onexit_table(void *table) { +int CDECL _execute_onexit_table(void *table) { HOST_CONTEXT_GUARD(); DEBUG_LOG("STUB: _execute_onexit_table(%p)\n", table); wibo::executeOnExitTable(table); return 0; } -void WIN_ENTRY exit(int status) { +void CDECL exit(int status) { HOST_CONTEXT_GUARD(); DEBUG_LOG("exit(%i)\n", status); - auto *tib = wibo::getThreadTibForHost(); for (auto it = atexitFuncs.rbegin(); it != atexitFuncs.rend(); ++it) { DEBUG_LOG("Calling atexit function %p\n", *it); - { - GUEST_CONTEXT_GUARD(tib); - (*it)(); - } + call__PVFV(*it); } kernel32::exitInternal(status); } -void WIN_ENTRY _cexit() { +void CDECL _cexit() { HOST_CONTEXT_GUARD(); DEBUG_LOG("_cexit()\n"); - auto *tib = wibo::getThreadTibForHost(); for (auto it = atexitFuncs.rbegin(); it != atexitFuncs.rend(); ++it) { DEBUG_LOG("Calling atexit function %p\n", *it); - { - GUEST_CONTEXT_GUARD(tib); - (*it)(); - } + call__PVFV(*it); } } -void WIN_ENTRY _exit(int status) { +void CDECL _exit(int status) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_exit(%i)\n", status); kernel32::exitInternal(status); } -void WIN_ENTRY abort(void) { +void CDECL abort() { HOST_CONTEXT_GUARD(); DEBUG_LOG("abort()\n"); std::abort(); } -using signal_handler = void (*)(int); - -signal_handler WIN_ENTRY signal(int signum, signal_handler handler) { +signal_handler CDECL signal(int signum, signal_handler handler) { HOST_CONTEXT_GUARD(); DEBUG_LOG("signal(%i, %p)\n", signum, handler); return std::signal(signum, handler); } -void *WIN_ENTRY __acrt_iob_func(unsigned int index) { +void *CDECL __acrt_iob_func(unsigned int index) { HOST_CONTEXT_GUARD(); DEBUG_LOG("__acrt_iob_func(%u)\n", index); if (index == 0) @@ -340,15 +301,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 CDECL __stdio_common_vfprintf(unsigned long long options, FILE *stream, const char *format, void *locale, + va_list args) { HOST_CONTEXT_GUARD(); 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 CDECL __stdio_common_vsprintf(unsigned long long options, char *buffer, SIZE_T len, const char *format, + void *locale, va_list args) { HOST_CONTEXT_GUARD(); DEBUG_LOG("__stdio_common_vsprintf(%llu, %p, %zu, %s, %p, ...)\n", options, buffer, len, format, locale); if (!buffer || !format) @@ -356,113 +317,38 @@ int WIN_ENTRY __stdio_common_vsprintf(unsigned long long options, char *buffer, int result = vsnprintf(buffer, len, format, args); if (result < 0) return -1; - if (len > 0 && static_cast(result) >= len) + if (len > 0 && static_cast(result) >= len) return -1; return result; } -int WIN_ENTRY qsort(void *base, size_t num, size_t size, int (*compar)(const void *, const void *)) { +static thread_local sort_compare currentCompare = nullptr; + +static int doCompare(const void *a, const void *b) { return call_sort_compare(currentCompare, a, b); } + +void CDECL qsort(void *base, SIZE_T num, SIZE_T size, sort_compare compare) { HOST_CONTEXT_GUARD(); - DEBUG_LOG("qsort(%p, %zu, %zu, %p)\n", base, num, size, compar); - ::qsort(base, num, size, compar); + DEBUG_LOG("qsort(%p, %zu, %zu, %p)\n", base, num, size, compare); + currentCompare = compare; + ::qsort(base, num, size, doCompare); +} + +int CDECL puts(const char *str) { + HOST_CONTEXT_GUARD(); + if (!str) { + str = "(null)"; + } + DEBUG_LOG("puts(%s)\n", str); + if (std::fputs(str, stdout) < 0) + return EOF; + if (std::fputc('\n', stdout) == EOF) + return EOF; return 0; } } // namespace crt -static void *resolveByName(const char *name) { - if (strcmp(name, "_initterm") == 0) - return (void *)crt::_initterm; - if (strcmp(name, "_initterm_e") == 0) - return (void *)crt::_initterm_e; - if (strcmp(name, "_set_app_type") == 0) - return (void *)crt::_set_app_type; - if (strcmp(name, "_set_fmode") == 0) - return (void *)crt::_set_fmode; - if (strcmp(name, "__p__commode") == 0) - return (void *)crt::__p__commode; - if (strcmp(name, "__p__fmode") == 0) - return (void *)crt::__p__fmode; - if (strcmp(name, "_crt_atexit") == 0) - return (void *)crt::_crt_atexit; - if (strcmp(name, "_configure_narrow_argv") == 0) - return (void *)crt::_configure_narrow_argv; - if (strcmp(name, "_set_invalid_parameter_handler") == 0) - return (void *)crt::_set_invalid_parameter_handler; - if (strcmp(name, "_controlfp_s") == 0) - return (void *)crt::_controlfp_s; - if (strcmp(name, "_configthreadlocale") == 0) - return (void *)crt::_configthreadlocale; - if (strcmp(name, "_initialize_narrow_environment") == 0) - return (void *)crt::_initialize_narrow_environment; - if (strcmp(name, "_set_new_mode") == 0) - return (void *)crt::_set_new_mode; - if (strcmp(name, "_get_initial_narrow_environment") == 0) - return (void *)crt::_get_initial_narrow_environment; - if (strcmp(name, "__p__environ") == 0) - return (void *)crt::__p__environ; - if (strcmp(name, "__p___argv") == 0) - return (void *)crt::__p___argv; - if (strcmp(name, "__p___argc") == 0) - return (void *)crt::__p___argc; - if (strcmp(name, "strlen") == 0) - return (void *)crt::strlen; - if (strcmp(name, "strcmp") == 0) - return (void *)crt::strcmp; - if (strcmp(name, "strncmp") == 0) - return (void *)crt::strncmp; - if (strcmp(name, "strcpy") == 0) - return (void *)crt::strcpy; - if (strcmp(name, "strncpy") == 0) - return (void *)crt::strncpy; - if (strcmp(name, "strrchr") == 0) - return (void *)crt::strrchr; - if (strcmp(name, "malloc") == 0) - return (void *)crt::malloc; - if (strcmp(name, "calloc") == 0) - return (void *)crt::calloc; - if (strcmp(name, "realloc") == 0) - return (void *)crt::realloc; - if (strcmp(name, "free") == 0) - return (void *)crt::free; - if (strcmp(name, "memcpy") == 0) - return (void *)crt::memcpy; - if (strcmp(name, "memmove") == 0) - return (void *)crt::memmove; - if (strcmp(name, "memset") == 0) - return (void *)crt::memset; - if (strcmp(name, "memcmp") == 0) - return (void *)crt::memcmp; - if (strcmp(name, "exit") == 0) - return (void *)crt::exit; - if (strcmp(name, "_cexit") == 0) - return (void *)crt::_cexit; - if (strcmp(name, "_exit") == 0) - return (void *)crt::_exit; - if (strcmp(name, "abort") == 0) - return (void *)crt::abort; - if (strcmp(name, "signal") == 0) - return (void *)crt::signal; - if (strcmp(name, "__acrt_iob_func") == 0) - return (void *)crt::__acrt_iob_func; - if (strcmp(name, "__stdio_common_vfprintf") == 0) - return (void *)crt::__stdio_common_vfprintf; - if (strcmp(name, "__stdio_common_vsprintf") == 0) - return (void *)crt::__stdio_common_vsprintf; - if (strcmp(name, "puts") == 0) - return (void *)msvcrt::puts; - if (strcmp(name, "__setusermatherr") == 0) - return (void *)crt::__setusermatherr; - if (strcmp(name, "_initialize_onexit_table") == 0) - return (void *)crt::_initialize_onexit_table; - if (strcmp(name, "_register_onexit_function") == 0) - return (void *)crt::_register_onexit_function; - if (strcmp(name, "_execute_onexit_table") == 0) - return (void *)crt::_execute_onexit_table; - if (strcmp(name, "qsort") == 0) - return (void *)crt::qsort; - return nullptr; -} +#include "crt_trampolines.h" extern const wibo::ModuleStub lib_crt = { (const char *[]){ @@ -477,6 +363,6 @@ extern const wibo::ModuleStub lib_crt = { "api-ms-win-crt-utility-l1-1-0", nullptr, }, - resolveByName, + crtThunkByName, nullptr, }; diff --git a/dll/crt.h b/dll/crt.h new file mode 100644 index 0000000..9fa41c6 --- /dev/null +++ b/dll/crt.h @@ -0,0 +1,76 @@ +#pragma once + +#include "types.h" +#include + +typedef void (_CC_CDECL *_PVFV)(); +typedef int (_CC_CDECL *_PIFV)(); +typedef void (_CC_CDECL *_invalid_parameter_handler)(const WCHAR *, const WCHAR *, const WCHAR *, unsigned int, uintptr_t); + +typedef enum _crt_app_type { + _crt_unknown_app, + _crt_console_app, + _crt_gui_app, +} _crt_app_type; + +typedef enum _crt_argv_mode { + _crt_argv_no_arguments, + _crt_argv_unexpanded_arguments, + _crt_argv_expanded_arguments, +} _crt_argv_mode; + +typedef void (_CC_CDECL *signal_handler)(int); +typedef int (_CC_CDECL *sort_compare)(const void *, const void *); +using FILE = struct _IO_FILE; + +namespace crt { + +void CDECL _initterm(const _PVFV *ppfn, const _PVFV *end); +int CDECL _initterm_e(const _PIFV *ppfn, const _PIFV *end); +void CDECL _set_app_type(_crt_app_type type); +int CDECL _set_fmode(int mode); +int *CDECL __p__commode(); +int *CDECL __p__fmode(); +int CDECL _crt_atexit(void (*func)()); +int CDECL _configure_narrow_argv(_crt_argv_mode mode); +_invalid_parameter_handler CDECL _set_invalid_parameter_handler(_invalid_parameter_handler newHandler); +int CDECL _controlfp_s(unsigned int *currentControl, unsigned int newControl, unsigned int mask); +int CDECL _configthreadlocale(int per_thread_locale_type); +int CDECL _initialize_narrow_environment(); +int CDECL _set_new_mode(int newhandlermode); +char **CDECL _get_initial_narrow_environment(); +char ***CDECL __p__environ(); +char ***CDECL __p___argv(); +int *CDECL __p___argc(); +SIZE_T CDECL strlen(const char *str); +int CDECL strcmp(const char *lhs, const char *rhs); +int CDECL strncmp(const char *lhs, const char *rhs, SIZE_T count); +char *CDECL strcpy(char *dest, const char *src); +char *CDECL strncpy(char *dest, const char *src, SIZE_T count); +const char *CDECL strrchr(const char *str, int ch); +void *CDECL malloc(SIZE_T size); +void *CDECL calloc(SIZE_T count, SIZE_T size); +void *CDECL realloc(void *ptr, SIZE_T newSize); +void CDECL free(void *ptr); +void *CDECL memcpy(void *dest, const void *src, SIZE_T count); +void *CDECL memmove(void *dest, const void *src, SIZE_T count); +void *CDECL memset(void *dest, int ch, SIZE_T count); +int CDECL memcmp(const void *lhs, const void *rhs, SIZE_T count); +int CDECL __setusermatherr(void *handler); +int CDECL _initialize_onexit_table(void *table); +int CDECL _register_onexit_function(void *table, void (*func)()); +int CDECL _execute_onexit_table(void *table); +void CDECL exit(int status); +void CDECL _cexit(); +void CDECL _exit(int status); +void CDECL abort(); +signal_handler CDECL signal(int signum, signal_handler handler); +void *CDECL __acrt_iob_func(unsigned int index); +int CDECL __stdio_common_vfprintf(unsigned long long options, FILE *stream, const char *format, void *locale, + va_list args); +int CDECL __stdio_common_vsprintf(unsigned long long options, char *buffer, SIZE_T len, const char *format, + void *locale, va_list args); +void CDECL qsort(void *base, SIZE_T num, SIZE_T size, sort_compare compare); +int CDECL puts(const char *str); + +} // namespace crt diff --git a/dll/kernel32.cpp b/dll/kernel32.cpp index f00a125..c760755 100644 --- a/dll/kernel32.cpp +++ b/dll/kernel32.cpp @@ -1,12 +1,12 @@ -#include "modules.h" +#include "kernel32.h" -#include "kernel32_trampolines.h" +#include "modules.h" extern const wibo::ModuleStub lib_kernel32 = { (const char *[]){ "kernel32", nullptr, }, - kernel32_trampoline_by_name, + kernel32ThunkByName, nullptr, }; diff --git a/dll/kernel32.h b/dll/kernel32.h new file mode 100644 index 0000000..a0c7172 --- /dev/null +++ b/dll/kernel32.h @@ -0,0 +1,29 @@ +#pragma once + +#include "kernel32/debugapi.h" // IWYU pragma: export +#include "kernel32/errhandlingapi.h" // IWYU pragma: export +#include "kernel32/fibersapi.h" // IWYU pragma: export +#include "kernel32/fileapi.h" // IWYU pragma: export +#include "kernel32/handleapi.h" // IWYU pragma: export +#include "kernel32/heapapi.h" // IWYU pragma: export +#include "kernel32/interlockedapi.h" // IWYU pragma: export +#include "kernel32/ioapiset.h" // IWYU pragma: export +#include "kernel32/libloaderapi.h" // IWYU pragma: export +#include "kernel32/memoryapi.h" // IWYU pragma: export +#include "kernel32/namedpipeapi.h" // IWYU pragma: export +#include "kernel32/processenv.h" // IWYU pragma: export +#include "kernel32/processthreadsapi.h" // IWYU pragma: export +#include "kernel32/profileapi.h" // IWYU pragma: export +#include "kernel32/stringapiset.h" // IWYU pragma: export +#include "kernel32/synchapi.h" // IWYU pragma: export +#include "kernel32/sysinfoapi.h" // IWYU pragma: export +#include "kernel32/timezoneapi.h" // IWYU pragma: export +#include "kernel32/winbase.h" // IWYU pragma: export +#include "kernel32/wincon.h" // IWYU pragma: export +#include "kernel32/winnls.h" // IWYU pragma: export +#include "kernel32/winnt.h" // IWYU pragma: export +#include "kernel32/wow64apiset.h" // IWYU pragma: export + +#ifndef WIBO_CODEGEN +#include "kernel32_trampolines.h" // IWYU pragma: export +#endif diff --git a/dll/kernel32/errhandlingapi.cpp b/dll/kernel32/errhandlingapi.cpp index c824b4d..80c2899 100644 --- a/dll/kernel32/errhandlingapi.cpp +++ b/dll/kernel32/errhandlingapi.cpp @@ -14,34 +14,22 @@ UINT g_processErrorMode = 0; namespace kernel32 { -DWORD getLastError() { return wibo::getThreadTibForHost()->LastErrorValue; } +DWORD getLastError() { return currentThreadTeb->LastErrorValue; } -void setLastError(DWORD error) { wibo::getThreadTibForHost()->LastErrorValue = error; } +void setLastError(DWORD error) { currentThreadTeb->LastErrorValue = error; } void setLastErrorFromErrno() { setLastError(wibo::winErrorFromErrno(errno)); } DWORD WINAPI GetLastError() { -#ifndef NDEBUG - { - HOST_CONTEXT_GUARD(); - DEBUG_LOG("GetLastError() -> %u\n", getLastError()); - } -#endif - // In guest context, fetch via TIB - DWORD err; - __asm__ __volatile__("movl %%fs:%c1, %0" : "=r"(err) : "i"(offsetof(TEB, LastErrorValue))); - return err; + HOST_CONTEXT_GUARD(); + DEBUG_LOG("GetLastError() -> %u\n", getLastError()); + return currentThreadTeb->LastErrorValue; } void WINAPI SetLastError(DWORD dwErrCode) { -#ifndef NDEBUG - { - HOST_CONTEXT_GUARD(); - DEBUG_LOG("SetLastError(%u)\n", dwErrCode); - } -#endif - // In guest context, store via TIB - __asm__ __volatile__("movl %0, %%fs:%c1" : : "r"(dwErrCode), "i"(offsetof(TEB, LastErrorValue)) : "memory"); + HOST_CONTEXT_GUARD(); + DEBUG_LOG("SetLastError(%u)\n", dwErrCode); + currentThreadTeb->LastErrorValue = dwErrCode; } void WINAPI RaiseException(DWORD dwExceptionCode, DWORD dwExceptionFlags, DWORD nNumberOfArguments, diff --git a/dll/kernel32/errhandlingapi.h b/dll/kernel32/errhandlingapi.h index 7348ad1..0860b44 100644 --- a/dll/kernel32/errhandlingapi.h +++ b/dll/kernel32/errhandlingapi.h @@ -22,8 +22,8 @@ struct EXCEPTION_POINTERS { }; using PEXCEPTION_POINTERS = EXCEPTION_POINTERS *; -using PVECTORED_EXCEPTION_HANDLER = LONG(WIN_FUNC *)(PEXCEPTION_POINTERS ExceptionInfo); -using LPTOP_LEVEL_EXCEPTION_FILTER = LONG(WIN_FUNC *)(PEXCEPTION_POINTERS ExceptionInfo); +typedef LONG (_CC_STDCALL *PVECTORED_EXCEPTION_HANDLER)(PEXCEPTION_POINTERS ExceptionInfo); +typedef LONG (_CC_STDCALL *LPTOP_LEVEL_EXCEPTION_FILTER)(PEXCEPTION_POINTERS ExceptionInfo); constexpr LONG EXCEPTION_CONTINUE_EXECUTION = static_cast(-1); constexpr LONG EXCEPTION_CONTINUE_SEARCH = 0; diff --git a/dll/kernel32/fibersapi.h b/dll/kernel32/fibersapi.h index 654a3f8..169cf6a 100644 --- a/dll/kernel32/fibersapi.h +++ b/dll/kernel32/fibersapi.h @@ -2,7 +2,7 @@ #include "types.h" -using PFLS_CALLBACK_FUNCTION = void (*)(void *); +typedef void (_CC_STDCALL *PFLS_CALLBACK_FUNCTION)(void *); constexpr DWORD FLS_OUT_OF_INDEXES = 0xFFFFFFFF; namespace kernel32 { diff --git a/dll/kernel32/fileapi.cpp b/dll/kernel32/fileapi.cpp index 376dad3..9b971fb 100644 --- a/dll/kernel32/fileapi.cpp +++ b/dll/kernel32/fileapi.cpp @@ -613,9 +613,8 @@ UINT WINAPI GetDriveTypeW(LPCWSTR lpRootPathName) { } BOOL WINAPI GetVolumeInformationA(LPCSTR lpRootPathName, LPSTR lpVolumeNameBuffer, DWORD nVolumeNameSize, - LPDWORD lpVolumeSerialNumber, LPDWORD lpMaximumComponentLength, - LPDWORD lpFileSystemFlags, LPSTR lpFileSystemNameBuffer, - DWORD nFileSystemNameSize) { + LPDWORD lpVolumeSerialNumber, LPDWORD lpMaximumComponentLength, + LPDWORD lpFileSystemFlags, LPSTR lpFileSystemNameBuffer, DWORD nFileSystemNameSize) { HOST_CONTEXT_GUARD(); DEBUG_LOG("STUB: GetVolumeInformationA(%s)\n", lpRootPathName ? lpRootPathName : "(null)"); if (lpVolumeNameBuffer && nVolumeNameSize > 0) { @@ -642,9 +641,8 @@ BOOL WINAPI GetVolumeInformationA(LPCSTR lpRootPathName, LPSTR lpVolumeNameBuffe } BOOL WINAPI GetVolumeInformationW(LPCWSTR lpRootPathName, LPWSTR lpVolumeNameBuffer, DWORD nVolumeNameSize, - LPDWORD lpVolumeSerialNumber, LPDWORD lpMaximumComponentLength, - LPDWORD lpFileSystemFlags, LPWSTR lpFileSystemNameBuffer, - DWORD nFileSystemNameSize) { + LPDWORD lpVolumeSerialNumber, LPDWORD lpMaximumComponentLength, + LPDWORD lpFileSystemFlags, LPWSTR lpFileSystemNameBuffer, DWORD nFileSystemNameSize) { HOST_CONTEXT_GUARD(); DEBUG_LOG("STUB: GetVolumeInformationW(%p)\n", lpRootPathName); if (lpVolumeNameBuffer && nVolumeNameSize > 0) { @@ -694,7 +692,7 @@ LONG WINAPI CompareFileTime(const FILETIME *lpFileTime1, const FILETIME *lpFileT } BOOL WINAPI WriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten, - LPOVERLAPPED lpOverlapped) { + LPOVERLAPPED lpOverlapped) { HOST_CONTEXT_GUARD(); DEBUG_LOG("WriteFile(%p, %p, %u, %p, %p)\n", hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped); @@ -789,7 +787,7 @@ BOOL WINAPI FlushFileBuffers(HANDLE hFile) { } BOOL WINAPI ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, - LPOVERLAPPED lpOverlapped) { + LPOVERLAPPED lpOverlapped) { HOST_CONTEXT_GUARD(); DEBUG_LOG("ReadFile(%p, %p, %u, %p, %p)\n", hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped); @@ -877,8 +875,8 @@ BOOL WINAPI ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, } HANDLE WINAPI CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, - LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, - DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) { + LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, + DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) { HOST_CONTEXT_GUARD(); (void)hTemplateFile; if (!lpFileName) { @@ -1104,8 +1102,8 @@ HANDLE WINAPI CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShar } HANDLE WINAPI CreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, - LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, - DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) { + LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, + DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) { HOST_CONTEXT_GUARD(); DEBUG_LOG("CreateFileW -> "); if (!lpFileName) { @@ -1224,7 +1222,7 @@ DWORD WINAPI SetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistance } BOOL WINAPI SetFilePointerEx(HANDLE hFile, LARGE_INTEGER liDistanceToMove, PLARGE_INTEGER lpNewFilePointer, - DWORD dwMoveMethod) { + DWORD dwMoveMethod) { HOST_CONTEXT_GUARD(); if (hFile == nullptr) { setLastError(ERROR_INVALID_HANDLE); @@ -1239,7 +1237,7 @@ BOOL WINAPI SetFilePointerEx(HANDLE hFile, LARGE_INTEGER liDistanceToMove, PLARG // TODO access check std::lock_guard lk(file->m); off_t position = 0; - off_t offset = static_cast(liDistanceToMove); + off_t offset = static_cast(liDistanceToMove.QuadPart); if (dwMoveMethod == FILE_BEGIN) { position = offset; } else if (dwMoveMethod == FILE_CURRENT) { @@ -1265,7 +1263,7 @@ BOOL WINAPI SetFilePointerEx(HANDLE hFile, LARGE_INTEGER liDistanceToMove, PLARG return FALSE; } if (lpNewFilePointer) { - *lpNewFilePointer = static_cast(position); + lpNewFilePointer->QuadPart = position; } return TRUE; } @@ -1361,7 +1359,7 @@ DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh) { } BOOL WINAPI GetFileTime(HANDLE hFile, LPFILETIME lpCreationTime, LPFILETIME lpLastAccessTime, - LPFILETIME lpLastWriteTime) { + LPFILETIME lpLastWriteTime) { HOST_CONTEXT_GUARD(); DEBUG_LOG("GetFileTime(%p, %p, %p, %p)\n", hFile, lpCreationTime, lpLastAccessTime, lpLastWriteTime); HandleMeta meta{}; @@ -1403,7 +1401,7 @@ BOOL WINAPI GetFileTime(HANDLE hFile, LPFILETIME lpCreationTime, LPFILETIME lpLa } BOOL WINAPI SetFileTime(HANDLE hFile, const FILETIME *lpCreationTime, const FILETIME *lpLastAccessTime, - const FILETIME *lpLastWriteTime) { + const FILETIME *lpLastWriteTime) { HOST_CONTEXT_GUARD(); DEBUG_LOG("SetFileTime(%p, %p, %p, %p)\n", hFile, lpCreationTime, lpLastAccessTime, lpLastWriteTime); HandleMeta meta{}; @@ -1794,7 +1792,7 @@ HANDLE WINAPI FindFirstFileW(LPCWSTR lpFileName, LPWIN32_FIND_DATAW lpFindFileDa } HANDLE WINAPI FindFirstFileExA(LPCSTR lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, LPVOID lpFindFileData, - FINDEX_SEARCH_OPS fSearchOp, LPVOID lpSearchFilter, DWORD dwAdditionalFlags) { + FINDEX_SEARCH_OPS fSearchOp, LPVOID lpSearchFilter, DWORD dwAdditionalFlags) { HOST_CONTEXT_GUARD(); DEBUG_LOG("FindFirstFileExA(%s, %d, %p, %d, %p, 0x%x)", lpFileName ? lpFileName : "(null)", fInfoLevelId, lpFindFileData, fSearchOp, lpSearchFilter, dwAdditionalFlags); diff --git a/dll/kernel32/processthreadsapi.cpp b/dll/kernel32/processthreadsapi.cpp index b7a3e41..1cef501 100644 --- a/dll/kernel32/processthreadsapi.cpp +++ b/dll/kernel32/processthreadsapi.cpp @@ -6,6 +6,8 @@ #include "files.h" #include "handles.h" #include "internal.h" +#include "kernel32.h" +#include "kernel32_trampolines.h" #include "modules.h" #include "processes.h" #include "strutil.h" @@ -107,7 +109,7 @@ void threadCleanup(void *param) { } g_currentThreadObject = nullptr; wibo::notifyDllThreadDetach(); - wibo::setThreadTibForHost(nullptr); + currentThreadTeb = nullptr; // TODO: mark mutexes owned by this thread as abandoned obj->cv.notify_all(); obj->notifyWaiters(false); @@ -124,26 +126,12 @@ void *threadTrampoline(void *param) { g_currentThreadObject = data.obj; // Install TIB - TEB *threadTib = nullptr; - uint16_t previousFs = 0; - uint16_t previousGs = 0; - if (wibo::tibSelector) { - asm volatile("mov %%fs, %0" : "=r"(previousFs)); - asm volatile("mov %%gs, %0" : "=r"(previousGs)); - threadTib = wibo::allocateTib(); - if (threadTib) { - wibo::initializeTibStackInfo(threadTib); - if (wibo::installTibForCurrentThread(threadTib)) { - threadTib->hostFsSelector = previousFs; - threadTib->hostGsSelector = previousGs; - threadTib->hostSegmentsValid = 1; - wibo::setThreadTibForHost(threadTib); - } else { - fprintf(stderr, "!!! Failed to install TIB for new thread\n"); - wibo::destroyTib(threadTib); - threadTib = nullptr; - } - } + TEB *threadTib = wibo::allocateTib(); + wibo::initializeTibStackInfo(threadTib); + if (!wibo::installTibForCurrentThread(threadTib)) { + fprintf(stderr, "!!! Failed to install TIB for new thread\n"); + wibo::destroyTib(threadTib); + threadTib = nullptr; } // Wait until resumed (if suspended at start) @@ -161,7 +149,7 @@ void *threadTrampoline(void *param) { DWORD result = 0; if (data.entry) { GUEST_CONTEXT_GUARD(threadTib); - result = data.entry(data.userData); + result = call_LPTHREAD_START_ROUTINE(data.entry, data.userData); } DEBUG_LOG("Thread exiting with code %u\n", result); { @@ -220,8 +208,7 @@ HANDLE WINAPI GetCurrentThread() { return pseudoHandle; } -BOOL WINAPI GetProcessAffinityMask(HANDLE hProcess, PDWORD_PTR lpProcessAffinityMask, - PDWORD_PTR lpSystemAffinityMask) { +BOOL WINAPI GetProcessAffinityMask(HANDLE hProcess, PDWORD_PTR lpProcessAffinityMask, PDWORD_PTR lpSystemAffinityMask) { HOST_CONTEXT_GUARD(); DEBUG_LOG("GetProcessAffinityMask(%p, %p, %p)\n", hProcess, lpProcessAffinityMask, lpSystemAffinityMask); if (!lpProcessAffinityMask || !lpSystemAffinityMask) { @@ -465,8 +452,8 @@ HRESULT WINAPI SetThreadDescription(HANDLE hThread, LPCWSTR lpThreadDescription) } HANDLE WINAPI CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, - LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, - LPDWORD lpThreadId) { + LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, + LPDWORD lpThreadId) { HOST_CONTEXT_GUARD(); DEBUG_LOG("CreateThread(%p, %zu, %p, %p, %u, %p)\n", lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, dwCreationFlags, lpThreadId); @@ -574,7 +561,7 @@ DWORD WINAPI GetPriorityClass(HANDLE hProcess) { } BOOL WINAPI GetThreadTimes(HANDLE hThread, FILETIME *lpCreationTime, FILETIME *lpExitTime, FILETIME *lpKernelTime, - FILETIME *lpUserTime) { + FILETIME *lpUserTime) { HOST_CONTEXT_GUARD(); DEBUG_LOG("GetThreadTimes(%p, %p, %p, %p, %p)\n", hThread, lpCreationTime, lpExitTime, lpKernelTime, lpUserTime); @@ -618,9 +605,9 @@ BOOL WINAPI GetThreadTimes(HANDLE hThread, FILETIME *lpCreationTime, FILETIME *l } BOOL WINAPI CreateProcessA(LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, - LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, - LPVOID lpEnvironment, LPCSTR lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo, - LPPROCESS_INFORMATION lpProcessInformation) { + LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, + LPVOID lpEnvironment, LPCSTR lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo, + LPPROCESS_INFORMATION lpProcessInformation) { HOST_CONTEXT_GUARD(); DEBUG_LOG("CreateProcessA %s \"%s\" %p %p %d 0x%x %p %s %p %p\n", lpApplicationName ? lpApplicationName : "", lpCommandLine ? lpCommandLine : "", lpProcessAttributes, lpThreadAttributes, bInheritHandles, @@ -672,9 +659,9 @@ BOOL WINAPI CreateProcessA(LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSECU } BOOL WINAPI CreateProcessW(LPCWSTR lpApplicationName, LPWSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, - LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, - LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, - LPPROCESS_INFORMATION lpProcessInformation) { + LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, + LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, + LPPROCESS_INFORMATION lpProcessInformation) { HOST_CONTEXT_GUARD(); std::string applicationUtf8; if (lpApplicationName) { diff --git a/dll/kernel32/processthreadsapi.h b/dll/kernel32/processthreadsapi.h index 708b98c..a185efc 100644 --- a/dll/kernel32/processthreadsapi.h +++ b/dll/kernel32/processthreadsapi.h @@ -62,7 +62,7 @@ using LPSTARTUPINFOW = STARTUPINFOW *; constexpr DWORD TLS_OUT_OF_INDEXES = 0xFFFFFFFFu; constexpr DWORD NORMAL_PRIORITY_CLASS = 0x00000020; -typedef DWORD(WIN_FUNC *LPTHREAD_START_ROUTINE)(LPVOID); +typedef DWORD(_CC_STDCALL *LPTHREAD_START_ROUTINE)(LPVOID); namespace kernel32 { diff --git a/dll/kernel32/profileapi.cpp b/dll/kernel32/profileapi.cpp index a8f6300..2d849ac 100644 --- a/dll/kernel32/profileapi.cpp +++ b/dll/kernel32/profileapi.cpp @@ -14,7 +14,7 @@ BOOL WINAPI QueryPerformanceCounter(LARGE_INTEGER *lpPerformanceCount) { kernel32::setLastError(ERROR_INVALID_PARAMETER); return FALSE; } - *lpPerformanceCount = 0; + lpPerformanceCount->QuadPart = 0; return TRUE; } @@ -25,7 +25,7 @@ BOOL WINAPI QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency) { kernel32::setLastError(ERROR_INVALID_PARAMETER); return FALSE; } - *lpFrequency = 1; + lpFrequency->QuadPart = 1; return TRUE; } diff --git a/dll/kernel32/winbase.cpp b/dll/kernel32/winbase.cpp index 0dbeb81..de1d04e 100644 --- a/dll/kernel32/winbase.cpp +++ b/dll/kernel32/winbase.cpp @@ -7,6 +7,7 @@ #include "internal.h" #include "modules.h" #include "strutil.h" +#include "types.h" #include #include @@ -1141,8 +1142,8 @@ BOOL WINAPI GetDiskFreeSpaceW(LPCWSTR lpRootPathName, LPDWORD lpSectorsPerCluste lpNumberOfFreeClusters, lpTotalNumberOfClusters); } -BOOL WINAPI GetDiskFreeSpaceExA(LPCSTR lpDirectoryName, uint64_t *lpFreeBytesAvailableToCaller, - uint64_t *lpTotalNumberOfBytes, uint64_t *lpTotalNumberOfFreeBytes) { +BOOL WINAPI GetDiskFreeSpaceExA(LPCSTR lpDirectoryName, PULARGE_INTEGER lpFreeBytesAvailableToCaller, + PULARGE_INTEGER lpTotalNumberOfBytes, PULARGE_INTEGER lpTotalNumberOfFreeBytes) { HOST_CONTEXT_GUARD(); DEBUG_LOG("GetDiskFreeSpaceExA(%s)\n", lpDirectoryName ? lpDirectoryName : "(null)"); struct statvfs buf{}; @@ -1161,13 +1162,13 @@ BOOL WINAPI GetDiskFreeSpaceExA(LPCSTR lpDirectoryName, uint64_t *lpFreeBytesAva uint64_t totalFree = static_cast(buf.f_bfree) * blockSize; if (lpFreeBytesAvailableToCaller) { - *lpFreeBytesAvailableToCaller = freeToCaller; + lpFreeBytesAvailableToCaller->QuadPart = freeToCaller; } if (lpTotalNumberOfBytes) { - *lpTotalNumberOfBytes = totalBytes; + lpTotalNumberOfBytes->QuadPart = totalBytes; } if (lpTotalNumberOfFreeBytes) { - *lpTotalNumberOfFreeBytes = totalFree; + lpTotalNumberOfFreeBytes->QuadPart = totalFree; } DEBUG_LOG("\t-> host %s, free %llu, total %llu, total free %llu\n", resolvedPath.c_str(), @@ -1176,8 +1177,8 @@ BOOL WINAPI GetDiskFreeSpaceExA(LPCSTR lpDirectoryName, uint64_t *lpFreeBytesAva return TRUE; } -BOOL WINAPI GetDiskFreeSpaceExW(LPCWSTR lpDirectoryName, uint64_t *lpFreeBytesAvailableToCaller, - uint64_t *lpTotalNumberOfBytes, uint64_t *lpTotalNumberOfFreeBytes) { +BOOL WINAPI GetDiskFreeSpaceExW(LPCWSTR lpDirectoryName, PULARGE_INTEGER lpFreeBytesAvailableToCaller, + PULARGE_INTEGER lpTotalNumberOfBytes, PULARGE_INTEGER lpTotalNumberOfFreeBytes) { HOST_CONTEXT_GUARD(); DEBUG_LOG("GetDiskFreeSpaceExW -> "); std::string directoryName = wideStringToString(lpDirectoryName); diff --git a/dll/kernel32/wincon.h b/dll/kernel32/wincon.h index e716707..683030e 100644 --- a/dll/kernel32/wincon.h +++ b/dll/kernel32/wincon.h @@ -24,7 +24,7 @@ struct CONSOLE_SCREEN_BUFFER_INFO { struct INPUT_RECORD; -using PHANDLER_ROUTINE = BOOL(WIN_FUNC *)(DWORD CtrlType); +typedef BOOL (_CC_STDCALL *PHANDLER_ROUTINE)(DWORD CtrlType); namespace kernel32 { diff --git a/dll/kernel32/winnls.h b/dll/kernel32/winnls.h index 4168591..78341ac 100644 --- a/dll/kernel32/winnls.h +++ b/dll/kernel32/winnls.h @@ -12,7 +12,7 @@ struct CPINFO { }; using LPCPINFO = CPINFO *; -using LOCALE_ENUMPROCA = BOOL(WIN_FUNC *)(LPSTR); +typedef BOOL (_CC_STDCALL *LOCALE_ENUMPROCA)(LPSTR); namespace kernel32 { diff --git a/dll/lmgr.cpp b/dll/lmgr.cpp index 4ab6c62..02d044b 100644 --- a/dll/lmgr.cpp +++ b/dll/lmgr.cpp @@ -1,28 +1,34 @@ +#include "lmgr.h" + #include "common.h" #include "context.h" #include "modules.h" namespace lmgr { - int WIN_ENTRY lp_checkout(int a, int b, const char* c, const char* d, int e, const char* f, int* out) { - HOST_CONTEXT_GUARD(); - 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() { - HOST_CONTEXT_GUARD(); - DEBUG_LOG("lp_checkin()\n"); - return 0; - } +int CDECL lp_checkout(int a, int b, LPCSTR c, LPCSTR d, int e, LPCSTR f, int *out) { + HOST_CONTEXT_GUARD(); + DEBUG_LOG("lp_checkout(%d, %d, %s, %s, %d, %s)\n", a, b, c, d, e, f); + *out = 1234; + return 0; } +int CDECL lp_checkin() { + HOST_CONTEXT_GUARD(); + DEBUG_LOG("lp_checkin()\n"); + return 0; +} + +} // namespace lmgr + +#include "lmgr_trampolines.h" + static void *resolveByOrdinal(uint16_t ordinal) { switch (ordinal) { case 189: - return (void*)lmgr::lp_checkin; + return (void *)thunk_lmgr_lp_checkin; case 190: - return (void*)lmgr::lp_checkout; + return (void *)thunk_lmgr_lp_checkout; } return 0; } diff --git a/dll/lmgr.h b/dll/lmgr.h new file mode 100644 index 0000000..5be3434 --- /dev/null +++ b/dll/lmgr.h @@ -0,0 +1,10 @@ +#pragma once + +#include "types.h" + +namespace lmgr { + +int CDECL lp_checkout(int a, int b, LPCSTR c, LPCSTR d, int e, LPCSTR f, int *out); +int CDECL lp_checkin(); + +} // namespace lmgr diff --git a/dll/mscoree.cpp b/dll/mscoree.cpp index 15d7292..92debb2 100644 --- a/dll/mscoree.cpp +++ b/dll/mscoree.cpp @@ -1,13 +1,13 @@ +#include "mscoree.h" + #include "common.h" #include "context.h" #include "kernel32/internal.h" #include "modules.h" -#include - namespace mscoree { -void WIN_FUNC CorExitProcess(int exitCode) { +VOID WINAPI CorExitProcess(int exitCode) { HOST_CONTEXT_GUARD(); DEBUG_LOG("CorExitProcess(%i)\n", exitCode); kernel32::exitInternal(exitCode); @@ -15,17 +15,13 @@ void WIN_FUNC CorExitProcess(int exitCode) { } // namespace mscoree -static void *resolveByName(const char *name) { - if (strcmp(name, "CorExitProcess") == 0) - return (void *)mscoree::CorExitProcess; - return nullptr; -} +#include "mscoree_trampolines.h" extern const wibo::ModuleStub lib_mscoree = { (const char *[]){ "mscoree", nullptr, }, - resolveByName, + mscoreeThunkByName, nullptr, }; diff --git a/dll/mscoree.h b/dll/mscoree.h new file mode 100644 index 0000000..9862197 --- /dev/null +++ b/dll/mscoree.h @@ -0,0 +1,9 @@ +#pragma once + +#include "types.h" + +namespace mscoree { + +VOID WINAPI CorExitProcess(int exitCode); + +} // namespace mscoree diff --git a/dll/msvcrt.cpp b/dll/msvcrt.cpp index 4ddbd4e..9b584f8 100644 --- a/dll/msvcrt.cpp +++ b/dll/msvcrt.cpp @@ -1,8 +1,11 @@ +#include "msvcrt.h" + #include "common.h" #include "context.h" #include "files.h" #include "kernel32/internal.h" #include "modules.h" +#include "msvcrt_trampolines.h" #include "processes.h" #include "strutil.h" @@ -46,24 +49,8 @@ #define O_BINARY 0 #endif -typedef void (*_PVFV)(); -typedef int (*_PIFV)(); using _onexit_t = _PIFV; -extern "C" char **environ; - -struct _utimbuf { - long actime; - long modtime; -}; - -struct _timeb { - time_t time; - unsigned short millitm; - short timezone; - short dstflag; -}; - namespace msvcrt { int _commode; int _fmode; @@ -211,18 +198,7 @@ namespace msvcrt { return table; } - struct IOBProxy { - char *_ptr; - int _cnt; - char *_base; - int _flag; - int _file; - int _charbuf; - int _bufsiz; - char *_tmpfname; - }; - - int WIN_ENTRY _except_handler4_common(void *, void *, void *, void *); + int CDECL _except_handler4_common(void *, void *, void *, void *); std::vector &putenvStorage() { static std::vector storage; return storage; @@ -233,12 +209,12 @@ namespace msvcrt { return entries; } - IOBProxy *WIN_ENTRY __iob_func() { + IOBProxy *CDECL __iob_func() { HOST_CONTEXT_GUARD(); return standardIobEntries(); } - IOBProxy *WIN_ENTRY __p__iob() { + IOBProxy *CDECL __p__iob() { HOST_CONTEXT_GUARD(); return standardIobEntries(); } @@ -273,7 +249,7 @@ namespace msvcrt { return stream; } - void WIN_ENTRY setbuf(FILE *stream, char *buffer) { + void CDECL setbuf(FILE *stream, char *buffer) { HOST_CONTEXT_GUARD(); DEBUG_LOG("setbuf(%p, %p)\n", stream, buffer); if (!stream) { @@ -287,7 +263,7 @@ namespace msvcrt { } } - void WIN_ENTRY _splitpath(const char *path, char *drive, char *dir, char *fname, char *ext) { + void CDECL _splitpath(const char *path, char *drive, char *dir, char *fname, char *ext) { HOST_CONTEXT_GUARD(); if (drive) drive[0] = '\0'; if (dir) dir[0] = '\0'; @@ -319,7 +295,7 @@ namespace msvcrt { const char *filename = cursor; if (dirEnd) { if (dir) { - size_t dirLen = static_cast(dirEnd - cursor); + SIZE_T dirLen = static_cast(dirEnd - cursor); std::memcpy(dir, cursor, dirLen); dir[dirLen] = '\0'; } @@ -336,7 +312,7 @@ namespace msvcrt { const char *nameEnd = extStart ? extStart : filename + std::strlen(filename); if (fname) { - auto nameLen = static_cast(nameEnd - filename); + auto nameLen = static_cast(nameEnd - filename); std::memcpy(fname, filename, nameLen); fname[nameLen] = '\0'; } @@ -352,7 +328,7 @@ namespace msvcrt { ext ? ext : ""); } - int WIN_ENTRY _fileno(FILE *stream) { + int CDECL _fileno(FILE *stream) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_fileno(%p)\n", stream); if (!stream) { @@ -389,21 +365,21 @@ namespace msvcrt { mbCurMaxValue = mbCurMaxForCodePage(mbCodePageSetting); } - int WIN_ENTRY _getmbcp() { + int CDECL _getmbcp() { HOST_CONTEXT_GUARD(); ensureMbctypeInitialized(); DEBUG_LOG("_getmbcp() -> %d\n", mbCodePageSetting); return mbCodePageSetting; } - unsigned int* WIN_ENTRY __p___mb_cur_max() { + unsigned int* CDECL __p___mb_cur_max() { HOST_CONTEXT_GUARD(); ensureMbctypeInitialized(); DEBUG_LOG("__p___mb_cur_max() -> %u\n", mbCurMaxValue); return &mbCurMaxValue; } - int WIN_ENTRY _setmbcp(int codepage) { + int CDECL _setmbcp(int codepage) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_setmbcp(%d)\n", codepage); ensureMbctypeInitialized(); @@ -429,14 +405,14 @@ namespace msvcrt { return 0; } - unsigned char *WIN_ENTRY __p__mbctype() { + unsigned char *CDECL __p__mbctype() { HOST_CONTEXT_GUARD(); ensureMbctypeInitialized(); DEBUG_LOG("__p__mbctype() -> %p\n", mbctypeTable().data()); return mbctypeTable().data(); } - unsigned short **WIN_ENTRY __p__pctype() { + unsigned short **CDECL __p__pctype() { HOST_CONTEXT_GUARD(); DEBUG_LOG("__p__pctype()\n"); static unsigned short *pointer = nullptr; @@ -444,7 +420,7 @@ namespace msvcrt { return &pointer; } - int WIN_ENTRY _isctype(int ch, int mask) { + int CDECL _isctype(int ch, int mask) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_isctype(%d, %d)\n", ch, mask); if (ch == EOF) { @@ -453,7 +429,7 @@ namespace msvcrt { if (ch < 0 || ch > 255) { return 0; } - return (pctypeTable()[static_cast(ch) + 1] & mask) != 0; + return (pctypeTable()[static_cast(ch) + 1] & mask) != 0; } namespace { @@ -464,7 +440,7 @@ namespace msvcrt { bool registered; }; - constexpr size_t LOCK_TABLE_SIZE = 64; + constexpr SIZE_T LOCK_TABLE_SIZE = 64; std::array &lockTable() { static std::array table; return table; @@ -516,9 +492,9 @@ namespace msvcrt { std::string loweredResult = stringToLower(result); std::string loweredExe = stringToLower(exeDir); bool present = false; - size_t start = 0; + SIZE_T start = 0; while (start <= loweredResult.size()) { - size_t end = loweredResult.find(';', start); + SIZE_T end = loweredResult.find(';', start); if (end == std::string::npos) { end = loweredResult.size(); } @@ -556,7 +532,7 @@ namespace msvcrt { return nullptr; } - size_t count = 0; + SIZE_T count = 0; while (source[count]) { ++count; } @@ -565,7 +541,7 @@ namespace msvcrt { strings.reserve(count); pointers = std::make_unique(count + 1); - for (size_t i = 0; i < count; ++i) { + for (SIZE_T i = 0; i < count; ++i) { auto data = convert(source[i]); auto buffer = std::make_unique(data.size()); std::copy(data.begin(), data.end(), buffer.get()); @@ -581,7 +557,7 @@ namespace msvcrt { std::vector copyNarrowString(const char *src) { std::string normalized = normalizeEnvStringForWindows(src); - size_t len = normalized.size(); + SIZE_T len = normalized.size(); std::vector result(len + 1); if (len > 0) { std::memcpy(result.data(), normalized.data(), len); @@ -624,7 +600,7 @@ namespace msvcrt { } template - size_t envStringLength(const CharT *str) { + SIZE_T envStringLength(const CharT *str) { if (!str) { return 0; } @@ -636,7 +612,7 @@ namespace msvcrt { } template - int envStringCompare(const CharT *lhs, const CharT *rhs, size_t count) { + int envStringCompare(const CharT *lhs, const CharT *rhs, SIZE_T count) { if constexpr (std::is_same_v) { return std::strncmp(lhs, rhs, count); } else { @@ -647,7 +623,7 @@ namespace msvcrt { template struct EnvLookupResult { const CharT *value; - size_t length; + SIZE_T length; }; template @@ -656,7 +632,7 @@ namespace msvcrt { return std::nullopt; } - size_t nameLength = envStringLength(varname); + SIZE_T nameLength = envStringLength(varname); if (nameLength == 0) { return std::nullopt; } @@ -681,52 +657,43 @@ namespace msvcrt { } // namespace // Stub because we're only ever a console application - void WIN_ENTRY __set_app_type(int at) { + void CDECL __set_app_type(int at) { HOST_CONTEXT_GUARD(); DEBUG_LOG("STUB: __set_app_type(%d)\n", at); (void)at; } - int* WIN_FUNC __p__fmode() { + int* CDECL __p__fmode() { HOST_CONTEXT_GUARD(); DEBUG_LOG("__p__fmode() -> %p\n", &_fmode); return &_fmode; } - int* WIN_FUNC __p__commode() { + int* CDECL __p__commode() { HOST_CONTEXT_GUARD(); DEBUG_LOG("__p__commode() -> %p\n", &_commode); return &_commode; } - void WIN_ENTRY _initterm(const _PVFV *ppfn, const _PVFV* end) { + void CDECL _initterm(const _PVFV *ppfn, const _PVFV* end) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_initterm(%p, %p)\n", ppfn, end); - auto *tib = wibo::getThreadTibForHost(); for (; ppfn < end; ppfn++) { _PVFV func = *ppfn; if (func) { DEBUG_LOG("_initterm: calling %p\n", func); - { - GUEST_CONTEXT_GUARD(tib); - func(); - } + call__PVFV(func); } } } - int WIN_ENTRY _initterm_e(const _PIFV *ppfn, const _PIFV *end) { + int CDECL _initterm_e(const _PIFV *ppfn, const _PIFV *end) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_initterm_e(%p, %p)\n", ppfn, end); - auto *tib = wibo::getThreadTibForHost(); for (; ppfn < end; ppfn++) { _PIFV func = *ppfn; if (func) { - int err = 0; - { - GUEST_CONTEXT_GUARD(tib); - err = func(); - } + int err = call__PIFV(func); DEBUG_LOG("_initterm_e: calling %p -> %d\n", func, err); if (err != 0) return err; @@ -735,7 +702,7 @@ namespace msvcrt { return 0; } - unsigned int WIN_ENTRY _controlfp(unsigned int newControl, unsigned int mask) { + unsigned int CDECL _controlfp(unsigned int newControl, unsigned int mask) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_controlfp(newControl=%08x, mask=%08x)\n", newControl, mask); unsigned int previous = floatingPointControlWord; @@ -745,7 +712,7 @@ namespace msvcrt { return previous; } - int WIN_ENTRY _controlfp_s(unsigned int *currentControl, unsigned int newControl, unsigned int mask) { + int CDECL _controlfp_s(unsigned int *currentControl, unsigned int newControl, unsigned int mask) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_controlfp_s(currentControl=%p, newControl=%08x, mask=%08x)\n", currentControl, newControl, mask); if (mask != 0 && (mask & 0xFF000000) != 0) { @@ -761,7 +728,7 @@ namespace msvcrt { return 0; } - _PIFV WIN_ENTRY _onexit(_PIFV func) { + _PIFV CDECL _onexit(_PIFV func) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_onexit(%p)\n", func); if(!func) return nullptr; @@ -770,7 +737,7 @@ namespace msvcrt { } // NOLINTNEXTLINE(readability-non-const-parameter) - int WIN_ENTRY __wgetmainargs(int *wargc, uint16_t ***wargv, uint16_t ***wenv, int doWildcard, int *startInfo) { + int CDECL __wgetmainargs(int *wargc, uint16_t ***wargv, uint16_t ***wenv, int doWildcard, int *startInfo) { HOST_CONTEXT_GUARD(); DEBUG_LOG("__wgetmainargs(doWildcard=%d)\n", doWildcard); (void)startInfo; @@ -783,7 +750,7 @@ namespace msvcrt { } // NOLINTNEXTLINE(readability-non-const-parameter) - int WIN_ENTRY __getmainargs(int *argc, char ***argv, char ***env, int doWildcard, int *startInfo) { + int CDECL __getmainargs(int *argc, char ***argv, char ***env, int doWildcard, int *startInfo) { HOST_CONTEXT_GUARD(); DEBUG_LOG("__getmainargs(doWildcard=%d)\n", doWildcard); (void)startInfo; @@ -793,31 +760,31 @@ namespace msvcrt { return getMainArgsCommon(argc, argv, env, copyNarrowString); } - char* WIN_ENTRY getenv(const char *varname){ + char* CDECL getenv(const char *varname){ HOST_CONTEXT_GUARD(); DEBUG_LOG("getenv(%s)\n", varname); return std::getenv(varname); } - char*** WIN_ENTRY __p___initenv() { + char*** CDECL __p___initenv() { HOST_CONTEXT_GUARD(); DEBUG_LOG("__p___initenv() -> %p\n", &__initenv); return &__initenv; } - char* WIN_ENTRY strcat(char *dest, const char *src) { + char* CDECL strcat(char *dest, const char *src) { HOST_CONTEXT_GUARD(); VERBOSE_LOG("strcat(%p, %s)\n", dest, src); return std::strcat(dest, src); } - char* WIN_ENTRY strcpy(char *dest, const char *src) { + char* CDECL strcpy(char *dest, const char *src) { HOST_CONTEXT_GUARD(); VERBOSE_LOG("strcpy(%p, %s)\n", dest, src); return std::strcpy(dest, src); } - int WIN_ENTRY _access(const char *path, int mode) { + int CDECL _access(const char *path, int mode) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_access(%s, %d)\n", path ? path : "(null)", mode); if (!path) { @@ -844,7 +811,7 @@ namespace msvcrt { return -1; } - int WIN_ENTRY _ismbblead(unsigned int c) { + int CDECL _ismbblead(unsigned int c) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_ismbblead(%d)\n", c); if (c > 0xFF) { @@ -853,7 +820,7 @@ namespace msvcrt { return isLeadByte(static_cast(c)) ? 1 : 0; } - int WIN_ENTRY _ismbbtrail(unsigned int c) { + int CDECL _ismbbtrail(unsigned int c) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_ismbbtrail(%d)\n", c); if (c > 0xFF) { @@ -862,7 +829,7 @@ namespace msvcrt { return isTrailByte(static_cast(c)) ? 1 : 0; } - int WIN_ENTRY _ismbcspace(unsigned int c) { + int CDECL _ismbcspace(unsigned int c) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_ismbcspace(%d)\n", c); if (c <= 0xFF) { @@ -880,7 +847,7 @@ namespace msvcrt { return 0; } - void WIN_ENTRY _mbccpy(unsigned char *dest, const unsigned char *src) { + void CDECL _mbccpy(unsigned char *dest, const unsigned char *src) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_mbccpy(%p, %s)\n", dest, src); if (!dest || !src) { @@ -893,7 +860,7 @@ namespace msvcrt { } } - unsigned char* WIN_ENTRY _mbsinc(const unsigned char *str) { + unsigned char* CDECL _mbsinc(const unsigned char *str) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_mbsinc(%p)\n", str); if (!str) { @@ -908,7 +875,7 @@ namespace msvcrt { return const_cast(str + 1); } - unsigned char* WIN_ENTRY _mbsdec(const unsigned char *start, const unsigned char *current) { + unsigned char* CDECL _mbsdec(const unsigned char *start, const unsigned char *current) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_mbsdec(%p, %p)\n", start, current); if (!start || !current || current <= start) { @@ -945,7 +912,7 @@ namespace msvcrt { return const_cast(prev); } - unsigned int WIN_ENTRY _mbclen(const unsigned char *str) { + unsigned int CDECL _mbclen(const unsigned char *str) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_mbclen(%s)\n", str); if (!str || *str == '\0') { @@ -954,7 +921,7 @@ namespace msvcrt { return (isLeadByte(*str) && str[1] != '\0') ? 2U : 1U; } - int WIN_ENTRY _mbscmp(const unsigned char *lhs, const unsigned char *rhs) { + int CDECL _mbscmp(const unsigned char *lhs, const unsigned char *rhs) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_mbscmp(%s, %s)\n", lhs, rhs); if (!lhs || !rhs) { @@ -963,7 +930,7 @@ namespace msvcrt { return std::strcmp(reinterpret_cast(lhs), reinterpret_cast(rhs)); } - int WIN_ENTRY _mbsicmp(const unsigned char *lhs, const unsigned char *rhs) { + int CDECL _mbsicmp(const unsigned char *lhs, const unsigned char *rhs) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_mbsicmp(%s, %s)\n", lhs, rhs); if (!lhs || !rhs) { @@ -972,7 +939,7 @@ namespace msvcrt { return strcasecmp(reinterpret_cast(lhs), reinterpret_cast(rhs)); } - unsigned char* WIN_ENTRY _mbsstr(const unsigned char *haystack, const unsigned char *needle) { + unsigned char* CDECL _mbsstr(const unsigned char *haystack, const unsigned char *needle) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_mbsstr(%s, %s)\n", haystack, needle); if (!haystack || !needle) { @@ -982,7 +949,7 @@ namespace msvcrt { return result ? reinterpret_cast(const_cast(result)) : nullptr; } - unsigned char* WIN_ENTRY _mbschr(const unsigned char *str, unsigned int ch) { + unsigned char* CDECL _mbschr(const unsigned char *str, unsigned int ch) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_mbschr(%s, %d)\n", str, ch); if (!str) { @@ -993,7 +960,7 @@ namespace msvcrt { return result ? reinterpret_cast(const_cast(result)) : nullptr; } - unsigned char* WIN_ENTRY _mbsrchr(const unsigned char *str, unsigned int ch) { + unsigned char* CDECL _mbsrchr(const unsigned char *str, unsigned int ch) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_mbsrchr(%s, %d)\n", str, ch); if (!str) { @@ -1004,7 +971,7 @@ namespace msvcrt { return result ? reinterpret_cast(const_cast(result)) : nullptr; } - unsigned char* WIN_ENTRY _mbslwr(unsigned char *str) { + unsigned char* CDECL _mbslwr(unsigned char *str) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_mbslwr(%p)\n", str); if (!str) { @@ -1016,7 +983,7 @@ namespace msvcrt { return str; } - unsigned char* WIN_ENTRY _mbsupr(unsigned char *str) { + unsigned char* CDECL _mbsupr(unsigned char *str) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_mbsupr(%p)\n", str); if (!str) { @@ -1028,19 +995,19 @@ namespace msvcrt { return str; } - unsigned char *WIN_ENTRY _mbsinc_l(const unsigned char *str, void *) { + unsigned char *CDECL _mbsinc_l(const unsigned char *str, void *) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_mbsinc_l(%p)\n", str); return _mbsinc(str); } - unsigned char *WIN_ENTRY _mbsdec_l(const unsigned char *start, const unsigned char *current, void *locale) { + unsigned char *CDECL _mbsdec_l(const unsigned char *start, const unsigned char *current, void *locale) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_mbsdec_l(%p, %p, %p)\n", start, current, locale); return _mbsdec(start, current); } - int WIN_ENTRY _mbsncmp(const unsigned char *lhs, const unsigned char *rhs, size_t count) { + int CDECL _mbsncmp(const unsigned char *lhs, const unsigned char *rhs, SIZE_T count) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_mbsncmp(%s, %s, %zu)\n", lhs, rhs, count); if (!lhs || !rhs) { @@ -1049,7 +1016,7 @@ namespace msvcrt { return std::strncmp(reinterpret_cast(lhs), reinterpret_cast(rhs), count); } - size_t WIN_ENTRY _mbsspn(const unsigned char *str, const unsigned char *set) { + SIZE_T CDECL _mbsspn(const unsigned char *str, const unsigned char *set) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_mbsspn(%s, %s)\n", str, set); if (!str || !set) { @@ -1058,7 +1025,7 @@ namespace msvcrt { return std::strspn(reinterpret_cast(str), reinterpret_cast(set)); } - int WIN_ENTRY _ismbcdigit(unsigned int ch) { + int CDECL _ismbcdigit(unsigned int ch) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_ismbcdigit(%d)\n", ch); if (ch <= 0xFF) { @@ -1067,7 +1034,7 @@ namespace msvcrt { return 0; } - int WIN_ENTRY _stricmp(const char *lhs, const char *rhs) { + int CDECL _stricmp(const char *lhs, const char *rhs) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_stricmp(%s, %s)\n", lhs, rhs); if (!lhs || !rhs) { @@ -1076,7 +1043,7 @@ namespace msvcrt { return strcasecmp(lhs, rhs); } - int WIN_ENTRY _strnicmp(const char *lhs, const char *rhs, size_t count) { + int CDECL _strnicmp(const char *lhs, const char *rhs, SIZE_T count) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_strnicmp(%s, %s, %zu)\n", lhs, rhs, count); if (!lhs || !rhs) { @@ -1085,7 +1052,7 @@ namespace msvcrt { return strncasecmp(lhs, rhs, count); } - int WIN_ENTRY _memicmp(const void *lhs, const void *rhs, size_t count) { + int CDECL _memicmp(const void *lhs, const void *rhs, SIZE_T count) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_memicmp(%p, %p, %zu)\n", lhs, rhs, count); if (!lhs || !rhs) { @@ -1093,7 +1060,7 @@ namespace msvcrt { } const auto *a = static_cast(lhs); const auto *b = static_cast(rhs); - for (size_t i = 0; i < count; ++i) { + for (SIZE_T i = 0; i < count; ++i) { const auto ca = static_cast(std::tolower(a[i])); const auto cb = static_cast(std::tolower(b[i])); if (ca != cb) { @@ -1103,7 +1070,7 @@ namespace msvcrt { return 0; } - int WIN_ENTRY _vsnprintf(char *buffer, size_t count, const char *format, va_list args) { + int CDECL _vsnprintf(char *buffer, SIZE_T count, const char *format, va_list args) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_vsnprintf(%p, %zu, %s, %p)\n", buffer, count, format, args); if (!buffer || !format) { @@ -1114,14 +1081,14 @@ namespace msvcrt { if (result < 0) { return -1; } - if (static_cast(result) >= count) { + if (static_cast(result) >= count) { buffer[count ? count - 1 : 0] = '\0'; return -1; } return result; } - int WIN_ENTRY _snprintf(char *buffer, size_t count, const char *format, ...) { + int CDECL_NO_CONV _snprintf(char *buffer, SIZE_T count, const char *format, ...) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_snprintf(%p, %zu, %s, ...)\n", buffer, count, format); va_list args; @@ -1131,7 +1098,7 @@ namespace msvcrt { return result; } - int WIN_ENTRY sprintf(char *buffer, const char *format, ...) { + int CDECL_NO_CONV sprintf(char *buffer, const char *format, ...) { HOST_CONTEXT_GUARD(); DEBUG_LOG("sprintf(%p, %s, ...)\n", buffer, format); va_list args; @@ -1141,7 +1108,7 @@ namespace msvcrt { return result; } - int WIN_ENTRY printf(const char *format, ...) { + int CDECL_NO_CONV printf(const char *format, ...) { HOST_CONTEXT_GUARD(); DEBUG_LOG("printf(%s, ...)\n", format); va_list args; @@ -1151,7 +1118,7 @@ namespace msvcrt { return result; } - int WIN_ENTRY sscanf(const char *buffer, const char *format, ...) { + int CDECL_NO_CONV sscanf(const char *buffer, const char *format, ...) { HOST_CONTEXT_GUARD(); DEBUG_LOG("sscanf(%p, %p, ...)\n", buffer, format); va_list args; @@ -1161,7 +1128,7 @@ namespace msvcrt { return result; } - char *WIN_ENTRY fgets(char *str, int count, FILE *stream) { + char *CDECL fgets(char *str, int count, FILE *stream) { HOST_CONTEXT_GUARD(); DEBUG_LOG("fgets(%p, %d, %p)\n", str, count, stream); if (!str || count <= 0) { @@ -1171,14 +1138,14 @@ namespace msvcrt { return ::fgets(str, count, host); } - size_t WIN_ENTRY fread(void *buffer, size_t size, size_t count, FILE *stream) { + SIZE_T CDECL fread(void *buffer, SIZE_T size, SIZE_T count, FILE *stream) { HOST_CONTEXT_GUARD(); DEBUG_LOG("fread(%p, %zu, %zu, %p)\n", buffer, size, count, stream); FILE *host = mapToHostFile(stream); return ::fread(buffer, size, count, host); } - FILE *WIN_ENTRY _fsopen(const char *filename, const char *mode, int shflag) { + FILE *CDECL _fsopen(const char *filename, const char *mode, int shflag) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_fsopen(%s, %s, %d)\n", filename ? filename : "(null)", mode ? mode : "(null)", shflag); (void)shflag; @@ -1190,7 +1157,7 @@ namespace msvcrt { return ::fopen(hostPath.c_str(), mode); } - int WIN_ENTRY _sopen(const char *path, int oflag, int shflag, int pmode) { + int CDECL _sopen(const char *path, int oflag, int shflag, int pmode) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_sopen(%s, %d, %d, %d)\n", path ? path : "(null)", oflag, shflag, pmode); (void)shflag; @@ -1204,26 +1171,26 @@ namespace msvcrt { return ::open(hostPath.c_str(), flags, pmode); } - int WIN_ENTRY _read(int fd, void *buffer, unsigned int count) { + int CDECL _read(int fd, void *buffer, unsigned int count) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_read(%d, %p, %u)\n", fd, buffer, count); return static_cast(::read(fd, buffer, count)); } - int WIN_ENTRY _close(int fd) { + int CDECL _close(int fd) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_close(%d)\n", fd); return ::close(fd); } - long WIN_ENTRY _lseek(int fd, long offset, int origin) { + long CDECL _lseek(int fd, long offset, int origin) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_lseek(%d, %ld, %d)\n", fd, offset, origin); off_t result = ::lseek(fd, static_cast(offset), origin); return static_cast(result); } - int WIN_ENTRY _unlink(const char *path) { + int CDECL _unlink(const char *path) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_unlink(%s)\n", path ? path : "(null)"); if (!path) { @@ -1234,7 +1201,7 @@ namespace msvcrt { return ::unlink(hostPath.c_str()); } - int WIN_ENTRY _utime(const char *path, const _utimbuf *times) { + int CDECL _utime(const char *path, const _utimbuf *times) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_utime(%s, %p)\n", path ? path : "(null)", times); if (!path) { @@ -1249,58 +1216,58 @@ namespace msvcrt { return ::utime(hostPath.c_str(), &native); } - int WIN_ENTRY _chsize(int fd, long size) { + int CDECL _chsize(int fd, long size) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_chsize(%d, %ld)\n", fd, size); return ::ftruncate(fd, static_cast(size)); } - char* WIN_ENTRY strncpy(char *dest, const char *src, size_t count) { + char* CDECL strncpy(char *dest, const char *src, SIZE_T count) { HOST_CONTEXT_GUARD(); DEBUG_LOG("strncpy(%p, %s, %zu)\n", dest, src ? src : "(null)", count); return std::strncpy(dest, src, count); } - char* WIN_ENTRY strpbrk(const char *str, const char *accept) { + char* CDECL strpbrk(const char *str, const char *accept) { HOST_CONTEXT_GUARD(); const char *result = std::strpbrk(str, accept); DEBUG_LOG("strpbrk(%s, %s) -> %p\n", str ? str : "(null)", accept ? accept : "(null)", result); return result ? const_cast(result) : nullptr; } - char* WIN_ENTRY strstr(const char *haystack, const char *needle) { + char* CDECL strstr(const char *haystack, const char *needle) { HOST_CONTEXT_GUARD(); const char *result = std::strstr(haystack, needle); DEBUG_LOG("strstr(%s, %s) -> %p\n", haystack ? haystack : "(null)", needle ? needle : "(null)", result); return result ? const_cast(result) : nullptr; } - char* WIN_ENTRY strrchr(const char *str, int ch) { + char* CDECL strrchr(const char *str, int ch) { HOST_CONTEXT_GUARD(); DEBUG_LOG("strrchr(%s, %c)\n", str ? str : "(null)", ch); const char *result = std::strrchr(str, ch); return result ? const_cast(result) : nullptr; } - char* WIN_ENTRY strtok(char *str, const char *delim) { + char* CDECL strtok(char *str, const char *delim) { HOST_CONTEXT_GUARD(); DEBUG_LOG("strtok(%p, %s)\n", str, delim ? delim : "(null)"); return std::strtok(str, delim); } - long WIN_ENTRY _adj_fdiv_r(long value) { + long CDECL _adj_fdiv_r(long value) { HOST_CONTEXT_GUARD(); DEBUG_LOG("STUB: _adj_fdiv_r(%ld)\n", value); return value; } - void WIN_ENTRY _adjust_fdiv(long n) { + void CDECL _adjust_fdiv(long n) { HOST_CONTEXT_GUARD(); DEBUG_LOG("STUB: _adjust_fdiv(%ld)\n", n); (void)n; } - int WIN_ENTRY _ftime(struct _timeb *timeptr) { + int CDECL _ftime(struct _timeb *timeptr) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_ftime(%p)\n", timeptr); if (!timeptr) { @@ -1318,7 +1285,7 @@ namespace msvcrt { return 0; } - unsigned long WIN_ENTRY _ultoa(unsigned long value, char *str, int radix) { + unsigned long CDECL _ultoa(unsigned long value, char *str, int radix) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_ultoa(%lu, %p, %d)\n", value, str, radix); if (!str || radix < 2 || radix > 36) { @@ -1340,7 +1307,7 @@ namespace msvcrt { return static_cast(std::strlen(str)); } - char* WIN_ENTRY _ltoa(long value, char *str, int radix) { + char* CDECL _ltoa(long value, char *str, int radix) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_ltoa(%ld, %p, %d)\n", value, str, radix); if (!str || radix < 2 || radix > 36) { @@ -1360,7 +1327,7 @@ namespace msvcrt { return str; } - char* WIN_ENTRY _makepath(char *path, const char *drive, const char *dir, const char *fname, const char *ext) { + char* CDECL _makepath(char *path, const char *drive, const char *dir, const char *fname, const char *ext) { HOST_CONTEXT_GUARD(); if (!path) { return nullptr; @@ -1394,7 +1361,7 @@ namespace msvcrt { return path; } - char* WIN_ENTRY _fullpath(char *absPath, const char *relPath, size_t maxLength) { + char* CDECL _fullpath(char *absPath, const char *relPath, SIZE_T maxLength) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_fullpath(%p, %s, %zu)\n", absPath, relPath ? relPath : "(null)", maxLength); if (!relPath) { @@ -1425,7 +1392,7 @@ namespace msvcrt { return result; } - int WIN_ENTRY _putenv(const char *envString) { + int CDECL _putenv(const char *envString) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_putenv(%s)\n", envString ? envString : "(null)"); if (!envString) { @@ -1443,14 +1410,14 @@ namespace msvcrt { return ::putenv(stored); } - char *WIN_ENTRY _mktemp(char *templateName) { + char *CDECL _mktemp(char *templateName) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_mktemp(%s)\n", templateName); if (!templateName) { errno = EINVAL; return nullptr; } - size_t originalLen = std::strlen(templateName); + SIZE_T originalLen = std::strlen(templateName); std::string hostTemplate = files::pathFromWindows(templateName).string(); if (hostTemplate.empty()) { hostTemplate = templateName; @@ -1472,30 +1439,30 @@ namespace msvcrt { return templateName; } - int WIN_ENTRY _except_handler3(void *record, void *frame, void *context, void *dispatch) { + int CDECL _except_handler3(void *record, void *frame, void *context, void *dispatch) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_except_handler3(%p, %p, %p, %p)\n", record, frame, context, dispatch); return _except_handler4_common(record, frame, context, dispatch); } - int WIN_ENTRY getchar() { + int CDECL getchar() { HOST_CONTEXT_GUARD(); VERBOSE_LOG("getchar()\n"); return std::getchar(); } - time_t WIN_ENTRY time(time_t *t) { + TIME_T CDECL time(TIME_T *t) { HOST_CONTEXT_GUARD(); DEBUG_LOG("time(%p)\n", t); - time_t result = std::time(nullptr); + TIME_T result = std::time(nullptr); if (t) { *t = result; } return result; } - char *WIN_ENTRY __unDName(char *outputString, const char *mangledName, int maxStringLength, - void *(*allocFunc)(size_t), void (*freeFunc)(void *), unsigned short) { + char *CDECL __unDName(char *outputString, const char *mangledName, int maxStringLength, + void *(*allocFunc)(SIZE_T), void (*freeFunc)(void *), unsigned short) { HOST_CONTEXT_GUARD(); DEBUG_LOG("STUB: __unDName(%p, %s, %d, %p, %p)\n", outputString, mangledName ? mangledName : "(null)", maxStringLength, allocFunc, freeFunc); @@ -1508,7 +1475,7 @@ namespace msvcrt { return nullptr; } - char* WIN_ENTRY setlocale(int category, const char *locale){ + char* CDECL setlocale(int category, const char *locale){ HOST_CONTEXT_GUARD(); DEBUG_LOG("setlocale(%d, %s)\n", category, locale ? locale : "(null)"); char *result = std::setlocale(category, locale); @@ -1518,7 +1485,7 @@ namespace msvcrt { return result; } - int WIN_ENTRY _wdupenv_s(uint16_t **buffer, size_t *numberOfElements, const uint16_t *varname){ + int CDECL _wdupenv_s(uint16_t **buffer, SIZE_T *numberOfElements, const uint16_t *varname){ HOST_CONTEXT_GUARD(); DEBUG_LOG("_wdupenv_s(%p, %p, %s)\n", buffer, numberOfElements, wideStringToString(varname).c_str()); if (buffer) { @@ -1544,7 +1511,7 @@ namespace msvcrt { return 0; } - size_t value_len = match->length; + SIZE_T value_len = match->length; auto *copy = static_cast(malloc((value_len + 1) * sizeof(uint16_t))); if (!copy) { DEBUG_LOG("_wdupenv_s: allocation failed\n"); @@ -1561,7 +1528,7 @@ namespace msvcrt { return 0; } - int WIN_ENTRY _wgetenv_s(size_t* pReturnValue, uint16_t* buffer, size_t numberOfElements, const uint16_t* varname){ + int CDECL _wgetenv_s(SIZE_T* pReturnValue, uint16_t* buffer, SIZE_T numberOfElements, const uint16_t* varname){ HOST_CONTEXT_GUARD(); DEBUG_LOG("_wgetenv_s(%p, %p, %zu, %s)\n", pReturnValue, buffer, numberOfElements, wideStringToString(varname).c_str()); @@ -1588,7 +1555,7 @@ namespace msvcrt { return 0; } - size_t required = match->length + 1; + SIZE_T required = match->length + 1; *pReturnValue = required; if (!bufferRequired || !buffer) { return 0; @@ -1604,38 +1571,38 @@ namespace msvcrt { return 0; } - size_t WIN_ENTRY strlen(const char *str) { + SIZE_T CDECL strlen(const char *str) { HOST_CONTEXT_GUARD(); VERBOSE_LOG("strlen(%s)\n", str); return ::strlen(str); } - int WIN_ENTRY strcmp(const char *lhs, const char *rhs) { + int CDECL strcmp(const char *lhs, const char *rhs) { HOST_CONTEXT_GUARD(); VERBOSE_LOG("strcmp(%s, %s)\n", lhs, rhs); return ::strcmp(lhs, rhs); } - int WIN_ENTRY strncmp(const char *lhs, const char *rhs, size_t count) { + int CDECL strncmp(const char *lhs, const char *rhs, SIZE_T count) { HOST_CONTEXT_GUARD(); VERBOSE_LOG("strncmp(%s, %s, %zu)\n", lhs, rhs, count); return ::strncmp(lhs, rhs, count); } - void WIN_ENTRY _exit(int status) { + void CDECL _exit(int status) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_exit(%d)\n", status); kernel32::exitInternal(status); } - int WIN_ENTRY strcpy_s(char *dest, size_t dest_size, const char *src) { + int CDECL strcpy_s(char *dest, SIZE_T dest_size, const char *src) { HOST_CONTEXT_GUARD(); VERBOSE_LOG("strcpy_s(%p, %zu, %s)\n", dest, dest_size, src); if (!dest || !src || dest_size == 0) { return 22; } - size_t src_len = ::strlen(src); + SIZE_T src_len = ::strlen(src); if (src_len + 1 > dest_size) { dest[0] = 0; return 34; @@ -1645,15 +1612,15 @@ namespace msvcrt { return 0; } - int WIN_ENTRY strcat_s(char *dest, size_t numberOfElements, const char *src) { + int CDECL strcat_s(char *dest, SIZE_T numberOfElements, const char *src) { HOST_CONTEXT_GUARD(); DEBUG_LOG("strcat_s(%p, %zu, %s)\n", dest, numberOfElements, src); if (!dest || !src || numberOfElements == 0) { return 22; } - size_t dest_len = ::strlen(dest); - size_t src_len = ::strlen(src); + SIZE_T dest_len = ::strlen(dest); + SIZE_T src_len = ::strlen(src); if (dest_len + src_len + 1 > numberOfElements) { dest[0] = 0; return 34; @@ -1663,10 +1630,10 @@ namespace msvcrt { return 0; } - int WIN_ENTRY strncpy_s(char *dest, size_t dest_size, const char *src, size_t count) { + int CDECL strncpy_s(char *dest, SIZE_T dest_size, const char *src, SIZE_T count) { HOST_CONTEXT_GUARD(); DEBUG_LOG("strncpy_s(%p, %zu, %s, %zu)\n", dest, dest_size, src, count); - constexpr size_t TRUNCATE = static_cast(-1); + constexpr SIZE_T TRUNCATE = static_cast(-1); constexpr int STRUNCATE = 80; if (!dest || dest_size == 0) { @@ -1684,9 +1651,9 @@ namespace msvcrt { } if (count == TRUNCATE) { - size_t src_len = ::strlen(src); + SIZE_T src_len = ::strlen(src); if (src_len + 1 > dest_size) { - size_t copy_len = dest_size > 0 ? dest_size - 1 : 0; + SIZE_T copy_len = dest_size > 0 ? dest_size - 1 : 0; if (copy_len > 0) { std::memcpy(dest, src, copy_len); } @@ -1697,8 +1664,8 @@ namespace msvcrt { return 0; } - size_t src_len = ::strlen(src); - size_t copy_len = count < src_len ? count : src_len; + SIZE_T src_len = ::strlen(src); + SIZE_T copy_len = count < src_len ? count : src_len; if (copy_len >= dest_size) { dest[0] = 0; return 34; @@ -1711,14 +1678,14 @@ namespace msvcrt { return 0; } - char *WIN_ENTRY _strdup(const char *strSource) { + char *CDECL _strdup(const char *strSource) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_strdup(%s)\n", strSource); if (!strSource) { return nullptr; } - size_t length = ::strlen(strSource); + SIZE_T length = ::strlen(strSource); auto *copy = static_cast(std::malloc(length + 1)); if (!copy) { return nullptr; @@ -1728,57 +1695,57 @@ namespace msvcrt { return copy; } - unsigned long WIN_ENTRY strtoul(const char *str, char **endptr, int base) { + unsigned long CDECL strtoul(const char *str, char **endptr, int base) { HOST_CONTEXT_GUARD(); VERBOSE_LOG("strtoul(%s, %p, %d)\n", str, endptr, base); return ::strtoul(str, endptr, base); } - void* WIN_ENTRY malloc(size_t size){ + void* CDECL malloc(SIZE_T size){ HOST_CONTEXT_GUARD(); VERBOSE_LOG("malloc(%zu)\n", size); return std::malloc(size); } - void* WIN_ENTRY calloc(size_t count, size_t size){ + void* CDECL calloc(SIZE_T count, SIZE_T size){ HOST_CONTEXT_GUARD(); VERBOSE_LOG("calloc(%zu, %zu)\n", count, size); return std::calloc(count, size); } - void* WIN_ENTRY realloc(void *ptr, size_t size) { + void* CDECL realloc(void *ptr, SIZE_T size) { HOST_CONTEXT_GUARD(); VERBOSE_LOG("realloc(%p, %zu)\n", ptr, size); return std::realloc(ptr, size); } - void* WIN_ENTRY _malloc_crt(size_t size) { + void* CDECL _malloc_crt(SIZE_T size) { HOST_CONTEXT_GUARD(); VERBOSE_LOG("_malloc_crt(%zu)\n", size); return std::malloc(size); } - void WIN_ENTRY _lock(int locknum) { + void CDECL _lock(int locknum) { HOST_CONTEXT_GUARD(); VERBOSE_LOG("_lock(%d)\n", locknum); - if (locknum < 0 || static_cast(locknum) >= LOCK_TABLE_SIZE) { + if (locknum < 0 || static_cast(locknum) >= LOCK_TABLE_SIZE) { DEBUG_LOG("_lock: unsupported lock %d\n", locknum); return; } - lockTable()[static_cast(locknum)].lock(); + lockTable()[static_cast(locknum)].lock(); } - void WIN_ENTRY _unlock(int locknum) { + void CDECL _unlock(int locknum) { HOST_CONTEXT_GUARD(); VERBOSE_LOG("_unlock(%d)\n", locknum); - if (locknum < 0 || static_cast(locknum) >= LOCK_TABLE_SIZE) { + if (locknum < 0 || static_cast(locknum) >= LOCK_TABLE_SIZE) { DEBUG_LOG("_unlock: unsupported lock %d\n", locknum); return; } - lockTable()[static_cast(locknum)].unlock(); + lockTable()[static_cast(locknum)].unlock(); } - _onexit_t WIN_ENTRY __dllonexit(_onexit_t func, _PVFV **pbegin, _PVFV **pend) { + _onexit_t CDECL __dllonexit(_onexit_t func, _PVFV **pbegin, _PVFV **pend) { HOST_CONTEXT_GUARD(); DEBUG_LOG("__dllonexit(%p, %p, %p)\n", func, pbegin, pend); if (!pbegin || !pend) { @@ -1810,37 +1777,37 @@ namespace msvcrt { return reinterpret_cast<_onexit_t>(func); } - void WIN_ENTRY free(void* ptr){ + void CDECL free(void* ptr){ HOST_CONTEXT_GUARD(); VERBOSE_LOG("free(%p)\n", ptr); std::free(ptr); } - void* WIN_ENTRY memcpy(void *dest, const void *src, size_t count) { + void* CDECL memcpy(void *dest, const void *src, SIZE_T count) { HOST_CONTEXT_GUARD(); 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) { + void* CDECL memmove(void *dest, const void *src, SIZE_T count) { HOST_CONTEXT_GUARD(); VERBOSE_LOG("memmove(%p, %p, %zu)\n", dest, src, count); return std::memmove(dest, src, count); } - int WIN_ENTRY memcmp(const void *lhs, const void *rhs, size_t count) { + int CDECL memcmp(const void *lhs, const void *rhs, SIZE_T count) { HOST_CONTEXT_GUARD(); VERBOSE_LOG("memcmp(%p, %p, %zu)\n", lhs, rhs, count); return std::memcmp(lhs, rhs, count); } - void WIN_ENTRY qsort(void *base, size_t num, size_t size, int (*compar)(const void *, const void *)) { + void CDECL qsort(void *base, SIZE_T num, SIZE_T size, int (*compar)(const void *, const void *)) { HOST_CONTEXT_GUARD(); DEBUG_LOG("qsort(%p, %zu, %zu, %p)\n", base, num, size, compar); std::qsort(base, num, size, compar); } - int WIN_ENTRY fflush(FILE *stream) { + int CDECL fflush(FILE *stream) { HOST_CONTEXT_GUARD(); DEBUG_LOG("fflush(%p)\n", stream); if (!stream) { @@ -1850,7 +1817,7 @@ namespace msvcrt { return std::fflush(host); } - int WIN_ENTRY vfwprintf(FILE *stream, const uint16_t *format, va_list args) { + int CDECL vfwprintf(FILE *stream, const uint16_t *format, va_list args) { HOST_CONTEXT_GUARD(); DEBUG_LOG("vfwprintf(%p, %s, ...)\n", stream, wideStringToString(format).c_str()); FILE *host = mapToHostFile(stream ? stream : stdout); @@ -1864,43 +1831,43 @@ namespace msvcrt { return std::vfwprintf(host, fmt.c_str(), args); } - FILE *WIN_ENTRY fopen(const char *filename, const char *mode) { + FILE *CDECL fopen(const char *filename, const char *mode) { HOST_CONTEXT_GUARD(); DEBUG_LOG("fopen(%s, %s)\n", filename ? filename : "(null)", mode ? mode : "(null)"); return std::fopen(filename, mode); } - int WIN_ENTRY _dup2(int fd1, int fd2) { + int CDECL _dup2(int fd1, int fd2) { HOST_CONTEXT_GUARD(); VERBOSE_LOG("_dup2(%d, %d)\n", fd1, fd2); return dup2(fd1, fd2); } - int WIN_ENTRY _isatty(int fd) { + int CDECL _isatty(int fd) { HOST_CONTEXT_GUARD(); VERBOSE_LOG("_isatty(%d)\n", fd); return isatty(fd); } - int WIN_ENTRY fseek(FILE *stream, long offset, int origin) { + int CDECL fseek(FILE *stream, long offset, int origin) { HOST_CONTEXT_GUARD(); VERBOSE_LOG("fseek(%p, %ld, %d)\n", stream, offset, origin); return std::fseek(stream, offset, origin); } - long WIN_ENTRY ftell(FILE *stream) { + long CDECL ftell(FILE *stream) { HOST_CONTEXT_GUARD(); VERBOSE_LOG("ftell(%p)\n", stream); return std::ftell(stream); } - int WIN_ENTRY feof(FILE *stream) { + int CDECL feof(FILE *stream) { HOST_CONTEXT_GUARD(); VERBOSE_LOG("feof(%p)\n", stream); return std::feof(stream); } - int WIN_ENTRY fputws(const uint16_t *str, FILE *stream) { + int CDECL fputws(const uint16_t *str, FILE *stream) { HOST_CONTEXT_GUARD(); DEBUG_LOG("fputws(%s, %p)\n", wideStringToString(str).c_str(), stream); std::wstring temp; @@ -1912,19 +1879,19 @@ namespace msvcrt { return std::fputws(temp.c_str(), stream); } - int WIN_ENTRY _cputws(const uint16_t *string) { + int CDECL _cputws(const uint16_t *string) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_cputws(%s)\n", wideStringToString(string).c_str()); return fputws(string, stdout); } - uint16_t* WIN_ENTRY fgetws(uint16_t *buffer, int size, FILE *stream) { + uint16_t* CDECL fgetws(uint16_t *buffer, int size, FILE *stream) { HOST_CONTEXT_GUARD(); DEBUG_LOG("fgetws(%p, %d, %p)\n", buffer, size, stream); if (!buffer || size <= 0) { return nullptr; } - std::vector temp(static_cast(size)); + std::vector temp(static_cast(size)); wchar_t *res = std::fgetws(temp.data(), size, stream); if (!res) { return nullptr; @@ -1938,13 +1905,13 @@ namespace msvcrt { return buffer; } - wint_t WIN_ENTRY fgetwc(FILE *stream) { + WINT_T CDECL fgetwc(FILE *stream) { HOST_CONTEXT_GUARD(); VERBOSE_LOG("fgetwc(%p)\n", stream); return std::fgetwc(stream); } - int WIN_ENTRY _wfopen_s(FILE **stream, const uint16_t *filename, const uint16_t *mode) { + int CDECL _wfopen_s(FILE **stream, const uint16_t *filename, const uint16_t *mode) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_wfopen_s(%p, %s, %s)\n", stream, wideStringToString(filename).c_str(), wideStringToString(mode).c_str()); @@ -1963,7 +1930,7 @@ namespace msvcrt { return 0; } - int WIN_ENTRY _wcsicmp(const uint16_t *lhs, const uint16_t *rhs) { + int CDECL _wcsicmp(const uint16_t *lhs, const uint16_t *rhs) { HOST_CONTEXT_GUARD(); VERBOSE_LOG("_wcsicmp(%s, %s)\n", wideStringToString(lhs).c_str(), wideStringToString(rhs).c_str()); if (lhs == rhs) { @@ -1989,7 +1956,7 @@ namespace msvcrt { return static_cast(a) - static_cast(b); } - int WIN_ENTRY _wmakepath_s(uint16_t *path, size_t sizeInWords, const uint16_t *drive, const uint16_t *dir, + int CDECL _wmakepath_s(uint16_t *path, SIZE_T sizeInWords, const uint16_t *drive, const uint16_t *dir, const uint16_t *fname, const uint16_t *ext) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_wmakepath_s(%p, %zu, %s, %s, %s, %s)\n", path, sizeInWords, wideStringToString(drive).c_str(), @@ -2049,20 +2016,20 @@ namespace msvcrt { DEBUG_LOG("-> %s\n", wideStringToString(reinterpret_cast(result.c_str())).c_str()); - size_t required = result.size() + 1; + SIZE_T required = result.size() + 1; if (required > sizeInWords) { path[0] = 0; return ERANGE; } - for (size_t i = 0; i < result.size(); ++i) { + for (SIZE_T i = 0; i < result.size(); ++i) { path[i] = static_cast(result[i]); } path[result.size()] = 0; return 0; } - int WIN_ENTRY _wputenv_s(const uint16_t *varname, const uint16_t *value) { + int CDECL _wputenv_s(const uint16_t *varname, const uint16_t *value) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_wputenv_s(%p, %p)\n", varname, value); if (!varname || !value) { @@ -2110,7 +2077,7 @@ namespace msvcrt { return 0; } - unsigned long WIN_ENTRY wcsspn(const uint16_t *str1, const uint16_t *str2) { + unsigned long CDECL wcsspn(const uint16_t *str1, const uint16_t *str2) { HOST_CONTEXT_GUARD(); VERBOSE_LOG("wcsspn(%p, %p)\n", str1, str2); if (!str1 || !str2) { @@ -2133,51 +2100,51 @@ namespace msvcrt { return count; } - long WIN_ENTRY _wtol(const uint16_t *str) { + long CDECL _wtol(const uint16_t *str) { HOST_CONTEXT_GUARD(); VERBOSE_LOG("_wtol(%p)\n", str); return wstrtol(str, nullptr, 10); } - int WIN_ENTRY _wcsupr_s(uint16_t *str, size_t size) { + int CDECL _wcsupr_s(uint16_t *str, SIZE_T size) { HOST_CONTEXT_GUARD(); VERBOSE_LOG("_wcsupr_s(%p, %zu)\n", str, size); if (!str || size == 0) { return EINVAL; } - size_t len = wstrnlen(str, size); + SIZE_T len = wstrnlen(str, size); if (len >= size) { return ERANGE; } - for (size_t i = 0; i < len; ++i) { + for (SIZE_T i = 0; i < len; ++i) { str[i] = wcharToUpper(str[i]); } return 0; } - int WIN_ENTRY _wcslwr_s(uint16_t *str, size_t size) { + int CDECL _wcslwr_s(uint16_t *str, SIZE_T size) { HOST_CONTEXT_GUARD(); VERBOSE_LOG("_wcslwr_s(%p, %zu)\n", str, size); if (!str || size == 0) { return EINVAL; } - size_t len = wstrnlen(str, size); + SIZE_T len = wstrnlen(str, size); if (len >= size) { return ERANGE; } - for (size_t i = 0; i < len; ++i) { + for (SIZE_T i = 0; i < len; ++i) { str[i] = wcharToLower(str[i]); } return 0; } - wint_t WIN_ENTRY towlower(wint_t ch) { + WINT_T CDECL towlower(WINT_T ch) { HOST_CONTEXT_GUARD(); VERBOSE_LOG("towlower(%d)\n", ch); return wcharToLower(ch); } - unsigned int WIN_ENTRY _mbctolower(unsigned int ch) { + unsigned int CDECL _mbctolower(unsigned int ch) { HOST_CONTEXT_GUARD(); VERBOSE_LOG("_mbctolower(%u)\n", ch); if (ch <= 0xFF) { @@ -2188,33 +2155,33 @@ namespace msvcrt { return ch; } - int WIN_ENTRY toupper(int ch) { + int CDECL toupper(int ch) { HOST_CONTEXT_GUARD(); VERBOSE_LOG("toupper(%d)\n", ch); return std::toupper(ch); } - int WIN_ENTRY tolower(int ch) { + int CDECL tolower(int ch) { HOST_CONTEXT_GUARD(); VERBOSE_LOG("tolower(%d)\n", ch); return std::tolower(ch); } - int WIN_ENTRY _ftime64_s(void *timeb) { + int CDECL _ftime64_s(void *timeb) { HOST_CONTEXT_GUARD(); DEBUG_LOG("STUB: _ftime64_s(%p)\n", timeb); (void)timeb; return 0; } - int WIN_ENTRY _crt_debugger_hook(int value) { + int CDECL _crt_debugger_hook(int value) { HOST_CONTEXT_GUARD(); DEBUG_LOG("STUB: _crt_debugger_hook(%d)\n", value); (void)value; return 0; } - int WIN_ENTRY _configthreadlocale(int mode) { + int CDECL _configthreadlocale(int mode) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_configthreadlocale(mode=%d)\n", mode); static int currentMode = 0; @@ -2230,13 +2197,13 @@ namespace msvcrt { return -1; } - void WIN_ENTRY __setusermatherr(void* handler) { + void CDECL __setusermatherr(void* handler) { HOST_CONTEXT_GUARD(); DEBUG_LOG("STUB: __setusermatherr(handler=%p)\n", handler); (void)handler; } - void WIN_ENTRY _cexit() { + void CDECL _cexit() { HOST_CONTEXT_GUARD(); DEBUG_LOG("_cexit()\n"); std::fflush(nullptr); @@ -2249,7 +2216,7 @@ namespace msvcrt { return mapToHostFile(stream); } - int WIN_ENTRY vfprintf(FILE *stream, const char *format, va_list args) { + int CDECL vfprintf(FILE *stream, const char *format, va_list args) { HOST_CONTEXT_GUARD(); DEBUG_LOG("vfprintf(stream=%p, format=%s, args=%p)\n", stream, format, args); if (!format || !stream) { @@ -2268,7 +2235,7 @@ namespace msvcrt { return result; } - int WIN_ENTRY fprintf(FILE *stream, const char *format, ...) { + int CDECL_NO_CONV fprintf(FILE *stream, const char *format, ...) { HOST_CONTEXT_GUARD(); DEBUG_LOG("fprintf(%p, %s, ...)\n", stream, format); va_list args; @@ -2278,7 +2245,7 @@ namespace msvcrt { return result; } - int WIN_ENTRY fputc(int ch, FILE *stream) { + int CDECL fputc(int ch, FILE *stream) { HOST_CONTEXT_GUARD(); DEBUG_LOG("fputc(%d, %p)\n", ch, stream); if (!stream) { @@ -2293,7 +2260,7 @@ namespace msvcrt { return std::fputc(ch, native); } - size_t WIN_ENTRY fwrite(const void *buffer, size_t size, size_t count, FILE *stream) { + SIZE_T CDECL fwrite(const void *buffer, SIZE_T size, SIZE_T count, FILE *stream) { HOST_CONTEXT_GUARD(); DEBUG_LOG("fwrite(%p, %zu, %zu, %p)\n", buffer, size, count, stream); if (!buffer || !stream) { @@ -2308,27 +2275,25 @@ namespace msvcrt { return std::fwrite(buffer, size, count, native); } - char *WIN_ENTRY strerror(int errnum) { + char *CDECL strerror(int errnum) { HOST_CONTEXT_GUARD(); DEBUG_LOG("strerror(%d)\n", errnum); return std::strerror(errnum); } - char *WIN_ENTRY strchr(const char *str, int character) { + char *CDECL strchr(const char *str, int character) { HOST_CONTEXT_GUARD(); VERBOSE_LOG("strchr(%s, %d)\n", str, character); return const_cast(std::strchr(str, character)); } - struct lconv *WIN_ENTRY localeconv() { + struct lconv *CDECL localeconv() { HOST_CONTEXT_GUARD(); VERBOSE_LOG("localeconv()\n"); return std::localeconv(); } - using SignalHandler = void (*)(int); - - SignalHandler WIN_ENTRY signal(int sig, SignalHandler handler) { + signal_handler CDECL signal(int sig, signal_handler handler) { HOST_CONTEXT_GUARD(); DEBUG_LOG("signal(%d, %p)\n", sig, handler); if (sig != SIGABRT && sig != SIGFPE && sig != SIGILL && sig != SIGINT && @@ -2340,7 +2305,7 @@ namespace msvcrt { return std::signal(sig, handler); } - size_t WIN_ENTRY wcslen(const uint16_t *str) { + SIZE_T CDECL wcslen(const uint16_t *str) { HOST_CONTEXT_GUARD(); VERBOSE_LOG("wcslen(%p)\n", str); return wstrlen(str); @@ -2351,12 +2316,12 @@ namespace msvcrt { std::abort(); } - void WIN_ENTRY abort() { + void CDECL abort() { HOST_CONTEXT_GUARD(); abort_and_log("abort"); } - int WIN_ENTRY atoi(const char *str) { + int CDECL atoi(const char *str) { HOST_CONTEXT_GUARD(); VERBOSE_LOG("atoi(%s)\n", str); if (!str) { @@ -2366,43 +2331,43 @@ namespace msvcrt { return std::atoi(str); } - int WIN_ENTRY _amsg_exit(int reason) { + int CDECL _amsg_exit(int reason) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_amsg_exit(%d)\n", reason); abort_and_log("_amsg_exit"); return reason; } - void WIN_ENTRY _invoke_watson(const uint16_t *, const uint16_t *, const uint16_t *, unsigned int, uintptr_t) { + void CDECL _invoke_watson(const uint16_t *, const uint16_t *, const uint16_t *, unsigned int, uintptr_t) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_invoke_watson(...)\n"); abort_and_log("_invoke_watson"); } - void WIN_ENTRY terminateShim() { + void CDECL terminateShim() { HOST_CONTEXT_GUARD(); abort_and_log("terminate"); } - int WIN_ENTRY _purecall() { + int CDECL _purecall() { HOST_CONTEXT_GUARD(); abort_and_log("_purecall"); return 0; } - int WIN_ENTRY _except_handler4_common(void *, void *, void *, void *) { + int CDECL _except_handler4_common(void *, void *, void *, void *) { HOST_CONTEXT_GUARD(); DEBUG_LOG("STUB: _except_handler4_common\n"); return 0; } - long WIN_ENTRY _XcptFilter(unsigned long code, void *) { + long CDECL _XcptFilter(unsigned long code, void *) { HOST_CONTEXT_GUARD(); DEBUG_LOG("STUB: _XcptFilter(%lu)\n", code); return 0; } - int WIN_ENTRY _get_wpgmptr(uint16_t **pValue) { + int CDECL _get_wpgmptr(uint16_t **pValue) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_get_wpgmptr(%p)\n", pValue); if (!pValue) { @@ -2424,15 +2389,15 @@ namespace msvcrt { return 0; } - char** WIN_ENTRY __p__pgmptr() { + char** CDECL __p__pgmptr() { HOST_CONTEXT_GUARD(); DEBUG_LOG("__p__pgmptr()\n"); _pgmptr = const_cast(wibo::guestExecutablePath.c_str()); return &_pgmptr; } - int WIN_ENTRY _wsplitpath_s(const uint16_t * path, uint16_t * drive, size_t driveNumberOfElements, uint16_t *dir, size_t dirNumberOfElements, - uint16_t * fname, size_t nameNumberOfElements, uint16_t * ext, size_t extNumberOfElements){ + int CDECL _wsplitpath_s(const uint16_t * path, uint16_t * drive, SIZE_T driveNumberOfElements, uint16_t *dir, SIZE_T dirNumberOfElements, + uint16_t * fname, SIZE_T nameNumberOfElements, uint16_t * ext, SIZE_T extNumberOfElements){ HOST_CONTEXT_GUARD(); if(!path){ return 22; @@ -2455,21 +2420,21 @@ namespace msvcrt { if (dot && dot < filename_start) dot = nullptr; if (dir && dirNumberOfElements && slash) { - size_t dir_len = slash - path + 1; + SIZE_T dir_len = slash - path + 1; if (dir_len >= dirNumberOfElements) return 34; wstrncpy(dir, path, dir_len); dir[dir_len] = L'\0'; } if (fname && nameNumberOfElements) { - size_t fname_len = dot ? (size_t)(dot - filename_start) : wstrlen(filename_start); + SIZE_T fname_len = dot ? (SIZE_T)(dot - filename_start) : wstrlen(filename_start); if (fname_len >= nameNumberOfElements) return 34; wstrncpy(fname, filename_start, fname_len); fname[fname_len] = L'\0'; } if (ext && extNumberOfElements && dot) { - size_t ext_len = wstrlen(dot); + SIZE_T ext_len = wstrlen(dot); if (ext_len >= extNumberOfElements) return 34; wstrncpy(ext, dot, ext_len); ext[ext_len] = L'\0'; @@ -2485,15 +2450,15 @@ namespace msvcrt { return 0; } - int WIN_ENTRY wcscat_s(uint16_t *strDestination, size_t numberOfElements, const uint16_t *strSource){ + int CDECL wcscat_s(uint16_t *strDestination, SIZE_T numberOfElements, const uint16_t *strSource){ HOST_CONTEXT_GUARD(); std::string dst_str = wideStringToString(strDestination); std::string src_str = wideStringToString(strSource); DEBUG_LOG("wcscat_s %s %d %s", dst_str.c_str(), numberOfElements, src_str.c_str()); if(!strDestination || !strSource || numberOfElements == 0) return 22; - size_t dest_len = wstrlen(strDestination); - size_t src_len = wstrlen(strSource); + SIZE_T dest_len = wstrlen(strDestination); + SIZE_T src_len = wstrlen(strSource); if(dest_len + src_len + 1 > numberOfElements){ if(strDestination && numberOfElements > 0) strDestination[0] = L'\0'; @@ -2507,17 +2472,17 @@ namespace msvcrt { return 0; } - uint16_t* WIN_ENTRY _wcsdup(const uint16_t *strSource){ + uint16_t* CDECL _wcsdup(const uint16_t *strSource){ HOST_CONTEXT_GUARD(); // std::string src_str = wideStringToString(strSource); // DEBUG_LOG("_wcsdup: %s", src_str.c_str()); if(!strSource) return nullptr; - size_t strLen = wstrlen(strSource); + SIZE_T strLen = wstrlen(strSource); auto *dup = static_cast(malloc((strLen + 1) * sizeof(uint16_t))); if(!dup) return nullptr; - for(size_t i = 0; i <= strLen; i++){ + for(SIZE_T i = 0; i <= strLen; i++){ dup[i] = strSource[i]; } @@ -2526,7 +2491,7 @@ namespace msvcrt { return dup; } - int WIN_ENTRY _waccess_s(const uint16_t* path, int mode){ + int CDECL _waccess_s(const uint16_t* path, int mode){ HOST_CONTEXT_GUARD(); std::string original = wideStringToString(path); DEBUG_LOG("_waccess_s %s\n", original.c_str()); @@ -2541,12 +2506,12 @@ namespace msvcrt { return access(candidate.c_str(), mode); } - void* WIN_ENTRY memset(void *s, int c, size_t n){ + void* CDECL memset(void *s, int c, SIZE_T n){ HOST_CONTEXT_GUARD(); return std::memset(s, c, n); } - int WIN_ENTRY wcsncpy_s(uint16_t *strDest, size_t numberOfElements, const uint16_t *strSource, size_t count){ + int CDECL wcsncpy_s(uint16_t *strDest, SIZE_T numberOfElements, const uint16_t *strSource, SIZE_T count){ HOST_CONTEXT_GUARD(); std::string src_str = wideStringToString(strSource); DEBUG_LOG("wcsncpy_s(%p, %zu, %p, %zu)\n", strDest, numberOfElements, strSource, count); @@ -2556,7 +2521,7 @@ namespace msvcrt { return 1; } - if(count == (size_t)-1) count = wstrlen(strSource); + if(count == (SIZE_T)-1) count = wstrlen(strSource); if(count >= numberOfElements){ strDest[0] = L'\0'; @@ -2569,7 +2534,7 @@ namespace msvcrt { return 0; } - int WIN_ENTRY wcsncat_s(uint16_t *strDest, size_t numberOfElements, const uint16_t *strSource, size_t count){ + int CDECL wcsncat_s(uint16_t *strDest, SIZE_T numberOfElements, const uint16_t *strSource, SIZE_T count){ HOST_CONTEXT_GUARD(); std::string dst_str = wideStringToString(strDest); std::string src_str = wideStringToString(strSource); @@ -2580,8 +2545,8 @@ namespace msvcrt { return 1; } - size_t dest_len = wstrlen(strDest); - size_t src_len = (count == (size_t)-1) ? wstrlen(strSource) : wstrnlen(strSource, count); + SIZE_T dest_len = wstrlen(strDest); + SIZE_T src_len = (count == (SIZE_T)-1) ? wstrlen(strSource) : wstrnlen(strSource, count); if(dest_len + src_len + 1 > numberOfElements){ strDest[0] = L'\0'; @@ -2593,7 +2558,7 @@ namespace msvcrt { return 0; } - int WIN_ENTRY _itow_s(int value, uint16_t *buffer, size_t size, int radix){ + int CDECL _itow_s(int value, uint16_t *buffer, SIZE_T size, int radix){ HOST_CONTEXT_GUARD(); VERBOSE_LOG("_itow_s(%d, %p, %zu, %d)\n", value, buffer, size, radix); if (!buffer || size == 0) return 22; @@ -2613,13 +2578,13 @@ namespace msvcrt { return 0; } - int WIN_ENTRY _wtoi(const uint16_t* str) { + int CDECL _wtoi(const uint16_t* str) { HOST_CONTEXT_GUARD(); VERBOSE_LOG("_wtoi(%p)\n", str); return wstrtol(str, nullptr, 10); } - int WIN_ENTRY _ltoa_s(long value, char *buffer, size_t sizeInChars, int radix) { + int CDECL _ltoa_s(long value, char *buffer, SIZE_T sizeInChars, int radix) { HOST_CONTEXT_GUARD(); VERBOSE_LOG("_ltoa_s(%ld, %p, %zu, %d)\n", value, buffer, sizeInChars, radix); if (!buffer || sizeInChars == 0) { @@ -2633,7 +2598,7 @@ namespace msvcrt { bool isNegative = (value < 0) && (radix == 10); uint64_t magnitude = isNegative ? static_cast(-(int64_t)value) : static_cast(static_cast(value)); char temp[65]; - size_t index = 0; + SIZE_T index = 0; do { uint64_t digit = magnitude % static_cast(radix); temp[index++] = static_cast((digit < 10) ? ('0' + digit) : ('a' + (digit - 10))); @@ -2644,20 +2609,20 @@ namespace msvcrt { temp[index++] = '-'; } - size_t required = index + 1; // include null terminator + SIZE_T required = index + 1; // include null terminator if (required > sizeInChars) { buffer[0] = 0; return 34; } - for (size_t i = 0; i < index; ++i) { + for (SIZE_T i = 0; i < index; ++i) { buffer[i] = temp[index - i - 1]; } buffer[index] = '\0'; return 0; } - int WIN_ENTRY wcscpy_s(uint16_t *dest, size_t dest_size, const uint16_t *src) { + int CDECL wcscpy_s(uint16_t *dest, SIZE_T dest_size, const uint16_t *src) { HOST_CONTEXT_GUARD(); std::string src_str = wideStringToString(src); VERBOSE_LOG("wcscpy_s(%p, %zu, %p)\n", dest, dest_size, src); @@ -2674,7 +2639,7 @@ namespace msvcrt { return 0; } - int WIN_ENTRY swprintf_s(uint16_t *buffer, size_t sizeOfBuffer, const uint16_t *format, ...) { + int CDECL_NO_CONV swprintf_s(uint16_t *buffer, SIZE_T sizeOfBuffer, const uint16_t *format, ...) { HOST_CONTEXT_GUARD(); VERBOSE_LOG("swprintf_s(%p, %zu, %p, ...)\n", buffer, sizeOfBuffer, format); if (!buffer || sizeOfBuffer == 0 || !format) { @@ -2691,18 +2656,18 @@ namespace msvcrt { va_start(args, format); int written = std::vswprintf(temp.data(), temp.size(), fmt.c_str(), args); va_end(args); - if (written < 0 || static_cast(written) >= sizeOfBuffer) { + if (written < 0 || static_cast(written) >= sizeOfBuffer) { buffer[0] = 0; errno = ERANGE; return ERANGE; } for (int i = 0; i <= written; ++i) { - buffer[i] = static_cast(temp[static_cast(i)]); + buffer[i] = static_cast(temp[static_cast(i)]); } return written; } - int WIN_ENTRY swscanf_s(const uint16_t *buffer, const uint16_t *format, ...) { + int CDECL_NO_CONV swscanf_s(const uint16_t *buffer, const uint16_t *format, ...) { HOST_CONTEXT_GUARD(); VERBOSE_LOG("swscanf_s(%p, %p, ...)\n", buffer, format); if (!buffer || !format) { @@ -2726,31 +2691,31 @@ namespace msvcrt { return result; } - int* WIN_ENTRY _get_osfhandle(int fd){ + int* CDECL _get_osfhandle(int fd){ HOST_CONTEXT_GUARD(); DEBUG_LOG("STUB: _get_osfhandle(%d)\n", fd); return (int*)fd; } - int WIN_ENTRY _write(int fd, const void* buffer, unsigned int count) { + int CDECL _write(int fd, const void* buffer, unsigned int count) { HOST_CONTEXT_GUARD(); VERBOSE_LOG("_write(fd=%d, buffer=%p, count=%u)\n", fd, buffer, count); return (int)write(fd, buffer, count); } - void WIN_ENTRY exit(int status) { + void CDECL exit(int status) { HOST_CONTEXT_GUARD(); VERBOSE_LOG("exit(%d)\n", status); kernel32::exitInternal(status); } - int WIN_ENTRY wcsncmp(const uint16_t *string1, const uint16_t *string2, size_t count) { + int CDECL wcsncmp(const uint16_t *string1, const uint16_t *string2, SIZE_T count) { HOST_CONTEXT_GUARD(); VERBOSE_LOG("wcsncmp(%p, %p, %zu)\n", string1, string2, count); return wstrncmp(string1, string2, count); } - int WIN_ENTRY _vswprintf_c_l(uint16_t *buffer, size_t size, const uint16_t *format, ...) { + int CDECL_NO_CONV _vswprintf_c_l(uint16_t *buffer, SIZE_T size, const uint16_t *format, ...) { HOST_CONTEXT_GUARD(); DEBUG_LOG("_vswprintf_c_l(%p, %zu, %p, ...)\n", buffer, size, format); if (!buffer || !format || size == 0) { @@ -2776,7 +2741,7 @@ namespace msvcrt { return -1; } - std::vector narrowBuffer(static_cast(required) + 1); + std::vector narrowBuffer(static_cast(required) + 1); int written = vsnprintf(narrowBuffer.data(), narrowBuffer.size(), narrow_fmt.c_str(), args); va_end(args); @@ -2787,13 +2752,13 @@ namespace msvcrt { DEBUG_LOG("\tBuffer: %s\n", narrowBuffer.data()); std::vector wide = stringToWideString(narrowBuffer.data()); - size_t wideLen = wide.size(); + SIZE_T wideLen = wide.size(); if (wideLen + 1 > size) { buffer[0] = 0; return -1; } - if (wideLen > static_cast(std::numeric_limits::max())) { + if (wideLen > static_cast(std::numeric_limits::max())) { buffer[0] = 0; return -1; } @@ -2806,43 +2771,43 @@ namespace msvcrt { return static_cast(wideLen); } - const uint16_t* WIN_ENTRY wcsstr( const uint16_t *dest, const uint16_t *src ){ + const uint16_t* CDECL wcsstr( const uint16_t *dest, const uint16_t *src ){ HOST_CONTEXT_GUARD(); VERBOSE_LOG("wcsstr(%p, %p)\n", dest, src); return wstrstr(dest, src); } - int WIN_ENTRY iswspace(uint32_t w){ + int CDECL iswspace(uint32_t w){ HOST_CONTEXT_GUARD(); VERBOSE_LOG("iswspace(%u)\n", w); return std::iswspace(w); } - int WIN_ENTRY iswdigit(uint32_t w){ + int CDECL iswdigit(uint32_t w){ HOST_CONTEXT_GUARD(); VERBOSE_LOG("iswdigit(%u)\n", w); return std::iswdigit(w); } - const uint16_t* WIN_ENTRY wcschr(const uint16_t* str, uint16_t c){ + const uint16_t* CDECL wcschr(const uint16_t* str, uint16_t c){ HOST_CONTEXT_GUARD(); VERBOSE_LOG("wcschr(%p, %u)\n", str, c); return wstrchr(str, c); } - const uint16_t* WIN_ENTRY wcsrchr(const uint16_t *str, uint16_t c){ + const uint16_t* CDECL wcsrchr(const uint16_t *str, uint16_t c){ HOST_CONTEXT_GUARD(); VERBOSE_LOG("wcsrchr(%p, %u)\n", str, c); return wstrrchr(str, c); } - unsigned long WIN_ENTRY wcstoul(const uint16_t *strSource, uint16_t **endptr, int base){ + unsigned long CDECL wcstoul(const uint16_t *strSource, uint16_t **endptr, int base){ HOST_CONTEXT_GUARD(); VERBOSE_LOG("wcstoul(%p, %p, %d)\n", strSource, endptr, base); return wstrtoul(strSource, endptr, base); } - FILE* WIN_ENTRY _wfsopen(const uint16_t* filename, const uint16_t* mode, int shflag){ + FILE* CDECL _wfsopen(const uint16_t* filename, const uint16_t* mode, int shflag){ HOST_CONTEXT_GUARD(); if (!filename || !mode) return nullptr; std::string fname_str = wideStringToString(filename); @@ -2853,7 +2818,7 @@ namespace msvcrt { return fopen(fname_str.c_str(), mode_str.c_str()); } - int WIN_ENTRY puts(const char *str) { + int CDECL puts(const char *str) { HOST_CONTEXT_GUARD(); if (!str) { str = "(null)"; @@ -2866,13 +2831,13 @@ namespace msvcrt { return 0; } - int WIN_ENTRY fclose(FILE* stream){ + int CDECL fclose(FILE* stream){ HOST_CONTEXT_GUARD(); VERBOSE_LOG("fclose(%p)\n", stream); return ::fclose(stream); } - int WIN_ENTRY _flushall(){ + int CDECL _flushall(){ HOST_CONTEXT_GUARD(); DEBUG_LOG("_flushall()\n"); int count = 0; @@ -2884,13 +2849,13 @@ namespace msvcrt { return count; } - int* WIN_ENTRY _errno() { + int* CDECL _errno() { HOST_CONTEXT_GUARD(); VERBOSE_LOG("_errno()\n"); return &errno; } - intptr_t WIN_ENTRY _wspawnvp(int mode, const uint16_t* cmdname, const uint16_t* const * argv) { + intptr_t CDECL _wspawnvp(int mode, const uint16_t* cmdname, const uint16_t* const * argv) { HOST_CONTEXT_GUARD(); if (!cmdname || !argv) { errno = EINVAL; @@ -2939,7 +2904,7 @@ namespace msvcrt { return static_cast(po->pid); } - intptr_t WIN_ENTRY _spawnvp(int mode, const char *cmdname, const char * const *argv) { + intptr_t CDECL _spawnvp(int mode, const char *cmdname, const char * const *argv) { HOST_CONTEXT_GUARD(); if (!cmdname || !argv) { errno = EINVAL; @@ -2987,14 +2952,14 @@ namespace msvcrt { return static_cast(po->pid); } - int WIN_ENTRY _wunlink(const uint16_t *filename){ + int CDECL _wunlink(const uint16_t *filename){ HOST_CONTEXT_GUARD(); std::string str = wideStringToString(filename); DEBUG_LOG("_wunlink(%s)\n", str.c_str()); return unlink(str.c_str()); } - uint16_t* WIN_ENTRY _wfullpath(uint16_t* absPath, const uint16_t* relPath, size_t maxLength){ + uint16_t* CDECL _wfullpath(uint16_t* absPath, const uint16_t* relPath, SIZE_T maxLength){ HOST_CONTEXT_GUARD(); std::string relPathStr = wideStringToString(relPath); DEBUG_LOG("_wfullpath(%s, %zu)\n", relPathStr.c_str(), maxLength); @@ -3047,201 +3012,7 @@ namespace msvcrt { } } - -static void *resolveByName(const char *name) { - if (strcmp(name, "__set_app_type") == 0) return (void *) msvcrt::__set_app_type; - if (strcmp(name, "_fmode") == 0) return (void *)&msvcrt::_fmode; - if (strcmp(name, "_commode") == 0) return (void *)&msvcrt::_commode; - if (strcmp(name, "__initenv") == 0) return (void *)&msvcrt::__initenv; - if (strcmp(name, "__winitenv") == 0) return (void *)&msvcrt::__winitenv; - if (strcmp(name, "__iob_func") == 0) return (void *) msvcrt::__iob_func; - if (strcmp(name, "_exit") == 0) return (void *) msvcrt::_exit; - if (strcmp(name, "__p__fmode") == 0) return (void *) msvcrt::__p__fmode; - if (strcmp(name, "__p__commode") == 0) return (void *) msvcrt::__p__commode; - if (strcmp(name, "_initterm") == 0) return (void *)msvcrt::_initterm; - if (strcmp(name, "_initterm_e") == 0) return (void *)msvcrt::_initterm_e; - if (strcmp(name, "_controlfp") == 0) return (void *)msvcrt::_controlfp; - if (strcmp(name, "_controlfp_s") == 0) return (void *)msvcrt::_controlfp_s; - if (strcmp(name, "__p___initenv") == 0) return (void *)msvcrt::__p___initenv; - if (strcmp(name, "_onexit") == 0) return (void*)msvcrt::_onexit; - if (strcmp(name, "__getmainargs") == 0) return (void*)msvcrt::__getmainargs; - if (strcmp(name, "__wgetmainargs") == 0) return (void*)msvcrt::__wgetmainargs; - if (strcmp(name, "setlocale") == 0) return (void*)msvcrt::setlocale; - if (strcmp(name, "__mb_cur_max") == 0) return (void *)&msvcrt::mbCurMaxValue; - if (strcmp(name, "__p__mbctype") == 0) return (void *)msvcrt::__p__mbctype; - if (strcmp(name, "__p__pctype") == 0) return (void *)msvcrt::__p__pctype; - if (strcmp(name, "__p___mb_cur_max") == 0) return (void *)msvcrt::__p___mb_cur_max; - if (strcmp(name, "_isctype") == 0) return (void *)msvcrt::_isctype; - if (strcmp(name, "__unDName") == 0) return (void *)msvcrt::__unDName; - if (strcmp(name, "__setusermatherr") == 0) return (void *)msvcrt::__setusermatherr; - if (strcmp(name, "_wdupenv_s") == 0) return (void*)msvcrt::_wdupenv_s; - if (strcmp(name, "strlen") == 0) return (void *)msvcrt::strlen; - if (strcmp(name, "strcmp") == 0) return (void *)msvcrt::strcmp; - if (strcmp(name, "strncmp") == 0) return (void *)msvcrt::strncmp; - if (strcmp(name, "strcat") == 0) return (void *)msvcrt::strcat; - if (strcmp(name, "strcpy") == 0) return (void *)msvcrt::strcpy; - if (strcmp(name, "strcpy_s") == 0) return (void *)msvcrt::strcpy_s; - if (strcmp(name, "strcat_s") == 0) return (void *)msvcrt::strcat_s; - if (strcmp(name, "strncpy_s") == 0) return (void *)msvcrt::strncpy_s; - if (strcmp(name, "_strdup") == 0) return (void *)msvcrt::_strdup; - if (strcmp(name, "strncpy") == 0) return (void *)msvcrt::strncpy; - if (strcmp(name, "strpbrk") == 0) return (void *)msvcrt::strpbrk; - if (strcmp(name, "strstr") == 0) return (void *)msvcrt::strstr; - if (strcmp(name, "strrchr") == 0) return (void *)msvcrt::strrchr; - if (strcmp(name, "strtok") == 0) return (void *)msvcrt::strtok; - if (strcmp(name, "sprintf") == 0) return (void *)msvcrt::sprintf; - if (strcmp(name, "printf") == 0) return (void *)msvcrt::printf; - if (strcmp(name, "sscanf") == 0) return (void *)msvcrt::sscanf; - if (strcmp(name, "strtoul") == 0) return (void *)msvcrt::strtoul; - if (strcmp(name, "malloc") == 0) return (void*)msvcrt::malloc; - if (strcmp(name, "calloc") == 0) return (void*)msvcrt::calloc; - if (strcmp(name, "_malloc_crt") == 0) return (void*)msvcrt::_malloc_crt; - if (strcmp(name, "_lock") == 0) return (void*)msvcrt::_lock; - if (strcmp(name, "_unlock") == 0) return (void*)msvcrt::_unlock; - if (strcmp(name, "__dllonexit") == 0) return (void*)msvcrt::__dllonexit; - if (strcmp(name, "free") == 0) return (void*)msvcrt::free; - if (strcmp(name, "_wcsicmp") == 0) return (void*)msvcrt::_wcsicmp; - if (strcmp(name, "_wmakepath_s") == 0) return (void*)msvcrt::_wmakepath_s; - if (strcmp(name, "_wputenv_s") == 0) return (void*)msvcrt::_wputenv_s; - if (strcmp(name, "_get_wpgmptr") == 0) return (void*)msvcrt::_get_wpgmptr; - if (strcmp(name, "_wsplitpath_s") == 0) return (void*)msvcrt::_wsplitpath_s; - if (strcmp(name, "wcscat_s") == 0) return (void*)msvcrt::wcscat_s; - if (strcmp(name, "_wcsdup") == 0) return (void*)msvcrt::_wcsdup; - if (strcmp(name, "__p__pgmptr") == 0) return (void*)msvcrt::__p__pgmptr; - if (strcmp(name, "_splitpath") == 0) return (void*)msvcrt::_splitpath; - if (strcmp(name, "memset") == 0) return (void*)msvcrt::memset; - if (strcmp(name, "memcpy") == 0) return (void*)msvcrt::memcpy; - if (strcmp(name, "memmove") == 0) return (void*)msvcrt::memmove; - if (strcmp(name, "memcmp") == 0) return (void*)msvcrt::memcmp; - if (strcmp(name, "qsort") == 0) return (void*)msvcrt::qsort; - if (strcmp(name, "fflush") == 0) return (void*)msvcrt::fflush; - if (strcmp(name, "fopen") == 0) return (void*)msvcrt::fopen; - if (strcmp(name, "fseek") == 0) return (void*)msvcrt::fseek; - if (strcmp(name, "ftell") == 0) return (void*)msvcrt::ftell; - if (strcmp(name, "feof") == 0) return (void*)msvcrt::feof; - if (strcmp(name, "fgetws") == 0) return (void*)msvcrt::fgetws; - if (strcmp(name, "fgetwc") == 0) return (void*)msvcrt::fgetwc; - if (strcmp(name, "fgets") == 0) return (void*)msvcrt::fgets; - if (strcmp(name, "fputws") == 0) return (void*)msvcrt::fputws; - if (strcmp(name, "_cputws") == 0) return (void*)msvcrt::_cputws; - if (strcmp(name, "vfwprintf") == 0) return (void*)msvcrt::vfwprintf; - if (strcmp(name, "_wfopen_s") == 0) return (void*)msvcrt::_wfopen_s; - if (strcmp(name, "wcsspn") == 0) return (void*)msvcrt::wcsspn; - if (strcmp(name, "_fileno") == 0) return (void*)msvcrt::_fileno; - if (strcmp(name, "_wtol") == 0) return (void*)msvcrt::_wtol; - if (strcmp(name, "_wcsupr_s") == 0) return (void*)msvcrt::_wcsupr_s; - if (strcmp(name, "_wcslwr_s") == 0) return (void*)msvcrt::_wcslwr_s; - if (strcmp(name, "_dup2") == 0) return (void*)msvcrt::_dup2; - if (strcmp(name, "_isatty") == 0) return (void*)msvcrt::_isatty; - if (strcmp(name, "swprintf_s") == 0) return (void*)msvcrt::swprintf_s; - if (strcmp(name, "swscanf_s") == 0) return (void*)msvcrt::swscanf_s; - if (strcmp(name, "towlower") == 0) return (void*)msvcrt::towlower; - if (strcmp(name, "toupper") == 0) return (void*)msvcrt::toupper; - if (strcmp(name, "tolower") == 0) return (void*)msvcrt::tolower; - if (strcmp(name, "setbuf") == 0) return (void*)msvcrt::setbuf; - if (strcmp(name, "_mbctolower") == 0) return (void*)msvcrt::_mbctolower; - if (strcmp(name, "_ismbcspace") == 0) return (void*)msvcrt::_ismbcspace; - if (strcmp(name, "_ismbcdigit") == 0) return (void*)msvcrt::_ismbcdigit; - if (strcmp(name, "_ismbblead") == 0) return (void*)msvcrt::_ismbblead; - if (strcmp(name, "_ismbbtrail") == 0) return (void*)msvcrt::_ismbbtrail; - if (strcmp(name, "_mbccpy") == 0) return (void*)msvcrt::_mbccpy; - if (strcmp(name, "_mbsinc") == 0) return (void*)msvcrt::_mbsinc; - if (strcmp(name, "_mbsdec") == 0) return (void*)msvcrt::_mbsdec; - if (strcmp(name, "_mbclen") == 0) return (void*)msvcrt::_mbclen; - if (strcmp(name, "_mbscmp") == 0) return (void*)msvcrt::_mbscmp; - if (strcmp(name, "_mbsicmp") == 0) return (void*)msvcrt::_mbsicmp; - if (strcmp(name, "_mbsstr") == 0) return (void*)msvcrt::_mbsstr; - if (strcmp(name, "_mbschr") == 0) return (void*)msvcrt::_mbschr; - if (strcmp(name, "_mbsrchr") == 0) return (void*)msvcrt::_mbsrchr; - if (strcmp(name, "_mbslwr") == 0) return (void*)msvcrt::_mbslwr; - if (strcmp(name, "_mbsupr") == 0) return (void*)msvcrt::_mbsupr; - if (strcmp(name, "_mbsspn") == 0) return (void*)msvcrt::_mbsspn; - if (strcmp(name, "_mbsncmp") == 0) return (void*)msvcrt::_mbsncmp; - if (strcmp(name, "_ftime64_s") == 0) return (void*)msvcrt::_ftime64_s; - if (strcmp(name, "_crt_debugger_hook") == 0) return (void*)msvcrt::_crt_debugger_hook; - if (strcmp(name, "_configthreadlocale") == 0) return (void*)msvcrt::_configthreadlocale; - if (strcmp(name, "_amsg_exit") == 0) return (void*)msvcrt::_amsg_exit; - if (strcmp(name, "_invoke_watson") == 0) return (void*)msvcrt::_invoke_watson; - if (strcmp(name, "_except_handler4_common") == 0) return (void*)msvcrt::_except_handler4_common; - if (strcmp(name, "_except_handler3") == 0) return (void*)msvcrt::_except_handler3; - if (strcmp(name, "_XcptFilter") == 0) return (void*)msvcrt::_XcptFilter; - if (strcmp(name, "?terminate@@YAXXZ") == 0) return (void*)msvcrt::terminateShim; - if (strcmp(name, "_purecall") == 0) return (void*)msvcrt::_purecall; - if (strcmp(name, "wcsncpy_s") == 0) return (void*)msvcrt::wcsncpy_s; - if (strcmp(name, "wcsncat_s") == 0) return (void*)msvcrt::wcsncat_s; - if (strcmp(name, "_itow_s") == 0) return (void*)msvcrt::_itow_s; - if (strcmp(name, "_wtoi") == 0) return (void*)msvcrt::_wtoi; - if (strcmp(name, "_ltoa_s") == 0) return (void*)msvcrt::_ltoa_s; - if (strcmp(name, "wcscpy_s") == 0) return (void*)msvcrt::wcscpy_s; - if (strcmp(name, "_get_osfhandle") == 0) return (void*)msvcrt::_get_osfhandle; - if (strcmp(name, "_write") == 0) return (void*)msvcrt::_write; - if (strcmp(name, "_read") == 0) return (void*)msvcrt::_read; - if (strcmp(name, "_close") == 0) return (void*)msvcrt::_close; - if (strcmp(name, "_lseek") == 0) return (void*)msvcrt::_lseek; - if (strcmp(name, "_chsize") == 0) return (void*)msvcrt::_chsize; - if (strcmp(name, "exit") == 0) return (void*)msvcrt::exit; - if (strcmp(name, "wcsncmp") == 0) return (void*)msvcrt::wcsncmp; - if (strcmp(name, "_vswprintf_c_l") == 0) return (void*)msvcrt::_vswprintf_c_l; - if (strcmp(name, "wcsstr") == 0) return (void*)msvcrt::wcsstr; - if (strcmp(name, "iswspace") == 0) return (void*)msvcrt::iswspace; - if (strcmp(name, "wcsrchr") == 0) return (void*)msvcrt::wcsrchr; - if (strcmp(name, "wcstoul") == 0) return (void*)msvcrt::wcstoul; - if (strcmp(name, "iswdigit") == 0) return (void*)msvcrt::iswdigit; - if (strcmp(name, "wcschr") == 0) return (void*)msvcrt::wcschr; - if (strcmp(name, "getenv") == 0) return (void*)msvcrt::getenv; - if (strcmp(name, "_wgetenv_s") == 0) return (void*)msvcrt::_wgetenv_s; - if (strcmp(name, "_waccess_s") == 0) return (void*)msvcrt::_waccess_s; - if (strcmp(name, "_access") == 0) return (void*)msvcrt::_access; - if (strcmp(name, "_dup2") == 0) return (void*)msvcrt::_dup2; - if (strcmp(name, "_wfsopen") == 0) return (void*)msvcrt::_wfsopen; - if (strcmp(name, "_fsopen") == 0) return (void*)msvcrt::_fsopen; - if (strcmp(name, "_sopen") == 0) return (void*)msvcrt::_sopen; - if (strcmp(name, "fputws") == 0) return (void*)msvcrt::fputws; - if (strcmp(name, "puts") == 0) return (void*)msvcrt::puts; - if (strcmp(name, "fclose") == 0) return (void*)msvcrt::fclose; - if (strcmp(name, "_flushall") == 0) return (void*)msvcrt::_flushall; - if (strcmp(name, "_errno") == 0) return (void*)msvcrt::_errno; - if (strcmp(name, "_getmbcp") == 0) return (void*)msvcrt::_getmbcp; - if (strcmp(name, "_setmbcp") == 0) return (void*)msvcrt::_setmbcp; - if (strcmp(name, "_wspawnvp") == 0) return (void*)msvcrt::_wspawnvp; - if (strcmp(name, "_wunlink") == 0) return (void*)msvcrt::_wunlink; - if (strcmp(name, "_wfullpath") == 0) return (void*)msvcrt::_wfullpath; - if (strcmp(name, "_cexit") == 0) return (void*)msvcrt::_cexit; - if (strcmp(name, "_iob") == 0) return (void*)msvcrt::standardIobEntries(); - if (strcmp(name, "__p__iob") == 0) return (void*)msvcrt::__p__iob; - if (strcmp(name, "abort") == 0) return (void*)msvcrt::abort; - if (strcmp(name, "atoi") == 0) return (void*)msvcrt::atoi; - if (strcmp(name, "fprintf") == 0) return (void*)msvcrt::fprintf; - if (strcmp(name, "vfprintf") == 0) return (void*)msvcrt::vfprintf; - if (strcmp(name, "fputc") == 0) return (void*)msvcrt::fputc; - if (strcmp(name, "fwrite") == 0) return (void*)msvcrt::fwrite; - if (strcmp(name, "localeconv") == 0) return (void*)msvcrt::localeconv; - if (strcmp(name, "signal") == 0) return (void*)msvcrt::signal; - if (strcmp(name, "strchr") == 0) return (void*)msvcrt::strchr; - if (strcmp(name, "strerror") == 0) return (void*)msvcrt::strerror; - if (strcmp(name, "wcslen") == 0) return (void*)msvcrt::wcslen; - if (strcmp(name, "fread") == 0) return (void*)msvcrt::fread; - if (strcmp(name, "_unlink") == 0) return (void*)msvcrt::_unlink; - if (strcmp(name, "_utime") == 0) return (void*)msvcrt::_utime; - if (strcmp(name, "_ultoa") == 0) return (void*)msvcrt::_ultoa; - if (strcmp(name, "_ltoa") == 0) return (void*)msvcrt::_ltoa; - if (strcmp(name, "_makepath") == 0) return (void*)msvcrt::_makepath; - if (strcmp(name, "_fullpath") == 0) return (void*)msvcrt::_fullpath; - if (strcmp(name, "_vsnprintf") == 0) return (void*)msvcrt::_vsnprintf; - if (strcmp(name, "_snprintf") == 0) return (void*)msvcrt::_snprintf; - if (strcmp(name, "_adj_fdiv_r") == 0) return (void*)msvcrt::_adj_fdiv_r; - if (strcmp(name, "_adjust_fdiv") == 0) return (void*)msvcrt::_adjust_fdiv; - if (strcmp(name, "_memicmp") == 0) return (void*)msvcrt::_memicmp; - if (strcmp(name, "_stricmp") == 0) return (void*)msvcrt::_stricmp; - if (strcmp(name, "_strnicmp") == 0) return (void*)msvcrt::_strnicmp; - if (strcmp(name, "_putenv") == 0) return (void*)msvcrt::_putenv; - if (strcmp(name, "_mktemp") == 0) return (void*)msvcrt::_mktemp; - if (strcmp(name, "_spawnvp") == 0) return (void*)msvcrt::_spawnvp; - if (strcmp(name, "_ftime") == 0) return (void*)msvcrt::_ftime; - if (strcmp(name, "getchar") == 0) return (void*)msvcrt::getchar; - if (strcmp(name, "time") == 0) return (void*)msvcrt::time; - return nullptr; -} +#include "msvcrt_trampolines.h" extern const wibo::ModuleStub lib_msvcrt = { (const char *[]){ @@ -3254,6 +3025,6 @@ extern const wibo::ModuleStub lib_msvcrt = { "msvcr100", nullptr, }, - resolveByName, + msvcrtThunkByName, nullptr, }; diff --git a/dll/msvcrt.h b/dll/msvcrt.h new file mode 100644 index 0000000..28a2f75 --- /dev/null +++ b/dll/msvcrt.h @@ -0,0 +1,234 @@ +#pragma once + +#include "types.h" +#include + +using TIME_T = int; +using WINT_T = unsigned short; + +typedef void (_CC_CDECL *_PVFV)(); +typedef int (_CC_CDECL *_PIFV)(); +using _onexit_t = _PIFV; + +struct _utimbuf { + long actime; + long modtime; +}; + +struct _timeb { + TIME_T time; + unsigned short millitm; + short timezone; + short dstflag; +}; + +typedef void (_CC_CDECL *signal_handler)(int); +using FILE = struct _IO_FILE; + +struct IOBProxy { + char *_ptr; + int _cnt; + char *_base; + int _flag; + int _file; + int _charbuf; + int _bufsiz; + char *_tmpfname; +}; + +struct lconv; + +namespace msvcrt { + +IOBProxy *CDECL __iob_func(); +IOBProxy *CDECL __p__iob(); +void CDECL setbuf(FILE *stream, char *buffer); +void CDECL _splitpath(const char *path, char *drive, char *dir, char *fname, char *ext); +int CDECL _fileno(FILE *stream); +int CDECL _getmbcp(); +unsigned int *CDECL __p___mb_cur_max(); +int CDECL _setmbcp(int codepage); +unsigned char *CDECL __p__mbctype(); +unsigned short **CDECL __p__pctype(); +int CDECL _isctype(int ch, int mask); +void CDECL __set_app_type(int at); +int *CDECL __p__fmode(); +int *CDECL __p__commode(); +void CDECL _initterm(const _PVFV *ppfn, const _PVFV *end); +int CDECL _initterm_e(const _PIFV *ppfn, const _PIFV *end); +unsigned int CDECL _controlfp(unsigned int newControl, unsigned int mask); +int CDECL _controlfp_s(unsigned int *currentControl, unsigned int newControl, unsigned int mask); +_PIFV CDECL _onexit(_PIFV func); +int CDECL __wgetmainargs(int *wargc, uint16_t ***wargv, uint16_t ***wenv, int doWildcard, int *startInfo); +int CDECL __getmainargs(int *argc, char ***argv, char ***env, int doWildcard, int *startInfo); +char *CDECL getenv(const char *varname); +char ***CDECL __p___initenv(); +char *CDECL strcat(char *dest, const char *src); +char *CDECL strcpy(char *dest, const char *src); +int CDECL _access(const char *path, int mode); +int CDECL _ismbblead(unsigned int c); +int CDECL _ismbbtrail(unsigned int c); +int CDECL _ismbcspace(unsigned int c); +void CDECL _mbccpy(unsigned char *dest, const unsigned char *src); +unsigned char *CDECL _mbsinc(const unsigned char *str); +unsigned char *CDECL _mbsdec(const unsigned char *start, const unsigned char *current); +unsigned int CDECL _mbclen(const unsigned char *str); +int CDECL _mbscmp(const unsigned char *lhs, const unsigned char *rhs); +int CDECL _mbsicmp(const unsigned char *lhs, const unsigned char *rhs); +unsigned char *CDECL _mbsstr(const unsigned char *haystack, const unsigned char *needle); +unsigned char *CDECL _mbschr(const unsigned char *str, unsigned int ch); +unsigned char *CDECL _mbsrchr(const unsigned char *str, unsigned int ch); +unsigned char *CDECL _mbslwr(unsigned char *str); +unsigned char *CDECL _mbsupr(unsigned char *str); +unsigned char *CDECL _mbsinc_l(const unsigned char *str, void *); +unsigned char *CDECL _mbsdec_l(const unsigned char *start, const unsigned char *current, void *locale); +int CDECL _mbsncmp(const unsigned char *lhs, const unsigned char *rhs, SIZE_T count); +SIZE_T CDECL _mbsspn(const unsigned char *str, const unsigned char *set); +int CDECL _ismbcdigit(unsigned int ch); +int CDECL _stricmp(const char *lhs, const char *rhs); +int CDECL _strnicmp(const char *lhs, const char *rhs, SIZE_T count); +int CDECL _memicmp(const void *lhs, const void *rhs, SIZE_T count); +int CDECL _vsnprintf(char *buffer, SIZE_T count, const char *format, va_list args); +int CDECL_NO_CONV _snprintf(char *buffer, SIZE_T count, const char *format, ...); +int CDECL_NO_CONV sprintf(char *buffer, const char *format, ...); +int CDECL_NO_CONV printf(const char *format, ...); +int CDECL_NO_CONV sscanf(const char *buffer, const char *format, ...); +char *CDECL fgets(char *str, int count, FILE *stream); +SIZE_T CDECL fread(void *buffer, SIZE_T size, SIZE_T count, FILE *stream); +FILE *CDECL _fsopen(const char *filename, const char *mode, int shflag); +int CDECL _sopen(const char *path, int oflag, int shflag, int pmode); +int CDECL _read(int fd, void *buffer, unsigned int count); +int CDECL _close(int fd); +long CDECL _lseek(int fd, long offset, int origin); +int CDECL _unlink(const char *path); +int CDECL _utime(const char *path, const _utimbuf *times); +int CDECL _chsize(int fd, long size); +char *CDECL strncpy(char *dest, const char *src, SIZE_T count); +char *CDECL strpbrk(const char *str, const char *accept); +char *CDECL strstr(const char *haystack, const char *needle); +char *CDECL strrchr(const char *str, int ch); +char *CDECL strtok(char *str, const char *delim); +long CDECL _adj_fdiv_r(long value); +void CDECL _adjust_fdiv(long n); +int CDECL _ftime(struct _timeb *timeptr); +unsigned long CDECL _ultoa(unsigned long value, char *str, int radix); +char *CDECL _ltoa(long value, char *str, int radix); +char *CDECL _makepath(char *path, const char *drive, const char *dir, const char *fname, const char *ext); +char *CDECL _fullpath(char *absPath, const char *relPath, SIZE_T maxLength); +int CDECL _putenv(const char *envString); +char *CDECL _mktemp(char *templateName); +int CDECL _except_handler3(void *record, void *frame, void *context, void *dispatch); +int CDECL getchar(); +TIME_T CDECL time(TIME_T *t); +char *CDECL __unDName(char *outputString, const char *mangledName, int maxStringLength, void *(*allocFunc)(SIZE_T), + void (*freeFunc)(void *), unsigned short); +char *CDECL setlocale(int category, const char *locale); +int CDECL _wdupenv_s(uint16_t **buffer, SIZE_T *numberOfElements, const uint16_t *varname); +int CDECL _wgetenv_s(SIZE_T *pReturnValue, uint16_t *buffer, SIZE_T numberOfElements, const uint16_t *varname); +SIZE_T CDECL strlen(const char *str); +int CDECL strcmp(const char *lhs, const char *rhs); +int CDECL strncmp(const char *lhs, const char *rhs, SIZE_T count); +void CDECL _exit(int status); +int CDECL strcpy_s(char *dest, SIZE_T dest_size, const char *src); +int CDECL strcat_s(char *dest, SIZE_T numberOfElements, const char *src); +int CDECL strncpy_s(char *dest, SIZE_T dest_size, const char *src, SIZE_T count); +char *CDECL _strdup(const char *strSource); +unsigned long CDECL strtoul(const char *str, char **endptr, int base); +void *CDECL malloc(SIZE_T size); +void *CDECL calloc(SIZE_T count, SIZE_T size); +void *CDECL realloc(void *ptr, SIZE_T size); +void *CDECL _malloc_crt(SIZE_T size); +void CDECL _lock(int locknum); +void CDECL _unlock(int locknum); +_onexit_t CDECL __dllonexit(_onexit_t func, _PVFV **pbegin, _PVFV **pend); +void CDECL free(void *ptr); +void *CDECL memcpy(void *dest, const void *src, SIZE_T count); +void *CDECL memmove(void *dest, const void *src, SIZE_T count); +int CDECL memcmp(const void *lhs, const void *rhs, SIZE_T count); +void CDECL qsort(void *base, SIZE_T num, SIZE_T size, int (*compar)(const void *, const void *)); +int CDECL fflush(FILE *stream); +int CDECL vfwprintf(FILE *stream, const uint16_t *format, va_list args); +FILE *CDECL fopen(const char *filename, const char *mode); +int CDECL _dup2(int fd1, int fd2); +int CDECL _isatty(int fd); +int CDECL fseek(FILE *stream, long offset, int origin); +long CDECL ftell(FILE *stream); +int CDECL feof(FILE *stream); +int CDECL fputws(const uint16_t *str, FILE *stream); +int CDECL _cputws(const uint16_t *string); +uint16_t *CDECL fgetws(uint16_t *buffer, int size, FILE *stream); +WINT_T CDECL fgetwc(FILE *stream); +int CDECL _wfopen_s(FILE **stream, const uint16_t *filename, const uint16_t *mode); +int CDECL _wcsicmp(const uint16_t *lhs, const uint16_t *rhs); +int CDECL _wmakepath_s(uint16_t *path, SIZE_T sizeInWords, const uint16_t *drive, const uint16_t *dir, + const uint16_t *fname, const uint16_t *ext); +int CDECL _wputenv_s(const uint16_t *varname, const uint16_t *value); +unsigned long CDECL wcsspn(const uint16_t *str1, const uint16_t *str2); +long CDECL _wtol(const uint16_t *str); +int CDECL _wcsupr_s(uint16_t *str, SIZE_T size); +int CDECL _wcslwr_s(uint16_t *str, SIZE_T size); +WINT_T CDECL towlower(WINT_T ch); +unsigned int CDECL _mbctolower(unsigned int ch); +int CDECL toupper(int ch); +int CDECL tolower(int ch); +int CDECL _ftime64_s(void *timeb); +int CDECL _crt_debugger_hook(int value); +int CDECL _configthreadlocale(int mode); +void CDECL __setusermatherr(void *handler); +void CDECL _cexit(); +int CDECL vfprintf(FILE *stream, const char *format, va_list args); +int CDECL_NO_CONV fprintf(FILE *stream, const char *format, ...); +int CDECL fputc(int ch, FILE *stream); +SIZE_T CDECL fwrite(const void *buffer, SIZE_T size, SIZE_T count, FILE *stream); +char *CDECL strerror(int errnum); +char *CDECL strchr(const char *str, int character); +struct lconv *CDECL localeconv(); +signal_handler CDECL signal(int sig, signal_handler handler); +SIZE_T CDECL wcslen(const uint16_t *str); +void CDECL abort(); +int CDECL atoi(const char *str); +int CDECL _amsg_exit(int reason); +void CDECL _invoke_watson(const uint16_t *, const uint16_t *, const uint16_t *, unsigned int, uintptr_t); +void CDECL terminateShim(); +int CDECL _purecall(); +int CDECL _except_handler4_common(void *, void *, void *, void *); +long CDECL _XcptFilter(unsigned long code, void *); +int CDECL _get_wpgmptr(uint16_t **pValue); +char **CDECL __p__pgmptr(); +int CDECL _wsplitpath_s(const uint16_t *path, uint16_t *drive, SIZE_T driveNumberOfElements, uint16_t *dir, + SIZE_T dirNumberOfElements, uint16_t *fname, SIZE_T nameNumberOfElements, uint16_t *ext, + SIZE_T extNumberOfElements); +int CDECL wcscat_s(uint16_t *strDestination, SIZE_T numberOfElements, const uint16_t *strSource); +uint16_t *CDECL _wcsdup(const uint16_t *strSource); +int CDECL _waccess_s(const uint16_t *path, int mode); +void *CDECL memset(void *s, int c, SIZE_T n); +int CDECL wcsncpy_s(uint16_t *strDest, SIZE_T numberOfElements, const uint16_t *strSource, SIZE_T count); +int CDECL wcsncat_s(uint16_t *strDest, SIZE_T numberOfElements, const uint16_t *strSource, SIZE_T count); +int CDECL _itow_s(int value, uint16_t *buffer, SIZE_T size, int radix); +int CDECL _wtoi(const uint16_t *str); +int CDECL _ltoa_s(long value, char *buffer, SIZE_T sizeInChars, int radix); +int CDECL wcscpy_s(uint16_t *dest, SIZE_T dest_size, const uint16_t *src); +int CDECL_NO_CONV swprintf_s(uint16_t *buffer, SIZE_T sizeOfBuffer, const uint16_t *format, ...); +int CDECL_NO_CONV swscanf_s(const uint16_t *buffer, const uint16_t *format, ...); +int *CDECL _get_osfhandle(int fd); +int CDECL _write(int fd, const void *buffer, unsigned int count); +void CDECL exit(int status); +int CDECL wcsncmp(const uint16_t *string1, const uint16_t *string2, SIZE_T count); +int CDECL_NO_CONV _vswprintf_c_l(uint16_t *buffer, SIZE_T size, const uint16_t *format, ...); +const uint16_t *CDECL wcsstr(const uint16_t *dest, const uint16_t *src); +int CDECL iswspace(uint32_t w); +int CDECL iswdigit(uint32_t w); +const uint16_t *CDECL wcschr(const uint16_t *str, uint16_t c); +const uint16_t *CDECL wcsrchr(const uint16_t *str, uint16_t c); +unsigned long CDECL wcstoul(const uint16_t *strSource, uint16_t **endptr, int base); +FILE *CDECL _wfsopen(const uint16_t *filename, const uint16_t *mode, int shflag); +int CDECL puts(const char *str); +int CDECL fclose(FILE *stream); +int CDECL _flushall(); +int *CDECL _errno(); +intptr_t CDECL _wspawnvp(int mode, const uint16_t *cmdname, const uint16_t *const *argv); +intptr_t CDECL _spawnvp(int mode, const char *cmdname, const char *const *argv); +int CDECL _wunlink(const uint16_t *filename); +uint16_t *CDECL _wfullpath(uint16_t *absPath, const uint16_t *relPath, SIZE_T maxLength); + +} // namespace msvcrt diff --git a/dll/ntdll.cpp b/dll/ntdll.cpp index 6217fdf..233e7af 100644 --- a/dll/ntdll.cpp +++ b/dll/ntdll.cpp @@ -1,3 +1,5 @@ +#include "ntdll.h" + #include "common.h" #include "context.h" #include "errors.h" @@ -8,6 +10,7 @@ #include "modules.h" #include "processes.h" #include "strutil.h" +#include "types.h" #include #include @@ -17,24 +20,8 @@ #include -using PIO_APC_ROUTINE = void *; - -typedef struct _IO_STATUS_BLOCK { - union { - NTSTATUS Status; - PVOID Pointer; - }; - ULONG_PTR Information; -} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK; - namespace { -enum PROCESSINFOCLASS { - ProcessBasicInformation = 0, - ProcessWow64Information = 26, - ProcessImageFileName = 27, -}; - struct PROCESS_BASIC_INFORMATION { NTSTATUS ExitStatus; PEB *PebBaseAddress; @@ -53,17 +40,6 @@ struct ProcessHandleDetails { constexpr LONG kDefaultBasePriority = 8; -struct RTL_OSVERSIONINFOW { - ULONG dwOSVersionInfoSize; - ULONG dwMajorVersion; - ULONG dwMinorVersion; - ULONG dwBuildNumber; - ULONG dwPlatformId; - WCHAR szCSDVersion[128]; -}; - -using PRTL_OSVERSIONINFOW = RTL_OSVERSIONINFOW *; - struct RTL_OSVERSIONINFOEXW : RTL_OSVERSIONINFOW { WORD wServicePackMajor; WORD wServicePackMinor; @@ -124,17 +100,17 @@ BOOL WIN_FUNC ResetEvent(HANDLE hEvent); namespace ntdll { -constexpr LARGE_INTEGER FILE_WRITE_TO_END_OF_FILE = static_cast(-1); -constexpr LARGE_INTEGER FILE_USE_FILE_POINTER_POSITION = static_cast(-2); +constexpr LARGE_INTEGER FILE_WRITE_TO_END_OF_FILE = {.QuadPart = -1}; +constexpr LARGE_INTEGER FILE_USE_FILE_POINTER_POSITION = {.QuadPart = -2}; -void *WIN_ENTRY memset(void *dest, int ch, size_t count) { +PVOID CDECL memset(PVOID dest, int ch, SIZE_T count) { VERBOSE_LOG("ntdll::memset(%p, %i, %zu)\n", dest, ch, count); return std::memset(dest, ch, count); } -NTSTATUS WIN_FUNC NtReadFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, - PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer, ULONG Length, PLARGE_INTEGER ByteOffset, - PULONG Key) { +NTSTATUS WINAPI NtReadFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, + PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer, ULONG Length, PLARGE_INTEGER ByteOffset, + PULONG Key) { HOST_CONTEXT_GUARD(); DEBUG_LOG("NtReadFile(%p, %p, %p, %p, %p, %p, %u, %p, %p) ", FileHandle, Event, ApcRoutine, ApcContext, IoStatusBlock, Buffer, Length, ByteOffset, Key); @@ -156,13 +132,13 @@ NTSTATUS WIN_FUNC NtReadFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE Ap bool useOverlapped = file->overlapped; bool useCurrentFilePosition = (ByteOffset == nullptr); - if (!useCurrentFilePosition && *ByteOffset == FILE_USE_FILE_POINTER_POSITION) { + if (!useCurrentFilePosition && ByteOffset->QuadPart == FILE_USE_FILE_POINTER_POSITION.QuadPart) { useCurrentFilePosition = true; } std::optional offset; if (!useCurrentFilePosition) { - offset = static_cast(*ByteOffset); + offset = static_cast(ByteOffset->QuadPart); } if (useOverlapped && useCurrentFilePosition) { @@ -202,9 +178,9 @@ NTSTATUS WIN_FUNC NtReadFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE Ap return status; } -NTSTATUS WIN_FUNC NtWriteFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, - PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer, ULONG Length, PLARGE_INTEGER ByteOffset, - PULONG Key) { +NTSTATUS WINAPI NtWriteFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, + PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer, ULONG Length, PLARGE_INTEGER ByteOffset, + PULONG Key) { HOST_CONTEXT_GUARD(); DEBUG_LOG("NtWriteFile(%p, %p, %p, %p, %p, %p, %u, %p, %p) ", FileHandle, Event, ApcRoutine, ApcContext, IoStatusBlock, Buffer, Length, ByteOffset, Key); @@ -227,16 +203,16 @@ NTSTATUS WIN_FUNC NtWriteFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE A bool useCurrentFilePosition = (ByteOffset == nullptr); bool writeToEndOfFile = false; if (ByteOffset) { - if (*ByteOffset == FILE_USE_FILE_POINTER_POSITION) { + if (ByteOffset->QuadPart == FILE_USE_FILE_POINTER_POSITION.QuadPart) { useCurrentFilePosition = true; - } else if (*ByteOffset == FILE_WRITE_TO_END_OF_FILE) { + } else if (ByteOffset->QuadPart == FILE_WRITE_TO_END_OF_FILE.QuadPart) { writeToEndOfFile = true; } } std::optional offset; if (!useCurrentFilePosition && !writeToEndOfFile) { - offset = static_cast(*ByteOffset); + offset = static_cast(ByteOffset->QuadPart); } if (useOverlapped && useCurrentFilePosition) { @@ -286,8 +262,8 @@ NTSTATUS WIN_FUNC NtWriteFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE A return status; } -NTSTATUS WIN_FUNC NtAllocateVirtualMemory(HANDLE ProcessHandle, PVOID *BaseAddress, ULONG_PTR ZeroBits, - PSIZE_T RegionSize, ULONG AllocationType, ULONG Protect) { +NTSTATUS WINAPI NtAllocateVirtualMemory(HANDLE ProcessHandle, PVOID *BaseAddress, ULONG_PTR ZeroBits, + PSIZE_T RegionSize, ULONG AllocationType, ULONG Protect) { HOST_CONTEXT_GUARD(); DEBUG_LOG("NtAllocateVirtualMemory(%p, %p, %lu, %p, %lu, %lu) ", ProcessHandle, BaseAddress, ZeroBits, RegionSize, AllocationType, Protect); @@ -325,8 +301,8 @@ NTSTATUS WIN_FUNC NtAllocateVirtualMemory(HANDLE ProcessHandle, PVOID *BaseAddre return STATUS_SUCCESS; } -NTSTATUS WIN_FUNC NtProtectVirtualMemory(HANDLE ProcessHandle, PVOID *BaseAddress, PSIZE_T NumberOfBytesToProtect, - ULONG NewAccessProtection, PULONG OldAccessProtection) { +NTSTATUS WINAPI NtProtectVirtualMemory(HANDLE ProcessHandle, PVOID *BaseAddress, PSIZE_T NumberOfBytesToProtect, + ULONG NewAccessProtection, PULONG OldAccessProtection) { HOST_CONTEXT_GUARD(); DEBUG_LOG("NtProtectVirtualMemory(%p, %p, %p, %lu, %p) ", ProcessHandle, BaseAddress, NumberOfBytesToProtect, NewAccessProtection, OldAccessProtection); @@ -366,7 +342,7 @@ NTSTATUS WIN_FUNC NtProtectVirtualMemory(HANDLE ProcessHandle, PVOID *BaseAddres return STATUS_SUCCESS; } -NTSTATUS WIN_FUNC RtlGetVersion(PRTL_OSVERSIONINFOW lpVersionInformation) { +NTSTATUS WINAPI RtlGetVersion(PRTL_OSVERSIONINFOW lpVersionInformation) { HOST_CONTEXT_GUARD(); DEBUG_LOG("RtlGetVersion(%p) ", lpVersionInformation); if (!lpVersionInformation) { @@ -396,9 +372,9 @@ NTSTATUS WIN_FUNC RtlGetVersion(PRTL_OSVERSIONINFOW lpVersionInformation) { return STATUS_SUCCESS; } -NTSTATUS WIN_FUNC NtQueryInformationProcess(HANDLE ProcessHandle, PROCESSINFOCLASS ProcessInformationClass, - PVOID ProcessInformation, ULONG ProcessInformationLength, - PULONG ReturnLength) { +NTSTATUS WINAPI NtQueryInformationProcess(HANDLE ProcessHandle, PROCESSINFOCLASS ProcessInformationClass, + PVOID ProcessInformation, ULONG ProcessInformationLength, + PULONG ReturnLength) { HOST_CONTEXT_GUARD(); DEBUG_LOG("NtQueryInformationProcess(%p, %u, %p, %u, %p) ", ProcessHandle, ProcessInformationClass, ProcessInformation, ProcessInformationLength, ReturnLength); @@ -501,29 +477,13 @@ NTSTATUS WIN_FUNC NtQueryInformationProcess(HANDLE ProcessHandle, PROCESSINFOCLA } // namespace ntdll -static void *resolveByName(const char *name) { - if (strcmp(name, "NtReadFile") == 0) - return (void *)ntdll::NtReadFile; - if (strcmp(name, "NtWriteFile") == 0) - return (void *)ntdll::NtWriteFile; - if (strcmp(name, "NtAllocateVirtualMemory") == 0) - return (void *)ntdll::NtAllocateVirtualMemory; - if (strcmp(name, "NtProtectVirtualMemory") == 0) - return (void *)ntdll::NtProtectVirtualMemory; - if (strcmp(name, "RtlGetVersion") == 0) - return (void *)ntdll::RtlGetVersion; - if (strcmp(name, "NtQueryInformationProcess") == 0) - return (void *)ntdll::NtQueryInformationProcess; - if (strcmp(name, "memset") == 0) - return (void *)ntdll::memset; - return nullptr; -} +#include "ntdll_trampolines.h" extern const wibo::ModuleStub lib_ntdll = { (const char *[]){ "ntdll", nullptr, }, - resolveByName, + ntdllThunkByName, nullptr, }; diff --git a/dll/ntdll.h b/dll/ntdll.h new file mode 100644 index 0000000..aa5b908 --- /dev/null +++ b/dll/ntdll.h @@ -0,0 +1,49 @@ +#pragma once + +#include "types.h" + +using PIO_APC_ROUTINE = PVOID; + +typedef struct _IO_STATUS_BLOCK { + union { + NTSTATUS Status; + PVOID Pointer; + }; + ULONG_PTR Information; +} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK; + +enum PROCESSINFOCLASS { + ProcessBasicInformation = 0, + ProcessWow64Information = 26, + ProcessImageFileName = 27, +}; + +struct RTL_OSVERSIONINFOW { + ULONG dwOSVersionInfoSize; + ULONG dwMajorVersion; + ULONG dwMinorVersion; + ULONG dwBuildNumber; + ULONG dwPlatformId; + WCHAR szCSDVersion[128]; +}; + +using PRTL_OSVERSIONINFOW = RTL_OSVERSIONINFOW *; + +namespace ntdll { + +PVOID CDECL memset(PVOID dest, int ch, SIZE_T count); +NTSTATUS WINAPI NtReadFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, + PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer, ULONG Length, PLARGE_INTEGER ByteOffset, + PULONG Key); +NTSTATUS WINAPI NtWriteFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, + PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer, ULONG Length, PLARGE_INTEGER ByteOffset, + PULONG Key); +NTSTATUS WINAPI NtAllocateVirtualMemory(HANDLE ProcessHandle, PVOID *BaseAddress, ULONG_PTR ZeroBits, PSIZE_T RegionSize, + ULONG AllocationType, ULONG Protect); +NTSTATUS WINAPI NtProtectVirtualMemory(HANDLE ProcessHandle, PVOID *BaseAddress, PSIZE_T NumberOfBytesToProtect, + ULONG NewAccessProtection, PULONG OldAccessProtection); +NTSTATUS WINAPI RtlGetVersion(PRTL_OSVERSIONINFOW lpVersionInformation); +NTSTATUS WINAPI NtQueryInformationProcess(HANDLE ProcessHandle, PROCESSINFOCLASS ProcessInformationClass, + PVOID ProcessInformation, ULONG ProcessInformationLength, PULONG ReturnLength); + +} // namespace ntdll diff --git a/dll/ole32.cpp b/dll/ole32.cpp index 1fc47ac..1ba7e57 100644 --- a/dll/ole32.cpp +++ b/dll/ole32.cpp @@ -1,3 +1,5 @@ +#include "ole32.h" + #include "common.h" #include "context.h" #include "errors.h" @@ -108,15 +110,16 @@ HRESULT parseGuidString(const uint16_t *first, const uint16_t *last, GUID &out) } // namespace namespace ole32 { -int WIN_FUNC CoInitialize(void *pvReserved) { + +HRESULT WINAPI CoInitialize(LPVOID pvReserved) { HOST_CONTEXT_GUARD(); DEBUG_LOG("STUB: CoInitialize(%p)\n", pvReserved); (void)pvReserved; return 0; // S_OK } -int WIN_FUNC CoCreateInstance(const GUID *rclsid, void *pUnkOuter, unsigned int dwClsContext, const GUID *riid, - void **ppv) { +HRESULT WINAPI CoCreateInstance(const GUID *rclsid, LPVOID pUnkOuter, DWORD dwClsContext, const GUID *riid, + LPVOID *ppv) { HOST_CONTEXT_GUARD(); DEBUG_LOG("STUB: CoCreateInstance(0x%x, %p, %d, 0x%x, %p)\n", rclsid->Data1, pUnkOuter, dwClsContext, riid->Data1, *ppv); @@ -126,7 +129,7 @@ int WIN_FUNC CoCreateInstance(const GUID *rclsid, void *pUnkOuter, unsigned int return 0x80004003; // E_POINTER } -int WIN_FUNC CLSIDFromString(const uint16_t *lpsz, GUID *pclsid) { +HRESULT WINAPI CLSIDFromString(LPCWSTR lpsz, GUID *pclsid) { HOST_CONTEXT_GUARD(); if (pclsid == nullptr) { @@ -150,23 +153,16 @@ int WIN_FUNC CLSIDFromString(const uint16_t *lpsz, GUID *pclsid) { return parseGuidString(begin, end, *pclsid); } + } // namespace ole32 -static void *resolveByName(const char *name) { - if (strcmp(name, "CoInitialize") == 0) - return (void *)ole32::CoInitialize; - if (strcmp(name, "CoCreateInstance") == 0) - return (void *)ole32::CoCreateInstance; - if (strcmp(name, "CLSIDFromString") == 0) - return (void *)ole32::CLSIDFromString; - return nullptr; -} +#include "ole32_trampolines.h" extern const wibo::ModuleStub lib_ole32 = { (const char *[]){ "ole32", nullptr, }, - resolveByName, + ole32ThunkByName, nullptr, }; diff --git a/dll/ole32.h b/dll/ole32.h new file mode 100644 index 0000000..c2f0292 --- /dev/null +++ b/dll/ole32.h @@ -0,0 +1,11 @@ +#pragma once + +#include "types.h" + +namespace ole32 { + +HRESULT WINAPI CoInitialize(LPVOID pvReserved); +HRESULT WINAPI CoCreateInstance(const GUID *rclsid, LPVOID pUnkOuter, DWORD dwClsContext, const GUID *riid, LPVOID *ppv); +HRESULT WINAPI CLSIDFromString(LPCWSTR lpsz, GUID *pclsid); + +} // namespace ole32 diff --git a/dll/rpcrt4.cpp b/dll/rpcrt4.cpp index 2eb04fb..648a98e 100644 --- a/dll/rpcrt4.cpp +++ b/dll/rpcrt4.cpp @@ -1,3 +1,5 @@ +#include "rpcrt4.h" + #include "common.h" #include "context.h" #include "modules.h" @@ -11,15 +13,6 @@ namespace { -using RPC_STATUS = unsigned long; -using RPC_WSTR = uint16_t *; -using RPC_BINDING_HANDLE = void *; -using RPC_AUTH_IDENTITY_HANDLE = void *; -using LONG_PTR = intptr_t; -using PMIDL_STUB_DESC = void *; -using PFORMAT_STRING = unsigned char *; -using PRPC_MESSAGE = void *; - constexpr RPC_STATUS RPC_S_OK = 0; constexpr RPC_STATUS RPC_S_INVALID_STRING_BINDING = 1700; constexpr RPC_STATUS RPC_S_INVALID_BINDING = 1702; @@ -27,14 +20,6 @@ constexpr RPC_STATUS RPC_S_SERVER_UNAVAILABLE = 1722; constexpr RPC_STATUS RPC_S_INVALID_ARG = 87; constexpr RPC_STATUS RPC_S_OUT_OF_MEMORY = 14; -struct RPC_SECURITY_QOS { - unsigned long Version = 0; - unsigned long Capabilities = 0; - unsigned long IdentityTracking = 0; - unsigned long ImpersonationType = 0; - void *AdditionalSecurityInfo = nullptr; -}; - struct BindingComponents { std::u16string objectUuid; std::u16string protocolSequence; @@ -57,11 +42,6 @@ struct BindingHandleData { bool serverReachable = false; }; -union CLIENT_CALL_RETURN { - void *Pointer; - LONG_PTR Simple; -}; - std::unordered_map g_stringBindings; std::unordered_map> g_bindingHandles; @@ -128,10 +108,10 @@ BindingHandleData *getBinding(RPC_BINDING_HANDLE handle) { } // namespace -extern "C" { +namespace rpcrt4 { -RPC_STATUS WIN_FUNC RpcStringBindingComposeW(RPC_WSTR objUuid, RPC_WSTR protSeq, RPC_WSTR networkAddr, - RPC_WSTR endpoint, RPC_WSTR options, RPC_WSTR *stringBinding) { +RPC_STATUS WINAPI RpcStringBindingComposeW(RPC_WSTR objUuid, RPC_WSTR protSeq, RPC_WSTR networkAddr, RPC_WSTR endpoint, + RPC_WSTR options, RPC_WSTR *stringBinding) { HOST_CONTEXT_GUARD(); BindingComponents components; components.objectUuid = toU16(objUuid); @@ -161,7 +141,7 @@ RPC_STATUS WIN_FUNC RpcStringBindingComposeW(RPC_WSTR objUuid, RPC_WSTR protSeq, return RPC_S_OK; } -RPC_STATUS WIN_FUNC RpcBindingFromStringBindingW(RPC_WSTR stringBinding, RPC_BINDING_HANDLE *binding) { +RPC_STATUS WINAPI RpcBindingFromStringBindingW(RPC_WSTR stringBinding, RPC_BINDING_HANDLE *binding) { HOST_CONTEXT_GUARD(); if (!binding) { return RPC_S_INVALID_ARG; @@ -185,10 +165,9 @@ RPC_STATUS WIN_FUNC RpcBindingFromStringBindingW(RPC_WSTR stringBinding, RPC_BIN return RPC_S_OK; } -RPC_STATUS WIN_FUNC RpcBindingSetAuthInfoExW(RPC_BINDING_HANDLE binding, RPC_WSTR serverPrincName, - unsigned long authnLevel, unsigned long authnSvc, - RPC_AUTH_IDENTITY_HANDLE authIdentity, unsigned long authzSvc, - RPC_SECURITY_QOS *securityQos) { +RPC_STATUS WINAPI RpcBindingSetAuthInfoExW(RPC_BINDING_HANDLE binding, RPC_WSTR serverPrincName, ULONG authnLevel, + ULONG authnSvc, RPC_AUTH_IDENTITY_HANDLE authIdentity, ULONG authzSvc, + RPC_SECURITY_QOS *securityQos) { HOST_CONTEXT_GUARD(); BindingHandleData *data = getBinding(binding); if (!data) { @@ -210,7 +189,7 @@ RPC_STATUS WIN_FUNC RpcBindingSetAuthInfoExW(RPC_BINDING_HANDLE binding, RPC_WST return RPC_S_OK; } -RPC_STATUS WIN_FUNC RpcBindingFree(RPC_BINDING_HANDLE *binding) { +RPC_STATUS WINAPI RpcBindingFree(RPC_BINDING_HANDLE *binding) { HOST_CONTEXT_GUARD(); if (!binding) { return RPC_S_INVALID_ARG; @@ -229,7 +208,7 @@ RPC_STATUS WIN_FUNC RpcBindingFree(RPC_BINDING_HANDLE *binding) { return RPC_S_OK; } -RPC_STATUS WIN_FUNC RpcStringFreeW(RPC_WSTR *string) { +RPC_STATUS WINAPI RpcStringFreeW(RPC_WSTR *string) { HOST_CONTEXT_GUARD(); if (!string) { return RPC_S_INVALID_ARG; @@ -247,7 +226,7 @@ RPC_STATUS WIN_FUNC RpcStringFreeW(RPC_WSTR *string) { return RPC_S_OK; } -CLIENT_CALL_RETURN WIN_ENTRY NdrClientCall2(PMIDL_STUB_DESC stubDescriptor, PFORMAT_STRING format, ...) { +CLIENT_CALL_RETURN CDECL_NO_CONV NdrClientCall2(PMIDL_STUB_DESC stubDescriptor, PFORMAT_STRING format, ...) { DEBUG_LOG("STUB: NdrClientCall2 stubDescriptor=%p format=%p\n", stubDescriptor, format); CLIENT_CALL_RETURN result = {}; result.Simple = RPC_S_SERVER_UNAVAILABLE; @@ -255,37 +234,17 @@ CLIENT_CALL_RETURN WIN_ENTRY NdrClientCall2(PMIDL_STUB_DESC stubDescriptor, PFOR return result; } -void WIN_FUNC NdrServerCall2(PRPC_MESSAGE message) { +VOID WINAPI NdrServerCall2(PRPC_MESSAGE message) { HOST_CONTEXT_GUARD(); DEBUG_LOG("STUB: NdrServerCall2 message=%p\n", message); } -} // extern "C" +} // namespace rpcrt4 -namespace { - -void *resolveByName(const char *name) { - if (std::strcmp(name, "RpcStringBindingComposeW") == 0) - return (void *)RpcStringBindingComposeW; - if (std::strcmp(name, "RpcBindingFromStringBindingW") == 0) - return (void *)RpcBindingFromStringBindingW; - if (std::strcmp(name, "RpcStringFreeW") == 0) - return (void *)RpcStringFreeW; - if (std::strcmp(name, "RpcBindingFree") == 0) - return (void *)RpcBindingFree; - if (std::strcmp(name, "RpcBindingSetAuthInfoExW") == 0) - return (void *)RpcBindingSetAuthInfoExW; - if (std::strcmp(name, "NdrClientCall2") == 0) - return (void *)NdrClientCall2; - if (std::strcmp(name, "NdrServerCall2") == 0) - return (void *)NdrServerCall2; - return nullptr; -} - -} // namespace +#include "rpcrt4_trampolines.h" extern const wibo::ModuleStub lib_rpcrt4 = { (const char *[]){"rpcrt4", nullptr}, - resolveByName, + rpcrt4ThunkByName, nullptr, }; diff --git a/dll/rpcrt4.h b/dll/rpcrt4.h new file mode 100644 index 0000000..8260826 --- /dev/null +++ b/dll/rpcrt4.h @@ -0,0 +1,39 @@ +#pragma once + +#include "types.h" + +using RPC_STATUS = ULONG; +using RPC_WSTR = LPWSTR; +using RPC_BINDING_HANDLE = PVOID; +using RPC_AUTH_IDENTITY_HANDLE = PVOID; +using PMIDL_STUB_DESC = PVOID; +using PFORMAT_STRING = PUCHAR; +using PRPC_MESSAGE = PVOID; + +struct RPC_SECURITY_QOS { + ULONG Version; + ULONG Capabilities; + ULONG IdentityTracking; + ULONG ImpersonationType; + PVOID AdditionalSecurityInfo; +}; + +union CLIENT_CALL_RETURN { + PVOID Pointer; + LONG_PTR Simple; +}; + +namespace rpcrt4 { + +RPC_STATUS WINAPI RpcStringBindingComposeW(RPC_WSTR objUuid, RPC_WSTR protSeq, RPC_WSTR networkAddr, RPC_WSTR endpoint, + RPC_WSTR options, RPC_WSTR *stringBinding); +RPC_STATUS WINAPI RpcBindingFromStringBindingW(RPC_WSTR stringBinding, RPC_BINDING_HANDLE *binding); +RPC_STATUS WINAPI RpcBindingSetAuthInfoExW(RPC_BINDING_HANDLE binding, RPC_WSTR serverPrincName, ULONG authnLevel, + ULONG authnSvc, RPC_AUTH_IDENTITY_HANDLE authIdentity, ULONG authzSvc, + RPC_SECURITY_QOS *securityQos); +RPC_STATUS WINAPI RpcBindingFree(RPC_BINDING_HANDLE *binding); +RPC_STATUS WINAPI RpcStringFreeW(RPC_WSTR *string); +CLIENT_CALL_RETURN CDECL_NO_CONV NdrClientCall2(PMIDL_STUB_DESC stubDescriptor, PFORMAT_STRING format, ...); +VOID WINAPI NdrServerCall2(PRPC_MESSAGE message); + +} // namespace rpcrt4 diff --git a/dll/user32.cpp b/dll/user32.cpp index 30a17b5..f134e74 100644 --- a/dll/user32.cpp +++ b/dll/user32.cpp @@ -1,3 +1,5 @@ +#include "user32.h" + #include "common.h" #include "context.h" #include "errors.h" @@ -20,7 +22,7 @@ struct USEROBJECTFLAGS { DWORD dwFlags; }; -int WIN_FUNC LoadStringA(void *hInstance, unsigned int uID, char *lpBuffer, int cchBufferMax) { +int WINAPI LoadStringA(HMODULE hInstance, UINT uID, LPSTR lpBuffer, int cchBufferMax) { HOST_CONTEXT_GUARD(); DEBUG_LOG("LoadStringA(%p, %u, %p, %d)\n", hInstance, uID, lpBuffer, cchBufferMax); if (!lpBuffer || cchBufferMax <= 0) { @@ -68,7 +70,7 @@ int WIN_FUNC LoadStringA(void *hInstance, unsigned int uID, char *lpBuffer, int return copyLength; } -int WIN_FUNC LoadStringW(void *hInstance, unsigned int uID, uint16_t *lpBuffer, int cchBufferMax) { +int WINAPI LoadStringW(HMODULE hInstance, UINT uID, LPWSTR lpBuffer, int cchBufferMax) { HOST_CONTEXT_GUARD(); DEBUG_LOG("LoadStringW(%p, %u, %p, %d)\n", hInstance, uID, lpBuffer, cchBufferMax); wibo::Executable *mod = wibo::executableFromModule((HMODULE)hInstance); @@ -122,7 +124,7 @@ int WIN_FUNC LoadStringW(void *hInstance, unsigned int uID, uint16_t *lpBuffer, return copyLength; } -int WIN_FUNC MessageBoxA(void *hwnd, const char *lpText, const char *lpCaption, unsigned int uType) { +int WINAPI MessageBoxA(HWND hwnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType) { HOST_CONTEXT_GUARD(); (void)hwnd; (void)uType; @@ -131,20 +133,20 @@ int WIN_FUNC MessageBoxA(void *hwnd, const char *lpText, const char *lpCaption, return 1; } -HKL WIN_FUNC GetKeyboardLayout(DWORD idThread) { +HKL WINAPI GetKeyboardLayout(DWORD idThread) { HOST_CONTEXT_GUARD(); DEBUG_LOG("GetKeyboardLayout(%u)\n", idThread); (void)idThread; return reinterpret_cast(kDefaultKeyboardLayout); } -HWINSTA WIN_FUNC GetProcessWindowStation() { +HWINSTA WINAPI GetProcessWindowStation() { DEBUG_LOG("GetProcessWindowStation()\n"); static int kWindowStationStub; return reinterpret_cast(&kWindowStationStub); } -BOOL WIN_FUNC GetUserObjectInformationA(HANDLE hObj, int nIndex, PVOID pvInfo, DWORD nLength, LPDWORD lpnLengthNeeded) { +BOOL WINAPI GetUserObjectInformationA(HANDLE hObj, int nIndex, PVOID pvInfo, DWORD nLength, LPDWORD lpnLengthNeeded) { DEBUG_LOG("GetUserObjectInformationA(%p, %d, %p, %u, %p)\n", hObj, nIndex, pvInfo, nLength, lpnLengthNeeded); (void)hObj; @@ -169,36 +171,20 @@ BOOL WIN_FUNC GetUserObjectInformationA(HANDLE hObj, int nIndex, PVOID pvInfo, D return TRUE; } -HWND WIN_FUNC GetActiveWindow() { +HWND WINAPI GetActiveWindow() { DEBUG_LOG("GetActiveWindow()\n"); return nullptr; } } // namespace user32 -static void *resolveByName(const char *name) { - if (strcmp(name, "LoadStringA") == 0) - return (void *)user32::LoadStringA; - if (strcmp(name, "LoadStringW") == 0) - return (void *)user32::LoadStringW; - if (strcmp(name, "MessageBoxA") == 0) - return (void *)user32::MessageBoxA; - if (strcmp(name, "GetKeyboardLayout") == 0) - return (void *)user32::GetKeyboardLayout; - if (strcmp(name, "GetProcessWindowStation") == 0) - return (void *)user32::GetProcessWindowStation; - if (strcmp(name, "GetUserObjectInformationA") == 0) - return (void *)user32::GetUserObjectInformationA; - if (strcmp(name, "GetActiveWindow") == 0) - return (void *)user32::GetActiveWindow; - return nullptr; -} +#include "user32_trampolines.h" extern const wibo::ModuleStub lib_user32 = { (const char *[]){ "user32", nullptr, }, - resolveByName, + user32ThunkByName, nullptr, }; diff --git a/dll/user32.h b/dll/user32.h new file mode 100644 index 0000000..2fdd833 --- /dev/null +++ b/dll/user32.h @@ -0,0 +1,15 @@ +#pragma once + +#include "types.h" + +namespace user32 { + +int WINAPI LoadStringA(HMODULE hInstance, UINT uID, LPSTR lpBuffer, int cchBufferMax); +int WINAPI LoadStringW(HMODULE hInstance, UINT uID, LPWSTR lpBuffer, int cchBufferMax); +int WINAPI MessageBoxA(HWND hwnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType); +HKL WINAPI GetKeyboardLayout(DWORD idThread); +HWINSTA WINAPI GetProcessWindowStation(); +BOOL WINAPI GetUserObjectInformationA(HANDLE hObj, int nIndex, PVOID pvInfo, DWORD nLength, LPDWORD lpnLengthNeeded); +HWND WINAPI GetActiveWindow(); + +} // namespace user32 diff --git a/dll/vcruntime.cpp b/dll/vcruntime.cpp index 5e4292a..67f8674 100644 --- a/dll/vcruntime.cpp +++ b/dll/vcruntime.cpp @@ -1,3 +1,5 @@ +#include "vcruntime.h" + #include "common.h" #include "context.h" #include "modules.h" @@ -6,45 +8,35 @@ namespace vcruntime { -void *WIN_ENTRY memcpy(void *dest, const void *src, size_t count) { +PVOID CDECL memcpy(PVOID dest, LPCVOID src, SIZE_T count) { HOST_CONTEXT_GUARD(); return ::memcpy(dest, src, count); } -void *WIN_ENTRY memset(void *dest, int ch, size_t count) { +PVOID CDECL memset(PVOID dest, int ch, SIZE_T count) { HOST_CONTEXT_GUARD(); return ::memset(dest, ch, count); } -int WIN_ENTRY memcmp(const void *buf1, const void *buf2, size_t count) { +int CDECL memcmp(LPCVOID buf1, LPCVOID buf2, SIZE_T count) { HOST_CONTEXT_GUARD(); return ::memcmp(buf1, buf2, count); } -void *WIN_ENTRY memmove(void *dest, const void *src, size_t count) { +PVOID CDECL memmove(PVOID dest, LPCVOID src, SIZE_T count) { HOST_CONTEXT_GUARD(); return ::memmove(dest, src, count); } } // namespace vcruntime -static void *resolveByName(const char *name) { - if (strcmp(name, "memcpy") == 0) - return (void *)vcruntime::memcpy; - if (strcmp(name, "memset") == 0) - return (void *)vcruntime::memset; - if (strcmp(name, "memcmp") == 0) - return (void *)vcruntime::memcmp; - if (strcmp(name, "memmove") == 0) - return (void *)vcruntime::memmove; - return nullptr; -} +#include "vcruntime_trampolines.h" extern const wibo::ModuleStub lib_vcruntime = { (const char *[]){ "vcruntime140", nullptr, }, - resolveByName, + vcruntimeThunkByName, nullptr, }; diff --git a/dll/vcruntime.h b/dll/vcruntime.h new file mode 100644 index 0000000..a201248 --- /dev/null +++ b/dll/vcruntime.h @@ -0,0 +1,12 @@ +#pragma once + +#include "types.h" + +namespace vcruntime { + +PVOID CDECL memcpy(PVOID dest, LPCVOID src, SIZE_T count); +PVOID CDECL memset(PVOID dest, int ch, SIZE_T count); +int CDECL memcmp(LPCVOID buf1, LPCVOID buf2, SIZE_T count); +PVOID CDECL memmove(PVOID dest, LPCVOID src, SIZE_T count); + +} // namespace vcruntime diff --git a/dll/version.cpp b/dll/version.cpp index 04ff556..dbac1b0 100644 --- a/dll/version.cpp +++ b/dll/version.cpp @@ -1,3 +1,5 @@ +#include "version.h" + #include "common.h" #include "context.h" #include "errors.h" @@ -200,7 +202,7 @@ bool loadVersionResource(const char *fileName, std::vector &buffer) { namespace version { -unsigned int WIN_FUNC GetFileVersionInfoSizeA(const char *lptstrFilename, unsigned int *lpdwHandle) { +UINT WINAPI GetFileVersionInfoSizeA(LPCSTR lptstrFilename, LPDWORD lpdwHandle) { HOST_CONTEXT_GUARD(); DEBUG_LOG("GetFileVersionInfoSizeA(%s, %p)\n", lptstrFilename, lpdwHandle); if (lpdwHandle) @@ -212,8 +214,7 @@ unsigned int WIN_FUNC GetFileVersionInfoSizeA(const char *lptstrFilename, unsign return static_cast(buffer.size()); } -unsigned int WIN_FUNC GetFileVersionInfoA(const char *lptstrFilename, unsigned int dwHandle, unsigned int dwLen, - void *lpData) { +UINT WINAPI GetFileVersionInfoA(LPCSTR lptstrFilename, DWORD dwHandle, DWORD dwLen, LPVOID lpData) { HOST_CONTEXT_GUARD(); (void)dwHandle; DEBUG_LOG("GetFileVersionInfoA(%s, %u, %p)\n", lptstrFilename, dwLen, lpData); @@ -276,8 +277,7 @@ static unsigned int VerQueryValueImpl(const void *pBlock, const std::string &sub return 1; } -unsigned int WIN_FUNC VerQueryValueA(const void *pBlock, const char *lpSubBlock, void **lplpBuffer, - unsigned int *puLen) { +UINT WINAPI VerQueryValueA(LPCVOID pBlock, LPCSTR lpSubBlock, LPVOID *lplpBuffer, PUINT puLen) { HOST_CONTEXT_GUARD(); DEBUG_LOG("VerQueryValueA(%p, %s, %p, %p)\n", pBlock, lpSubBlock ? lpSubBlock : "(null)", lplpBuffer, puLen); if (!lpSubBlock) @@ -285,23 +285,21 @@ unsigned int WIN_FUNC VerQueryValueA(const void *pBlock, const char *lpSubBlock, return VerQueryValueImpl(pBlock, lpSubBlock, lplpBuffer, puLen); } -unsigned int WIN_FUNC GetFileVersionInfoSizeW(const uint16_t *lptstrFilename, unsigned int *lpdwHandle) { +UINT WINAPI GetFileVersionInfoSizeW(LPCWSTR lptstrFilename, LPDWORD lpdwHandle) { HOST_CONTEXT_GUARD(); DEBUG_LOG("GetFileVersionInfoSizeW -> "); auto narrow = wideStringToString(lptstrFilename); return GetFileVersionInfoSizeA(narrow.c_str(), lpdwHandle); } -unsigned int WIN_FUNC GetFileVersionInfoW(const uint16_t *lptstrFilename, unsigned int dwHandle, unsigned int dwLen, - void *lpData) { +UINT WINAPI GetFileVersionInfoW(LPCWSTR lptstrFilename, DWORD dwHandle, DWORD dwLen, LPVOID lpData) { HOST_CONTEXT_GUARD(); DEBUG_LOG("GetFileVersionInfoW -> "); auto narrow = wideStringToString(lptstrFilename); return GetFileVersionInfoA(narrow.c_str(), dwHandle, dwLen, lpData); } -unsigned int WIN_FUNC VerQueryValueW(const void *pBlock, const uint16_t *lpSubBlock, void **lplpBuffer, - unsigned int *puLen) { +UINT WINAPI VerQueryValueW(LPCVOID pBlock, LPCWSTR lpSubBlock, LPVOID *lplpBuffer, PUINT puLen) { HOST_CONTEXT_GUARD(); if (!lpSubBlock) return 0; @@ -312,27 +310,13 @@ unsigned int WIN_FUNC VerQueryValueW(const void *pBlock, const uint16_t *lpSubBl } // namespace version -static void *resolveByName(const char *name) { - if (strcmp(name, "GetFileVersionInfoSizeA") == 0) - return (void *)version::GetFileVersionInfoSizeA; - if (strcmp(name, "GetFileVersionInfoA") == 0) - return (void *)version::GetFileVersionInfoA; - if (strcmp(name, "VerQueryValueA") == 0) - return (void *)version::VerQueryValueA; - if (strcmp(name, "GetFileVersionInfoSizeW") == 0) - return (void *)version::GetFileVersionInfoSizeW; - if (strcmp(name, "GetFileVersionInfoW") == 0) - return (void *)version::GetFileVersionInfoW; - if (strcmp(name, "VerQueryValueW") == 0) - return (void *)version::VerQueryValueW; - return nullptr; -} +#include "version_trampolines.h" extern const wibo::ModuleStub lib_version = { (const char *[]){ "version", nullptr, }, - resolveByName, + versionThunkByName, nullptr, }; diff --git a/dll/version.h b/dll/version.h new file mode 100644 index 0000000..ab71966 --- /dev/null +++ b/dll/version.h @@ -0,0 +1,14 @@ +#pragma once + +#include "types.h" + +namespace version { + +UINT WINAPI GetFileVersionInfoSizeA(LPCSTR lptstrFilename, LPDWORD lpdwHandle); +UINT WINAPI GetFileVersionInfoA(LPCSTR lptstrFilename, DWORD dwHandle, DWORD dwLen, LPVOID lpData); +UINT WINAPI VerQueryValueA(LPCVOID pBlock, LPCSTR lpSubBlock, LPVOID *lplpBuffer, PUINT puLen); +UINT WINAPI GetFileVersionInfoSizeW(LPCWSTR lptstrFilename, LPDWORD lpdwHandle); +UINT WINAPI GetFileVersionInfoW(LPCWSTR lptstrFilename, DWORD dwHandle, DWORD dwLen, LPVOID lpData); +UINT WINAPI VerQueryValueW(LPCVOID pBlock, LPCWSTR lpSubBlock, LPVOID *lplpBuffer, PUINT puLen); + +} // namespace version diff --git a/src/common.h b/src/common.h index 9c08ef2..0362605 100644 --- a/src/common.h +++ b/src/common.h @@ -22,6 +22,8 @@ #define VERBOSE_LOG(...) ((void)0) #endif +extern "C" thread_local TEB *currentThreadTeb; + namespace wibo { extern char **argv; @@ -32,7 +34,6 @@ extern std::string commandLine; extern std::vector commandLineW; extern bool debugEnabled; extern unsigned int debugIndent; -extern uint16_t tibSelector; extern int tibEntryNumber; extern PEB *processPeb; @@ -40,8 +41,6 @@ TEB *allocateTib(); void destroyTib(TEB *tib); void initializeTibStackInfo(TEB *tib); bool installTibForCurrentThread(TEB *tib); -void setThreadTibForHost(TEB *tib); -TEB *getThreadTibForHost(); void debug_log(const char *fmt, ...); diff --git a/src/context.cpp b/src/context.cpp deleted file mode 100644 index 8d7bf7a..0000000 --- a/src/context.cpp +++ /dev/null @@ -1,65 +0,0 @@ -#include "context.h" - -#include - -namespace { - -constexpr size_t kHostFsOffset = offsetof(TEB, hostFsSelector); -constexpr size_t kHostGsOffset = offsetof(TEB, hostGsSelector); -constexpr size_t kHostValidOffset = offsetof(TEB, hostSegmentsValid); -thread_local TEB *g_threadTibForHost = nullptr; - -} // namespace - -namespace wibo { - -void setThreadTibForHost(TEB *tib) { g_threadTibForHost = tib; } - -TEB *getThreadTibForHost() { return g_threadTibForHost; } - -HostContextGuard::HostContextGuard() : previousFs_(0), previousGs_(0), restore_(false) { - asm volatile("mov %%fs, %0" : "=r"(previousFs_)); - asm volatile("mov %%gs, %0" : "=r"(previousGs_)); - if (previousFs_ == wibo::tibSelector) { - unsigned char hostValid = 0; - asm volatile("movb %%fs:%c1, %0" : "=r"(hostValid) : "i"(kHostValidOffset)); - if (hostValid) { - uint16_t hostFs = 0; - uint16_t hostGs = 0; - asm volatile("movw %%fs:%c1, %0" : "=r"(hostFs) : "i"(kHostFsOffset)); - asm volatile("movw %%fs:%c1, %0" : "=r"(hostGs) : "i"(kHostGsOffset)); - asm volatile("movw %0, %%fs" : : "r"(hostFs) : "memory"); - asm volatile("movw %0, %%gs" : : "r"(hostGs) : "memory"); - restore_ = true; - } - } -} - -HostContextGuard::~HostContextGuard() { - if (restore_) { - asm volatile("movw %0, %%fs" : : "r"(previousFs_) : "memory"); - asm volatile("movw %0, %%gs" : : "r"(previousGs_) : "memory"); - } -} - -GuestContextGuard::GuestContextGuard(TEB *tib) : previousFs_(0), previousGs_(0), applied_(false) { - if (!tib || !wibo::tibSelector) { - return; - } - asm volatile("mov %%fs, %0" : "=r"(previousFs_)); - asm volatile("mov %%gs, %0" : "=r"(previousGs_)); - tib->hostFsSelector = previousFs_; - tib->hostGsSelector = previousGs_; - tib->hostSegmentsValid = 1; - asm volatile("movw %0, %%fs" : : "r"(wibo::tibSelector) : "memory"); - applied_ = true; -} - -GuestContextGuard::~GuestContextGuard() { - if (applied_) { - asm volatile("movw %0, %%fs" : : "r"(previousFs_) : "memory"); - asm volatile("movw %0, %%gs" : : "r"(previousGs_) : "memory"); - } -} - -} // namespace wibo diff --git a/src/context.h b/src/context.h index 8d35d97..246d7cd 100644 --- a/src/context.h +++ b/src/context.h @@ -1,36 +1,4 @@ #pragma once -#include "common.h" - -namespace wibo { - -class HostContextGuard { - public: - HostContextGuard(); - ~HostContextGuard(); - HostContextGuard(const HostContextGuard &) = delete; - HostContextGuard &operator=(const HostContextGuard &) = delete; - - private: - uint16_t previousFs_; - uint16_t previousGs_; - bool restore_; -}; - -class GuestContextGuard { - public: - explicit GuestContextGuard(TEB *tib); - ~GuestContextGuard(); - GuestContextGuard(const GuestContextGuard &) = delete; - GuestContextGuard &operator=(const GuestContextGuard &) = delete; - - private: - uint16_t previousFs_; - uint16_t previousGs_; - bool applied_; -}; - -} // namespace wibo - -#define HOST_CONTEXT_GUARD() wibo::HostContextGuard _wiboHostContextGuard -#define GUEST_CONTEXT_GUARD(tibPtr) wibo::GuestContextGuard _wiboGuestContextGuard(tibPtr) +#define HOST_CONTEXT_GUARD() +#define GUEST_CONTEXT_GUARD(tibPtr) diff --git a/src/entry.h b/src/entry.h new file mode 100644 index 0000000..191b0d2 --- /dev/null +++ b/src/entry.h @@ -0,0 +1,7 @@ +#pragma once + +#include "types.h" + +typedef VOID(_CC_CDECL *EntryProc)(); +typedef BOOL(_CC_STDCALL *DllEntryProc)(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved); +typedef VOID(_CC_STDCALL *PIMAGE_TLS_CALLBACK)(PVOID DllHandle, DWORD Reason, PVOID Reserved); diff --git a/src/main.cpp b/src/main.cpp index 445a6e4..f5fa939 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,7 @@ #include "common.h" #include "context.h" +#include "entry.h" +#include "entry_trampolines.h" #include "files.h" #include "modules.h" #include "processes.h" @@ -8,7 +10,6 @@ #include "version_info.h" #include -#include #include #include #include @@ -19,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -32,9 +32,9 @@ std::vector wibo::commandLineW; wibo::ModuleInfo *wibo::mainModule = nullptr; bool wibo::debugEnabled = false; unsigned int wibo::debugIndent = 0; -uint16_t wibo::tibSelector = 0; int wibo::tibEntryNumber = -1; PEB *wibo::processPeb = nullptr; +thread_local TEB *currentThreadTeb = nullptr; void wibo::debug_log(const char *fmt, ...) { va_list args; @@ -74,27 +74,24 @@ void wibo::initializeTibStackInfo(TEB *tibPtr) { if (!tibPtr) { return; } - pthread_attr_t attr; - if (pthread_getattr_np(pthread_self(), &attr) != 0) { - perror("Failed to get thread attributes"); - return; + // Allocate a stack for the thread in the guest address space (below 2GB) + void *guestLimit = nullptr; + void *guestBase = nullptr; + if (!wibo::heap::reserveGuestStack(1 * 1024 * 1024, &guestLimit, &guestBase)) { + fprintf(stderr, "Failed to reserve guest stack\n"); + std::abort(); } - void *stackAddr = nullptr; - size_t stackSize = 0; - if (pthread_attr_getstack(&attr, &stackAddr, &stackSize) == 0 && stackAddr && stackSize > 0) { - tibPtr->Tib.StackLimit = stackAddr; - tibPtr->Tib.StackBase = static_cast(stackAddr) + stackSize; - } else { - perror("Failed to get thread stack info"); - } - DEBUG_LOG("initializeTibStackInfo: stackBase=%p stackLimit=%p\n", tibPtr->Tib.StackBase, tibPtr->Tib.StackLimit); - pthread_attr_destroy(&attr); + tibPtr->Tib.StackLimit = guestLimit; + tibPtr->Tib.StackBase = guestBase; + DEBUG_LOG("initializeTibStackInfo: using guest stack base=%p limit=%p\n", tibPtr->Tib.StackBase, + tibPtr->Tib.StackLimit); } bool wibo::installTibForCurrentThread(TEB *tibPtr) { if (!tibPtr) { return false; } + struct user_desc desc; std::memset(&desc, 0, sizeof(desc)); desc.entry_number = tibEntryNumber; @@ -110,21 +107,22 @@ bool wibo::installTibForCurrentThread(TEB *tibPtr) { perror("set_thread_area failed"); return false; } - if (tibSelector == 0) { + if (tibEntryNumber != static_cast(desc.entry_number)) { tibEntryNumber = static_cast(desc.entry_number); - tibSelector = static_cast((desc.entry_number << 3) | 3); - DEBUG_LOG("set_thread_area: allocated selector=0x%x entry=%d base=%p\n", tibSelector, tibEntryNumber, tibPtr); + DEBUG_LOG("set_thread_area: allocated entry=%d base=%p\n", tibEntryNumber, tibPtr); } else { - DEBUG_LOG("set_thread_area: reused selector=0x%x entry=%d base=%p\n", tibSelector, tibEntryNumber, tibPtr); + DEBUG_LOG("set_thread_area: reused entry=%d base=%p\n", tibEntryNumber, tibPtr); } + + tibPtr->HostFsSelector = static_cast((desc.entry_number << 3) | 3); + tibPtr->HostGsSelector = 0; + currentThreadTeb = tibPtr; return true; } // Make this global to ease debugging TEB tib; -const size_t MAPS_BUFFER_SIZE = 0x10000; - static std::string getExeName(const char *argv0) { std::filesystem::path exePath(argv0 ? argv0 : "wibo"); return exePath.filename().string(); @@ -248,108 +246,6 @@ static int handlePathCommand(int argc, char **argv, const char *argv0) { return 0; } -/** - * Read /proc/self/maps into a buffer. - * - * While reading /proc/self/maps, we need to be extremely careful not to allocate any memory, - * as that could cause libc to modify memory mappings while we're attempting to fill them. - * To accomplish this, we use Linux syscalls directly. - * - * @param buffer The buffer to read into. - * @return The number of bytes read. - */ -static size_t readMaps(char *buffer) { - int fd = open("/proc/self/maps", O_RDONLY); - if (fd == -1) { - perror("Failed to open /proc/self/maps"); - exit(1); - } - - char *cur = buffer; - char *bufferEnd = buffer + MAPS_BUFFER_SIZE; - while (cur < bufferEnd) { - int ret = read(fd, cur, static_cast(bufferEnd - cur)); - if (ret == -1) { - if (errno == EINTR) { - continue; - } - perror("Failed to read /proc/self/maps"); - exit(1); - } else if (ret == 0) { - break; - } - cur += ret; - } - close(fd); - - if (cur == bufferEnd) { - fprintf(stderr, "Buffer too small while reading /proc/self/maps\n"); - exit(1); - } - *cur = '\0'; - return static_cast(cur - buffer); -} - -/** - * Map the upper 2GB of memory to prevent libc from allocating there. - * - * This is necessary because 32-bit windows only reserves the lowest 2GB of memory for use by a process - * (https://www.tenouk.com/WinVirtualAddressSpace.html). Linux, on the other hand, will happily allow - * nearly the entire 4GB address space to be used. Some Windows programs rely on heap allocations to be - * in the lower 2GB of memory, otherwise they misbehave or crash. - * - * Between reading /proc/self/maps and mmap-ing the upper 2GB, we must be extremely careful not to allocate - * any memory, as that could cause libc to modify memory mappings while we're attempting to fill them. - */ -static void blockUpper2GB() { - const unsigned int FILL_MEMORY_ABOVE = 0x80000000; // 2GB - - DEBUG_LOG("Blocking upper 2GB address space\n"); - - // Buffer lives on the stack to avoid heap allocation - char buffer[MAPS_BUFFER_SIZE]; - size_t len = readMaps(buffer); - std::string_view procLine(buffer, len); - unsigned int lastMapEnd = 0; - while (true) { - size_t newline = procLine.find('\n'); - if (newline == std::string::npos) { - break; - } - - unsigned int mapStart = 0; - auto result = std::from_chars(procLine.data(), procLine.data() + procLine.size(), mapStart, 16); - if (result.ec != std::errc()) { - break; - } - unsigned int mapEnd = 0; - result = std::from_chars(result.ptr + 1, procLine.data() + procLine.size(), mapEnd, 16); - if (result.ec != std::errc()) { - break; - } - - // The empty space we want to map out is now between lastMapEnd and mapStart - unsigned int holdingMapStart = lastMapEnd; - unsigned int holdingMapEnd = mapStart; - - if ((holdingMapEnd - holdingMapStart) != 0 && holdingMapEnd > FILL_MEMORY_ABOVE) { - holdingMapStart = std::max(holdingMapStart, FILL_MEMORY_ABOVE); - - // DEBUG_LOG("Mapping %08x-%08x\n", holdingMapStart, holdingMapEnd); - void *holdingMap = mmap((void *)holdingMapStart, holdingMapEnd - holdingMapStart, PROT_READ | PROT_WRITE, - MAP_ANONYMOUS | MAP_FIXED | MAP_PRIVATE, -1, 0); - - if (holdingMap == MAP_FAILED) { - perror("Failed to create holding map"); - exit(1); - } - } - - lastMapEnd = mapEnd; - procLine = procLine.substr(newline + 1); - } -} - int main(int argc, char **argv) { if (argc >= 2 && strcmp(argv[1], "path") == 0) { return handlePathCommand(argc - 2, argv + 2, argv[0]); @@ -447,7 +343,6 @@ int main(int argc, char **argv) { wibo::debugIndent = std::stoul(debugIndentEnv); } - blockUpper2GB(); files::init(); // Create TIB @@ -463,7 +358,6 @@ int main(int argc, char **argv) { fprintf(stderr, "Failed to install TIB for main thread\n"); return 1; } - wibo::setThreadTibForHost(&tib); // Determine the guest program name auto guestArgs = wibo::splitCommandLine(cmdLine.c_str()); @@ -579,7 +473,7 @@ int main(int argc, char **argv) { } fclose(f); - const auto entryPoint = executable->entryPoint; + const auto entryPoint = reinterpret_cast(executable->entryPoint); if (!entryPoint) { fprintf(stderr, "Executable %s has no entry point\n", resolvedGuestPath.c_str()); return 1; @@ -609,7 +503,7 @@ int main(int argc, char **argv) { // Invoke the damn thing { GUEST_CONTEXT_GUARD(&tib); - asm volatile("call *%0" : : "r"(entryPoint) : "memory"); + call_EntryProc(entryPoint); } DEBUG_LOG("We came back\n"); wibo::shutdownModuleRegistry(); diff --git a/src/modules.cpp b/src/modules.cpp index a736a8e..5c57f26 100644 --- a/src/modules.cpp +++ b/src/modules.cpp @@ -2,9 +2,13 @@ #include "common.h" #include "context.h" +#include "entry.h" +#include "entry_trampolines.h" #include "errors.h" #include "files.h" #include "kernel32/internal.h" +#include "msvcrt.h" +#include "msvcrt_trampolines.h" #include "strutil.h" #include "tls.h" @@ -346,18 +350,11 @@ void runModuleTlsCallbacks(wibo::ModuleInfo &module, DWORD reason) { if (!module.tlsInfo.hasTls || module.tlsInfo.callbacks.empty()) { return; } - TEB *tib = wibo::getThreadTibForHost(); - if (!tib) { - return; - } - GUEST_CONTEXT_GUARD(tib); - using TlsCallback = void(WIN_FUNC *)(void *, DWORD, void *); - for (void *callbackAddr : module.tlsInfo.callbacks) { - if (!callbackAddr) { + for (auto *callback : module.tlsInfo.callbacks) { + if (!callback) { continue; } - auto callback = reinterpret_cast(callbackAddr); - callback(module.handle, reason, nullptr); + call_PIMAGE_TLS_CALLBACK(callback, module.handle, reason, nullptr); } } @@ -565,8 +562,7 @@ BOOL callDllMain(wibo::ModuleInfo &info, DWORD reason, LPVOID reserved) { // Reset last error kernel32::setLastError(ERROR_SUCCESS); - using DllMainFunc = BOOL(WIN_FUNC *)(HMODULE, DWORD, LPVOID); - auto dllMain = reinterpret_cast(entry); + auto dllMain = reinterpret_cast(entry); auto invokeWithGuestTIB = [&](DWORD callReason, LPVOID callReserved, bool force) -> BOOL { if (!force) { @@ -586,14 +582,8 @@ BOOL callDllMain(wibo::ModuleInfo &info, DWORD reason, LPVOID reserved) { reinterpret_cast(info.executable->imageBase), callReason, callReserved, info.normalizedName.c_str()); - BOOL result = TRUE; - if (!wibo::tibSelector) { - result = dllMain(reinterpret_cast(info.executable->imageBase), callReason, callReserved); - } else { - TEB *tib = wibo::getThreadTibForHost(); - GUEST_CONTEXT_GUARD(tib); - result = dllMain(reinterpret_cast(info.executable->imageBase), callReason, callReserved); - } + BOOL result = + call_DllEntryProc(dllMain, reinterpret_cast(info.executable->imageBase), callReason, callReserved); DEBUG_LOG(" callDllMain: %s DllMain returned %d\n", info.normalizedName.c_str(), result); return result; }; @@ -873,7 +863,7 @@ void registerOnExitTable(void *table) { } } -void addOnExitFunction(void *table, void (*func)()) { +void addOnExitFunction(void *table, _PVFV func) { if (!func) return; auto reg = registry(); @@ -887,17 +877,15 @@ void addOnExitFunction(void *table, void (*func)()) { reg->onExitTables[table] = info; } if (info) { - info->onExitFunctions.push_back(reinterpret_cast(func)); + info->onExitFunctions.push_back(func); } } void runPendingOnExit(ModuleInfo &info) { - TEB *tib = wibo::getThreadTibForHost(); for (auto it = info.onExitFunctions.rbegin(); it != info.onExitFunctions.rend(); ++it) { - auto fn = reinterpret_cast(*it); + auto *fn = *it; if (fn) { - GUEST_CONTEXT_GUARD(tib); - fn(); + call__PVFV(fn); } } info.onExitFunctions.clear(); @@ -932,7 +920,7 @@ bool initializeModuleTls(ModuleInfo &module) { if (callbacksArray) { auto callbackPtr = reinterpret_cast(callbacksArray); while (callbackPtr && *callbackPtr) { - info.callbacks.push_back(reinterpret_cast(resolveModuleAddress(exec, *callbackPtr))); + info.callbacks.push_back(reinterpret_cast(resolveModuleAddress(exec, *callbackPtr))); ++callbackPtr; } } @@ -1068,10 +1056,9 @@ void notifyDllThreadAttach() { targets.push_back(info); } } - TEB *tib = wibo::getThreadTibForHost(); for (wibo::ModuleInfo *info : targets) { - if (info && info->tlsInfo.hasTls && tib) { - if (!allocateModuleTlsForThread(*info, tib)) { + if (info && info->tlsInfo.hasTls) { + if (!allocateModuleTlsForThread(*info, currentThreadTeb)) { DEBUG_LOG("notifyDllThreadAttach: failed to allocate TLS for %s\n", info->originalName.c_str()); } runModuleTlsCallbacks(*info, TLS_THREAD_ATTACH); @@ -1093,9 +1080,8 @@ void notifyDllThreadDetach() { targets.push_back(info); } } - TEB *tib = wibo::getThreadTibForHost(); for (auto it = targets.rbegin(); it != targets.rend(); ++it) { - if (*it && (*it)->tlsInfo.hasTls && tib) { + if (*it && (*it)->tlsInfo.hasTls) { runModuleTlsCallbacks(**it, TLS_THREAD_DETACH); } } @@ -1103,8 +1089,8 @@ void notifyDllThreadDetach() { callDllMain(**it, DLL_THREAD_DETACH, nullptr); } for (auto it = targets.rbegin(); it != targets.rend(); ++it) { - if (*it && (*it)->tlsInfo.hasTls && tib) { - freeModuleTlsForThread(**it, tib); + if (*it && (*it)->tlsInfo.hasTls) { + freeModuleTlsForThread(**it, currentThreadTeb); } } kernel32::setLastError(ERROR_SUCCESS); diff --git a/src/modules.h b/src/modules.h index 4d9e1c0..41270d6 100644 --- a/src/modules.h +++ b/src/modules.h @@ -1,6 +1,8 @@ #pragma once #include "common.h" +#include "entry.h" +#include "msvcrt.h" #include "tls.h" #include @@ -73,7 +75,7 @@ struct ModuleTlsInfo { size_t zeroFillSize = 0; uint32_t characteristics = 0; size_t allocationSize = 0; - std::vector callbacks; + std::vector callbacks; std::unordered_map threadAllocations; }; @@ -100,7 +102,7 @@ struct ModuleInfo { std::vector exportsByOrdinal; std::unordered_map exportNameToOrdinal; bool exportsInitialized = false; - std::vector onExitFunctions; + std::vector<_PVFV> onExitFunctions; ModuleTlsInfo tlsInfo; }; extern ModuleInfo *mainModule; @@ -115,7 +117,7 @@ void clearDllDirectoryOverride(); std::optional dllDirectoryOverride(); ModuleInfo *findLoadedModule(const char *name); void registerOnExitTable(void *table); -void addOnExitFunction(void *table, void (*func)()); +void addOnExitFunction(void *table, _PVFV func); void executeOnExitTable(void *table); void runPendingOnExit(ModuleInfo &info); void notifyDllThreadAttach(); diff --git a/src/tls.cpp b/src/tls.cpp index 8aac0ef..131ed9b 100644 --- a/src/tls.cpp +++ b/src/tls.cpp @@ -357,9 +357,9 @@ bool setValue(TEB *tib, DWORD index, void *value) { return true; } -void *getValue(DWORD index) { return getValue(getThreadTibForHost(), index); } +void *getValue(DWORD index) { return getValue(currentThreadTeb, index); } -bool setValue(DWORD index, void *value) { return setValue(getThreadTibForHost(), index, value); } +bool setValue(DWORD index, void *value) { return setValue(currentThreadTeb, index, value); } void forEachTib(void (*callback)(TEB *, void *), void *context) { if (!callback) { diff --git a/src/types.h b/src/types.h index 0e98503..483a6d6 100644 --- a/src/types.h +++ b/src/types.h @@ -28,10 +28,16 @@ #define _Out_writes_bytes_(n) WIBO_ANNOTATE("SAL:out_bcount(" #n ")") // Codegen annotation for calling convention +#define _CC_CDECL WIBO_ANNOTATE("CC:cdecl") #define _CC_STDCALL WIBO_ANNOTATE("CC:stdcall") -// Instructs codegen to convert stdcall to fastcall +// Instructs codegen to convert between calling conventions #define WINAPI _CC_STDCALL __attribute__((fastcall)) +#define CDECL _CC_CDECL __attribute__((fastcall)) +#define CDECL_NO_CONV _CC_CDECL __attribute__((cdecl, force_align_arg_pointer)) + +// Used for host-to-guest calls +#define GUEST_STDCALL __attribute__((stdcall)) using VOID = void; using HANDLE = VOID *; @@ -39,6 +45,7 @@ using HMODULE = VOID *; using HGLOBAL = HANDLE; using HLOCAL = HANDLE; using HRSRC = HANDLE; +using HINSTANCE = HANDLE; using LPHANDLE = HANDLE *; using PHANDLE = HANDLE *; using HKL = HANDLE; @@ -57,13 +64,13 @@ using LONG = int; using PLONG = LONG *; using ULONG = unsigned int; using PULONG = ULONG *; -using LARGE_INTEGER = long long; -using PLARGE_INTEGER = LARGE_INTEGER *; -using ULARGE_INTEGER = unsigned long long; -using PULARGE_INTEGER = ULARGE_INTEGER *; +using LONGLONG = long long; +using ULONGLONG = unsigned long long; +using LONG_PTR = long; +static_assert(sizeof(LONG_PTR) == sizeof(void *), "LONG_PTR must be pointer-sized"); using ULONG_PTR = unsigned long; -using UINT_PTR = unsigned long; static_assert(sizeof(ULONG_PTR) == sizeof(void *), "ULONG_PTR must be pointer-sized"); +using UINT_PTR = unsigned long; static_assert(sizeof(UINT_PTR) == sizeof(void *), "UINT_PTR must be pointer-sized"); using DWORD_PTR = ULONG_PTR; using PDWORD_PTR = DWORD_PTR *; @@ -89,6 +96,7 @@ using PSIZE_T = SIZE_T *; using BYTE = unsigned char; using BOOLEAN = unsigned char; using UINT = unsigned int; +using PUINT = UINT *; using HKEY = VOID *; using PHKEY = HKEY *; using PSID = VOID *; @@ -105,6 +113,30 @@ using PWSTR = WCHAR *; using NTSTATUS = LONG; using HRESULT = LONG; +typedef union _LARGE_INTEGER { + struct { + DWORD LowPart; + LONG HighPart; + } DUMMYSTRUCTNAME; + struct { + DWORD LowPart; + LONG HighPart; + } u; + LONGLONG QuadPart; +} LARGE_INTEGER, *PLARGE_INTEGER; + +typedef union _ULARGE_INTEGER { + struct { + DWORD LowPart; + DWORD HighPart; + } DUMMYSTRUCTNAME; + struct { + DWORD LowPart; + DWORD HighPart; + } u; + ULONGLONG QuadPart; +} ULARGE_INTEGER, *PULARGE_INTEGER; + struct GUID { DWORD Data1; WORD Data2; @@ -260,7 +292,7 @@ typedef struct _PEB_LDR_DATA { LIST_ENTRY InMemoryOrderModuleList; } PEB_LDR_DATA, *PPEB_LDR_DATA; -using PS_POST_PROCESS_INIT_ROUTINE = void(WIN_FUNC *)(void); +typedef void(_CC_STDCALL *PS_POST_PROCESS_INIT_ROUTINE)(); using PPS_POST_PROCESS_INIT_ROUTINE = PS_POST_PROCESS_INIT_ROUTINE *; typedef struct _PEB { @@ -327,69 +359,70 @@ typedef struct _NT_TIB { } NT_TIB, *PNT_TIB; typedef struct _TEB { - NT_TIB Tib; /* 000 */ - PVOID EnvironmentPointer; /* 01c */ - CLIENT_ID ClientId; /* 020 */ - PVOID ActiveRpcHandle; /* 028 */ - PVOID ThreadLocalStoragePointer; /* 02c */ - PPEB Peb; /* 030 */ - ULONG LastErrorValue; /* 034 */ - ULONG CountOfOwnedCriticalSections; /* 038 */ - PVOID CsrClientThread; /* 03c */ - PVOID Win32ThreadInfo; /* 040 */ - ULONG Win32ClientInfo[31]; /* 044 used for user32 private data in Wine */ - PVOID WOW32Reserved; /* 0c0 */ - ULONG CurrentLocale; /* 0c4 */ - ULONG FpSoftwareStatusRegister; /* 0c8 */ - PVOID SystemReserved1[54]; /* 0cc used for kernel32 private data in Wine */ - PVOID Spare1; /* 1a4 */ - LONG ExceptionCode; /* 1a8 */ - PVOID ActivationContextStackPointer; /* 1a8/02c8 */ - BYTE SpareBytes1[36]; /* 1ac */ - PVOID SystemReserved2[10]; /* 1d4 used for ntdll private data in Wine */ - GDI_TEB_BATCH GdiTebBatch; /* 1fc */ - ULONG gdiRgn; /* 6dc */ - ULONG gdiPen; /* 6e0 */ - ULONG gdiBrush; /* 6e4 */ - CLIENT_ID RealClientId; /* 6e8 */ - HANDLE GdiCachedProcessHandle; /* 6f0 */ - ULONG GdiClientPID; /* 6f4 */ - ULONG GdiClientTID; /* 6f8 */ - PVOID GdiThreadLocaleInfo; /* 6fc */ - PVOID UserReserved[5]; /* 700 */ - PVOID glDispatchTable[280]; /* 714 */ - ULONG glReserved1[26]; /* b74 */ - PVOID glReserved2; /* bdc */ - PVOID glSectionInfo; /* be0 */ - PVOID glSection; /* be4 */ - PVOID glTable; /* be8 */ - PVOID glCurrentRC; /* bec */ - PVOID glContext; /* bf0 */ - ULONG LastStatusValue; /* bf4 */ - UNICODE_STRING StaticUnicodeString; /* bf8 used by advapi32 */ - WCHAR StaticUnicodeBuffer[261]; /* c00 used by advapi32 */ - PVOID DeallocationStack; /* e0c */ - PVOID TlsSlots[64]; /* e10 */ - LIST_ENTRY TlsLinks; /* f10 */ - PVOID Vdm; /* f18 */ - PVOID ReservedForNtRpc; /* f1c */ - PVOID DbgSsReserved[2]; /* f20 */ - ULONG HardErrorDisabled; /* f28 */ - PVOID Instrumentation[16]; /* f2c */ - PVOID WinSockData; /* f6c */ - ULONG GdiBatchCount; /* f70 */ - ULONG Spare2; /* f74 */ - ULONG Spare3; /* f78 */ - ULONG Spare4; /* f7c */ - PVOID ReservedForOle; /* f80 */ - ULONG WaitingOnLoaderLock; /* f84 */ - PVOID Reserved5[3]; /* f88 */ - PVOID *TlsExpansionSlots; /* f94 */ - // Custom - unsigned short hostFsSelector; - unsigned short hostGsSelector; - bool hostSegmentsValid; - unsigned char padding[3]; + NT_TIB Tib; + PVOID EnvironmentPointer; + CLIENT_ID ClientId; + PVOID ActiveRpcHandle; + PVOID ThreadLocalStoragePointer; + PPEB Peb; + ULONG LastErrorValue; + ULONG CountOfOwnedCriticalSections; + PVOID CsrClientThread; + PVOID Win32ThreadInfo; + ULONG Win32ClientInfo[31]; /* used for user32 private data in Wine */ + PVOID WOW32Reserved; + ULONG CurrentLocale; + ULONG FpSoftwareStatusRegister; + PVOID SystemReserved1[54]; /* used for kernel32 private data in Wine */ + PVOID Spare1; + LONG ExceptionCode; + PVOID ActivationContextStackPointer; + BYTE SpareBytes1[36]; + PVOID SystemReserved2[10]; /* used for ntdll private data in Wine */ + GDI_TEB_BATCH GdiTebBatch; + ULONG gdiRgn; + ULONG gdiPen; + ULONG gdiBrush; + CLIENT_ID RealClientId; + HANDLE GdiCachedProcessHandle; + ULONG GdiClientPID; + ULONG GdiClientTID; + PVOID GdiThreadLocaleInfo; + PVOID UserReserved[5]; + PVOID glDispatchTable[280]; + ULONG glReserved1[26]; + PVOID glReserved2; + PVOID glSectionInfo; + PVOID glSection; + PVOID glTable; + PVOID glCurrentRC; + PVOID glContext; + ULONG LastStatusValue; + UNICODE_STRING StaticUnicodeString; + WCHAR StaticUnicodeBuffer[261]; + PVOID DeallocationStack; + PVOID TlsSlots[64]; + LIST_ENTRY TlsLinks; + PVOID Vdm; + PVOID ReservedForNtRpc; + PVOID DbgSsReserved[2]; + ULONG HardErrorDisabled; + PVOID Instrumentation[16]; + PVOID WinSockData; + ULONG GdiBatchCount; + ULONG Spare2; + ULONG Spare3; + ULONG Spare4; + PVOID ReservedForOle; + ULONG WaitingOnLoaderLock; + PVOID Reserved5[3]; + PVOID *TlsExpansionSlots; + // wibo + WORD HostFsSelector; + WORD HostGsSelector; + PVOID HostStackBase; + PVOID HostStackLimit; + PVOID HostStackPointer; } TEB, *PTEB; #ifndef offsetof diff --git a/test/test_findfile.c b/test/test_findfile.c index 93c6f01..b73bcf8 100644 --- a/test/test_findfile.c +++ b/test/test_findfile.c @@ -39,6 +39,8 @@ static void create_file_with_content(const char *path, const char *content) { } static void setup_fixture(void) { + TEST_CHECK_EQ(2, sizeof(wint_t)); + DWORD len = GetCurrentDirectoryA(sizeof(g_original_dir), g_original_dir); TEST_CHECK(len > 0 && len < sizeof(g_original_dir)); diff --git a/tools/gen_trampolines.py b/tools/gen_trampolines.py index 2a408a0..8f4a1c0 100644 --- a/tools/gen_trampolines.py +++ b/tools/gen_trampolines.py @@ -15,9 +15,14 @@ if __name__ == "__main__": script_venv.bootstrap_venv(__file__) import argparse +import ctypes import os import sys import tempfile +from dataclasses import dataclass, field +from enum import IntEnum +from pathlib import Path +from typing import Iterable, List, Optional from clang.cindex import ( Config, @@ -25,10 +30,12 @@ from clang.cindex import ( CursorKind, Index, TranslationUnit, + TypeKind, + conf, +) +from clang.cindex import ( + Type as CXType, ) -from dataclasses import dataclass -from pathlib import Path -from typing import Iterable, List, Optional # Allow libclang path to be specified via environment variable if "LIBCLANG_PATH" in os.environ: @@ -43,13 +50,75 @@ if "LIBCLANG_PATH" in os.environ: ) +class CallingConv(IntEnum): + """CXCallingConv enum values from clang-c/Index.h""" + + DEFAULT = 0 + C = 1 + X86_STDCALL = 2 + X86_FASTCALL = 3 + X86_THISCALL = 4 + X86_PASCAL = 5 + AAPCS = 6 + AAPCS_VFP = 7 + X86_REGCALL = 8 + INTELOCLBICC = 9 + WIN64 = 10 + X86_64_WIN64 = 11 + X86_64_SYSV = 12 + X86_VECTORCALL = 13 + SWIFT = 14 + PRESERVEMOST = 15 + PRESERVEALL = 16 + AARCH64_VECTORCALL = 17 + SWIFTASYNC = 18 + AARCH64_SVEPCS = 19 + M68K_RTD = 20 + INVALID = 100 + UNEXPOSED = 200 + + +# Register the clang_getFunctionTypeCallingConv function +_get_calling_conv = conf.lib.clang_getFunctionTypeCallingConv +_get_calling_conv.argtypes = [CXType] +_get_calling_conv.restype = ctypes.c_int + + +def _get_function_calling_conv(func_type: CXType) -> CallingConv: + """ + Get the calling convention of a function type. + """ + return CallingConv(_get_calling_conv(func_type)) + + +@dataclass +class ArgInfo: + size: int + slot_size: int + primitive: bool + sign_extended: bool + type_str: str + + @dataclass class FuncInfo: qualified_ns: str name: str mangled: str - argc: int - stdcall: bool + source_cc: CallingConv + target_cc: CallingConv + variadic: bool + args: List[ArgInfo] = field(default_factory=list) + + +@dataclass +class TypedefInfo: + name: str + source_cc: CallingConv + target_cc: CallingConv + variadic: bool + return_type: str + args: List[ArgInfo] = field(default_factory=list) def parse_tu( @@ -89,15 +158,85 @@ def _cursor_namespace(cursor: Cursor) -> List[str]: return list(reversed(ns)) -def _has_stdcall_annotation(func: Cursor) -> bool: +def _source_cc_from_annotations(func: Cursor) -> CallingConv: for child in func.get_children(): - if child.kind == CursorKind.ANNOTATE_ATTR and child.spelling == "CC:stdcall": - return True + if child.kind == CursorKind.ANNOTATE_ATTR: + if child.spelling == "CC:fastcall": + return CallingConv.X86_FASTCALL + elif child.spelling == "CC:stdcall": + return CallingConv.X86_STDCALL + elif child.spelling == "CC:cdecl": + return CallingConv.C + return CallingConv.DEFAULT + + +def _is_handle_typedef(arg_type: CXType) -> bool: + """Check if a type is a HANDLE-like typedef (HWND, HINSTANCE, etc.).""" + t = arg_type + # Trace through ELABORATED and TYPEDEF to find the original typedef name + while t.kind == TypeKind.ELABORATED or t.kind == TypeKind.TYPEDEF: + if t.kind == TypeKind.TYPEDEF: + decl = t.get_declaration() + name = decl.spelling + # Windows HANDLE types conventionally start with 'H' + if name and name.startswith("H") and name.isupper(): + return True + t = decl.underlying_typedef_type + elif t.kind == TypeKind.ELABORATED: + named = t.get_named_type() + if named is None: + break + t = named + else: + break return False -def _arg_count(func: Cursor) -> int: - return sum(1 for _ in func.type.argument_types()) +SIGNED_KINDS = [ + TypeKind.SCHAR, + TypeKind.CHAR_S, + TypeKind.SHORT, + TypeKind.INT, + TypeKind.LONG, + TypeKind.LONGLONG, + TypeKind.INT128, +] + + +def _collect_args(func_type: CXType) -> List[ArgInfo]: + """Collect argument information for a function.""" + args: List[ArgInfo] = [] + for t in func_type.argument_types(): + size = t.get_size() + canonical = t.get_canonical() + + # Determine if primitive (not struct/union) + is_primitive = canonical.kind != TypeKind.RECORD + + # Determine if sign-extended + # Sign-extend signed integers and HANDLE-like typedefs + is_sign_extended = canonical in SIGNED_KINDS or _is_handle_typedef(t) + + # Calculate stack slot size + if size <= 4: + slot_size = 4 + elif size <= 8: + slot_size = 8 + else: + raise NotImplementedError( + f"Argument size {size} not supported for function {func_type.spelling}" + ) + + args.append( + ArgInfo( + size=size, + slot_size=slot_size, + primitive=is_primitive, + sign_extended=is_sign_extended, + type_str=_type_to_string(t), + ) + ) + return args def collect_functions(tu: TranslationUnit, ns_filter: Optional[str]) -> List[FuncInfo]: @@ -109,83 +248,267 @@ def collect_functions(tu: TranslationUnit, ns_filter: Optional[str]) -> List[Fun ns_parts = _cursor_namespace(node) if want_ns is not None and ns_parts != want_ns: return - name = node.spelling or "" - mangled = getattr(node, "mangled_name", None) or "" - if not name or not mangled: + name = node.spelling + if not name: return + source_cc = _source_cc_from_annotations(node) + if source_cc == CallingConv.DEFAULT: + return # No CC annotation; skip out[name] = FuncInfo( qualified_ns="::".join(ns_parts), name=name, - mangled=mangled, - argc=_arg_count(node), - stdcall=_has_stdcall_annotation(node), + mangled=node.mangled_name or name, + args=_collect_args(node.type), + source_cc=source_cc, + target_cc=_get_function_calling_conv(node.type), + variadic=node.type.is_function_variadic(), ) - # Recurse into children where it makes sense + + # Recurse into children if node.kind in (CursorKind.TRANSLATION_UNIT, CursorKind.NAMESPACE): for c in node.get_children(): visit(c) - visit(tu.cursor) + if tu.cursor is not None: + visit(tu.cursor) return sorted(out.values(), key=lambda f: f.name) -def emit_x86_asm_trampolines(dll: str, funcs: Iterable[FuncInfo]) -> str: - lines: List[str] = [] - lines.append("#\tAuto-generated trampolines; DO NOT EDIT.") - lines.append(".section .note.GNU-stack, \"\", @progbits") - lines.append(".text") - for f in funcs: - name = f.name - mangled = f.mangled - # Ensure ms_abi is encoded for stdcall function-pointer types to match GCC - # mangled = mangled.replace("U7stdcall", "U7stdcallU6ms_abi") - tramp = f"thunk_{dll}_{name}" - lines.append("") - lines.append(f".globl {tramp}") - lines.append(f".type {tramp}, @function") - lines.append(f"{tramp}:") - argc = int(f.argc or 0) - # Calculate number of stack args (fastcall uses ECX/EDX for first 2) - stack_argc = max(0, argc - 2) - stack_bytes = stack_argc * 4 - # Use frame pointer for clean alignment and argument access - lines.append("\tpush %ebp") - lines.append("\tmovl %esp, %ebp") - # Align stack: we want ESP = 16n before the call, - # so that after call pushes return address, callee sees ESP = 16n - 4 - # After pushing stack_bytes worth of args, we need ESP = 16n + stack_bytes - if stack_bytes > 0: - lines.append(f"\tleal -{stack_bytes}(%ebp), %esp") - lines.append("\tandl $0xFFFFFFF0, %esp") - lines.append(f"\taddl ${stack_bytes}, %esp") - else: - # No stack args, just align to 16n for the call - lines.append("\tandl $0xFFFFFFF0, %esp") - # Move first two args into ECX/EDX for fastcall - if argc >= 1: - lines.append("\tmovl 8(%ebp), %ecx") - if argc >= 2: - lines.append("\tmovl 12(%ebp), %edx") - # Push remaining args (from last down to the 3rd) so layout matches fastcall - for i in range(argc, 2, -1): - off = 4 * (i + 1) # +1 because EBP offset includes pushed EBP - lines.append(f"\tpushl {off}(%ebp)") - # Call into fastcall stub - lines.append(f"\tcall {mangled}") - # Restore stack and frame pointer - lines.append("\tleave") - # Return to guest - argb = argc * 4 - if f.stdcall and argb: - lines.append(f"\tret ${argb}") +def _type_to_string(t: CXType) -> str: + """Convert a CXType to a C type string.""" + spelling = t.spelling + # Clean up common type spellings + spelling = ( + spelling.replace("struct ", "").replace("union ", "").replace("enum ", "") + ) + return spelling + + +def collect_typedefs(tu: TranslationUnit) -> List[TypedefInfo]: + """Collect function pointer typedefs and type aliases from the translation unit.""" + out: dict[str, TypedefInfo] = {} + + def process_function_pointer_type( + name: str, node: Cursor, func_type: CXType + ) -> None: + """Process a function pointer type and add it to the output.""" + if not name: + return + + # Determine calling convention + source_cc = _get_function_calling_conv(func_type) + target_cc = _source_cc_from_annotations(node) + if target_cc == CallingConv.DEFAULT: + return # No CC annotation; skip + + variadic = func_type.is_function_variadic() + args = _collect_args(func_type) + return_type = _type_to_string(func_type.get_result()) + + out[name] = TypedefInfo( + name=name, + source_cc=source_cc, + target_cc=target_cc, + variadic=variadic, + return_type=return_type, + args=args, + ) + + def visit(node: Cursor) -> None: + if node.kind == CursorKind.TYPEDEF_DECL: + name = node.spelling + if not name: + return + underlying = node.underlying_typedef_type + if underlying.kind == TypeKind.POINTER: + pointee = underlying.get_pointee() + if pointee.kind == TypeKind.FUNCTIONPROTO: + process_function_pointer_type(name, node, pointee) + + # Recurse into children + if node.kind in (CursorKind.TRANSLATION_UNIT, CursorKind.NAMESPACE): + for c in node.get_children(): + visit(c) + + if tu.cursor is not None: + visit(tu.cursor) + return sorted(out.values(), key=lambda t: t.name) + + +def emit_cc_thunk(f: FuncInfo | TypedefInfo, lines: List[str]): + if isinstance(f, TypedefInfo): + # Host-to-guest + target = "[ebp+8]" + arg_off = 12 + align = 0 + host_to_guest = True + elif isinstance(f, FuncInfo): + # Guest-to-host + target = f.mangled + arg_off = 8 + align = 16 + host_to_guest = False + + if f.variadic: + # Variadic functions are not yet supported for calling convention conversion. + assert f.source_cc == CallingConv.C and f.target_cc == CallingConv.C, ( + "Variadic functions must be cdecl" + ) + lines.append(f"\tjmp {target}") + return + + # Compute argument stack offsets + offsets: List[int] = [] + for arg in f.args: + offsets.append(arg_off) + arg_off += arg.slot_size + + reg_indices: List[int] = [] + if f.target_cc == CallingConv.X86_FASTCALL: + # Store the first two non-record 4-byte args in ECX/EDX for GCC/Clang x86 fastcall + if len(f.args) >= 1 and f.args[0].primitive and f.args[0].slot_size == 4: + reg_indices.append(0) # ECX + if len(f.args) >= 2 and f.args[1].primitive and f.args[1].slot_size == 4: + reg_indices.append(1) # EDX + elif f.target_cc == CallingConv.C or f.target_cc == CallingConv.X86_STDCALL: + # No register args for cdecl or stdcall + pass + else: + raise NotImplementedError( + f"Unsupported target calling convention {f.target_cc} for function {f.name}" + ) + + # Bytes we will push for the call (exclude args passed in registers) + stack_bytes = sum( + arg.slot_size for i, arg in enumerate(f.args) if i not in reg_indices + ) + + # Save frame pointer and use EBP for argument access + lines.append("\tpush ebp") + lines.append("\tmov ebp, esp") + + # Get current TIB + if host_to_guest: + lines.append("\tmov edx, [gs:currentThreadTeb@ntpoff]") + else: + lines.append("\tmov edx, [fs:0x18]") + # Save previous fs and gs + lines.append("\tmov cx, fs") + lines.append("\txchg cx, word ptr [edx+0xf98]") + lines.append("\tmov fs, cx") + lines.append("\tmov cx, gs") + lines.append("\txchg cx, word ptr [edx+0xf9a]") + lines.append("\tmov gs, cx") + + # TODO: switch stacks here + + # Allocate stack space for arguments + if stack_bytes > 0: + lines.append(f"\tsub esp, {stack_bytes}") + + # Align stack if needed (must be done after allocating args) + if align > 0: + lines.append(f"\tand esp, ~{align - 1}") + + # Load args into registers as needed + if len(reg_indices) > 0: + i = reg_indices[0] + offset = offsets[i] + lines.append(f"\tmov ecx, [ebp+{offset}]") + if len(reg_indices) > 1: + i = reg_indices[1] + offset = offsets[i] + lines.append(f"\tmov edx, [ebp+{offset}]") + + # Copy remaining args onto stack + cur_off = 0 + for i, arg in enumerate(f.args): + if i in reg_indices: + continue + base = offsets[i] + for part_off in range(0, arg.slot_size, 4): + lines.append(f"\tmov eax, [ebp+{base + part_off}]") + lines.append(f"\tmov [esp+{cur_off + part_off}], eax") + cur_off += arg.slot_size + + # Call into target + lines.append(f"\tcall {target}") + + # Restore segment registers + if host_to_guest: + lines.append("\tmov edx, [fs:0x18]") + else: + lines.append("\tmov edx, [gs:currentThreadTeb@ntpoff]") + lines.append("\tmov cx, fs") + lines.append("\txchg cx, word ptr [edx+0xf98]") + lines.append("\tmov fs, cx") + lines.append("\tmov cx, gs") + lines.append("\txchg cx, word ptr [edx+0xf9a]") + lines.append("\tmov gs, cx") + + # Restore stack and frame pointer + lines.append("\tleave") + + # Return to guest + if f.source_cc == CallingConv.X86_STDCALL: + ret_bytes = sum(arg.slot_size for arg in f.args) + if ret_bytes > 0: + lines.append(f"\tret {ret_bytes}") else: lines.append("\tret") - lines.append(f".size {tramp}, . - {tramp}") - return "\n".join(lines) + "\n" + elif f.source_cc == CallingConv.C: + lines.append("\tret") + else: + raise NotImplementedError( + f"Unsupported source calling convention {f.source_cc} for function {f.name}" + ) -def emit_header_mapping(dll: str, funcs: Iterable[FuncInfo]) -> str: - guard = f"WIBO_GEN_{dll.upper()}_TRAMPOLINES_H" +def emit_guest_to_host_thunks( + lines: List[str], dll: str, funcs: Iterable[FuncInfo] +) -> None: + for f in funcs: + thunk = f"thunk_{dll}_{f.name}" + lines.append("") + lines.append( + f"# {f.qualified_ns}::{f.name} (source_cc={f.source_cc.name}, target_cc={f.target_cc.name}, variadic={f.variadic})" + ) + for i, arg in enumerate(f.args): + lines.append( + f"\t# Arg {i} (slot_size={arg.slot_size}, primitive={arg.primitive}, sign_extended={arg.sign_extended})" + ) + lines.append(f".globl {thunk}") + lines.append(f".type {thunk}, @function") + lines.append(f"{thunk}:") + emit_cc_thunk(f, lines) + lines.append(f".size {thunk}, .-{thunk}") + + +def emit_host_to_guest_thunks( + lines: List[str], typedefs: Iterable[TypedefInfo] +) -> None: + for f in typedefs: + thunk = f"call_{f.name}" + lines.append("") + lines.append( + f"# {f.name} (target_cc={f.target_cc.name}, variadic={f.variadic})" + ) + for i, arg in enumerate(f.args): + lines.append( + f"\t# Arg {i} (slot_size={arg.slot_size}, primitive={arg.primitive}, sign_extended={arg.sign_extended})" + ) + lines.append(f".globl {thunk}") + lines.append(f".weak {thunk}") + lines.append(f".type {thunk}, @function") + lines.append(f"{thunk}:") + emit_cc_thunk(f, lines) + lines.append(f".size {thunk}, .-{thunk}") + + +def emit_header_mapping( + dll: str, funcs: Iterable[FuncInfo], typedefs: Iterable[TypedefInfo] +) -> str: + guard = f"WIBO_GEN_{dll.upper()}_THUNKS_H" lines: List[str] = [] lines.append("/* Auto-generated; DO NOT EDIT. */") lines.append(f"#ifndef {guard}") @@ -193,19 +516,36 @@ def emit_header_mapping(dll: str, funcs: Iterable[FuncInfo]) -> str: lines.append("#include ") lines.append("#include ") lines.append('#ifdef __cplusplus\nextern "C" {\n#endif') + + # Guest-to-host thunk functions for f in funcs: - tramp = f"thunk_{dll}_{f.name}" - lines.append(f"void {tramp}(void);") + thunk = f"thunk_{dll}_{f.name}" + lines.append(f"void {thunk}(void);") + + # Host-to-guest thunk functions + for td in typedefs: + thunk = f"call_{td.name}" + if td.variadic: + continue + + params = [f"{td.name} fn"] + for i, arg in enumerate(td.args): + params.append(f"{arg.type_str} arg{i}") + + param_list = ", ".join(params) + lines.append(f"{td.return_type} {thunk}({param_list});") + lines.append("#ifdef __cplusplus\n}\n#endif") lines.append("") # name->address helper for resolveByName - lines.append("static inline void *%s_trampoline_by_name(const char *name) {" % dll) + lines.append("static inline void *%sThunkByName(const char *name) {" % dll) for f in funcs: lines.append( f'\tif (strcmp(name, "{f.name}") == 0) return (void*)&thunk_{dll}_{f.name};' ) lines.append("\treturn NULL;") lines.append("}") + lines.append(f"#endif /* {guard} */\n") return "\n".join(lines) @@ -230,12 +570,23 @@ def main() -> int: target = "i686-pc-linux-gnu" if args.arch == "x86" else "x86_64-pc-linux-gnu" tu = parse_tu(args.headers, args.incs, target) funcs = collect_functions(tu, args.ns) - if not funcs: - sys.stderr.write("No functions found for generation.\n") + typedefs = collect_typedefs(tu) + + if not funcs and not typedefs: + sys.stderr.write("No functions or typedefs found for generation.\n") return 1 - asm = emit_x86_asm_trampolines(args.dll, funcs) - hdr = emit_header_mapping(args.dll, funcs) + lines: List[str] = [] + lines.append("# Auto-generated thunks; DO NOT EDIT.") + lines.append(".intel_syntax noprefix") + lines.append('.section .note.GNU-stack, "", @progbits') + lines.append(".text") + + emit_guest_to_host_thunks(lines, args.dll, funcs) + emit_host_to_guest_thunks(lines, typedefs) + + asm = "\n".join(lines) + "\n" + hdr = emit_header_mapping(args.dll, funcs, typedefs) args.out_asm.parent.mkdir(parents=True, exist_ok=True) args.out_hdr.parent.mkdir(parents=True, exist_ok=True)