Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -220,11 +220,13 @@ add_executable(wibo
dll/mscoree.cpp
dll/ntdll.cpp
dll/ole32.cpp
dll/psapi.cpp
dll/rpcrt4.cpp
dll/shlwapi.cpp
dll/user32.cpp
dll/vcruntime.cpp
dll/version.cpp
dll/winmm.cpp
dll/ws2.cpp
src/access.cpp
src/async_io.cpp
Expand Down Expand Up @@ -376,8 +378,10 @@ wibo_codegen_module(NAME bcrypt HEADERS dll/bcrypt.h)
wibo_codegen_module(NAME entry HEADERS src/entry.h)
wibo_codegen_module(NAME mscoree HEADERS dll/mscoree.h)
wibo_codegen_module(NAME version HEADERS dll/version.h)
wibo_codegen_module(NAME psapi HEADERS dll/psapi.h)
wibo_codegen_module(NAME rpcrt4 HEADERS dll/rpcrt4.h)
wibo_codegen_module(NAME shlwapi HEADERS dll/shlwapi.h)
wibo_codegen_module(NAME winmm HEADERS dll/winmm.h)
wibo_codegen_module(NAME ws2 HEADERS dll/ws2.h)
wibo_codegen_module(NAME vcruntime HEADERS dll/vcruntime.h)
wibo_codegen_module(NAME lmgr HEADERS dll/lmgr.h)
Expand Down
116 changes: 116 additions & 0 deletions dll/kernel32/fileapi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -539,11 +539,35 @@ std::optional<DWORD> stdHandleForConsoleDevice(const std::string &name, DWORD de
return std::nullopt;
}

bool isConsoleOutputDevice(const std::string &name, DWORD desiredAccess) {
std::string lowered = stringToLower(name);
return lowered == "conout$" || (lowered == "con" && (desiredAccess & GENERIC_WRITE) != 0);
}

bool tryOpenHostConsoleOutput(DWORD desiredAccess, HANDLE &outHandle) {
int fd = open("/dev/tty", O_WRONLY | O_CLOEXEC);
if (fd < 0) {
return false;
}

auto fileObj = make_pin<FileObject>(fd);
fileObj->appendOnly = true;
uint32_t grantedAccess = FILE_GENERIC_WRITE;
if ((desiredAccess & GENERIC_READ) != 0) {
grantedAccess |= FILE_GENERIC_READ;
}
outHandle = wibo::handles().alloc(std::move(fileObj), grantedAccess, 0);
return true;
}

bool tryOpenConsoleDevice(DWORD dwDesiredAccess, DWORD dwShareMode, DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes, HANDLE &outHandle, const std::string &originalName) {
(void)dwShareMode;
(void)dwCreationDisposition;
(void)dwFlagsAndAttributes;
if (isConsoleOutputDevice(originalName, dwDesiredAccess) && tryOpenHostConsoleOutput(dwDesiredAccess, outHandle)) {
return true;
}
auto stdHandleKind = stdHandleForConsoleDevice(originalName, dwDesiredAccess);
if (!stdHandleKind) {
return false;
Expand Down Expand Up @@ -1597,6 +1621,98 @@ DWORD WINAPI GetFileType(HANDLE hFile) {
return type;
}

BOOL WINAPI ClearCommBreak(HANDLE hFile) {
HOST_CONTEXT_GUARD();
DEBUG_LOG("ClearCommBreak(%p) -> ERROR_INVALID_HANDLE\n", hFile);
setLastError(ERROR_INVALID_HANDLE);
return FALSE;
}

BOOL WINAPI ClearCommError(HANDLE hFile, LPDWORD lpErrors, LPVOID lpStat) {
HOST_CONTEXT_GUARD();
DEBUG_LOG("ClearCommError(%p, %p, %p) -> ERROR_INVALID_HANDLE\n", hFile, lpErrors, lpStat);
if (lpErrors) {
*lpErrors = 0;
}
setLastError(ERROR_INVALID_HANDLE);
return FALSE;
}

BOOL WINAPI EscapeCommFunction(HANDLE hFile, DWORD dwFunc) {
HOST_CONTEXT_GUARD();
DEBUG_LOG("EscapeCommFunction(%p, %u) -> ERROR_INVALID_HANDLE\n", hFile, dwFunc);
setLastError(ERROR_INVALID_HANDLE);
return FALSE;
}

BOOL WINAPI GetCommModemStatus(HANDLE hFile, LPDWORD lpModemStat) {
HOST_CONTEXT_GUARD();
DEBUG_LOG("GetCommModemStatus(%p, %p) -> ERROR_INVALID_HANDLE\n", hFile, lpModemStat);
if (lpModemStat) {
*lpModemStat = 0;
}
setLastError(ERROR_INVALID_HANDLE);
return FALSE;
}

BOOL WINAPI GetCommState(HANDLE hFile, LPVOID lpDCB) {
HOST_CONTEXT_GUARD();
DEBUG_LOG("GetCommState(%p, %p) -> ERROR_INVALID_HANDLE\n", hFile, lpDCB);
// Cygwin probes std handles as possible serial devices during fd setup.
// wibo does not emulate COM ports, so non-console pipes/files must fail this probe.
setLastError(ERROR_INVALID_HANDLE);
return FALSE;
}

BOOL WINAPI PurgeComm(HANDLE hFile, DWORD dwFlags) {
HOST_CONTEXT_GUARD();
DEBUG_LOG("PurgeComm(%p, 0x%x) -> ERROR_INVALID_HANDLE\n", hFile, dwFlags);
setLastError(ERROR_INVALID_HANDLE);
return FALSE;
}

BOOL WINAPI SetCommBreak(HANDLE hFile) {
HOST_CONTEXT_GUARD();
DEBUG_LOG("SetCommBreak(%p) -> ERROR_INVALID_HANDLE\n", hFile);
setLastError(ERROR_INVALID_HANDLE);
return FALSE;
}

BOOL WINAPI SetCommMask(HANDLE hFile, DWORD dwEvtMask) {
HOST_CONTEXT_GUARD();
DEBUG_LOG("SetCommMask(%p, 0x%x) -> ERROR_INVALID_HANDLE\n", hFile, dwEvtMask);
setLastError(ERROR_INVALID_HANDLE);
return FALSE;
}

BOOL WINAPI SetCommState(HANDLE hFile, LPVOID lpDCB) {
HOST_CONTEXT_GUARD();
DEBUG_LOG("SetCommState(%p, %p) -> ERROR_INVALID_HANDLE\n", hFile, lpDCB);
setLastError(ERROR_INVALID_HANDLE);
return FALSE;
}

BOOL WINAPI SetCommTimeouts(HANDLE hFile, LPVOID lpCommTimeouts) {
HOST_CONTEXT_GUARD();
DEBUG_LOG("SetCommTimeouts(%p, %p) -> ERROR_INVALID_HANDLE\n", hFile, lpCommTimeouts);
setLastError(ERROR_INVALID_HANDLE);
return FALSE;
}

BOOL WINAPI TransmitCommChar(HANDLE hFile, char cChar) {
HOST_CONTEXT_GUARD();
DEBUG_LOG("TransmitCommChar(%p, 0x%x) -> ERROR_INVALID_HANDLE\n", hFile, static_cast<unsigned char>(cChar));
setLastError(ERROR_INVALID_HANDLE);
return FALSE;
}

BOOL WINAPI WaitCommEvent(HANDLE hFile, LPDWORD lpEvtMask, LPOVERLAPPED lpOverlapped) {
HOST_CONTEXT_GUARD();
DEBUG_LOG("WaitCommEvent(%p, %p, %p) -> ERROR_INVALID_HANDLE\n", hFile, lpEvtMask, lpOverlapped);
setLastError(ERROR_INVALID_HANDLE);
return FALSE;
}

DWORD WINAPI GetFullPathNameA(LPCSTR lpFileName, DWORD nBufferLength, LPSTR lpBuffer, GUEST_PTR *lpFilePart) {
HOST_CONTEXT_GUARD();
DEBUG_LOG("GetFullPathNameA(%s, %u)\n", lpFileName ? lpFileName : "(null)", nBufferLength);
Expand Down
12 changes: 12 additions & 0 deletions dll/kernel32/fileapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,18 @@ BOOL WINAPI SetFileTime(HANDLE hFile, const FILETIME *lpCreationTime, const FILE
const FILETIME *lpLastWriteTime);
BOOL WINAPI GetFileInformationByHandle(HANDLE hFile, LPBY_HANDLE_FILE_INFORMATION lpFileInformation);
DWORD WINAPI GetFileType(HANDLE hFile);
BOOL WINAPI ClearCommBreak(HANDLE hFile);
BOOL WINAPI ClearCommError(HANDLE hFile, LPDWORD lpErrors, LPVOID lpStat);
BOOL WINAPI EscapeCommFunction(HANDLE hFile, DWORD dwFunc);
BOOL WINAPI GetCommModemStatus(HANDLE hFile, LPDWORD lpModemStat);
BOOL WINAPI GetCommState(HANDLE hFile, LPVOID lpDCB);
BOOL WINAPI PurgeComm(HANDLE hFile, DWORD dwFlags);
BOOL WINAPI SetCommBreak(HANDLE hFile);
BOOL WINAPI SetCommMask(HANDLE hFile, DWORD dwEvtMask);
BOOL WINAPI SetCommState(HANDLE hFile, LPVOID lpDCB);
BOOL WINAPI SetCommTimeouts(HANDLE hFile, LPVOID lpCommTimeouts);
BOOL WINAPI TransmitCommChar(HANDLE hFile, char cChar);
BOOL WINAPI WaitCommEvent(HANDLE hFile, LPDWORD lpEvtMask, LPOVERLAPPED lpOverlapped);
LONG WINAPI CompareFileTime(const FILETIME *lpFileTime1, const FILETIME *lpFileTime2);
BOOL WINAPI GetVolumeInformationA(LPCSTR lpRootPathName, LPSTR lpVolumeNameBuffer, DWORD nVolumeNameSize,
LPDWORD lpVolumeSerialNumber, LPDWORD lpMaximumComponentLength,
Expand Down
57 changes: 54 additions & 3 deletions dll/kernel32/processthreadsapi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,11 +145,28 @@ void *threadTrampoline(void *param) {
}
}

LPTHREAD_START_ROUTINE entry = data.entry;
void **entrySlot = nullptr;
void *savedGuestStack = nullptr;
if (threadTib && entry) {
// Cygwin 1.x scans the initial thread stack during DLL_THREAD_ATTACH
// and rewrites the start routine slot to its own signal-aware wrapper.
savedGuestStack = threadTib->CurrentStackPointer;
entrySlot = static_cast<void **>(savedGuestStack) - 1;
*entrySlot = reinterpret_cast<void *>(entry);
threadTib->CurrentStackPointer = entrySlot;
}

wibo::notifyDllThreadAttach();
DEBUG_LOG("Calling thread entry %p with userData %p\n", data.entry, data.userData);

if (entrySlot) {
entry = reinterpret_cast<LPTHREAD_START_ROUTINE>(*entrySlot);
threadTib->CurrentStackPointer = savedGuestStack;
}
DEBUG_LOG("Calling thread entry %p with userData %p\n", entry, data.userData);
DWORD result = 0;
if (data.entry) {
result = call_LPTHREAD_START_ROUTINE(data.entry, data.userData);
if (entry) {
result = call_LPTHREAD_START_ROUTINE(entry, data.userData);
}
DEBUG_LOG("Thread exiting with code %u\n", result);
{
Expand Down Expand Up @@ -577,6 +594,40 @@ DWORD WINAPI GetPriorityClass(HANDLE hProcess) {
return NORMAL_PRIORITY_CLASS;
}

BOOL WINAPI GetProcessTimes(HANDLE hProcess, FILETIME *lpCreationTime, FILETIME *lpExitTime, FILETIME *lpKernelTime,
FILETIME *lpUserTime) {
HOST_CONTEXT_GUARD();
DEBUG_LOG("GetProcessTimes(%p, %p, %p, %p, %p)\n", hProcess, lpCreationTime, lpExitTime, lpKernelTime, lpUserTime);
if (!lpKernelTime || !lpUserTime) {
setLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
if (!isPseudoCurrentProcessHandle(hProcess) && !wibo::handles().getAs<ProcessObject>(hProcess)) {
setLastError(ERROR_INVALID_HANDLE);
return FALSE;
}

if (lpCreationTime) {
*lpCreationTime = kDefaultThreadFileTime;
}
if (lpExitTime) {
lpExitTime->dwLowDateTime = 0;
lpExitTime->dwHighDateTime = 0;
}

struct rusage usage{};
if (getrusage(RUSAGE_SELF, &usage) == 0) {
*lpKernelTime = fileTimeFromTimeval(usage.ru_stime);
*lpUserTime = fileTimeFromTimeval(usage.ru_utime);
return TRUE;
}

kernel32::setLastErrorFromErrno();
*lpKernelTime = fileTimeFromDuration(0);
*lpUserTime = fileTimeFromDuration(0);
return FALSE;
}

BOOL WINAPI GetThreadTimes(HANDLE hThread, FILETIME *lpCreationTime, FILETIME *lpExitTime, FILETIME *lpKernelTime,
FILETIME *lpUserTime) {
HOST_CONTEXT_GUARD();
Expand Down
2 changes: 2 additions & 0 deletions dll/kernel32/processthreadsapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ BOOL WINAPI GetExitCodeThread(HANDLE hThread, LPDWORD lpExitCode);
BOOL WINAPI SetThreadPriority(HANDLE hThread, int nPriority);
int WINAPI GetThreadPriority(HANDLE hThread);
DWORD WINAPI GetPriorityClass(HANDLE hProcess);
BOOL WINAPI GetProcessTimes(HANDLE hProcess, FILETIME *lpCreationTime, FILETIME *lpExitTime, FILETIME *lpKernelTime,
FILETIME *lpUserTime);
BOOL WINAPI GetThreadTimes(HANDLE hThread, FILETIME *lpCreationTime, FILETIME *lpExitTime, FILETIME *lpKernelTime,
FILETIME *lpUserTime);
BOOL WINAPI CreateProcessA(LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes,
Expand Down
Loading
Loading