mirror of
https://github.com/decompals/wibo.git
synced 2025-12-12 14:46:09 +00:00
Fully functional guest<->host trampolines
This commit is contained in:
@@ -170,7 +170,6 @@ add_executable(wibo
|
|||||||
src/access.cpp
|
src/access.cpp
|
||||||
src/async_io.cpp
|
src/async_io.cpp
|
||||||
src/async_io_epoll.cpp
|
src/async_io_epoll.cpp
|
||||||
src/context.cpp
|
|
||||||
src/errors.cpp
|
src/errors.cpp
|
||||||
src/files.cpp
|
src/files.cpp
|
||||||
src/handles.cpp
|
src/handles.cpp
|
||||||
@@ -260,6 +259,17 @@ wibo_codegen_module(NAME advapi32 HEADERS
|
|||||||
dll/advapi32/winreg.h
|
dll/advapi32/winreg.h
|
||||||
)
|
)
|
||||||
wibo_codegen_module(NAME bcrypt HEADERS dll/bcrypt.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
|
wibo_codegen_module(NAME kernel32 HEADERS
|
||||||
dll/kernel32/debugapi.h
|
dll/kernel32/debugapi.h
|
||||||
dll/kernel32/errhandlingapi.h
|
dll/kernel32/errhandlingapi.h
|
||||||
|
|||||||
@@ -7,6 +7,6 @@ extern const wibo::ModuleStub lib_advapi32 = {
|
|||||||
"advapi32",
|
"advapi32",
|
||||||
nullptr,
|
nullptr,
|
||||||
},
|
},
|
||||||
advapi32_trampoline_by_name,
|
advapi32ThunkByName,
|
||||||
nullptr,
|
nullptr,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
namespace advapi32 {
|
namespace advapi32 {
|
||||||
|
|
||||||
BOOL WIN_FUNC OpenProcessToken(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle) {
|
BOOL WINAPI OpenProcessToken(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("OpenProcessToken(%p, %u, %p)\n", ProcessHandle, DesiredAccess, TokenHandle);
|
DEBUG_LOG("OpenProcessToken(%p, %u, %p)\n", ProcessHandle, DesiredAccess, TokenHandle);
|
||||||
if (!TokenHandle) {
|
if (!TokenHandle) {
|
||||||
|
|||||||
@@ -4,6 +4,6 @@
|
|||||||
|
|
||||||
namespace advapi32 {
|
namespace advapi32 {
|
||||||
|
|
||||||
BOOL WIN_FUNC OpenProcessToken(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle);
|
BOOL WINAPI OpenProcessToken(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle);
|
||||||
|
|
||||||
} // namespace advapi32
|
} // namespace advapi32
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ bool writeLocalSystemSid(Sid *sid) {
|
|||||||
|
|
||||||
namespace advapi32 {
|
namespace advapi32 {
|
||||||
|
|
||||||
BOOL WIN_FUNC InitializeAcl(PACL pAcl, DWORD nAclLength, DWORD dwAclRevision) {
|
BOOL WINAPI InitializeAcl(PACL pAcl, DWORD nAclLength, DWORD dwAclRevision) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("InitializeAcl(%p, %u, %u)\n", pAcl, nAclLength, dwAclRevision);
|
DEBUG_LOG("InitializeAcl(%p, %u, %u)\n", pAcl, nAclLength, dwAclRevision);
|
||||||
if (!pAcl) {
|
if (!pAcl) {
|
||||||
@@ -133,7 +133,7 @@ BOOL WIN_FUNC InitializeAcl(PACL pAcl, DWORD nAclLength, DWORD dwAclRevision) {
|
|||||||
return TRUE;
|
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();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("AddAccessAllowedAce(%p, %u, 0x%x, %p)\n", pAcl, dwAceRevision, AccessMask, pSid);
|
DEBUG_LOG("AddAccessAllowedAce(%p, %u, 0x%x, %p)\n", pAcl, dwAceRevision, AccessMask, pSid);
|
||||||
if (!pAcl || !pSid) {
|
if (!pAcl || !pSid) {
|
||||||
@@ -202,7 +202,7 @@ BOOL WIN_FUNC AddAccessAllowedAce(PACL pAcl, DWORD dwAceRevision, DWORD AccessMa
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL WIN_FUNC FindFirstFreeAce(PACL pAcl, LPVOID *pAce) {
|
BOOL WINAPI FindFirstFreeAce(PACL pAcl, LPVOID *pAce) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("FindFirstFreeAce(%p, %p)\n", pAcl, pAce);
|
DEBUG_LOG("FindFirstFreeAce(%p, %p)\n", pAcl, pAce);
|
||||||
if (!pAce) {
|
if (!pAce) {
|
||||||
@@ -225,7 +225,7 @@ BOOL WIN_FUNC FindFirstFreeAce(PACL pAcl, LPVOID *pAce) {
|
|||||||
return TRUE;
|
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) {
|
LPBOOL lpbDaclDefaulted) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("GetSecurityDescriptorDacl(%p, %p, %p, %p)\n", pSecurityDescriptor, lpbDaclPresent, pDacl,
|
DEBUG_LOG("GetSecurityDescriptorDacl(%p, %p, %p, %p)\n", pSecurityDescriptor, lpbDaclPresent, pDacl,
|
||||||
@@ -262,7 +262,7 @@ BOOL WIN_FUNC GetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR pSecurityDescriptor
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
PSID_IDENTIFIER_AUTHORITY WIN_FUNC GetSidIdentifierAuthority(PSID pSid) {
|
PSID_IDENTIFIER_AUTHORITY WINAPI GetSidIdentifierAuthority(PSID pSid) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("GetSidIdentifierAuthority(%p)\n", pSid);
|
DEBUG_LOG("GetSidIdentifierAuthority(%p)\n", pSid);
|
||||||
if (!pSid) {
|
if (!pSid) {
|
||||||
@@ -277,7 +277,7 @@ PSID_IDENTIFIER_AUTHORITY WIN_FUNC GetSidIdentifierAuthority(PSID pSid) {
|
|||||||
return reinterpret_cast<PSID_IDENTIFIER_AUTHORITY>(&sid->IdentifierAuthority);
|
return reinterpret_cast<PSID_IDENTIFIER_AUTHORITY>(&sid->IdentifierAuthority);
|
||||||
}
|
}
|
||||||
|
|
||||||
PUCHAR WIN_FUNC GetSidSubAuthorityCount(PSID pSid) {
|
PUCHAR WINAPI GetSidSubAuthorityCount(PSID pSid) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("GetSidSubAuthorityCount(%p)\n", pSid);
|
DEBUG_LOG("GetSidSubAuthorityCount(%p)\n", pSid);
|
||||||
if (!pSid) {
|
if (!pSid) {
|
||||||
@@ -292,7 +292,7 @@ PUCHAR WIN_FUNC GetSidSubAuthorityCount(PSID pSid) {
|
|||||||
return &sid->SubAuthorityCount;
|
return &sid->SubAuthorityCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
PDWORD WIN_FUNC GetSidSubAuthority(PSID pSid, DWORD nSubAuthority) {
|
PDWORD WINAPI GetSidSubAuthority(PSID pSid, DWORD nSubAuthority) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("GetSidSubAuthority(%p, %u)\n", pSid, nSubAuthority);
|
DEBUG_LOG("GetSidSubAuthority(%p, %u)\n", pSid, nSubAuthority);
|
||||||
if (!pSid) {
|
if (!pSid) {
|
||||||
@@ -307,14 +307,14 @@ PDWORD WIN_FUNC GetSidSubAuthority(PSID pSid, DWORD nSubAuthority) {
|
|||||||
return &sid->SubAuthority[nSubAuthority];
|
return &sid->SubAuthority[nSubAuthority];
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL WIN_FUNC ImpersonateLoggedOnUser(HANDLE hToken) {
|
BOOL WINAPI ImpersonateLoggedOnUser(HANDLE hToken) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("STUB: ImpersonateLoggedOnUser(%p)\n", hToken);
|
DEBUG_LOG("STUB: ImpersonateLoggedOnUser(%p)\n", hToken);
|
||||||
(void)hToken;
|
(void)hToken;
|
||||||
return TRUE;
|
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) {
|
DWORD ImpersonationLevel, DWORD TokenType, PHANDLE phNewToken) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("DuplicateTokenEx(%p, 0x%x, %p, %u, %u, %p)\n", hExistingToken, dwDesiredAccess, lpTokenAttributes,
|
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;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL WIN_FUNC CopySid(DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid) {
|
BOOL WINAPI CopySid(DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("CopySid(%u, %p, %p)\n", nDestinationSidLength, pDestinationSid, pSourceSid);
|
DEBUG_LOG("CopySid(%u, %p, %p)\n", nDestinationSidLength, pDestinationSid, pSourceSid);
|
||||||
if (!pDestinationSid || !pSourceSid) {
|
if (!pDestinationSid || !pSourceSid) {
|
||||||
@@ -354,7 +354,7 @@ BOOL WIN_FUNC CopySid(DWORD nDestinationSidLength, PSID pDestinationSid, PSID pS
|
|||||||
return TRUE;
|
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();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("InitializeSid(%p, %p, %u)\n", sid, pIdentifierAuthority, nSubAuthorityCount);
|
DEBUG_LOG("InitializeSid(%p, %p, %u)\n", sid, pIdentifierAuthority, nSubAuthorityCount);
|
||||||
if (!sid || !pIdentifierAuthority) {
|
if (!sid || !pIdentifierAuthority) {
|
||||||
@@ -375,7 +375,7 @@ BOOL WIN_FUNC InitializeSid(PSID sid, PSID_IDENTIFIER_AUTHORITY pIdentifierAutho
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL WIN_FUNC EqualSid(PSID pSid1, PSID pSid2) {
|
BOOL WINAPI EqualSid(PSID pSid1, PSID pSid2) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("EqualSid(%p, %p)\n", pSid1, pSid2);
|
DEBUG_LOG("EqualSid(%p, %p)\n", pSid1, pSid2);
|
||||||
if (!pSid1 || !pSid2) {
|
if (!pSid1 || !pSid2) {
|
||||||
@@ -398,7 +398,7 @@ BOOL WIN_FUNC EqualSid(PSID pSid1, PSID pSid2) {
|
|||||||
return equal ? TRUE : FALSE;
|
return equal ? TRUE : FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL WIN_FUNC SetKernelObjectSecurity(HANDLE Handle, SECURITY_INFORMATION SecurityInformation,
|
BOOL WINAPI SetKernelObjectSecurity(HANDLE Handle, SECURITY_INFORMATION SecurityInformation,
|
||||||
PSECURITY_DESCRIPTOR SecurityDescriptor) {
|
PSECURITY_DESCRIPTOR SecurityDescriptor) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("STUB: SetKernelObjectSecurity(%p, 0x%x, %p)\n", Handle, SecurityInformation, SecurityDescriptor);
|
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;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL WIN_FUNC InitializeSecurityDescriptor(PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD dwRevision) {
|
BOOL WINAPI InitializeSecurityDescriptor(PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD dwRevision) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("InitializeSecurityDescriptor(%p, %u)\n", pSecurityDescriptor, dwRevision);
|
DEBUG_LOG("InitializeSecurityDescriptor(%p, %u)\n", pSecurityDescriptor, dwRevision);
|
||||||
if (!pSecurityDescriptor || dwRevision != SECURITY_DESCRIPTOR_REVISION) {
|
if (!pSecurityDescriptor || dwRevision != SECURITY_DESCRIPTOR_REVISION) {
|
||||||
@@ -432,7 +432,7 @@ BOOL WIN_FUNC InitializeSecurityDescriptor(PSECURITY_DESCRIPTOR pSecurityDescrip
|
|||||||
return TRUE;
|
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) {
|
BOOL bDaclDefaulted) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("SetSecurityDescriptorDacl(%p, %u, %p, %u)\n", pSecurityDescriptor, bDaclPresent, pDacl, bDaclDefaulted);
|
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;
|
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) {
|
LPVOID TokenInformation, DWORD TokenInformationLength, LPDWORD ReturnLength) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("STUB: GetTokenInformation(%p, %u, %p, %u, %p)\n", TokenHandle, TokenInformationClass, TokenInformation,
|
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;
|
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) {
|
DWORD BufferLength, PTOKEN_PRIVILEGES PreviousState, LPDWORD ReturnLength) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("AdjustTokenPrivileges(%p, %u, %p, %u, %p, %p)\n", TokenHandle, DisableAllPrivileges, NewState,
|
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;
|
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) {
|
LPVOID TokenInformation, DWORD TokenInformationLength) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("STUB: SetTokenInformation(%p, %u, %p, %u)\n", TokenHandle, TokenInformationClass, TokenInformation,
|
DEBUG_LOG("STUB: SetTokenInformation(%p, %u, %p, %u)\n", TokenHandle, TokenInformationClass, TokenInformation,
|
||||||
|
|||||||
@@ -83,30 +83,30 @@ enum TOKEN_INFORMATION_CLASS : DWORD {
|
|||||||
|
|
||||||
namespace advapi32 {
|
namespace advapi32 {
|
||||||
|
|
||||||
BOOL WIN_FUNC InitializeAcl(PACL pAcl, DWORD nAclLength, DWORD dwAclRevision);
|
BOOL WINAPI InitializeAcl(PACL pAcl, DWORD nAclLength, DWORD dwAclRevision);
|
||||||
BOOL WIN_FUNC AddAccessAllowedAce(PACL pAcl, DWORD dwAceRevision, DWORD AccessMask, PSID pSid);
|
BOOL WINAPI AddAccessAllowedAce(PACL pAcl, DWORD dwAceRevision, DWORD AccessMask, PSID pSid);
|
||||||
BOOL WIN_FUNC FindFirstFreeAce(PACL pAcl, LPVOID *pAce);
|
BOOL WINAPI FindFirstFreeAce(PACL pAcl, LPVOID *pAce);
|
||||||
PSID_IDENTIFIER_AUTHORITY WIN_FUNC GetSidIdentifierAuthority(PSID pSid);
|
PSID_IDENTIFIER_AUTHORITY WINAPI GetSidIdentifierAuthority(PSID pSid);
|
||||||
PUCHAR WIN_FUNC GetSidSubAuthorityCount(PSID pSid);
|
PUCHAR WINAPI GetSidSubAuthorityCount(PSID pSid);
|
||||||
PDWORD WIN_FUNC GetSidSubAuthority(PSID pSid, DWORD nSubAuthority);
|
PDWORD WINAPI GetSidSubAuthority(PSID pSid, DWORD nSubAuthority);
|
||||||
BOOL WIN_FUNC ImpersonateLoggedOnUser(HANDLE hToken);
|
BOOL WINAPI ImpersonateLoggedOnUser(HANDLE hToken);
|
||||||
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);
|
DWORD ImpersonationLevel, DWORD TokenType, PHANDLE phNewToken);
|
||||||
BOOL WIN_FUNC CopySid(DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid);
|
BOOL WINAPI CopySid(DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid);
|
||||||
BOOL WIN_FUNC InitializeSid(PSID sid, PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority, BYTE nSubAuthorityCount);
|
BOOL WINAPI InitializeSid(PSID sid, PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority, BYTE nSubAuthorityCount);
|
||||||
BOOL WIN_FUNC EqualSid(PSID pSid1, PSID pSid2);
|
BOOL WINAPI EqualSid(PSID pSid1, PSID pSid2);
|
||||||
BOOL WIN_FUNC GetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR pSecurityDescriptor, LPBOOL lpbDaclPresent, PACL *pDacl,
|
BOOL WINAPI GetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR pSecurityDescriptor, LPBOOL lpbDaclPresent, PACL *pDacl,
|
||||||
LPBOOL lpbDaclDefaulted);
|
LPBOOL lpbDaclDefaulted);
|
||||||
BOOL WIN_FUNC SetKernelObjectSecurity(HANDLE Handle, SECURITY_INFORMATION SecurityInformation,
|
BOOL WINAPI SetKernelObjectSecurity(HANDLE Handle, SECURITY_INFORMATION SecurityInformation,
|
||||||
PSECURITY_DESCRIPTOR SecurityDescriptor);
|
PSECURITY_DESCRIPTOR SecurityDescriptor);
|
||||||
BOOL WIN_FUNC InitializeSecurityDescriptor(PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD dwRevision);
|
BOOL WINAPI InitializeSecurityDescriptor(PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD dwRevision);
|
||||||
BOOL WIN_FUNC SetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR pSecurityDescriptor, BOOL bDaclPresent, PACL pDacl,
|
BOOL WINAPI SetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR pSecurityDescriptor, BOOL bDaclPresent, PACL pDacl,
|
||||||
BOOL bDaclDefaulted);
|
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);
|
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);
|
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);
|
LPVOID TokenInformation, DWORD TokenInformationLength);
|
||||||
|
|
||||||
} // namespace advapi32
|
} // namespace advapi32
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ LUID lookupOrGeneratePrivilegeLuid(const std::string &normalizedName) {
|
|||||||
|
|
||||||
namespace advapi32 {
|
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) {
|
LPWSTR ReferencedDomainName, LPDWORD cchReferencedDomainName, SID_NAME_USE *peUse) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
std::string systemName = lpSystemName ? wideStringToString(lpSystemName) : std::string("(null)");
|
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;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL WIN_FUNC LookupPrivilegeValueA(LPCSTR lpSystemName, LPCSTR lpName, PLUID lpLuid) {
|
BOOL WINAPI LookupPrivilegeValueA(LPCSTR lpSystemName, LPCSTR lpName, PLUID lpLuid) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("LookupPrivilegeValueA(%s, %s, %p)\n", lpSystemName ? lpSystemName : "(null)", lpName ? lpName : "(null)",
|
DEBUG_LOG("LookupPrivilegeValueA(%s, %s, %p)\n", lpSystemName ? lpSystemName : "(null)", lpName ? lpName : "(null)",
|
||||||
lpLuid);
|
lpLuid);
|
||||||
@@ -130,7 +130,7 @@ BOOL WIN_FUNC LookupPrivilegeValueA(LPCSTR lpSystemName, LPCSTR lpName, PLUID lp
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL WIN_FUNC LookupPrivilegeValueW(LPCWSTR lpSystemName, LPCWSTR lpName, PLUID lpLuid) {
|
BOOL WINAPI LookupPrivilegeValueW(LPCWSTR lpSystemName, LPCWSTR lpName, PLUID lpLuid) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("LookupPrivilegeValueW(%p, %p, %p)\n", lpSystemName, lpName, lpLuid);
|
DEBUG_LOG("LookupPrivilegeValueW(%p, %p, %p)\n", lpSystemName, lpName, lpLuid);
|
||||||
(void)lpSystemName; // only local lookup supported
|
(void)lpSystemName; // only local lookup supported
|
||||||
@@ -145,7 +145,7 @@ BOOL WIN_FUNC LookupPrivilegeValueW(LPCWSTR lpSystemName, LPCWSTR lpName, PLUID
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL WIN_FUNC GetUserNameA(LPSTR lpBuffer, LPDWORD pcbBuffer) {
|
BOOL WINAPI GetUserNameA(LPSTR lpBuffer, LPDWORD pcbBuffer) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("GetUserNameA(%p, %p)\n", lpBuffer, pcbBuffer);
|
DEBUG_LOG("GetUserNameA(%p, %p)\n", lpBuffer, pcbBuffer);
|
||||||
if (!pcbBuffer) {
|
if (!pcbBuffer) {
|
||||||
@@ -164,7 +164,7 @@ BOOL WIN_FUNC GetUserNameA(LPSTR lpBuffer, LPDWORD pcbBuffer) {
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL WIN_FUNC GetUserNameW(LPWSTR lpBuffer, LPDWORD pcbBuffer) {
|
BOOL WINAPI GetUserNameW(LPWSTR lpBuffer, LPDWORD pcbBuffer) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("GetUserNameW(%p, %p)\n", lpBuffer, pcbBuffer);
|
DEBUG_LOG("GetUserNameW(%p, %p)\n", lpBuffer, pcbBuffer);
|
||||||
if (!pcbBuffer) {
|
if (!pcbBuffer) {
|
||||||
|
|||||||
@@ -17,11 +17,11 @@ enum SID_NAME_USE : DWORD {
|
|||||||
|
|
||||||
namespace advapi32 {
|
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);
|
LPWSTR ReferencedDomainName, LPDWORD cchReferencedDomainName, SID_NAME_USE *peUse);
|
||||||
BOOL WIN_FUNC LookupPrivilegeValueA(LPCSTR lpSystemName, LPCSTR lpName, PLUID lpLuid);
|
BOOL WINAPI LookupPrivilegeValueA(LPCSTR lpSystemName, LPCSTR lpName, PLUID lpLuid);
|
||||||
BOOL WIN_FUNC LookupPrivilegeValueW(LPCWSTR lpSystemName, LPCWSTR lpName, PLUID lpLuid);
|
BOOL WINAPI LookupPrivilegeValueW(LPCWSTR lpSystemName, LPCWSTR lpName, PLUID lpLuid);
|
||||||
BOOL WIN_FUNC GetUserNameA(LPSTR lpBuffer, LPDWORD pcbBuffer);
|
BOOL WINAPI GetUserNameA(LPSTR lpBuffer, LPDWORD pcbBuffer);
|
||||||
BOOL WIN_FUNC GetUserNameW(LPWSTR lpBuffer, LPDWORD pcbBuffer);
|
BOOL WINAPI GetUserNameW(LPWSTR lpBuffer, LPDWORD pcbBuffer);
|
||||||
|
|
||||||
} // namespace advapi32
|
} // namespace advapi32
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ DWORD hashSizeForAlgid(ALG_ID algid) {
|
|||||||
|
|
||||||
namespace advapi32 {
|
namespace advapi32 {
|
||||||
|
|
||||||
BOOL WIN_FUNC CryptReleaseContext(HCRYPTPROV hProv, DWORD dwFlags) {
|
BOOL WINAPI CryptReleaseContext(HCRYPTPROV hProv, DWORD dwFlags) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("STUB: CryptReleaseContext(%p, %u)\n", reinterpret_cast<void *>(static_cast<uintptr_t>(hProv)), dwFlags);
|
DEBUG_LOG("STUB: CryptReleaseContext(%p, %u)\n", reinterpret_cast<void *>(static_cast<uintptr_t>(hProv)), dwFlags);
|
||||||
(void)hProv;
|
(void)hProv;
|
||||||
@@ -68,7 +68,7 @@ BOOL WIN_FUNC CryptReleaseContext(HCRYPTPROV hProv, DWORD dwFlags) {
|
|||||||
return TRUE;
|
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) {
|
DWORD dwFlags) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("STUB: CryptAcquireContextW(%p, %p, %p, %u, %u)\n", phProv, pszContainer, pszProvider, dwProvType,
|
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;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL WIN_FUNC CryptGenRandom(HCRYPTPROV hProv, DWORD dwLen, BYTE *pbBuffer) {
|
BOOL WINAPI CryptGenRandom(HCRYPTPROV hProv, DWORD dwLen, BYTE *pbBuffer) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("CryptGenRandom(%p)\n", reinterpret_cast<void *>(static_cast<uintptr_t>(hProv)));
|
DEBUG_LOG("CryptGenRandom(%p)\n", reinterpret_cast<void *>(static_cast<uintptr_t>(hProv)));
|
||||||
(void)hProv;
|
(void)hProv;
|
||||||
@@ -101,7 +101,7 @@ BOOL WIN_FUNC CryptGenRandom(HCRYPTPROV hProv, DWORD dwLen, BYTE *pbBuffer) {
|
|||||||
return TRUE;
|
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();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("CryptCreateHash(%p, %u, %p, %u, %p)\n", reinterpret_cast<void *>(static_cast<uintptr_t>(hProv)), Algid,
|
DEBUG_LOG("CryptCreateHash(%p, %u, %p, %u, %p)\n", reinterpret_cast<void *>(static_cast<uintptr_t>(hProv)), Algid,
|
||||||
reinterpret_cast<void *>(static_cast<uintptr_t>(hKey)), dwFlags, phHash);
|
reinterpret_cast<void *>(static_cast<uintptr_t>(hKey)), dwFlags, phHash);
|
||||||
@@ -133,7 +133,7 @@ BOOL WIN_FUNC CryptCreateHash(HCRYPTPROV hProv, ALG_ID Algid, HCRYPTKEY hKey, DW
|
|||||||
return TRUE;
|
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();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("CryptHashData(%p, %p, %u, %u)\n", reinterpret_cast<void *>(static_cast<uintptr_t>(hHash)), pbData,
|
DEBUG_LOG("CryptHashData(%p, %p, %u, %u)\n", reinterpret_cast<void *>(static_cast<uintptr_t>(hHash)), pbData,
|
||||||
dwDataLen, dwFlags);
|
dwDataLen, dwFlags);
|
||||||
@@ -156,7 +156,7 @@ BOOL WIN_FUNC CryptHashData(HCRYPTHASH hHash, const BYTE *pbData, DWORD dwDataLe
|
|||||||
return TRUE;
|
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();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("CryptGetHashParam(%p, %u, %p, %p, %u)\n", reinterpret_cast<void *>(static_cast<uintptr_t>(hHash)),
|
DEBUG_LOG("CryptGetHashParam(%p, %u, %p, %p, %u)\n", reinterpret_cast<void *>(static_cast<uintptr_t>(hHash)),
|
||||||
dwParam, pbData, pdwDataLen, dwFlags);
|
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();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("CryptDestroyHash(%p)\n", reinterpret_cast<void *>(static_cast<uintptr_t>(hHash)));
|
DEBUG_LOG("CryptDestroyHash(%p)\n", reinterpret_cast<void *>(static_cast<uintptr_t>(hHash)));
|
||||||
auto *hash = hashObjectFromHandle(hHash);
|
auto *hash = hashObjectFromHandle(hHash);
|
||||||
|
|||||||
@@ -16,13 +16,13 @@ constexpr DWORD HP_HASHSIZE = 0x00000004;
|
|||||||
|
|
||||||
namespace advapi32 {
|
namespace advapi32 {
|
||||||
|
|
||||||
BOOL WIN_FUNC CryptReleaseContext(HCRYPTPROV hProv, DWORD dwFlags);
|
BOOL WINAPI CryptReleaseContext(HCRYPTPROV hProv, DWORD dwFlags);
|
||||||
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);
|
DWORD dwFlags);
|
||||||
BOOL WIN_FUNC CryptGenRandom(HCRYPTPROV hProv, DWORD dwLen, BYTE *pbBuffer);
|
BOOL WINAPI CryptGenRandom(HCRYPTPROV hProv, DWORD dwLen, BYTE *pbBuffer);
|
||||||
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);
|
||||||
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);
|
||||||
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);
|
||||||
BOOL WIN_FUNC CryptDestroyHash(HCRYPTHASH hHash);
|
BOOL WINAPI CryptDestroyHash(HCRYPTHASH hHash);
|
||||||
|
|
||||||
} // namespace advapi32
|
} // namespace advapi32
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ bool isPredefinedKeyHandle(HKEY hKey) {
|
|||||||
|
|
||||||
namespace advapi32 {
|
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,
|
REGSAM samDesired, void *lpSecurityAttributes, PHKEY phkResult,
|
||||||
LPDWORD lpdwDisposition) {
|
LPDWORD lpdwDisposition) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
@@ -192,7 +192,7 @@ LSTATUS WIN_FUNC RegCreateKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD Reserved, LP
|
|||||||
return ERROR_SUCCESS;
|
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,
|
REGSAM samDesired, void *lpSecurityAttributes, PHKEY phkResult,
|
||||||
LPDWORD lpdwDisposition) {
|
LPDWORD lpdwDisposition) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
@@ -212,7 +212,7 @@ LSTATUS WIN_FUNC RegCreateKeyExA(HKEY hKey, LPCSTR lpSubKey, DWORD Reserved, LPS
|
|||||||
lpSecurityAttributes, phkResult, lpdwDisposition);
|
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();
|
HOST_CONTEXT_GUARD();
|
||||||
std::string subKeyString = lpSubKey ? wideStringToString(lpSubKey) : std::string("(null)");
|
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);
|
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;
|
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();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("RegOpenKeyExA(%p, %s, %u, 0x%x, %p)\n", hKey, lpSubKey ? lpSubKey : "(null)", ulOptions, samDesired,
|
DEBUG_LOG("RegOpenKeyExA(%p, %s, %u, 0x%x, %p)\n", hKey, lpSubKey ? lpSubKey : "(null)", ulOptions, samDesired,
|
||||||
phkResult);
|
phkResult);
|
||||||
@@ -282,7 +282,7 @@ LSTATUS WIN_FUNC RegOpenKeyExA(HKEY hKey, LPCSTR lpSubKey, DWORD ulOptions, REGS
|
|||||||
return RegOpenKeyExW(hKey, widePtr, ulOptions, samDesired, phkResult);
|
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) {
|
LPDWORD lpcbData) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
std::string valueName = lpValueName ? wideStringToString(lpValueName) : std::string("(default)");
|
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;
|
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) {
|
LPDWORD lpcbData) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("RegQueryValueExA(%p, %s, %p, %p, %p, %p)\n", hKey, lpValueName ? lpValueName : "(null)", lpReserved,
|
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);
|
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) {
|
LPWSTR lpClass, LPDWORD lpcchClass, FILETIME *lpftLastWriteTime) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("RegEnumKeyExW(%p, %u, %p, %p, %p, %p, %p, %p)\n", hKey, dwIndex, lpName, lpcchName, lpReserved, lpClass,
|
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;
|
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) {
|
LPSTR lpClass, LPDWORD lpcchClass, FILETIME *lpftLastWriteTime) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("RegEnumKeyExA(%p, %u, %p, %p, %p, %p, %p, %p)\n", hKey, dwIndex, lpName, lpcchName, lpReserved, lpClass,
|
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;
|
return ERROR_NO_MORE_ITEMS;
|
||||||
}
|
}
|
||||||
|
|
||||||
LSTATUS WIN_FUNC RegCloseKey(HKEY hKey) {
|
LSTATUS WINAPI RegCloseKey(HKEY hKey) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("RegCloseKey(%p)\n", hKey);
|
DEBUG_LOG("RegCloseKey(%p)\n", hKey);
|
||||||
if (isPredefinedKeyHandle(hKey)) {
|
if (isPredefinedKeyHandle(hKey)) {
|
||||||
|
|||||||
@@ -33,22 +33,22 @@ constexpr REGSAM KEY_WOW64_32KEY = 0x00000200;
|
|||||||
|
|
||||||
namespace advapi32 {
|
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,
|
REGSAM samDesired, void *lpSecurityAttributes, PHKEY phkResult,
|
||||||
LPDWORD lpdwDisposition);
|
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,
|
REGSAM samDesired, void *lpSecurityAttributes, PHKEY phkResult,
|
||||||
LPDWORD lpdwDisposition);
|
LPDWORD lpdwDisposition);
|
||||||
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);
|
||||||
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);
|
||||||
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);
|
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);
|
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);
|
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);
|
LPWSTR lpClass, LPDWORD lpcchClass, FILETIME *lpftLastWriteTime);
|
||||||
LSTATUS WIN_FUNC RegCloseKey(HKEY hKey);
|
LSTATUS WINAPI RegCloseKey(HKEY hKey);
|
||||||
|
|
||||||
} // namespace advapi32
|
} // namespace advapi32
|
||||||
|
|||||||
@@ -85,6 +85,6 @@ extern const wibo::ModuleStub lib_bcrypt = {
|
|||||||
"bcryptprimitives",
|
"bcryptprimitives",
|
||||||
nullptr,
|
nullptr,
|
||||||
},
|
},
|
||||||
bcrypt_trampoline_by_name,
|
bcryptThunkByName,
|
||||||
nullptr,
|
nullptr,
|
||||||
};
|
};
|
||||||
|
|||||||
264
dll/crt.cpp
264
dll/crt.cpp
@@ -1,5 +1,8 @@
|
|||||||
|
#include "crt.h"
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "context.h"
|
#include "context.h"
|
||||||
|
#include "crt_trampolines.h"
|
||||||
#include "kernel32/internal.h"
|
#include "kernel32/internal.h"
|
||||||
#include "modules.h"
|
#include "modules.h"
|
||||||
|
|
||||||
@@ -11,29 +14,6 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
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 {
|
namespace crt {
|
||||||
|
|
||||||
int _commode = 0;
|
int _commode = 0;
|
||||||
@@ -42,33 +22,24 @@ int _fmode = 0;
|
|||||||
std::vector<_PVFV> atexitFuncs;
|
std::vector<_PVFV> atexitFuncs;
|
||||||
_invalid_parameter_handler invalidParameterHandler = nullptr;
|
_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();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("_initterm(%p, %p)\n", ppfn, end);
|
DEBUG_LOG("_initterm(%p, %p)\n", ppfn, end);
|
||||||
auto *tib = wibo::getThreadTibForHost();
|
|
||||||
do {
|
do {
|
||||||
if (_PVFV pfn = *++ppfn) {
|
if (_PVFV pfn = *++ppfn) {
|
||||||
DEBUG_LOG("-> calling %p\n", pfn);
|
DEBUG_LOG("-> calling %p\n", pfn);
|
||||||
{
|
call__PVFV(pfn);
|
||||||
GUEST_CONTEXT_GUARD(tib);
|
|
||||||
pfn();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} while (ppfn < end);
|
} 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();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("_initterm_e(%p, %p)\n", ppfn, end);
|
DEBUG_LOG("_initterm_e(%p, %p)\n", ppfn, end);
|
||||||
auto *tib = wibo::getThreadTibForHost();
|
|
||||||
do {
|
do {
|
||||||
if (_PIFV pfn = *++ppfn) {
|
if (_PIFV pfn = *++ppfn) {
|
||||||
DEBUG_LOG("-> calling %p\n", pfn);
|
DEBUG_LOG("-> calling %p\n", pfn);
|
||||||
int err = 0;
|
int err = call__PIFV(pfn);
|
||||||
{
|
|
||||||
GUEST_CONTEXT_GUARD(tib);
|
|
||||||
err = pfn();
|
|
||||||
}
|
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -77,44 +48,44 @@ int WIN_ENTRY _initterm_e(const _PIFV *ppfn, const _PIFV *end) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WIN_ENTRY _set_app_type(_crt_app_type type) {
|
void CDECL _set_app_type(_crt_app_type type) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("STUB: _set_app_type(%i)\n", type);
|
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();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("_set_fmode(%i)\n", mode);
|
DEBUG_LOG("_set_fmode(%i)\n", mode);
|
||||||
_fmode = mode;
|
_fmode = mode;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int *WIN_ENTRY __p__commode() {
|
int *CDECL __p__commode() {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("__p__commode()\n");
|
DEBUG_LOG("__p__commode()\n");
|
||||||
return &_commode;
|
return &_commode;
|
||||||
}
|
}
|
||||||
|
|
||||||
int *WIN_ENTRY __p__fmode() {
|
int *CDECL __p__fmode() {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("__p__fmode()\n");
|
DEBUG_LOG("__p__fmode()\n");
|
||||||
return &_fmode;
|
return &_fmode;
|
||||||
}
|
}
|
||||||
|
|
||||||
int WIN_ENTRY _crt_atexit(void (*func)()) {
|
int CDECL _crt_atexit(void (*func)()) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("_crt_atexit(%p)\n", func);
|
DEBUG_LOG("_crt_atexit(%p)\n", func);
|
||||||
atexitFuncs.push_back(func);
|
atexitFuncs.push_back(func);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int WIN_ENTRY _configure_narrow_argv(_crt_argv_mode mode) {
|
int CDECL _configure_narrow_argv(_crt_argv_mode mode) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("STUB: _configure_narrow_argv(%i)\n", mode);
|
DEBUG_LOG("STUB: _configure_narrow_argv(%i)\n", mode);
|
||||||
return 0;
|
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();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("STUB: _set_invalid_parameter_handler(%p)\n", newHandler);
|
DEBUG_LOG("STUB: _set_invalid_parameter_handler(%p)\n", newHandler);
|
||||||
_invalid_parameter_handler oldHandler = invalidParameterHandler;
|
_invalid_parameter_handler oldHandler = invalidParameterHandler;
|
||||||
@@ -122,213 +93,203 @@ _invalid_parameter_handler WIN_ENTRY _set_invalid_parameter_handler(_invalid_par
|
|||||||
return oldHandler;
|
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();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("STUB: _controlfp_s(%p, %u, %u)\n", currentControl, newControl, mask);
|
DEBUG_LOG("STUB: _controlfp_s(%p, %u, %u)\n", currentControl, newControl, mask);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int WIN_ENTRY _configthreadlocale(int per_thread_locale_type) {
|
int CDECL _configthreadlocale(int per_thread_locale_type) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("STUB: _configthreadlocale(%i)\n", per_thread_locale_type);
|
DEBUG_LOG("STUB: _configthreadlocale(%i)\n", per_thread_locale_type);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int WIN_ENTRY _initialize_narrow_environment() {
|
int CDECL _initialize_narrow_environment() {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("STUB: _initialize_narrow_environment()\n");
|
DEBUG_LOG("STUB: _initialize_narrow_environment()\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int WIN_ENTRY _set_new_mode(int newhandlermode) {
|
int CDECL _set_new_mode(int newhandlermode) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("STUB: _set_new_mode(%i)\n", newhandlermode);
|
DEBUG_LOG("STUB: _set_new_mode(%i)\n", newhandlermode);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
char **WIN_ENTRY _get_initial_narrow_environment() {
|
char **CDECL _get_initial_narrow_environment() {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("_get_initial_narrow_environment()\n");
|
DEBUG_LOG("_get_initial_narrow_environment()\n");
|
||||||
return environ;
|
return environ;
|
||||||
}
|
}
|
||||||
|
|
||||||
char ***WIN_ENTRY __p__environ() {
|
char ***CDECL __p__environ() {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("__p__environ()\n");
|
DEBUG_LOG("__p__environ()\n");
|
||||||
return &environ;
|
return &environ;
|
||||||
}
|
}
|
||||||
|
|
||||||
char ***WIN_ENTRY __p___argv() {
|
char ***CDECL __p___argv() {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("__p___argv()\n");
|
DEBUG_LOG("__p___argv()\n");
|
||||||
return &wibo::argv;
|
return &wibo::argv;
|
||||||
}
|
}
|
||||||
|
|
||||||
int *WIN_ENTRY __p___argc() {
|
int *CDECL __p___argc() {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("__p___argc()\n");
|
DEBUG_LOG("__p___argc()\n");
|
||||||
return &wibo::argc;
|
return &wibo::argc;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t WIN_ENTRY strlen(const char *str) {
|
SIZE_T CDECL strlen(const char *str) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
VERBOSE_LOG("strlen(%p)\n", str);
|
VERBOSE_LOG("strlen(%p)\n", str);
|
||||||
return ::strlen(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();
|
HOST_CONTEXT_GUARD();
|
||||||
VERBOSE_LOG("strcmp(%p, %p)\n", lhs, rhs);
|
VERBOSE_LOG("strcmp(%p, %p)\n", lhs, rhs);
|
||||||
return ::strcmp(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();
|
HOST_CONTEXT_GUARD();
|
||||||
VERBOSE_LOG("strncmp(%p, %p, %zu)\n", lhs, rhs, count);
|
VERBOSE_LOG("strncmp(%p, %p, %zu)\n", lhs, rhs, count);
|
||||||
return ::strncmp(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();
|
HOST_CONTEXT_GUARD();
|
||||||
VERBOSE_LOG("strcpy(%p, %p)\n", dest, src);
|
VERBOSE_LOG("strcpy(%p, %p)\n", dest, src);
|
||||||
return ::strcpy(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();
|
HOST_CONTEXT_GUARD();
|
||||||
VERBOSE_LOG("strncpy(%p, %p, %zu)\n", dest, src, count);
|
VERBOSE_LOG("strncpy(%p, %p, %zu)\n", dest, src, count);
|
||||||
return ::strncpy(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();
|
HOST_CONTEXT_GUARD();
|
||||||
VERBOSE_LOG("strrchr(%p, %i)\n", str, ch);
|
VERBOSE_LOG("strrchr(%p, %i)\n", str, ch);
|
||||||
return ::strrchr(str, ch);
|
return ::strrchr(str, ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *WIN_ENTRY malloc(size_t size) {
|
void *CDECL malloc(SIZE_T size) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
VERBOSE_LOG("malloc(%zu)\n", size);
|
VERBOSE_LOG("malloc(%zu)\n", size);
|
||||||
return ::malloc(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();
|
HOST_CONTEXT_GUARD();
|
||||||
VERBOSE_LOG("calloc(%zu, %zu)\n", count, size);
|
VERBOSE_LOG("calloc(%zu, %zu)\n", count, size);
|
||||||
return ::calloc(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();
|
HOST_CONTEXT_GUARD();
|
||||||
VERBOSE_LOG("realloc(%p, %zu)\n", ptr, newSize);
|
VERBOSE_LOG("realloc(%p, %zu)\n", ptr, newSize);
|
||||||
return ::realloc(ptr, newSize);
|
return ::realloc(ptr, newSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WIN_ENTRY free(void *ptr) {
|
void CDECL free(void *ptr) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
VERBOSE_LOG("free(%p)\n", ptr);
|
VERBOSE_LOG("free(%p)\n", ptr);
|
||||||
::free(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();
|
HOST_CONTEXT_GUARD();
|
||||||
VERBOSE_LOG("memcpy(%p, %p, %zu)\n", dest, src, count);
|
VERBOSE_LOG("memcpy(%p, %p, %zu)\n", dest, src, count);
|
||||||
return std::memcpy(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();
|
HOST_CONTEXT_GUARD();
|
||||||
VERBOSE_LOG("memmove(%p, %p, %zu)\n", dest, src, count);
|
VERBOSE_LOG("memmove(%p, %p, %zu)\n", dest, src, count);
|
||||||
return std::memmove(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();
|
HOST_CONTEXT_GUARD();
|
||||||
VERBOSE_LOG("memset(%p, %i, %zu)\n", dest, ch, count);
|
VERBOSE_LOG("memset(%p, %i, %zu)\n", dest, ch, count);
|
||||||
return std::memset(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();
|
HOST_CONTEXT_GUARD();
|
||||||
VERBOSE_LOG("memcmp(%p, %p, %zu)\n", lhs, rhs, count);
|
VERBOSE_LOG("memcmp(%p, %p, %zu)\n", lhs, rhs, count);
|
||||||
return std::memcmp(lhs, rhs, count);
|
return std::memcmp(lhs, rhs, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
int WIN_ENTRY __setusermatherr(void *handler) {
|
int CDECL __setusermatherr(void *handler) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("STUB: __setusermatherr(%p)\n", handler);
|
DEBUG_LOG("STUB: __setusermatherr(%p)\n", handler);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int WIN_ENTRY _initialize_onexit_table(void *table) {
|
int CDECL _initialize_onexit_table(void *table) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("STUB: _initialize_onexit_table(%p)\n", table);
|
DEBUG_LOG("STUB: _initialize_onexit_table(%p)\n", table);
|
||||||
wibo::registerOnExitTable(table);
|
wibo::registerOnExitTable(table);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int WIN_ENTRY _register_onexit_function(void *table, void (*func)()) {
|
int CDECL _register_onexit_function(void *table, void (*func)()) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("STUB: _register_onexit_function(%p, %p)\n", table, func);
|
DEBUG_LOG("STUB: _register_onexit_function(%p, %p)\n", table, func);
|
||||||
wibo::addOnExitFunction(table, func);
|
wibo::addOnExitFunction(table, func);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int WIN_ENTRY _execute_onexit_table(void *table) {
|
int CDECL _execute_onexit_table(void *table) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("STUB: _execute_onexit_table(%p)\n", table);
|
DEBUG_LOG("STUB: _execute_onexit_table(%p)\n", table);
|
||||||
wibo::executeOnExitTable(table);
|
wibo::executeOnExitTable(table);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WIN_ENTRY exit(int status) {
|
void CDECL exit(int status) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("exit(%i)\n", status);
|
DEBUG_LOG("exit(%i)\n", status);
|
||||||
auto *tib = wibo::getThreadTibForHost();
|
|
||||||
for (auto it = atexitFuncs.rbegin(); it != atexitFuncs.rend(); ++it) {
|
for (auto it = atexitFuncs.rbegin(); it != atexitFuncs.rend(); ++it) {
|
||||||
DEBUG_LOG("Calling atexit function %p\n", *it);
|
DEBUG_LOG("Calling atexit function %p\n", *it);
|
||||||
{
|
call__PVFV(*it);
|
||||||
GUEST_CONTEXT_GUARD(tib);
|
|
||||||
(*it)();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
kernel32::exitInternal(status);
|
kernel32::exitInternal(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WIN_ENTRY _cexit() {
|
void CDECL _cexit() {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("_cexit()\n");
|
DEBUG_LOG("_cexit()\n");
|
||||||
auto *tib = wibo::getThreadTibForHost();
|
|
||||||
for (auto it = atexitFuncs.rbegin(); it != atexitFuncs.rend(); ++it) {
|
for (auto it = atexitFuncs.rbegin(); it != atexitFuncs.rend(); ++it) {
|
||||||
DEBUG_LOG("Calling atexit function %p\n", *it);
|
DEBUG_LOG("Calling atexit function %p\n", *it);
|
||||||
{
|
call__PVFV(*it);
|
||||||
GUEST_CONTEXT_GUARD(tib);
|
|
||||||
(*it)();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WIN_ENTRY _exit(int status) {
|
void CDECL _exit(int status) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("_exit(%i)\n", status);
|
DEBUG_LOG("_exit(%i)\n", status);
|
||||||
kernel32::exitInternal(status);
|
kernel32::exitInternal(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WIN_ENTRY abort(void) {
|
void CDECL abort() {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("abort()\n");
|
DEBUG_LOG("abort()\n");
|
||||||
std::abort();
|
std::abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
using signal_handler = void (*)(int);
|
signal_handler CDECL signal(int signum, signal_handler handler) {
|
||||||
|
|
||||||
signal_handler WIN_ENTRY signal(int signum, signal_handler handler) {
|
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("signal(%i, %p)\n", signum, handler);
|
DEBUG_LOG("signal(%i, %p)\n", signum, handler);
|
||||||
return std::signal(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();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("__acrt_iob_func(%u)\n", index);
|
DEBUG_LOG("__acrt_iob_func(%u)\n", index);
|
||||||
if (index == 0)
|
if (index == 0)
|
||||||
@@ -340,15 +301,15 @@ void *WIN_ENTRY __acrt_iob_func(unsigned int index) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
int WIN_ENTRY __stdio_common_vfprintf(unsigned long long options, FILE *stream, const char *format, void *locale,
|
int CDECL __stdio_common_vfprintf(unsigned long long options, FILE *stream, const char *format, void *locale,
|
||||||
va_list args) {
|
va_list args) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("__stdio_common_vfprintf(%llu, %p, %s, %p, %p)\n", options, stream, format, locale, args);
|
DEBUG_LOG("__stdio_common_vfprintf(%llu, %p, %s, %p, %p)\n", options, stream, format, locale, args);
|
||||||
return vfprintf(stream, format, args);
|
return vfprintf(stream, format, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
int WIN_ENTRY __stdio_common_vsprintf(unsigned long long options, char *buffer, size_t len, const char *format,
|
int CDECL __stdio_common_vsprintf(unsigned long long options, char *buffer, SIZE_T len, const char *format,
|
||||||
void *locale, va_list args) {
|
void *locale, va_list args) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("__stdio_common_vsprintf(%llu, %p, %zu, %s, %p, ...)\n", options, buffer, len, format, locale);
|
DEBUG_LOG("__stdio_common_vsprintf(%llu, %p, %zu, %s, %p, ...)\n", options, buffer, len, format, locale);
|
||||||
if (!buffer || !format)
|
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);
|
int result = vsnprintf(buffer, len, format, args);
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
return -1;
|
return -1;
|
||||||
if (len > 0 && static_cast<size_t>(result) >= len)
|
if (len > 0 && static_cast<SIZE_T>(result) >= len)
|
||||||
return -1;
|
return -1;
|
||||||
return result;
|
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();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("qsort(%p, %zu, %zu, %p)\n", base, num, size, compar);
|
DEBUG_LOG("qsort(%p, %zu, %zu, %p)\n", base, num, size, compare);
|
||||||
::qsort(base, num, size, compar);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace crt
|
} // namespace crt
|
||||||
|
|
||||||
static void *resolveByName(const char *name) {
|
#include "crt_trampolines.h"
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern const wibo::ModuleStub lib_crt = {
|
extern const wibo::ModuleStub lib_crt = {
|
||||||
(const char *[]){
|
(const char *[]){
|
||||||
@@ -477,6 +363,6 @@ extern const wibo::ModuleStub lib_crt = {
|
|||||||
"api-ms-win-crt-utility-l1-1-0",
|
"api-ms-win-crt-utility-l1-1-0",
|
||||||
nullptr,
|
nullptr,
|
||||||
},
|
},
|
||||||
resolveByName,
|
crtThunkByName,
|
||||||
nullptr,
|
nullptr,
|
||||||
};
|
};
|
||||||
|
|||||||
76
dll/crt.h
Normal file
76
dll/crt.h
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
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
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
#include "modules.h"
|
#include "kernel32.h"
|
||||||
|
|
||||||
#include "kernel32_trampolines.h"
|
#include "modules.h"
|
||||||
|
|
||||||
extern const wibo::ModuleStub lib_kernel32 = {
|
extern const wibo::ModuleStub lib_kernel32 = {
|
||||||
(const char *[]){
|
(const char *[]){
|
||||||
"kernel32",
|
"kernel32",
|
||||||
nullptr,
|
nullptr,
|
||||||
},
|
},
|
||||||
kernel32_trampoline_by_name,
|
kernel32ThunkByName,
|
||||||
nullptr,
|
nullptr,
|
||||||
};
|
};
|
||||||
|
|||||||
29
dll/kernel32.h
Normal file
29
dll/kernel32.h
Normal file
@@ -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
|
||||||
@@ -14,34 +14,22 @@ UINT g_processErrorMode = 0;
|
|||||||
|
|
||||||
namespace kernel32 {
|
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)); }
|
void setLastErrorFromErrno() { setLastError(wibo::winErrorFromErrno(errno)); }
|
||||||
|
|
||||||
DWORD WINAPI GetLastError() {
|
DWORD WINAPI GetLastError() {
|
||||||
#ifndef NDEBUG
|
HOST_CONTEXT_GUARD();
|
||||||
{
|
DEBUG_LOG("GetLastError() -> %u\n", getLastError());
|
||||||
HOST_CONTEXT_GUARD();
|
return currentThreadTeb->LastErrorValue;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WINAPI SetLastError(DWORD dwErrCode) {
|
void WINAPI SetLastError(DWORD dwErrCode) {
|
||||||
#ifndef NDEBUG
|
HOST_CONTEXT_GUARD();
|
||||||
{
|
DEBUG_LOG("SetLastError(%u)\n", dwErrCode);
|
||||||
HOST_CONTEXT_GUARD();
|
currentThreadTeb->LastErrorValue = dwErrCode;
|
||||||
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");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WINAPI RaiseException(DWORD dwExceptionCode, DWORD dwExceptionFlags, DWORD nNumberOfArguments,
|
void WINAPI RaiseException(DWORD dwExceptionCode, DWORD dwExceptionFlags, DWORD nNumberOfArguments,
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ struct EXCEPTION_POINTERS {
|
|||||||
};
|
};
|
||||||
|
|
||||||
using PEXCEPTION_POINTERS = EXCEPTION_POINTERS *;
|
using PEXCEPTION_POINTERS = EXCEPTION_POINTERS *;
|
||||||
using PVECTORED_EXCEPTION_HANDLER = LONG(WIN_FUNC *)(PEXCEPTION_POINTERS ExceptionInfo);
|
typedef LONG (_CC_STDCALL *PVECTORED_EXCEPTION_HANDLER)(PEXCEPTION_POINTERS ExceptionInfo);
|
||||||
using LPTOP_LEVEL_EXCEPTION_FILTER = LONG(WIN_FUNC *)(PEXCEPTION_POINTERS ExceptionInfo);
|
typedef LONG (_CC_STDCALL *LPTOP_LEVEL_EXCEPTION_FILTER)(PEXCEPTION_POINTERS ExceptionInfo);
|
||||||
|
|
||||||
constexpr LONG EXCEPTION_CONTINUE_EXECUTION = static_cast<LONG>(-1);
|
constexpr LONG EXCEPTION_CONTINUE_EXECUTION = static_cast<LONG>(-1);
|
||||||
constexpr LONG EXCEPTION_CONTINUE_SEARCH = 0;
|
constexpr LONG EXCEPTION_CONTINUE_SEARCH = 0;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
using PFLS_CALLBACK_FUNCTION = void (*)(void *);
|
typedef void (_CC_STDCALL *PFLS_CALLBACK_FUNCTION)(void *);
|
||||||
constexpr DWORD FLS_OUT_OF_INDEXES = 0xFFFFFFFF;
|
constexpr DWORD FLS_OUT_OF_INDEXES = 0xFFFFFFFF;
|
||||||
|
|
||||||
namespace kernel32 {
|
namespace kernel32 {
|
||||||
|
|||||||
@@ -613,9 +613,8 @@ UINT WINAPI GetDriveTypeW(LPCWSTR lpRootPathName) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
BOOL WINAPI GetVolumeInformationA(LPCSTR lpRootPathName, LPSTR lpVolumeNameBuffer, DWORD nVolumeNameSize,
|
BOOL WINAPI GetVolumeInformationA(LPCSTR lpRootPathName, LPSTR lpVolumeNameBuffer, DWORD nVolumeNameSize,
|
||||||
LPDWORD lpVolumeSerialNumber, LPDWORD lpMaximumComponentLength,
|
LPDWORD lpVolumeSerialNumber, LPDWORD lpMaximumComponentLength,
|
||||||
LPDWORD lpFileSystemFlags, LPSTR lpFileSystemNameBuffer,
|
LPDWORD lpFileSystemFlags, LPSTR lpFileSystemNameBuffer, DWORD nFileSystemNameSize) {
|
||||||
DWORD nFileSystemNameSize) {
|
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("STUB: GetVolumeInformationA(%s)\n", lpRootPathName ? lpRootPathName : "(null)");
|
DEBUG_LOG("STUB: GetVolumeInformationA(%s)\n", lpRootPathName ? lpRootPathName : "(null)");
|
||||||
if (lpVolumeNameBuffer && nVolumeNameSize > 0) {
|
if (lpVolumeNameBuffer && nVolumeNameSize > 0) {
|
||||||
@@ -642,9 +641,8 @@ BOOL WINAPI GetVolumeInformationA(LPCSTR lpRootPathName, LPSTR lpVolumeNameBuffe
|
|||||||
}
|
}
|
||||||
|
|
||||||
BOOL WINAPI GetVolumeInformationW(LPCWSTR lpRootPathName, LPWSTR lpVolumeNameBuffer, DWORD nVolumeNameSize,
|
BOOL WINAPI GetVolumeInformationW(LPCWSTR lpRootPathName, LPWSTR lpVolumeNameBuffer, DWORD nVolumeNameSize,
|
||||||
LPDWORD lpVolumeSerialNumber, LPDWORD lpMaximumComponentLength,
|
LPDWORD lpVolumeSerialNumber, LPDWORD lpMaximumComponentLength,
|
||||||
LPDWORD lpFileSystemFlags, LPWSTR lpFileSystemNameBuffer,
|
LPDWORD lpFileSystemFlags, LPWSTR lpFileSystemNameBuffer, DWORD nFileSystemNameSize) {
|
||||||
DWORD nFileSystemNameSize) {
|
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("STUB: GetVolumeInformationW(%p)\n", lpRootPathName);
|
DEBUG_LOG("STUB: GetVolumeInformationW(%p)\n", lpRootPathName);
|
||||||
if (lpVolumeNameBuffer && nVolumeNameSize > 0) {
|
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,
|
BOOL WINAPI WriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten,
|
||||||
LPOVERLAPPED lpOverlapped) {
|
LPOVERLAPPED lpOverlapped) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("WriteFile(%p, %p, %u, %p, %p)\n", hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten,
|
DEBUG_LOG("WriteFile(%p, %p, %u, %p, %p)\n", hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten,
|
||||||
lpOverlapped);
|
lpOverlapped);
|
||||||
@@ -789,7 +787,7 @@ BOOL WINAPI FlushFileBuffers(HANDLE hFile) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
BOOL WINAPI ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead,
|
BOOL WINAPI ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead,
|
||||||
LPOVERLAPPED lpOverlapped) {
|
LPOVERLAPPED lpOverlapped) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("ReadFile(%p, %p, %u, %p, %p)\n", hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead,
|
DEBUG_LOG("ReadFile(%p, %p, %u, %p, %p)\n", hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead,
|
||||||
lpOverlapped);
|
lpOverlapped);
|
||||||
@@ -877,8 +875,8 @@ BOOL WINAPI ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
|
|||||||
}
|
}
|
||||||
|
|
||||||
HANDLE WINAPI CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
|
HANDLE WINAPI CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
|
||||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
|
LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
|
||||||
DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) {
|
DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
(void)hTemplateFile;
|
(void)hTemplateFile;
|
||||||
if (!lpFileName) {
|
if (!lpFileName) {
|
||||||
@@ -1104,8 +1102,8 @@ HANDLE WINAPI CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShar
|
|||||||
}
|
}
|
||||||
|
|
||||||
HANDLE WINAPI CreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
|
HANDLE WINAPI CreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
|
||||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
|
LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
|
||||||
DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) {
|
DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("CreateFileW -> ");
|
DEBUG_LOG("CreateFileW -> ");
|
||||||
if (!lpFileName) {
|
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,
|
BOOL WINAPI SetFilePointerEx(HANDLE hFile, LARGE_INTEGER liDistanceToMove, PLARGE_INTEGER lpNewFilePointer,
|
||||||
DWORD dwMoveMethod) {
|
DWORD dwMoveMethod) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
if (hFile == nullptr) {
|
if (hFile == nullptr) {
|
||||||
setLastError(ERROR_INVALID_HANDLE);
|
setLastError(ERROR_INVALID_HANDLE);
|
||||||
@@ -1239,7 +1237,7 @@ BOOL WINAPI SetFilePointerEx(HANDLE hFile, LARGE_INTEGER liDistanceToMove, PLARG
|
|||||||
// TODO access check
|
// TODO access check
|
||||||
std::lock_guard lk(file->m);
|
std::lock_guard lk(file->m);
|
||||||
off_t position = 0;
|
off_t position = 0;
|
||||||
off_t offset = static_cast<off_t>(liDistanceToMove);
|
off_t offset = static_cast<off_t>(liDistanceToMove.QuadPart);
|
||||||
if (dwMoveMethod == FILE_BEGIN) {
|
if (dwMoveMethod == FILE_BEGIN) {
|
||||||
position = offset;
|
position = offset;
|
||||||
} else if (dwMoveMethod == FILE_CURRENT) {
|
} else if (dwMoveMethod == FILE_CURRENT) {
|
||||||
@@ -1265,7 +1263,7 @@ BOOL WINAPI SetFilePointerEx(HANDLE hFile, LARGE_INTEGER liDistanceToMove, PLARG
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
if (lpNewFilePointer) {
|
if (lpNewFilePointer) {
|
||||||
*lpNewFilePointer = static_cast<LARGE_INTEGER>(position);
|
lpNewFilePointer->QuadPart = position;
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@@ -1361,7 +1359,7 @@ DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
BOOL WINAPI GetFileTime(HANDLE hFile, LPFILETIME lpCreationTime, LPFILETIME lpLastAccessTime,
|
BOOL WINAPI GetFileTime(HANDLE hFile, LPFILETIME lpCreationTime, LPFILETIME lpLastAccessTime,
|
||||||
LPFILETIME lpLastWriteTime) {
|
LPFILETIME lpLastWriteTime) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("GetFileTime(%p, %p, %p, %p)\n", hFile, lpCreationTime, lpLastAccessTime, lpLastWriteTime);
|
DEBUG_LOG("GetFileTime(%p, %p, %p, %p)\n", hFile, lpCreationTime, lpLastAccessTime, lpLastWriteTime);
|
||||||
HandleMeta meta{};
|
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,
|
BOOL WINAPI SetFileTime(HANDLE hFile, const FILETIME *lpCreationTime, const FILETIME *lpLastAccessTime,
|
||||||
const FILETIME *lpLastWriteTime) {
|
const FILETIME *lpLastWriteTime) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("SetFileTime(%p, %p, %p, %p)\n", hFile, lpCreationTime, lpLastAccessTime, lpLastWriteTime);
|
DEBUG_LOG("SetFileTime(%p, %p, %p, %p)\n", hFile, lpCreationTime, lpLastAccessTime, lpLastWriteTime);
|
||||||
HandleMeta meta{};
|
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,
|
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();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("FindFirstFileExA(%s, %d, %p, %d, %p, 0x%x)", lpFileName ? lpFileName : "(null)", fInfoLevelId,
|
DEBUG_LOG("FindFirstFileExA(%s, %d, %p, %d, %p, 0x%x)", lpFileName ? lpFileName : "(null)", fInfoLevelId,
|
||||||
lpFindFileData, fSearchOp, lpSearchFilter, dwAdditionalFlags);
|
lpFindFileData, fSearchOp, lpSearchFilter, dwAdditionalFlags);
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
#include "files.h"
|
#include "files.h"
|
||||||
#include "handles.h"
|
#include "handles.h"
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
#include "kernel32.h"
|
||||||
|
#include "kernel32_trampolines.h"
|
||||||
#include "modules.h"
|
#include "modules.h"
|
||||||
#include "processes.h"
|
#include "processes.h"
|
||||||
#include "strutil.h"
|
#include "strutil.h"
|
||||||
@@ -107,7 +109,7 @@ void threadCleanup(void *param) {
|
|||||||
}
|
}
|
||||||
g_currentThreadObject = nullptr;
|
g_currentThreadObject = nullptr;
|
||||||
wibo::notifyDllThreadDetach();
|
wibo::notifyDllThreadDetach();
|
||||||
wibo::setThreadTibForHost(nullptr);
|
currentThreadTeb = nullptr;
|
||||||
// TODO: mark mutexes owned by this thread as abandoned
|
// TODO: mark mutexes owned by this thread as abandoned
|
||||||
obj->cv.notify_all();
|
obj->cv.notify_all();
|
||||||
obj->notifyWaiters(false);
|
obj->notifyWaiters(false);
|
||||||
@@ -124,26 +126,12 @@ void *threadTrampoline(void *param) {
|
|||||||
g_currentThreadObject = data.obj;
|
g_currentThreadObject = data.obj;
|
||||||
|
|
||||||
// Install TIB
|
// Install TIB
|
||||||
TEB *threadTib = nullptr;
|
TEB *threadTib = wibo::allocateTib();
|
||||||
uint16_t previousFs = 0;
|
wibo::initializeTibStackInfo(threadTib);
|
||||||
uint16_t previousGs = 0;
|
if (!wibo::installTibForCurrentThread(threadTib)) {
|
||||||
if (wibo::tibSelector) {
|
fprintf(stderr, "!!! Failed to install TIB for new thread\n");
|
||||||
asm volatile("mov %%fs, %0" : "=r"(previousFs));
|
wibo::destroyTib(threadTib);
|
||||||
asm volatile("mov %%gs, %0" : "=r"(previousGs));
|
threadTib = nullptr;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait until resumed (if suspended at start)
|
// Wait until resumed (if suspended at start)
|
||||||
@@ -161,7 +149,7 @@ void *threadTrampoline(void *param) {
|
|||||||
DWORD result = 0;
|
DWORD result = 0;
|
||||||
if (data.entry) {
|
if (data.entry) {
|
||||||
GUEST_CONTEXT_GUARD(threadTib);
|
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);
|
DEBUG_LOG("Thread exiting with code %u\n", result);
|
||||||
{
|
{
|
||||||
@@ -220,8 +208,7 @@ HANDLE WINAPI GetCurrentThread() {
|
|||||||
return pseudoHandle;
|
return pseudoHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL WINAPI GetProcessAffinityMask(HANDLE hProcess, PDWORD_PTR lpProcessAffinityMask,
|
BOOL WINAPI GetProcessAffinityMask(HANDLE hProcess, PDWORD_PTR lpProcessAffinityMask, PDWORD_PTR lpSystemAffinityMask) {
|
||||||
PDWORD_PTR lpSystemAffinityMask) {
|
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("GetProcessAffinityMask(%p, %p, %p)\n", hProcess, lpProcessAffinityMask, lpSystemAffinityMask);
|
DEBUG_LOG("GetProcessAffinityMask(%p, %p, %p)\n", hProcess, lpProcessAffinityMask, lpSystemAffinityMask);
|
||||||
if (!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,
|
HANDLE WINAPI CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize,
|
||||||
LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags,
|
LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags,
|
||||||
LPDWORD lpThreadId) {
|
LPDWORD lpThreadId) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("CreateThread(%p, %zu, %p, %p, %u, %p)\n", lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter,
|
DEBUG_LOG("CreateThread(%p, %zu, %p, %p, %u, %p)\n", lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter,
|
||||||
dwCreationFlags, lpThreadId);
|
dwCreationFlags, lpThreadId);
|
||||||
@@ -574,7 +561,7 @@ DWORD WINAPI GetPriorityClass(HANDLE hProcess) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
BOOL WINAPI GetThreadTimes(HANDLE hThread, FILETIME *lpCreationTime, FILETIME *lpExitTime, FILETIME *lpKernelTime,
|
BOOL WINAPI GetThreadTimes(HANDLE hThread, FILETIME *lpCreationTime, FILETIME *lpExitTime, FILETIME *lpKernelTime,
|
||||||
FILETIME *lpUserTime) {
|
FILETIME *lpUserTime) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("GetThreadTimes(%p, %p, %p, %p, %p)\n", hThread, lpCreationTime, lpExitTime, lpKernelTime, lpUserTime);
|
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,
|
BOOL WINAPI CreateProcessA(LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes,
|
||||||
LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags,
|
LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags,
|
||||||
LPVOID lpEnvironment, LPCSTR lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo,
|
LPVOID lpEnvironment, LPCSTR lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo,
|
||||||
LPPROCESS_INFORMATION lpProcessInformation) {
|
LPPROCESS_INFORMATION lpProcessInformation) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("CreateProcessA %s \"%s\" %p %p %d 0x%x %p %s %p %p\n", lpApplicationName ? lpApplicationName : "<null>",
|
DEBUG_LOG("CreateProcessA %s \"%s\" %p %p %d 0x%x %p %s %p %p\n", lpApplicationName ? lpApplicationName : "<null>",
|
||||||
lpCommandLine ? lpCommandLine : "<null>", lpProcessAttributes, lpThreadAttributes, bInheritHandles,
|
lpCommandLine ? lpCommandLine : "<null>", 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,
|
BOOL WINAPI CreateProcessW(LPCWSTR lpApplicationName, LPWSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes,
|
||||||
LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags,
|
LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags,
|
||||||
LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo,
|
LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo,
|
||||||
LPPROCESS_INFORMATION lpProcessInformation) {
|
LPPROCESS_INFORMATION lpProcessInformation) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
std::string applicationUtf8;
|
std::string applicationUtf8;
|
||||||
if (lpApplicationName) {
|
if (lpApplicationName) {
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ using LPSTARTUPINFOW = STARTUPINFOW *;
|
|||||||
constexpr DWORD TLS_OUT_OF_INDEXES = 0xFFFFFFFFu;
|
constexpr DWORD TLS_OUT_OF_INDEXES = 0xFFFFFFFFu;
|
||||||
constexpr DWORD NORMAL_PRIORITY_CLASS = 0x00000020;
|
constexpr DWORD NORMAL_PRIORITY_CLASS = 0x00000020;
|
||||||
|
|
||||||
typedef DWORD(WIN_FUNC *LPTHREAD_START_ROUTINE)(LPVOID);
|
typedef DWORD(_CC_STDCALL *LPTHREAD_START_ROUTINE)(LPVOID);
|
||||||
|
|
||||||
namespace kernel32 {
|
namespace kernel32 {
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ BOOL WINAPI QueryPerformanceCounter(LARGE_INTEGER *lpPerformanceCount) {
|
|||||||
kernel32::setLastError(ERROR_INVALID_PARAMETER);
|
kernel32::setLastError(ERROR_INVALID_PARAMETER);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
*lpPerformanceCount = 0;
|
lpPerformanceCount->QuadPart = 0;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@ BOOL WINAPI QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency) {
|
|||||||
kernel32::setLastError(ERROR_INVALID_PARAMETER);
|
kernel32::setLastError(ERROR_INVALID_PARAMETER);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
*lpFrequency = 1;
|
lpFrequency->QuadPart = 1;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#include "modules.h"
|
#include "modules.h"
|
||||||
#include "strutil.h"
|
#include "strutil.h"
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
@@ -1141,8 +1142,8 @@ BOOL WINAPI GetDiskFreeSpaceW(LPCWSTR lpRootPathName, LPDWORD lpSectorsPerCluste
|
|||||||
lpNumberOfFreeClusters, lpTotalNumberOfClusters);
|
lpNumberOfFreeClusters, lpTotalNumberOfClusters);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL WINAPI GetDiskFreeSpaceExA(LPCSTR lpDirectoryName, uint64_t *lpFreeBytesAvailableToCaller,
|
BOOL WINAPI GetDiskFreeSpaceExA(LPCSTR lpDirectoryName, PULARGE_INTEGER lpFreeBytesAvailableToCaller,
|
||||||
uint64_t *lpTotalNumberOfBytes, uint64_t *lpTotalNumberOfFreeBytes) {
|
PULARGE_INTEGER lpTotalNumberOfBytes, PULARGE_INTEGER lpTotalNumberOfFreeBytes) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("GetDiskFreeSpaceExA(%s)\n", lpDirectoryName ? lpDirectoryName : "(null)");
|
DEBUG_LOG("GetDiskFreeSpaceExA(%s)\n", lpDirectoryName ? lpDirectoryName : "(null)");
|
||||||
struct statvfs buf{};
|
struct statvfs buf{};
|
||||||
@@ -1161,13 +1162,13 @@ BOOL WINAPI GetDiskFreeSpaceExA(LPCSTR lpDirectoryName, uint64_t *lpFreeBytesAva
|
|||||||
uint64_t totalFree = static_cast<uint64_t>(buf.f_bfree) * blockSize;
|
uint64_t totalFree = static_cast<uint64_t>(buf.f_bfree) * blockSize;
|
||||||
|
|
||||||
if (lpFreeBytesAvailableToCaller) {
|
if (lpFreeBytesAvailableToCaller) {
|
||||||
*lpFreeBytesAvailableToCaller = freeToCaller;
|
lpFreeBytesAvailableToCaller->QuadPart = freeToCaller;
|
||||||
}
|
}
|
||||||
if (lpTotalNumberOfBytes) {
|
if (lpTotalNumberOfBytes) {
|
||||||
*lpTotalNumberOfBytes = totalBytes;
|
lpTotalNumberOfBytes->QuadPart = totalBytes;
|
||||||
}
|
}
|
||||||
if (lpTotalNumberOfFreeBytes) {
|
if (lpTotalNumberOfFreeBytes) {
|
||||||
*lpTotalNumberOfFreeBytes = totalFree;
|
lpTotalNumberOfFreeBytes->QuadPart = totalFree;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG_LOG("\t-> host %s, free %llu, total %llu, total free %llu\n", resolvedPath.c_str(),
|
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;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL WINAPI GetDiskFreeSpaceExW(LPCWSTR lpDirectoryName, uint64_t *lpFreeBytesAvailableToCaller,
|
BOOL WINAPI GetDiskFreeSpaceExW(LPCWSTR lpDirectoryName, PULARGE_INTEGER lpFreeBytesAvailableToCaller,
|
||||||
uint64_t *lpTotalNumberOfBytes, uint64_t *lpTotalNumberOfFreeBytes) {
|
PULARGE_INTEGER lpTotalNumberOfBytes, PULARGE_INTEGER lpTotalNumberOfFreeBytes) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("GetDiskFreeSpaceExW -> ");
|
DEBUG_LOG("GetDiskFreeSpaceExW -> ");
|
||||||
std::string directoryName = wideStringToString(lpDirectoryName);
|
std::string directoryName = wideStringToString(lpDirectoryName);
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ struct CONSOLE_SCREEN_BUFFER_INFO {
|
|||||||
|
|
||||||
struct INPUT_RECORD;
|
struct INPUT_RECORD;
|
||||||
|
|
||||||
using PHANDLER_ROUTINE = BOOL(WIN_FUNC *)(DWORD CtrlType);
|
typedef BOOL (_CC_STDCALL *PHANDLER_ROUTINE)(DWORD CtrlType);
|
||||||
|
|
||||||
namespace kernel32 {
|
namespace kernel32 {
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ struct CPINFO {
|
|||||||
};
|
};
|
||||||
|
|
||||||
using LPCPINFO = CPINFO *;
|
using LPCPINFO = CPINFO *;
|
||||||
using LOCALE_ENUMPROCA = BOOL(WIN_FUNC *)(LPSTR);
|
typedef BOOL (_CC_STDCALL *LOCALE_ENUMPROCA)(LPSTR);
|
||||||
|
|
||||||
namespace kernel32 {
|
namespace kernel32 {
|
||||||
|
|
||||||
|
|||||||
32
dll/lmgr.cpp
32
dll/lmgr.cpp
@@ -1,28 +1,34 @@
|
|||||||
|
#include "lmgr.h"
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "context.h"
|
#include "context.h"
|
||||||
#include "modules.h"
|
#include "modules.h"
|
||||||
|
|
||||||
namespace lmgr {
|
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() {
|
int CDECL lp_checkout(int a, int b, LPCSTR c, LPCSTR d, int e, LPCSTR f, int *out) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("lp_checkin()\n");
|
DEBUG_LOG("lp_checkout(%d, %d, %s, %s, %d, %s)\n", a, b, c, d, e, f);
|
||||||
return 0;
|
*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) {
|
static void *resolveByOrdinal(uint16_t ordinal) {
|
||||||
switch (ordinal) {
|
switch (ordinal) {
|
||||||
case 189:
|
case 189:
|
||||||
return (void*)lmgr::lp_checkin;
|
return (void *)thunk_lmgr_lp_checkin;
|
||||||
case 190:
|
case 190:
|
||||||
return (void*)lmgr::lp_checkout;
|
return (void *)thunk_lmgr_lp_checkout;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
10
dll/lmgr.h
Normal file
10
dll/lmgr.h
Normal file
@@ -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
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
|
#include "mscoree.h"
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "context.h"
|
#include "context.h"
|
||||||
#include "kernel32/internal.h"
|
#include "kernel32/internal.h"
|
||||||
#include "modules.h"
|
#include "modules.h"
|
||||||
|
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
namespace mscoree {
|
namespace mscoree {
|
||||||
|
|
||||||
void WIN_FUNC CorExitProcess(int exitCode) {
|
VOID WINAPI CorExitProcess(int exitCode) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("CorExitProcess(%i)\n", exitCode);
|
DEBUG_LOG("CorExitProcess(%i)\n", exitCode);
|
||||||
kernel32::exitInternal(exitCode);
|
kernel32::exitInternal(exitCode);
|
||||||
@@ -15,17 +15,13 @@ void WIN_FUNC CorExitProcess(int exitCode) {
|
|||||||
|
|
||||||
} // namespace mscoree
|
} // namespace mscoree
|
||||||
|
|
||||||
static void *resolveByName(const char *name) {
|
#include "mscoree_trampolines.h"
|
||||||
if (strcmp(name, "CorExitProcess") == 0)
|
|
||||||
return (void *)mscoree::CorExitProcess;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern const wibo::ModuleStub lib_mscoree = {
|
extern const wibo::ModuleStub lib_mscoree = {
|
||||||
(const char *[]){
|
(const char *[]){
|
||||||
"mscoree",
|
"mscoree",
|
||||||
nullptr,
|
nullptr,
|
||||||
},
|
},
|
||||||
resolveByName,
|
mscoreeThunkByName,
|
||||||
nullptr,
|
nullptr,
|
||||||
};
|
};
|
||||||
|
|||||||
9
dll/mscoree.h
Normal file
9
dll/mscoree.h
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
namespace mscoree {
|
||||||
|
|
||||||
|
VOID WINAPI CorExitProcess(int exitCode);
|
||||||
|
|
||||||
|
} // namespace mscoree
|
||||||
735
dll/msvcrt.cpp
735
dll/msvcrt.cpp
File diff suppressed because it is too large
Load Diff
234
dll/msvcrt.h
Normal file
234
dll/msvcrt.h
Normal file
@@ -0,0 +1,234 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
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
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#include "ntdll.h"
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "context.h"
|
#include "context.h"
|
||||||
#include "errors.h"
|
#include "errors.h"
|
||||||
@@ -8,6 +10,7 @@
|
|||||||
#include "modules.h"
|
#include "modules.h"
|
||||||
#include "processes.h"
|
#include "processes.h"
|
||||||
#include "strutil.h"
|
#include "strutil.h"
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
@@ -17,24 +20,8 @@
|
|||||||
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
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 {
|
namespace {
|
||||||
|
|
||||||
enum PROCESSINFOCLASS {
|
|
||||||
ProcessBasicInformation = 0,
|
|
||||||
ProcessWow64Information = 26,
|
|
||||||
ProcessImageFileName = 27,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PROCESS_BASIC_INFORMATION {
|
struct PROCESS_BASIC_INFORMATION {
|
||||||
NTSTATUS ExitStatus;
|
NTSTATUS ExitStatus;
|
||||||
PEB *PebBaseAddress;
|
PEB *PebBaseAddress;
|
||||||
@@ -53,17 +40,6 @@ struct ProcessHandleDetails {
|
|||||||
|
|
||||||
constexpr LONG kDefaultBasePriority = 8;
|
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 {
|
struct RTL_OSVERSIONINFOEXW : RTL_OSVERSIONINFOW {
|
||||||
WORD wServicePackMajor;
|
WORD wServicePackMajor;
|
||||||
WORD wServicePackMinor;
|
WORD wServicePackMinor;
|
||||||
@@ -124,17 +100,17 @@ BOOL WIN_FUNC ResetEvent(HANDLE hEvent);
|
|||||||
|
|
||||||
namespace ntdll {
|
namespace ntdll {
|
||||||
|
|
||||||
constexpr LARGE_INTEGER FILE_WRITE_TO_END_OF_FILE = static_cast<LARGE_INTEGER>(-1);
|
constexpr LARGE_INTEGER FILE_WRITE_TO_END_OF_FILE = {.QuadPart = -1};
|
||||||
constexpr LARGE_INTEGER FILE_USE_FILE_POINTER_POSITION = static_cast<LARGE_INTEGER>(-2);
|
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);
|
VERBOSE_LOG("ntdll::memset(%p, %i, %zu)\n", dest, ch, count);
|
||||||
return std::memset(dest, ch, count);
|
return std::memset(dest, ch, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS WIN_FUNC NtReadFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext,
|
NTSTATUS WINAPI NtReadFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext,
|
||||||
PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer, ULONG Length, PLARGE_INTEGER ByteOffset,
|
PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer, ULONG Length, PLARGE_INTEGER ByteOffset,
|
||||||
PULONG Key) {
|
PULONG Key) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("NtReadFile(%p, %p, %p, %p, %p, %p, %u, %p, %p) ", FileHandle, Event, ApcRoutine, ApcContext,
|
DEBUG_LOG("NtReadFile(%p, %p, %p, %p, %p, %p, %u, %p, %p) ", FileHandle, Event, ApcRoutine, ApcContext,
|
||||||
IoStatusBlock, Buffer, Length, ByteOffset, Key);
|
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 useOverlapped = file->overlapped;
|
||||||
bool useCurrentFilePosition = (ByteOffset == nullptr);
|
bool useCurrentFilePosition = (ByteOffset == nullptr);
|
||||||
if (!useCurrentFilePosition && *ByteOffset == FILE_USE_FILE_POINTER_POSITION) {
|
if (!useCurrentFilePosition && ByteOffset->QuadPart == FILE_USE_FILE_POINTER_POSITION.QuadPart) {
|
||||||
useCurrentFilePosition = true;
|
useCurrentFilePosition = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<off_t> offset;
|
std::optional<off_t> offset;
|
||||||
if (!useCurrentFilePosition) {
|
if (!useCurrentFilePosition) {
|
||||||
offset = static_cast<off_t>(*ByteOffset);
|
offset = static_cast<off_t>(ByteOffset->QuadPart);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (useOverlapped && useCurrentFilePosition) {
|
if (useOverlapped && useCurrentFilePosition) {
|
||||||
@@ -202,9 +178,9 @@ NTSTATUS WIN_FUNC NtReadFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE Ap
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS WIN_FUNC NtWriteFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext,
|
NTSTATUS WINAPI NtWriteFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext,
|
||||||
PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer, ULONG Length, PLARGE_INTEGER ByteOffset,
|
PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer, ULONG Length, PLARGE_INTEGER ByteOffset,
|
||||||
PULONG Key) {
|
PULONG Key) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("NtWriteFile(%p, %p, %p, %p, %p, %p, %u, %p, %p) ", FileHandle, Event, ApcRoutine, ApcContext,
|
DEBUG_LOG("NtWriteFile(%p, %p, %p, %p, %p, %p, %u, %p, %p) ", FileHandle, Event, ApcRoutine, ApcContext,
|
||||||
IoStatusBlock, Buffer, Length, ByteOffset, Key);
|
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 useCurrentFilePosition = (ByteOffset == nullptr);
|
||||||
bool writeToEndOfFile = false;
|
bool writeToEndOfFile = false;
|
||||||
if (ByteOffset) {
|
if (ByteOffset) {
|
||||||
if (*ByteOffset == FILE_USE_FILE_POINTER_POSITION) {
|
if (ByteOffset->QuadPart == FILE_USE_FILE_POINTER_POSITION.QuadPart) {
|
||||||
useCurrentFilePosition = true;
|
useCurrentFilePosition = true;
|
||||||
} else if (*ByteOffset == FILE_WRITE_TO_END_OF_FILE) {
|
} else if (ByteOffset->QuadPart == FILE_WRITE_TO_END_OF_FILE.QuadPart) {
|
||||||
writeToEndOfFile = true;
|
writeToEndOfFile = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<off_t> offset;
|
std::optional<off_t> offset;
|
||||||
if (!useCurrentFilePosition && !writeToEndOfFile) {
|
if (!useCurrentFilePosition && !writeToEndOfFile) {
|
||||||
offset = static_cast<off_t>(*ByteOffset);
|
offset = static_cast<off_t>(ByteOffset->QuadPart);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (useOverlapped && useCurrentFilePosition) {
|
if (useOverlapped && useCurrentFilePosition) {
|
||||||
@@ -286,8 +262,8 @@ NTSTATUS WIN_FUNC NtWriteFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE A
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS WIN_FUNC NtAllocateVirtualMemory(HANDLE ProcessHandle, PVOID *BaseAddress, ULONG_PTR ZeroBits,
|
NTSTATUS WINAPI NtAllocateVirtualMemory(HANDLE ProcessHandle, PVOID *BaseAddress, ULONG_PTR ZeroBits,
|
||||||
PSIZE_T RegionSize, ULONG AllocationType, ULONG Protect) {
|
PSIZE_T RegionSize, ULONG AllocationType, ULONG Protect) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("NtAllocateVirtualMemory(%p, %p, %lu, %p, %lu, %lu) ", ProcessHandle, BaseAddress, ZeroBits, RegionSize,
|
DEBUG_LOG("NtAllocateVirtualMemory(%p, %p, %lu, %p, %lu, %lu) ", ProcessHandle, BaseAddress, ZeroBits, RegionSize,
|
||||||
AllocationType, Protect);
|
AllocationType, Protect);
|
||||||
@@ -325,8 +301,8 @@ NTSTATUS WIN_FUNC NtAllocateVirtualMemory(HANDLE ProcessHandle, PVOID *BaseAddre
|
|||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS WIN_FUNC NtProtectVirtualMemory(HANDLE ProcessHandle, PVOID *BaseAddress, PSIZE_T NumberOfBytesToProtect,
|
NTSTATUS WINAPI NtProtectVirtualMemory(HANDLE ProcessHandle, PVOID *BaseAddress, PSIZE_T NumberOfBytesToProtect,
|
||||||
ULONG NewAccessProtection, PULONG OldAccessProtection) {
|
ULONG NewAccessProtection, PULONG OldAccessProtection) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("NtProtectVirtualMemory(%p, %p, %p, %lu, %p) ", ProcessHandle, BaseAddress, NumberOfBytesToProtect,
|
DEBUG_LOG("NtProtectVirtualMemory(%p, %p, %p, %lu, %p) ", ProcessHandle, BaseAddress, NumberOfBytesToProtect,
|
||||||
NewAccessProtection, OldAccessProtection);
|
NewAccessProtection, OldAccessProtection);
|
||||||
@@ -366,7 +342,7 @@ NTSTATUS WIN_FUNC NtProtectVirtualMemory(HANDLE ProcessHandle, PVOID *BaseAddres
|
|||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS WIN_FUNC RtlGetVersion(PRTL_OSVERSIONINFOW lpVersionInformation) {
|
NTSTATUS WINAPI RtlGetVersion(PRTL_OSVERSIONINFOW lpVersionInformation) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("RtlGetVersion(%p) ", lpVersionInformation);
|
DEBUG_LOG("RtlGetVersion(%p) ", lpVersionInformation);
|
||||||
if (!lpVersionInformation) {
|
if (!lpVersionInformation) {
|
||||||
@@ -396,9 +372,9 @@ NTSTATUS WIN_FUNC RtlGetVersion(PRTL_OSVERSIONINFOW lpVersionInformation) {
|
|||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS WIN_FUNC NtQueryInformationProcess(HANDLE ProcessHandle, PROCESSINFOCLASS ProcessInformationClass,
|
NTSTATUS WINAPI NtQueryInformationProcess(HANDLE ProcessHandle, PROCESSINFOCLASS ProcessInformationClass,
|
||||||
PVOID ProcessInformation, ULONG ProcessInformationLength,
|
PVOID ProcessInformation, ULONG ProcessInformationLength,
|
||||||
PULONG ReturnLength) {
|
PULONG ReturnLength) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("NtQueryInformationProcess(%p, %u, %p, %u, %p) ", ProcessHandle, ProcessInformationClass,
|
DEBUG_LOG("NtQueryInformationProcess(%p, %u, %p, %u, %p) ", ProcessHandle, ProcessInformationClass,
|
||||||
ProcessInformation, ProcessInformationLength, ReturnLength);
|
ProcessInformation, ProcessInformationLength, ReturnLength);
|
||||||
@@ -501,29 +477,13 @@ NTSTATUS WIN_FUNC NtQueryInformationProcess(HANDLE ProcessHandle, PROCESSINFOCLA
|
|||||||
|
|
||||||
} // namespace ntdll
|
} // namespace ntdll
|
||||||
|
|
||||||
static void *resolveByName(const char *name) {
|
#include "ntdll_trampolines.h"
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern const wibo::ModuleStub lib_ntdll = {
|
extern const wibo::ModuleStub lib_ntdll = {
|
||||||
(const char *[]){
|
(const char *[]){
|
||||||
"ntdll",
|
"ntdll",
|
||||||
nullptr,
|
nullptr,
|
||||||
},
|
},
|
||||||
resolveByName,
|
ntdllThunkByName,
|
||||||
nullptr,
|
nullptr,
|
||||||
};
|
};
|
||||||
|
|||||||
49
dll/ntdll.h
Normal file
49
dll/ntdll.h
Normal file
@@ -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
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#include "ole32.h"
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "context.h"
|
#include "context.h"
|
||||||
#include "errors.h"
|
#include "errors.h"
|
||||||
@@ -108,15 +110,16 @@ HRESULT parseGuidString(const uint16_t *first, const uint16_t *last, GUID &out)
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace ole32 {
|
namespace ole32 {
|
||||||
int WIN_FUNC CoInitialize(void *pvReserved) {
|
|
||||||
|
HRESULT WINAPI CoInitialize(LPVOID pvReserved) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("STUB: CoInitialize(%p)\n", pvReserved);
|
DEBUG_LOG("STUB: CoInitialize(%p)\n", pvReserved);
|
||||||
(void)pvReserved;
|
(void)pvReserved;
|
||||||
return 0; // S_OK
|
return 0; // S_OK
|
||||||
}
|
}
|
||||||
|
|
||||||
int WIN_FUNC CoCreateInstance(const GUID *rclsid, void *pUnkOuter, unsigned int dwClsContext, const GUID *riid,
|
HRESULT WINAPI CoCreateInstance(const GUID *rclsid, LPVOID pUnkOuter, DWORD dwClsContext, const GUID *riid,
|
||||||
void **ppv) {
|
LPVOID *ppv) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("STUB: CoCreateInstance(0x%x, %p, %d, 0x%x, %p)\n", rclsid->Data1, pUnkOuter, dwClsContext, riid->Data1,
|
DEBUG_LOG("STUB: CoCreateInstance(0x%x, %p, %d, 0x%x, %p)\n", rclsid->Data1, pUnkOuter, dwClsContext, riid->Data1,
|
||||||
*ppv);
|
*ppv);
|
||||||
@@ -126,7 +129,7 @@ int WIN_FUNC CoCreateInstance(const GUID *rclsid, void *pUnkOuter, unsigned int
|
|||||||
return 0x80004003; // E_POINTER
|
return 0x80004003; // E_POINTER
|
||||||
}
|
}
|
||||||
|
|
||||||
int WIN_FUNC CLSIDFromString(const uint16_t *lpsz, GUID *pclsid) {
|
HRESULT WINAPI CLSIDFromString(LPCWSTR lpsz, GUID *pclsid) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
|
|
||||||
if (pclsid == nullptr) {
|
if (pclsid == nullptr) {
|
||||||
@@ -150,23 +153,16 @@ int WIN_FUNC CLSIDFromString(const uint16_t *lpsz, GUID *pclsid) {
|
|||||||
|
|
||||||
return parseGuidString(begin, end, *pclsid);
|
return parseGuidString(begin, end, *pclsid);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ole32
|
} // namespace ole32
|
||||||
|
|
||||||
static void *resolveByName(const char *name) {
|
#include "ole32_trampolines.h"
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern const wibo::ModuleStub lib_ole32 = {
|
extern const wibo::ModuleStub lib_ole32 = {
|
||||||
(const char *[]){
|
(const char *[]){
|
||||||
"ole32",
|
"ole32",
|
||||||
nullptr,
|
nullptr,
|
||||||
},
|
},
|
||||||
resolveByName,
|
ole32ThunkByName,
|
||||||
nullptr,
|
nullptr,
|
||||||
};
|
};
|
||||||
|
|||||||
11
dll/ole32.h
Normal file
11
dll/ole32.h
Normal file
@@ -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
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#include "rpcrt4.h"
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "context.h"
|
#include "context.h"
|
||||||
#include "modules.h"
|
#include "modules.h"
|
||||||
@@ -11,15 +13,6 @@
|
|||||||
|
|
||||||
namespace {
|
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_OK = 0;
|
||||||
constexpr RPC_STATUS RPC_S_INVALID_STRING_BINDING = 1700;
|
constexpr RPC_STATUS RPC_S_INVALID_STRING_BINDING = 1700;
|
||||||
constexpr RPC_STATUS RPC_S_INVALID_BINDING = 1702;
|
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_INVALID_ARG = 87;
|
||||||
constexpr RPC_STATUS RPC_S_OUT_OF_MEMORY = 14;
|
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 {
|
struct BindingComponents {
|
||||||
std::u16string objectUuid;
|
std::u16string objectUuid;
|
||||||
std::u16string protocolSequence;
|
std::u16string protocolSequence;
|
||||||
@@ -57,11 +42,6 @@ struct BindingHandleData {
|
|||||||
bool serverReachable = false;
|
bool serverReachable = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
union CLIENT_CALL_RETURN {
|
|
||||||
void *Pointer;
|
|
||||||
LONG_PTR Simple;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::unordered_map<RPC_WSTR, BindingComponents> g_stringBindings;
|
std::unordered_map<RPC_WSTR, BindingComponents> g_stringBindings;
|
||||||
std::unordered_map<RPC_BINDING_HANDLE, std::unique_ptr<BindingHandleData>> g_bindingHandles;
|
std::unordered_map<RPC_BINDING_HANDLE, std::unique_ptr<BindingHandleData>> g_bindingHandles;
|
||||||
|
|
||||||
@@ -128,10 +108,10 @@ BindingHandleData *getBinding(RPC_BINDING_HANDLE handle) {
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
extern "C" {
|
namespace rpcrt4 {
|
||||||
|
|
||||||
RPC_STATUS WIN_FUNC RpcStringBindingComposeW(RPC_WSTR objUuid, RPC_WSTR protSeq, RPC_WSTR networkAddr,
|
RPC_STATUS WINAPI RpcStringBindingComposeW(RPC_WSTR objUuid, RPC_WSTR protSeq, RPC_WSTR networkAddr, RPC_WSTR endpoint,
|
||||||
RPC_WSTR endpoint, RPC_WSTR options, RPC_WSTR *stringBinding) {
|
RPC_WSTR options, RPC_WSTR *stringBinding) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
BindingComponents components;
|
BindingComponents components;
|
||||||
components.objectUuid = toU16(objUuid);
|
components.objectUuid = toU16(objUuid);
|
||||||
@@ -161,7 +141,7 @@ RPC_STATUS WIN_FUNC RpcStringBindingComposeW(RPC_WSTR objUuid, RPC_WSTR protSeq,
|
|||||||
return RPC_S_OK;
|
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();
|
HOST_CONTEXT_GUARD();
|
||||||
if (!binding) {
|
if (!binding) {
|
||||||
return RPC_S_INVALID_ARG;
|
return RPC_S_INVALID_ARG;
|
||||||
@@ -185,10 +165,9 @@ RPC_STATUS WIN_FUNC RpcBindingFromStringBindingW(RPC_WSTR stringBinding, RPC_BIN
|
|||||||
return RPC_S_OK;
|
return RPC_S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
RPC_STATUS WIN_FUNC RpcBindingSetAuthInfoExW(RPC_BINDING_HANDLE binding, RPC_WSTR serverPrincName,
|
RPC_STATUS WINAPI RpcBindingSetAuthInfoExW(RPC_BINDING_HANDLE binding, RPC_WSTR serverPrincName, ULONG authnLevel,
|
||||||
unsigned long authnLevel, unsigned long authnSvc,
|
ULONG authnSvc, RPC_AUTH_IDENTITY_HANDLE authIdentity, ULONG authzSvc,
|
||||||
RPC_AUTH_IDENTITY_HANDLE authIdentity, unsigned long authzSvc,
|
RPC_SECURITY_QOS *securityQos) {
|
||||||
RPC_SECURITY_QOS *securityQos) {
|
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
BindingHandleData *data = getBinding(binding);
|
BindingHandleData *data = getBinding(binding);
|
||||||
if (!data) {
|
if (!data) {
|
||||||
@@ -210,7 +189,7 @@ RPC_STATUS WIN_FUNC RpcBindingSetAuthInfoExW(RPC_BINDING_HANDLE binding, RPC_WST
|
|||||||
return RPC_S_OK;
|
return RPC_S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
RPC_STATUS WIN_FUNC RpcBindingFree(RPC_BINDING_HANDLE *binding) {
|
RPC_STATUS WINAPI RpcBindingFree(RPC_BINDING_HANDLE *binding) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
if (!binding) {
|
if (!binding) {
|
||||||
return RPC_S_INVALID_ARG;
|
return RPC_S_INVALID_ARG;
|
||||||
@@ -229,7 +208,7 @@ RPC_STATUS WIN_FUNC RpcBindingFree(RPC_BINDING_HANDLE *binding) {
|
|||||||
return RPC_S_OK;
|
return RPC_S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
RPC_STATUS WIN_FUNC RpcStringFreeW(RPC_WSTR *string) {
|
RPC_STATUS WINAPI RpcStringFreeW(RPC_WSTR *string) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
if (!string) {
|
if (!string) {
|
||||||
return RPC_S_INVALID_ARG;
|
return RPC_S_INVALID_ARG;
|
||||||
@@ -247,7 +226,7 @@ RPC_STATUS WIN_FUNC RpcStringFreeW(RPC_WSTR *string) {
|
|||||||
return RPC_S_OK;
|
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);
|
DEBUG_LOG("STUB: NdrClientCall2 stubDescriptor=%p format=%p\n", stubDescriptor, format);
|
||||||
CLIENT_CALL_RETURN result = {};
|
CLIENT_CALL_RETURN result = {};
|
||||||
result.Simple = RPC_S_SERVER_UNAVAILABLE;
|
result.Simple = RPC_S_SERVER_UNAVAILABLE;
|
||||||
@@ -255,37 +234,17 @@ CLIENT_CALL_RETURN WIN_ENTRY NdrClientCall2(PMIDL_STUB_DESC stubDescriptor, PFOR
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WIN_FUNC NdrServerCall2(PRPC_MESSAGE message) {
|
VOID WINAPI NdrServerCall2(PRPC_MESSAGE message) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("STUB: NdrServerCall2 message=%p\n", message);
|
DEBUG_LOG("STUB: NdrServerCall2 message=%p\n", message);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // extern "C"
|
} // namespace rpcrt4
|
||||||
|
|
||||||
namespace {
|
#include "rpcrt4_trampolines.h"
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
extern const wibo::ModuleStub lib_rpcrt4 = {
|
extern const wibo::ModuleStub lib_rpcrt4 = {
|
||||||
(const char *[]){"rpcrt4", nullptr},
|
(const char *[]){"rpcrt4", nullptr},
|
||||||
resolveByName,
|
rpcrt4ThunkByName,
|
||||||
nullptr,
|
nullptr,
|
||||||
};
|
};
|
||||||
|
|||||||
39
dll/rpcrt4.h
Normal file
39
dll/rpcrt4.h
Normal file
@@ -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
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#include "user32.h"
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "context.h"
|
#include "context.h"
|
||||||
#include "errors.h"
|
#include "errors.h"
|
||||||
@@ -20,7 +22,7 @@ struct USEROBJECTFLAGS {
|
|||||||
DWORD dwFlags;
|
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();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("LoadStringA(%p, %u, %p, %d)\n", hInstance, uID, lpBuffer, cchBufferMax);
|
DEBUG_LOG("LoadStringA(%p, %u, %p, %d)\n", hInstance, uID, lpBuffer, cchBufferMax);
|
||||||
if (!lpBuffer || cchBufferMax <= 0) {
|
if (!lpBuffer || cchBufferMax <= 0) {
|
||||||
@@ -68,7 +70,7 @@ int WIN_FUNC LoadStringA(void *hInstance, unsigned int uID, char *lpBuffer, int
|
|||||||
return copyLength;
|
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();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("LoadStringW(%p, %u, %p, %d)\n", hInstance, uID, lpBuffer, cchBufferMax);
|
DEBUG_LOG("LoadStringW(%p, %u, %p, %d)\n", hInstance, uID, lpBuffer, cchBufferMax);
|
||||||
wibo::Executable *mod = wibo::executableFromModule((HMODULE)hInstance);
|
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;
|
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();
|
HOST_CONTEXT_GUARD();
|
||||||
(void)hwnd;
|
(void)hwnd;
|
||||||
(void)uType;
|
(void)uType;
|
||||||
@@ -131,20 +133,20 @@ int WIN_FUNC MessageBoxA(void *hwnd, const char *lpText, const char *lpCaption,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
HKL WIN_FUNC GetKeyboardLayout(DWORD idThread) {
|
HKL WINAPI GetKeyboardLayout(DWORD idThread) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("GetKeyboardLayout(%u)\n", idThread);
|
DEBUG_LOG("GetKeyboardLayout(%u)\n", idThread);
|
||||||
(void)idThread;
|
(void)idThread;
|
||||||
return reinterpret_cast<HKL>(kDefaultKeyboardLayout);
|
return reinterpret_cast<HKL>(kDefaultKeyboardLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
HWINSTA WIN_FUNC GetProcessWindowStation() {
|
HWINSTA WINAPI GetProcessWindowStation() {
|
||||||
DEBUG_LOG("GetProcessWindowStation()\n");
|
DEBUG_LOG("GetProcessWindowStation()\n");
|
||||||
static int kWindowStationStub;
|
static int kWindowStationStub;
|
||||||
return reinterpret_cast<HWINSTA>(&kWindowStationStub);
|
return reinterpret_cast<HWINSTA>(&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);
|
DEBUG_LOG("GetUserObjectInformationA(%p, %d, %p, %u, %p)\n", hObj, nIndex, pvInfo, nLength, lpnLengthNeeded);
|
||||||
(void)hObj;
|
(void)hObj;
|
||||||
|
|
||||||
@@ -169,36 +171,20 @@ BOOL WIN_FUNC GetUserObjectInformationA(HANDLE hObj, int nIndex, PVOID pvInfo, D
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
HWND WIN_FUNC GetActiveWindow() {
|
HWND WINAPI GetActiveWindow() {
|
||||||
DEBUG_LOG("GetActiveWindow()\n");
|
DEBUG_LOG("GetActiveWindow()\n");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace user32
|
} // namespace user32
|
||||||
|
|
||||||
static void *resolveByName(const char *name) {
|
#include "user32_trampolines.h"
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern const wibo::ModuleStub lib_user32 = {
|
extern const wibo::ModuleStub lib_user32 = {
|
||||||
(const char *[]){
|
(const char *[]){
|
||||||
"user32",
|
"user32",
|
||||||
nullptr,
|
nullptr,
|
||||||
},
|
},
|
||||||
resolveByName,
|
user32ThunkByName,
|
||||||
nullptr,
|
nullptr,
|
||||||
};
|
};
|
||||||
|
|||||||
15
dll/user32.h
Normal file
15
dll/user32.h
Normal file
@@ -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
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#include "vcruntime.h"
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "context.h"
|
#include "context.h"
|
||||||
#include "modules.h"
|
#include "modules.h"
|
||||||
@@ -6,45 +8,35 @@
|
|||||||
|
|
||||||
namespace vcruntime {
|
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();
|
HOST_CONTEXT_GUARD();
|
||||||
return ::memcpy(dest, src, count);
|
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();
|
HOST_CONTEXT_GUARD();
|
||||||
return ::memset(dest, ch, count);
|
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();
|
HOST_CONTEXT_GUARD();
|
||||||
return ::memcmp(buf1, buf2, count);
|
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();
|
HOST_CONTEXT_GUARD();
|
||||||
return ::memmove(dest, src, count);
|
return ::memmove(dest, src, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace vcruntime
|
} // namespace vcruntime
|
||||||
|
|
||||||
static void *resolveByName(const char *name) {
|
#include "vcruntime_trampolines.h"
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern const wibo::ModuleStub lib_vcruntime = {
|
extern const wibo::ModuleStub lib_vcruntime = {
|
||||||
(const char *[]){
|
(const char *[]){
|
||||||
"vcruntime140",
|
"vcruntime140",
|
||||||
nullptr,
|
nullptr,
|
||||||
},
|
},
|
||||||
resolveByName,
|
vcruntimeThunkByName,
|
||||||
nullptr,
|
nullptr,
|
||||||
};
|
};
|
||||||
|
|||||||
12
dll/vcruntime.h
Normal file
12
dll/vcruntime.h
Normal file
@@ -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
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#include "version.h"
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "context.h"
|
#include "context.h"
|
||||||
#include "errors.h"
|
#include "errors.h"
|
||||||
@@ -200,7 +202,7 @@ bool loadVersionResource(const char *fileName, std::vector<uint8_t> &buffer) {
|
|||||||
|
|
||||||
namespace version {
|
namespace version {
|
||||||
|
|
||||||
unsigned int WIN_FUNC GetFileVersionInfoSizeA(const char *lptstrFilename, unsigned int *lpdwHandle) {
|
UINT WINAPI GetFileVersionInfoSizeA(LPCSTR lptstrFilename, LPDWORD lpdwHandle) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("GetFileVersionInfoSizeA(%s, %p)\n", lptstrFilename, lpdwHandle);
|
DEBUG_LOG("GetFileVersionInfoSizeA(%s, %p)\n", lptstrFilename, lpdwHandle);
|
||||||
if (lpdwHandle)
|
if (lpdwHandle)
|
||||||
@@ -212,8 +214,7 @@ unsigned int WIN_FUNC GetFileVersionInfoSizeA(const char *lptstrFilename, unsign
|
|||||||
return static_cast<unsigned int>(buffer.size());
|
return static_cast<unsigned int>(buffer.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int WIN_FUNC GetFileVersionInfoA(const char *lptstrFilename, unsigned int dwHandle, unsigned int dwLen,
|
UINT WINAPI GetFileVersionInfoA(LPCSTR lptstrFilename, DWORD dwHandle, DWORD dwLen, LPVOID lpData) {
|
||||||
void *lpData) {
|
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
(void)dwHandle;
|
(void)dwHandle;
|
||||||
DEBUG_LOG("GetFileVersionInfoA(%s, %u, %p)\n", lptstrFilename, dwLen, lpData);
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int WIN_FUNC VerQueryValueA(const void *pBlock, const char *lpSubBlock, void **lplpBuffer,
|
UINT WINAPI VerQueryValueA(LPCVOID pBlock, LPCSTR lpSubBlock, LPVOID *lplpBuffer, PUINT puLen) {
|
||||||
unsigned int *puLen) {
|
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("VerQueryValueA(%p, %s, %p, %p)\n", pBlock, lpSubBlock ? lpSubBlock : "(null)", lplpBuffer, puLen);
|
DEBUG_LOG("VerQueryValueA(%p, %s, %p, %p)\n", pBlock, lpSubBlock ? lpSubBlock : "(null)", lplpBuffer, puLen);
|
||||||
if (!lpSubBlock)
|
if (!lpSubBlock)
|
||||||
@@ -285,23 +285,21 @@ unsigned int WIN_FUNC VerQueryValueA(const void *pBlock, const char *lpSubBlock,
|
|||||||
return VerQueryValueImpl(pBlock, lpSubBlock, lplpBuffer, puLen);
|
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();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("GetFileVersionInfoSizeW -> ");
|
DEBUG_LOG("GetFileVersionInfoSizeW -> ");
|
||||||
auto narrow = wideStringToString(lptstrFilename);
|
auto narrow = wideStringToString(lptstrFilename);
|
||||||
return GetFileVersionInfoSizeA(narrow.c_str(), lpdwHandle);
|
return GetFileVersionInfoSizeA(narrow.c_str(), lpdwHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int WIN_FUNC GetFileVersionInfoW(const uint16_t *lptstrFilename, unsigned int dwHandle, unsigned int dwLen,
|
UINT WINAPI GetFileVersionInfoW(LPCWSTR lptstrFilename, DWORD dwHandle, DWORD dwLen, LPVOID lpData) {
|
||||||
void *lpData) {
|
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("GetFileVersionInfoW -> ");
|
DEBUG_LOG("GetFileVersionInfoW -> ");
|
||||||
auto narrow = wideStringToString(lptstrFilename);
|
auto narrow = wideStringToString(lptstrFilename);
|
||||||
return GetFileVersionInfoA(narrow.c_str(), dwHandle, dwLen, lpData);
|
return GetFileVersionInfoA(narrow.c_str(), dwHandle, dwLen, lpData);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int WIN_FUNC VerQueryValueW(const void *pBlock, const uint16_t *lpSubBlock, void **lplpBuffer,
|
UINT WINAPI VerQueryValueW(LPCVOID pBlock, LPCWSTR lpSubBlock, LPVOID *lplpBuffer, PUINT puLen) {
|
||||||
unsigned int *puLen) {
|
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
if (!lpSubBlock)
|
if (!lpSubBlock)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -312,27 +310,13 @@ unsigned int WIN_FUNC VerQueryValueW(const void *pBlock, const uint16_t *lpSubBl
|
|||||||
|
|
||||||
} // namespace version
|
} // namespace version
|
||||||
|
|
||||||
static void *resolveByName(const char *name) {
|
#include "version_trampolines.h"
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern const wibo::ModuleStub lib_version = {
|
extern const wibo::ModuleStub lib_version = {
|
||||||
(const char *[]){
|
(const char *[]){
|
||||||
"version",
|
"version",
|
||||||
nullptr,
|
nullptr,
|
||||||
},
|
},
|
||||||
resolveByName,
|
versionThunkByName,
|
||||||
nullptr,
|
nullptr,
|
||||||
};
|
};
|
||||||
|
|||||||
14
dll/version.h
Normal file
14
dll/version.h
Normal file
@@ -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
|
||||||
@@ -22,6 +22,8 @@
|
|||||||
#define VERBOSE_LOG(...) ((void)0)
|
#define VERBOSE_LOG(...) ((void)0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
extern "C" thread_local TEB *currentThreadTeb;
|
||||||
|
|
||||||
namespace wibo {
|
namespace wibo {
|
||||||
|
|
||||||
extern char **argv;
|
extern char **argv;
|
||||||
@@ -32,7 +34,6 @@ extern std::string commandLine;
|
|||||||
extern std::vector<uint16_t> commandLineW;
|
extern std::vector<uint16_t> commandLineW;
|
||||||
extern bool debugEnabled;
|
extern bool debugEnabled;
|
||||||
extern unsigned int debugIndent;
|
extern unsigned int debugIndent;
|
||||||
extern uint16_t tibSelector;
|
|
||||||
extern int tibEntryNumber;
|
extern int tibEntryNumber;
|
||||||
extern PEB *processPeb;
|
extern PEB *processPeb;
|
||||||
|
|
||||||
@@ -40,8 +41,6 @@ TEB *allocateTib();
|
|||||||
void destroyTib(TEB *tib);
|
void destroyTib(TEB *tib);
|
||||||
void initializeTibStackInfo(TEB *tib);
|
void initializeTibStackInfo(TEB *tib);
|
||||||
bool installTibForCurrentThread(TEB *tib);
|
bool installTibForCurrentThread(TEB *tib);
|
||||||
void setThreadTibForHost(TEB *tib);
|
|
||||||
TEB *getThreadTibForHost();
|
|
||||||
|
|
||||||
void debug_log(const char *fmt, ...);
|
void debug_log(const char *fmt, ...);
|
||||||
|
|
||||||
|
|||||||
@@ -1,65 +0,0 @@
|
|||||||
#include "context.h"
|
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
|
|
||||||
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
|
|
||||||
@@ -1,36 +1,4 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "common.h"
|
#define HOST_CONTEXT_GUARD()
|
||||||
|
#define GUEST_CONTEXT_GUARD(tibPtr)
|
||||||
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)
|
|
||||||
|
|||||||
7
src/entry.h
Normal file
7
src/entry.h
Normal file
@@ -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);
|
||||||
152
src/main.cpp
152
src/main.cpp
@@ -1,5 +1,7 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "context.h"
|
#include "context.h"
|
||||||
|
#include "entry.h"
|
||||||
|
#include "entry_trampolines.h"
|
||||||
#include "files.h"
|
#include "files.h"
|
||||||
#include "modules.h"
|
#include "modules.h"
|
||||||
#include "processes.h"
|
#include "processes.h"
|
||||||
@@ -8,7 +10,6 @@
|
|||||||
#include "version_info.h"
|
#include "version_info.h"
|
||||||
|
|
||||||
#include <asm/ldt.h>
|
#include <asm/ldt.h>
|
||||||
#include <charconv>
|
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
@@ -19,7 +20,6 @@
|
|||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
#include <system_error>
|
|
||||||
#include <threads.h>
|
#include <threads.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -32,9 +32,9 @@ std::vector<uint16_t> wibo::commandLineW;
|
|||||||
wibo::ModuleInfo *wibo::mainModule = nullptr;
|
wibo::ModuleInfo *wibo::mainModule = nullptr;
|
||||||
bool wibo::debugEnabled = false;
|
bool wibo::debugEnabled = false;
|
||||||
unsigned int wibo::debugIndent = 0;
|
unsigned int wibo::debugIndent = 0;
|
||||||
uint16_t wibo::tibSelector = 0;
|
|
||||||
int wibo::tibEntryNumber = -1;
|
int wibo::tibEntryNumber = -1;
|
||||||
PEB *wibo::processPeb = nullptr;
|
PEB *wibo::processPeb = nullptr;
|
||||||
|
thread_local TEB *currentThreadTeb = nullptr;
|
||||||
|
|
||||||
void wibo::debug_log(const char *fmt, ...) {
|
void wibo::debug_log(const char *fmt, ...) {
|
||||||
va_list args;
|
va_list args;
|
||||||
@@ -74,27 +74,24 @@ void wibo::initializeTibStackInfo(TEB *tibPtr) {
|
|||||||
if (!tibPtr) {
|
if (!tibPtr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pthread_attr_t attr;
|
// Allocate a stack for the thread in the guest address space (below 2GB)
|
||||||
if (pthread_getattr_np(pthread_self(), &attr) != 0) {
|
void *guestLimit = nullptr;
|
||||||
perror("Failed to get thread attributes");
|
void *guestBase = nullptr;
|
||||||
return;
|
if (!wibo::heap::reserveGuestStack(1 * 1024 * 1024, &guestLimit, &guestBase)) {
|
||||||
|
fprintf(stderr, "Failed to reserve guest stack\n");
|
||||||
|
std::abort();
|
||||||
}
|
}
|
||||||
void *stackAddr = nullptr;
|
tibPtr->Tib.StackLimit = guestLimit;
|
||||||
size_t stackSize = 0;
|
tibPtr->Tib.StackBase = guestBase;
|
||||||
if (pthread_attr_getstack(&attr, &stackAddr, &stackSize) == 0 && stackAddr && stackSize > 0) {
|
DEBUG_LOG("initializeTibStackInfo: using guest stack base=%p limit=%p\n", tibPtr->Tib.StackBase,
|
||||||
tibPtr->Tib.StackLimit = stackAddr;
|
tibPtr->Tib.StackLimit);
|
||||||
tibPtr->Tib.StackBase = static_cast<char *>(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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wibo::installTibForCurrentThread(TEB *tibPtr) {
|
bool wibo::installTibForCurrentThread(TEB *tibPtr) {
|
||||||
if (!tibPtr) {
|
if (!tibPtr) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct user_desc desc;
|
struct user_desc desc;
|
||||||
std::memset(&desc, 0, sizeof(desc));
|
std::memset(&desc, 0, sizeof(desc));
|
||||||
desc.entry_number = tibEntryNumber;
|
desc.entry_number = tibEntryNumber;
|
||||||
@@ -110,21 +107,22 @@ bool wibo::installTibForCurrentThread(TEB *tibPtr) {
|
|||||||
perror("set_thread_area failed");
|
perror("set_thread_area failed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (tibSelector == 0) {
|
if (tibEntryNumber != static_cast<int>(desc.entry_number)) {
|
||||||
tibEntryNumber = static_cast<int>(desc.entry_number);
|
tibEntryNumber = static_cast<int>(desc.entry_number);
|
||||||
tibSelector = static_cast<uint16_t>((desc.entry_number << 3) | 3);
|
DEBUG_LOG("set_thread_area: allocated entry=%d base=%p\n", tibEntryNumber, tibPtr);
|
||||||
DEBUG_LOG("set_thread_area: allocated selector=0x%x entry=%d base=%p\n", tibSelector, tibEntryNumber, tibPtr);
|
|
||||||
} else {
|
} 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<uint16_t>((desc.entry_number << 3) | 3);
|
||||||
|
tibPtr->HostGsSelector = 0;
|
||||||
|
currentThreadTeb = tibPtr;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make this global to ease debugging
|
// Make this global to ease debugging
|
||||||
TEB tib;
|
TEB tib;
|
||||||
|
|
||||||
const size_t MAPS_BUFFER_SIZE = 0x10000;
|
|
||||||
|
|
||||||
static std::string getExeName(const char *argv0) {
|
static std::string getExeName(const char *argv0) {
|
||||||
std::filesystem::path exePath(argv0 ? argv0 : "wibo");
|
std::filesystem::path exePath(argv0 ? argv0 : "wibo");
|
||||||
return exePath.filename().string();
|
return exePath.filename().string();
|
||||||
@@ -248,108 +246,6 @@ static int handlePathCommand(int argc, char **argv, const char *argv0) {
|
|||||||
return 0;
|
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<size_t>(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<size_t>(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) {
|
int main(int argc, char **argv) {
|
||||||
if (argc >= 2 && strcmp(argv[1], "path") == 0) {
|
if (argc >= 2 && strcmp(argv[1], "path") == 0) {
|
||||||
return handlePathCommand(argc - 2, argv + 2, argv[0]);
|
return handlePathCommand(argc - 2, argv + 2, argv[0]);
|
||||||
@@ -447,7 +343,6 @@ int main(int argc, char **argv) {
|
|||||||
wibo::debugIndent = std::stoul(debugIndentEnv);
|
wibo::debugIndent = std::stoul(debugIndentEnv);
|
||||||
}
|
}
|
||||||
|
|
||||||
blockUpper2GB();
|
|
||||||
files::init();
|
files::init();
|
||||||
|
|
||||||
// Create TIB
|
// Create TIB
|
||||||
@@ -463,7 +358,6 @@ int main(int argc, char **argv) {
|
|||||||
fprintf(stderr, "Failed to install TIB for main thread\n");
|
fprintf(stderr, "Failed to install TIB for main thread\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
wibo::setThreadTibForHost(&tib);
|
|
||||||
|
|
||||||
// Determine the guest program name
|
// Determine the guest program name
|
||||||
auto guestArgs = wibo::splitCommandLine(cmdLine.c_str());
|
auto guestArgs = wibo::splitCommandLine(cmdLine.c_str());
|
||||||
@@ -579,7 +473,7 @@ int main(int argc, char **argv) {
|
|||||||
}
|
}
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
const auto entryPoint = executable->entryPoint;
|
const auto entryPoint = reinterpret_cast<EntryProc>(executable->entryPoint);
|
||||||
if (!entryPoint) {
|
if (!entryPoint) {
|
||||||
fprintf(stderr, "Executable %s has no entry point\n", resolvedGuestPath.c_str());
|
fprintf(stderr, "Executable %s has no entry point\n", resolvedGuestPath.c_str());
|
||||||
return 1;
|
return 1;
|
||||||
@@ -609,7 +503,7 @@ int main(int argc, char **argv) {
|
|||||||
// Invoke the damn thing
|
// Invoke the damn thing
|
||||||
{
|
{
|
||||||
GUEST_CONTEXT_GUARD(&tib);
|
GUEST_CONTEXT_GUARD(&tib);
|
||||||
asm volatile("call *%0" : : "r"(entryPoint) : "memory");
|
call_EntryProc(entryPoint);
|
||||||
}
|
}
|
||||||
DEBUG_LOG("We came back\n");
|
DEBUG_LOG("We came back\n");
|
||||||
wibo::shutdownModuleRegistry();
|
wibo::shutdownModuleRegistry();
|
||||||
|
|||||||
@@ -2,9 +2,13 @@
|
|||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "context.h"
|
#include "context.h"
|
||||||
|
#include "entry.h"
|
||||||
|
#include "entry_trampolines.h"
|
||||||
#include "errors.h"
|
#include "errors.h"
|
||||||
#include "files.h"
|
#include "files.h"
|
||||||
#include "kernel32/internal.h"
|
#include "kernel32/internal.h"
|
||||||
|
#include "msvcrt.h"
|
||||||
|
#include "msvcrt_trampolines.h"
|
||||||
#include "strutil.h"
|
#include "strutil.h"
|
||||||
#include "tls.h"
|
#include "tls.h"
|
||||||
|
|
||||||
@@ -346,18 +350,11 @@ void runModuleTlsCallbacks(wibo::ModuleInfo &module, DWORD reason) {
|
|||||||
if (!module.tlsInfo.hasTls || module.tlsInfo.callbacks.empty()) {
|
if (!module.tlsInfo.hasTls || module.tlsInfo.callbacks.empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
TEB *tib = wibo::getThreadTibForHost();
|
for (auto *callback : module.tlsInfo.callbacks) {
|
||||||
if (!tib) {
|
if (!callback) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
GUEST_CONTEXT_GUARD(tib);
|
|
||||||
using TlsCallback = void(WIN_FUNC *)(void *, DWORD, void *);
|
|
||||||
for (void *callbackAddr : module.tlsInfo.callbacks) {
|
|
||||||
if (!callbackAddr) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
auto callback = reinterpret_cast<TlsCallback>(callbackAddr);
|
call_PIMAGE_TLS_CALLBACK(callback, module.handle, reason, nullptr);
|
||||||
callback(module.handle, reason, nullptr);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -565,8 +562,7 @@ BOOL callDllMain(wibo::ModuleInfo &info, DWORD reason, LPVOID reserved) {
|
|||||||
// Reset last error
|
// Reset last error
|
||||||
kernel32::setLastError(ERROR_SUCCESS);
|
kernel32::setLastError(ERROR_SUCCESS);
|
||||||
|
|
||||||
using DllMainFunc = BOOL(WIN_FUNC *)(HMODULE, DWORD, LPVOID);
|
auto dllMain = reinterpret_cast<DllEntryProc>(entry);
|
||||||
auto dllMain = reinterpret_cast<DllMainFunc>(entry);
|
|
||||||
|
|
||||||
auto invokeWithGuestTIB = [&](DWORD callReason, LPVOID callReserved, bool force) -> BOOL {
|
auto invokeWithGuestTIB = [&](DWORD callReason, LPVOID callReserved, bool force) -> BOOL {
|
||||||
if (!force) {
|
if (!force) {
|
||||||
@@ -586,14 +582,8 @@ BOOL callDllMain(wibo::ModuleInfo &info, DWORD reason, LPVOID reserved) {
|
|||||||
reinterpret_cast<HMODULE>(info.executable->imageBase), callReason, callReserved,
|
reinterpret_cast<HMODULE>(info.executable->imageBase), callReason, callReserved,
|
||||||
info.normalizedName.c_str());
|
info.normalizedName.c_str());
|
||||||
|
|
||||||
BOOL result = TRUE;
|
BOOL result =
|
||||||
if (!wibo::tibSelector) {
|
call_DllEntryProc(dllMain, reinterpret_cast<HMODULE>(info.executable->imageBase), callReason, callReserved);
|
||||||
result = dllMain(reinterpret_cast<HMODULE>(info.executable->imageBase), callReason, callReserved);
|
|
||||||
} else {
|
|
||||||
TEB *tib = wibo::getThreadTibForHost();
|
|
||||||
GUEST_CONTEXT_GUARD(tib);
|
|
||||||
result = dllMain(reinterpret_cast<HMODULE>(info.executable->imageBase), callReason, callReserved);
|
|
||||||
}
|
|
||||||
DEBUG_LOG(" callDllMain: %s DllMain returned %d\n", info.normalizedName.c_str(), result);
|
DEBUG_LOG(" callDllMain: %s DllMain returned %d\n", info.normalizedName.c_str(), result);
|
||||||
return 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)
|
if (!func)
|
||||||
return;
|
return;
|
||||||
auto reg = registry();
|
auto reg = registry();
|
||||||
@@ -887,17 +877,15 @@ void addOnExitFunction(void *table, void (*func)()) {
|
|||||||
reg->onExitTables[table] = info;
|
reg->onExitTables[table] = info;
|
||||||
}
|
}
|
||||||
if (info) {
|
if (info) {
|
||||||
info->onExitFunctions.push_back(reinterpret_cast<void *>(func));
|
info->onExitFunctions.push_back(func);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void runPendingOnExit(ModuleInfo &info) {
|
void runPendingOnExit(ModuleInfo &info) {
|
||||||
TEB *tib = wibo::getThreadTibForHost();
|
|
||||||
for (auto it = info.onExitFunctions.rbegin(); it != info.onExitFunctions.rend(); ++it) {
|
for (auto it = info.onExitFunctions.rbegin(); it != info.onExitFunctions.rend(); ++it) {
|
||||||
auto fn = reinterpret_cast<void (*)()>(*it);
|
auto *fn = *it;
|
||||||
if (fn) {
|
if (fn) {
|
||||||
GUEST_CONTEXT_GUARD(tib);
|
call__PVFV(fn);
|
||||||
fn();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
info.onExitFunctions.clear();
|
info.onExitFunctions.clear();
|
||||||
@@ -932,7 +920,7 @@ bool initializeModuleTls(ModuleInfo &module) {
|
|||||||
if (callbacksArray) {
|
if (callbacksArray) {
|
||||||
auto callbackPtr = reinterpret_cast<uintptr_t *>(callbacksArray);
|
auto callbackPtr = reinterpret_cast<uintptr_t *>(callbacksArray);
|
||||||
while (callbackPtr && *callbackPtr) {
|
while (callbackPtr && *callbackPtr) {
|
||||||
info.callbacks.push_back(reinterpret_cast<void *>(resolveModuleAddress(exec, *callbackPtr)));
|
info.callbacks.push_back(reinterpret_cast<PIMAGE_TLS_CALLBACK>(resolveModuleAddress(exec, *callbackPtr)));
|
||||||
++callbackPtr;
|
++callbackPtr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1068,10 +1056,9 @@ void notifyDllThreadAttach() {
|
|||||||
targets.push_back(info);
|
targets.push_back(info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TEB *tib = wibo::getThreadTibForHost();
|
|
||||||
for (wibo::ModuleInfo *info : targets) {
|
for (wibo::ModuleInfo *info : targets) {
|
||||||
if (info && info->tlsInfo.hasTls && tib) {
|
if (info && info->tlsInfo.hasTls) {
|
||||||
if (!allocateModuleTlsForThread(*info, tib)) {
|
if (!allocateModuleTlsForThread(*info, currentThreadTeb)) {
|
||||||
DEBUG_LOG("notifyDllThreadAttach: failed to allocate TLS for %s\n", info->originalName.c_str());
|
DEBUG_LOG("notifyDllThreadAttach: failed to allocate TLS for %s\n", info->originalName.c_str());
|
||||||
}
|
}
|
||||||
runModuleTlsCallbacks(*info, TLS_THREAD_ATTACH);
|
runModuleTlsCallbacks(*info, TLS_THREAD_ATTACH);
|
||||||
@@ -1093,9 +1080,8 @@ void notifyDllThreadDetach() {
|
|||||||
targets.push_back(info);
|
targets.push_back(info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TEB *tib = wibo::getThreadTibForHost();
|
|
||||||
for (auto it = targets.rbegin(); it != targets.rend(); ++it) {
|
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);
|
runModuleTlsCallbacks(**it, TLS_THREAD_DETACH);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1103,8 +1089,8 @@ void notifyDllThreadDetach() {
|
|||||||
callDllMain(**it, DLL_THREAD_DETACH, nullptr);
|
callDllMain(**it, DLL_THREAD_DETACH, nullptr);
|
||||||
}
|
}
|
||||||
for (auto it = targets.rbegin(); it != targets.rend(); ++it) {
|
for (auto it = targets.rbegin(); it != targets.rend(); ++it) {
|
||||||
if (*it && (*it)->tlsInfo.hasTls && tib) {
|
if (*it && (*it)->tlsInfo.hasTls) {
|
||||||
freeModuleTlsForThread(**it, tib);
|
freeModuleTlsForThread(**it, currentThreadTeb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
kernel32::setLastError(ERROR_SUCCESS);
|
kernel32::setLastError(ERROR_SUCCESS);
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "entry.h"
|
||||||
|
#include "msvcrt.h"
|
||||||
#include "tls.h"
|
#include "tls.h"
|
||||||
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
@@ -73,7 +75,7 @@ struct ModuleTlsInfo {
|
|||||||
size_t zeroFillSize = 0;
|
size_t zeroFillSize = 0;
|
||||||
uint32_t characteristics = 0;
|
uint32_t characteristics = 0;
|
||||||
size_t allocationSize = 0;
|
size_t allocationSize = 0;
|
||||||
std::vector<void *> callbacks;
|
std::vector<PIMAGE_TLS_CALLBACK> callbacks;
|
||||||
std::unordered_map<TEB *, void *> threadAllocations;
|
std::unordered_map<TEB *, void *> threadAllocations;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -100,7 +102,7 @@ struct ModuleInfo {
|
|||||||
std::vector<void *> exportsByOrdinal;
|
std::vector<void *> exportsByOrdinal;
|
||||||
std::unordered_map<std::string, uint16_t> exportNameToOrdinal;
|
std::unordered_map<std::string, uint16_t> exportNameToOrdinal;
|
||||||
bool exportsInitialized = false;
|
bool exportsInitialized = false;
|
||||||
std::vector<void *> onExitFunctions;
|
std::vector<_PVFV> onExitFunctions;
|
||||||
ModuleTlsInfo tlsInfo;
|
ModuleTlsInfo tlsInfo;
|
||||||
};
|
};
|
||||||
extern ModuleInfo *mainModule;
|
extern ModuleInfo *mainModule;
|
||||||
@@ -115,7 +117,7 @@ void clearDllDirectoryOverride();
|
|||||||
std::optional<std::filesystem::path> dllDirectoryOverride();
|
std::optional<std::filesystem::path> dllDirectoryOverride();
|
||||||
ModuleInfo *findLoadedModule(const char *name);
|
ModuleInfo *findLoadedModule(const char *name);
|
||||||
void registerOnExitTable(void *table);
|
void registerOnExitTable(void *table);
|
||||||
void addOnExitFunction(void *table, void (*func)());
|
void addOnExitFunction(void *table, _PVFV func);
|
||||||
void executeOnExitTable(void *table);
|
void executeOnExitTable(void *table);
|
||||||
void runPendingOnExit(ModuleInfo &info);
|
void runPendingOnExit(ModuleInfo &info);
|
||||||
void notifyDllThreadAttach();
|
void notifyDllThreadAttach();
|
||||||
|
|||||||
@@ -357,9 +357,9 @@ bool setValue(TEB *tib, DWORD index, void *value) {
|
|||||||
return true;
|
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) {
|
void forEachTib(void (*callback)(TEB *, void *), void *context) {
|
||||||
if (!callback) {
|
if (!callback) {
|
||||||
|
|||||||
173
src/types.h
173
src/types.h
@@ -28,10 +28,16 @@
|
|||||||
#define _Out_writes_bytes_(n) WIBO_ANNOTATE("SAL:out_bcount(" #n ")")
|
#define _Out_writes_bytes_(n) WIBO_ANNOTATE("SAL:out_bcount(" #n ")")
|
||||||
|
|
||||||
// Codegen annotation for calling convention
|
// Codegen annotation for calling convention
|
||||||
|
#define _CC_CDECL WIBO_ANNOTATE("CC:cdecl")
|
||||||
#define _CC_STDCALL WIBO_ANNOTATE("CC:stdcall")
|
#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 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 VOID = void;
|
||||||
using HANDLE = VOID *;
|
using HANDLE = VOID *;
|
||||||
@@ -39,6 +45,7 @@ using HMODULE = VOID *;
|
|||||||
using HGLOBAL = HANDLE;
|
using HGLOBAL = HANDLE;
|
||||||
using HLOCAL = HANDLE;
|
using HLOCAL = HANDLE;
|
||||||
using HRSRC = HANDLE;
|
using HRSRC = HANDLE;
|
||||||
|
using HINSTANCE = HANDLE;
|
||||||
using LPHANDLE = HANDLE *;
|
using LPHANDLE = HANDLE *;
|
||||||
using PHANDLE = HANDLE *;
|
using PHANDLE = HANDLE *;
|
||||||
using HKL = HANDLE;
|
using HKL = HANDLE;
|
||||||
@@ -57,13 +64,13 @@ using LONG = int;
|
|||||||
using PLONG = LONG *;
|
using PLONG = LONG *;
|
||||||
using ULONG = unsigned int;
|
using ULONG = unsigned int;
|
||||||
using PULONG = ULONG *;
|
using PULONG = ULONG *;
|
||||||
using LARGE_INTEGER = long long;
|
using LONGLONG = long long;
|
||||||
using PLARGE_INTEGER = LARGE_INTEGER *;
|
using ULONGLONG = unsigned long long;
|
||||||
using ULARGE_INTEGER = unsigned long long;
|
using LONG_PTR = long;
|
||||||
using PULARGE_INTEGER = ULARGE_INTEGER *;
|
static_assert(sizeof(LONG_PTR) == sizeof(void *), "LONG_PTR must be pointer-sized");
|
||||||
using ULONG_PTR = unsigned long;
|
using ULONG_PTR = unsigned long;
|
||||||
using UINT_PTR = unsigned long;
|
|
||||||
static_assert(sizeof(ULONG_PTR) == sizeof(void *), "ULONG_PTR must be pointer-sized");
|
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");
|
static_assert(sizeof(UINT_PTR) == sizeof(void *), "UINT_PTR must be pointer-sized");
|
||||||
using DWORD_PTR = ULONG_PTR;
|
using DWORD_PTR = ULONG_PTR;
|
||||||
using PDWORD_PTR = DWORD_PTR *;
|
using PDWORD_PTR = DWORD_PTR *;
|
||||||
@@ -89,6 +96,7 @@ using PSIZE_T = SIZE_T *;
|
|||||||
using BYTE = unsigned char;
|
using BYTE = unsigned char;
|
||||||
using BOOLEAN = unsigned char;
|
using BOOLEAN = unsigned char;
|
||||||
using UINT = unsigned int;
|
using UINT = unsigned int;
|
||||||
|
using PUINT = UINT *;
|
||||||
using HKEY = VOID *;
|
using HKEY = VOID *;
|
||||||
using PHKEY = HKEY *;
|
using PHKEY = HKEY *;
|
||||||
using PSID = VOID *;
|
using PSID = VOID *;
|
||||||
@@ -105,6 +113,30 @@ using PWSTR = WCHAR *;
|
|||||||
using NTSTATUS = LONG;
|
using NTSTATUS = LONG;
|
||||||
using HRESULT = 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 {
|
struct GUID {
|
||||||
DWORD Data1;
|
DWORD Data1;
|
||||||
WORD Data2;
|
WORD Data2;
|
||||||
@@ -260,7 +292,7 @@ typedef struct _PEB_LDR_DATA {
|
|||||||
LIST_ENTRY InMemoryOrderModuleList;
|
LIST_ENTRY InMemoryOrderModuleList;
|
||||||
} PEB_LDR_DATA, *PPEB_LDR_DATA;
|
} 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 *;
|
using PPS_POST_PROCESS_INIT_ROUTINE = PS_POST_PROCESS_INIT_ROUTINE *;
|
||||||
|
|
||||||
typedef struct _PEB {
|
typedef struct _PEB {
|
||||||
@@ -327,69 +359,70 @@ typedef struct _NT_TIB {
|
|||||||
} NT_TIB, *PNT_TIB;
|
} NT_TIB, *PNT_TIB;
|
||||||
|
|
||||||
typedef struct _TEB {
|
typedef struct _TEB {
|
||||||
NT_TIB Tib; /* 000 */
|
NT_TIB Tib;
|
||||||
PVOID EnvironmentPointer; /* 01c */
|
PVOID EnvironmentPointer;
|
||||||
CLIENT_ID ClientId; /* 020 */
|
CLIENT_ID ClientId;
|
||||||
PVOID ActiveRpcHandle; /* 028 */
|
PVOID ActiveRpcHandle;
|
||||||
PVOID ThreadLocalStoragePointer; /* 02c */
|
PVOID ThreadLocalStoragePointer;
|
||||||
PPEB Peb; /* 030 */
|
PPEB Peb;
|
||||||
ULONG LastErrorValue; /* 034 */
|
ULONG LastErrorValue;
|
||||||
ULONG CountOfOwnedCriticalSections; /* 038 */
|
ULONG CountOfOwnedCriticalSections;
|
||||||
PVOID CsrClientThread; /* 03c */
|
PVOID CsrClientThread;
|
||||||
PVOID Win32ThreadInfo; /* 040 */
|
PVOID Win32ThreadInfo;
|
||||||
ULONG Win32ClientInfo[31]; /* 044 used for user32 private data in Wine */
|
ULONG Win32ClientInfo[31]; /* used for user32 private data in Wine */
|
||||||
PVOID WOW32Reserved; /* 0c0 */
|
PVOID WOW32Reserved;
|
||||||
ULONG CurrentLocale; /* 0c4 */
|
ULONG CurrentLocale;
|
||||||
ULONG FpSoftwareStatusRegister; /* 0c8 */
|
ULONG FpSoftwareStatusRegister;
|
||||||
PVOID SystemReserved1[54]; /* 0cc used for kernel32 private data in Wine */
|
PVOID SystemReserved1[54]; /* used for kernel32 private data in Wine */
|
||||||
PVOID Spare1; /* 1a4 */
|
PVOID Spare1;
|
||||||
LONG ExceptionCode; /* 1a8 */
|
LONG ExceptionCode;
|
||||||
PVOID ActivationContextStackPointer; /* 1a8/02c8 */
|
PVOID ActivationContextStackPointer;
|
||||||
BYTE SpareBytes1[36]; /* 1ac */
|
BYTE SpareBytes1[36];
|
||||||
PVOID SystemReserved2[10]; /* 1d4 used for ntdll private data in Wine */
|
PVOID SystemReserved2[10]; /* used for ntdll private data in Wine */
|
||||||
GDI_TEB_BATCH GdiTebBatch; /* 1fc */
|
GDI_TEB_BATCH GdiTebBatch;
|
||||||
ULONG gdiRgn; /* 6dc */
|
ULONG gdiRgn;
|
||||||
ULONG gdiPen; /* 6e0 */
|
ULONG gdiPen;
|
||||||
ULONG gdiBrush; /* 6e4 */
|
ULONG gdiBrush;
|
||||||
CLIENT_ID RealClientId; /* 6e8 */
|
CLIENT_ID RealClientId;
|
||||||
HANDLE GdiCachedProcessHandle; /* 6f0 */
|
HANDLE GdiCachedProcessHandle;
|
||||||
ULONG GdiClientPID; /* 6f4 */
|
ULONG GdiClientPID;
|
||||||
ULONG GdiClientTID; /* 6f8 */
|
ULONG GdiClientTID;
|
||||||
PVOID GdiThreadLocaleInfo; /* 6fc */
|
PVOID GdiThreadLocaleInfo;
|
||||||
PVOID UserReserved[5]; /* 700 */
|
PVOID UserReserved[5];
|
||||||
PVOID glDispatchTable[280]; /* 714 */
|
PVOID glDispatchTable[280];
|
||||||
ULONG glReserved1[26]; /* b74 */
|
ULONG glReserved1[26];
|
||||||
PVOID glReserved2; /* bdc */
|
PVOID glReserved2;
|
||||||
PVOID glSectionInfo; /* be0 */
|
PVOID glSectionInfo;
|
||||||
PVOID glSection; /* be4 */
|
PVOID glSection;
|
||||||
PVOID glTable; /* be8 */
|
PVOID glTable;
|
||||||
PVOID glCurrentRC; /* bec */
|
PVOID glCurrentRC;
|
||||||
PVOID glContext; /* bf0 */
|
PVOID glContext;
|
||||||
ULONG LastStatusValue; /* bf4 */
|
ULONG LastStatusValue;
|
||||||
UNICODE_STRING StaticUnicodeString; /* bf8 used by advapi32 */
|
UNICODE_STRING StaticUnicodeString;
|
||||||
WCHAR StaticUnicodeBuffer[261]; /* c00 used by advapi32 */
|
WCHAR StaticUnicodeBuffer[261];
|
||||||
PVOID DeallocationStack; /* e0c */
|
PVOID DeallocationStack;
|
||||||
PVOID TlsSlots[64]; /* e10 */
|
PVOID TlsSlots[64];
|
||||||
LIST_ENTRY TlsLinks; /* f10 */
|
LIST_ENTRY TlsLinks;
|
||||||
PVOID Vdm; /* f18 */
|
PVOID Vdm;
|
||||||
PVOID ReservedForNtRpc; /* f1c */
|
PVOID ReservedForNtRpc;
|
||||||
PVOID DbgSsReserved[2]; /* f20 */
|
PVOID DbgSsReserved[2];
|
||||||
ULONG HardErrorDisabled; /* f28 */
|
ULONG HardErrorDisabled;
|
||||||
PVOID Instrumentation[16]; /* f2c */
|
PVOID Instrumentation[16];
|
||||||
PVOID WinSockData; /* f6c */
|
PVOID WinSockData;
|
||||||
ULONG GdiBatchCount; /* f70 */
|
ULONG GdiBatchCount;
|
||||||
ULONG Spare2; /* f74 */
|
ULONG Spare2;
|
||||||
ULONG Spare3; /* f78 */
|
ULONG Spare3;
|
||||||
ULONG Spare4; /* f7c */
|
ULONG Spare4;
|
||||||
PVOID ReservedForOle; /* f80 */
|
PVOID ReservedForOle;
|
||||||
ULONG WaitingOnLoaderLock; /* f84 */
|
ULONG WaitingOnLoaderLock;
|
||||||
PVOID Reserved5[3]; /* f88 */
|
PVOID Reserved5[3];
|
||||||
PVOID *TlsExpansionSlots; /* f94 */
|
PVOID *TlsExpansionSlots;
|
||||||
// Custom
|
// wibo
|
||||||
unsigned short hostFsSelector;
|
WORD HostFsSelector;
|
||||||
unsigned short hostGsSelector;
|
WORD HostGsSelector;
|
||||||
bool hostSegmentsValid;
|
PVOID HostStackBase;
|
||||||
unsigned char padding[3];
|
PVOID HostStackLimit;
|
||||||
|
PVOID HostStackPointer;
|
||||||
} TEB, *PTEB;
|
} TEB, *PTEB;
|
||||||
|
|
||||||
#ifndef offsetof
|
#ifndef offsetof
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ static void create_file_with_content(const char *path, const char *content) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void setup_fixture(void) {
|
static void setup_fixture(void) {
|
||||||
|
TEST_CHECK_EQ(2, sizeof(wint_t));
|
||||||
|
|
||||||
DWORD len = GetCurrentDirectoryA(sizeof(g_original_dir), g_original_dir);
|
DWORD len = GetCurrentDirectoryA(sizeof(g_original_dir), g_original_dir);
|
||||||
TEST_CHECK(len > 0 && len < sizeof(g_original_dir));
|
TEST_CHECK(len > 0 && len < sizeof(g_original_dir));
|
||||||
|
|
||||||
|
|||||||
@@ -15,9 +15,14 @@ if __name__ == "__main__":
|
|||||||
script_venv.bootstrap_venv(__file__)
|
script_venv.bootstrap_venv(__file__)
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
|
import ctypes
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
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 (
|
from clang.cindex import (
|
||||||
Config,
|
Config,
|
||||||
@@ -25,10 +30,12 @@ from clang.cindex import (
|
|||||||
CursorKind,
|
CursorKind,
|
||||||
Index,
|
Index,
|
||||||
TranslationUnit,
|
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
|
# Allow libclang path to be specified via environment variable
|
||||||
if "LIBCLANG_PATH" in os.environ:
|
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
|
@dataclass
|
||||||
class FuncInfo:
|
class FuncInfo:
|
||||||
qualified_ns: str
|
qualified_ns: str
|
||||||
name: str
|
name: str
|
||||||
mangled: str
|
mangled: str
|
||||||
argc: int
|
source_cc: CallingConv
|
||||||
stdcall: bool
|
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(
|
def parse_tu(
|
||||||
@@ -89,15 +158,85 @@ def _cursor_namespace(cursor: Cursor) -> List[str]:
|
|||||||
return list(reversed(ns))
|
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():
|
for child in func.get_children():
|
||||||
if child.kind == CursorKind.ANNOTATE_ATTR and child.spelling == "CC:stdcall":
|
if child.kind == CursorKind.ANNOTATE_ATTR:
|
||||||
return True
|
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
|
return False
|
||||||
|
|
||||||
|
|
||||||
def _arg_count(func: Cursor) -> int:
|
SIGNED_KINDS = [
|
||||||
return sum(1 for _ in func.type.argument_types())
|
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]:
|
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)
|
ns_parts = _cursor_namespace(node)
|
||||||
if want_ns is not None and ns_parts != want_ns:
|
if want_ns is not None and ns_parts != want_ns:
|
||||||
return
|
return
|
||||||
name = node.spelling or ""
|
name = node.spelling
|
||||||
mangled = getattr(node, "mangled_name", None) or ""
|
if not name:
|
||||||
if not name or not mangled:
|
|
||||||
return
|
return
|
||||||
|
source_cc = _source_cc_from_annotations(node)
|
||||||
|
if source_cc == CallingConv.DEFAULT:
|
||||||
|
return # No CC annotation; skip
|
||||||
out[name] = FuncInfo(
|
out[name] = FuncInfo(
|
||||||
qualified_ns="::".join(ns_parts),
|
qualified_ns="::".join(ns_parts),
|
||||||
name=name,
|
name=name,
|
||||||
mangled=mangled,
|
mangled=node.mangled_name or name,
|
||||||
argc=_arg_count(node),
|
args=_collect_args(node.type),
|
||||||
stdcall=_has_stdcall_annotation(node),
|
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):
|
if node.kind in (CursorKind.TRANSLATION_UNIT, CursorKind.NAMESPACE):
|
||||||
for c in node.get_children():
|
for c in node.get_children():
|
||||||
visit(c)
|
visit(c)
|
||||||
|
|
||||||
visit(tu.cursor)
|
if tu.cursor is not None:
|
||||||
|
visit(tu.cursor)
|
||||||
return sorted(out.values(), key=lambda f: f.name)
|
return sorted(out.values(), key=lambda f: f.name)
|
||||||
|
|
||||||
|
|
||||||
def emit_x86_asm_trampolines(dll: str, funcs: Iterable[FuncInfo]) -> str:
|
def _type_to_string(t: CXType) -> str:
|
||||||
lines: List[str] = []
|
"""Convert a CXType to a C type string."""
|
||||||
lines.append("#\tAuto-generated trampolines; DO NOT EDIT.")
|
spelling = t.spelling
|
||||||
lines.append(".section .note.GNU-stack, \"\", @progbits")
|
# Clean up common type spellings
|
||||||
lines.append(".text")
|
spelling = (
|
||||||
for f in funcs:
|
spelling.replace("struct ", "").replace("union ", "").replace("enum ", "")
|
||||||
name = f.name
|
)
|
||||||
mangled = f.mangled
|
return spelling
|
||||||
# Ensure ms_abi is encoded for stdcall function-pointer types to match GCC
|
|
||||||
# mangled = mangled.replace("U7stdcall", "U7stdcallU6ms_abi")
|
|
||||||
tramp = f"thunk_{dll}_{name}"
|
def collect_typedefs(tu: TranslationUnit) -> List[TypedefInfo]:
|
||||||
lines.append("")
|
"""Collect function pointer typedefs and type aliases from the translation unit."""
|
||||||
lines.append(f".globl {tramp}")
|
out: dict[str, TypedefInfo] = {}
|
||||||
lines.append(f".type {tramp}, @function")
|
|
||||||
lines.append(f"{tramp}:")
|
def process_function_pointer_type(
|
||||||
argc = int(f.argc or 0)
|
name: str, node: Cursor, func_type: CXType
|
||||||
# Calculate number of stack args (fastcall uses ECX/EDX for first 2)
|
) -> None:
|
||||||
stack_argc = max(0, argc - 2)
|
"""Process a function pointer type and add it to the output."""
|
||||||
stack_bytes = stack_argc * 4
|
if not name:
|
||||||
# Use frame pointer for clean alignment and argument access
|
return
|
||||||
lines.append("\tpush %ebp")
|
|
||||||
lines.append("\tmovl %esp, %ebp")
|
# Determine calling convention
|
||||||
# Align stack: we want ESP = 16n before the call,
|
source_cc = _get_function_calling_conv(func_type)
|
||||||
# so that after call pushes return address, callee sees ESP = 16n - 4
|
target_cc = _source_cc_from_annotations(node)
|
||||||
# After pushing stack_bytes worth of args, we need ESP = 16n + stack_bytes
|
if target_cc == CallingConv.DEFAULT:
|
||||||
if stack_bytes > 0:
|
return # No CC annotation; skip
|
||||||
lines.append(f"\tleal -{stack_bytes}(%ebp), %esp")
|
|
||||||
lines.append("\tandl $0xFFFFFFF0, %esp")
|
variadic = func_type.is_function_variadic()
|
||||||
lines.append(f"\taddl ${stack_bytes}, %esp")
|
args = _collect_args(func_type)
|
||||||
else:
|
return_type = _type_to_string(func_type.get_result())
|
||||||
# No stack args, just align to 16n for the call
|
|
||||||
lines.append("\tandl $0xFFFFFFF0, %esp")
|
out[name] = TypedefInfo(
|
||||||
# Move first two args into ECX/EDX for fastcall
|
name=name,
|
||||||
if argc >= 1:
|
source_cc=source_cc,
|
||||||
lines.append("\tmovl 8(%ebp), %ecx")
|
target_cc=target_cc,
|
||||||
if argc >= 2:
|
variadic=variadic,
|
||||||
lines.append("\tmovl 12(%ebp), %edx")
|
return_type=return_type,
|
||||||
# Push remaining args (from last down to the 3rd) so layout matches fastcall
|
args=args,
|
||||||
for i in range(argc, 2, -1):
|
)
|
||||||
off = 4 * (i + 1) # +1 because EBP offset includes pushed EBP
|
|
||||||
lines.append(f"\tpushl {off}(%ebp)")
|
def visit(node: Cursor) -> None:
|
||||||
# Call into fastcall stub
|
if node.kind == CursorKind.TYPEDEF_DECL:
|
||||||
lines.append(f"\tcall {mangled}")
|
name = node.spelling
|
||||||
# Restore stack and frame pointer
|
if not name:
|
||||||
lines.append("\tleave")
|
return
|
||||||
# Return to guest
|
underlying = node.underlying_typedef_type
|
||||||
argb = argc * 4
|
if underlying.kind == TypeKind.POINTER:
|
||||||
if f.stdcall and argb:
|
pointee = underlying.get_pointee()
|
||||||
lines.append(f"\tret ${argb}")
|
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:
|
else:
|
||||||
lines.append("\tret")
|
lines.append("\tret")
|
||||||
lines.append(f".size {tramp}, . - {tramp}")
|
elif f.source_cc == CallingConv.C:
|
||||||
return "\n".join(lines) + "\n"
|
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:
|
def emit_guest_to_host_thunks(
|
||||||
guard = f"WIBO_GEN_{dll.upper()}_TRAMPOLINES_H"
|
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: List[str] = []
|
||||||
lines.append("/* Auto-generated; DO NOT EDIT. */")
|
lines.append("/* Auto-generated; DO NOT EDIT. */")
|
||||||
lines.append(f"#ifndef {guard}")
|
lines.append(f"#ifndef {guard}")
|
||||||
@@ -193,19 +516,36 @@ def emit_header_mapping(dll: str, funcs: Iterable[FuncInfo]) -> str:
|
|||||||
lines.append("#include <stddef.h>")
|
lines.append("#include <stddef.h>")
|
||||||
lines.append("#include <string.h>")
|
lines.append("#include <string.h>")
|
||||||
lines.append('#ifdef __cplusplus\nextern "C" {\n#endif')
|
lines.append('#ifdef __cplusplus\nextern "C" {\n#endif')
|
||||||
|
|
||||||
|
# Guest-to-host thunk functions
|
||||||
for f in funcs:
|
for f in funcs:
|
||||||
tramp = f"thunk_{dll}_{f.name}"
|
thunk = f"thunk_{dll}_{f.name}"
|
||||||
lines.append(f"void {tramp}(void);")
|
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("#ifdef __cplusplus\n}\n#endif")
|
||||||
lines.append("")
|
lines.append("")
|
||||||
# name->address helper for resolveByName
|
# 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:
|
for f in funcs:
|
||||||
lines.append(
|
lines.append(
|
||||||
f'\tif (strcmp(name, "{f.name}") == 0) return (void*)&thunk_{dll}_{f.name};'
|
f'\tif (strcmp(name, "{f.name}") == 0) return (void*)&thunk_{dll}_{f.name};'
|
||||||
)
|
)
|
||||||
lines.append("\treturn NULL;")
|
lines.append("\treturn NULL;")
|
||||||
lines.append("}")
|
lines.append("}")
|
||||||
|
|
||||||
lines.append(f"#endif /* {guard} */\n")
|
lines.append(f"#endif /* {guard} */\n")
|
||||||
return "\n".join(lines)
|
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"
|
target = "i686-pc-linux-gnu" if args.arch == "x86" else "x86_64-pc-linux-gnu"
|
||||||
tu = parse_tu(args.headers, args.incs, target)
|
tu = parse_tu(args.headers, args.incs, target)
|
||||||
funcs = collect_functions(tu, args.ns)
|
funcs = collect_functions(tu, args.ns)
|
||||||
if not funcs:
|
typedefs = collect_typedefs(tu)
|
||||||
sys.stderr.write("No functions found for generation.\n")
|
|
||||||
|
if not funcs and not typedefs:
|
||||||
|
sys.stderr.write("No functions or typedefs found for generation.\n")
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
asm = emit_x86_asm_trampolines(args.dll, funcs)
|
lines: List[str] = []
|
||||||
hdr = emit_header_mapping(args.dll, funcs)
|
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_asm.parent.mkdir(parents=True, exist_ok=True)
|
||||||
args.out_hdr.parent.mkdir(parents=True, exist_ok=True)
|
args.out_hdr.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
|||||||
Reference in New Issue
Block a user