From f6ce1e4807f303d5fa3da0cee60cde15b62547cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Jab=C5=82o=C5=84ski?= Date: Sun, 14 Apr 2024 13:54:20 +0200 Subject: [PATCH] Implement some console control codes These changes make the command work correctly --- COREDLL/COREDLL.vcxproj | 1 + COREDLL/COREDLL.vcxproj.filters | 3 + COREDLL/stdafx.h | 2 + COREDLL/stdio_wcecl.cpp | 185 ++++++++++++++++++++++++++++++++ COREDLL/winbase_wcecl.cpp | 15 +++ 5 files changed, 206 insertions(+) create mode 100644 COREDLL/stdio_wcecl.cpp diff --git a/COREDLL/COREDLL.vcxproj b/COREDLL/COREDLL.vcxproj index 1bb75cf..2865c7c 100644 --- a/COREDLL/COREDLL.vcxproj +++ b/COREDLL/COREDLL.vcxproj @@ -240,6 +240,7 @@ + diff --git a/COREDLL/COREDLL.vcxproj.filters b/COREDLL/COREDLL.vcxproj.filters index b8a0a98..6aa94bb 100644 --- a/COREDLL/COREDLL.vcxproj.filters +++ b/COREDLL/COREDLL.vcxproj.filters @@ -24,6 +24,9 @@ Header Files + + Header Files + diff --git a/COREDLL/stdafx.h b/COREDLL/stdafx.h index 8f5c58a..b44d098 100644 --- a/COREDLL/stdafx.h +++ b/COREDLL/stdafx.h @@ -85,3 +85,5 @@ BOOL ProgramErrorDialog(LPCWSTR Text, BOOL YesNo); VOID DisplayAssert32ErrorDialog(LPCWSTR ExpressionText, LPCWSTR Comment, BOOL ShowLastError); DWORD GetBaseAddress(HANDLE pHandle); HMODULE GetModule(HANDLE pHandle); + +#include "stdio_wcecl.h" diff --git a/COREDLL/stdio_wcecl.cpp b/COREDLL/stdio_wcecl.cpp new file mode 100644 index 0000000..57c1bda --- /dev/null +++ b/COREDLL/stdio_wcecl.cpp @@ -0,0 +1,185 @@ +#include "stdafx.h" +#include +#include + +static DWORD GetWin32ConsoleModeFromWce(DWORD wceConsoleMode) +{ + DWORD out = 0; + + if (wceConsoleMode & CECONSOLE_MODE_ECHO_INPUT) + { + out |= ENABLE_ECHO_INPUT; + } + if (wceConsoleMode & CECONSOLE_MODE_LINE_INPUT) + { + out |= ENABLE_LINE_INPUT; + } + if (wceConsoleMode & CECONSOLE_MODE_PROCESSED_OUTPUT) + { + out |= ENABLE_PROCESSED_OUTPUT; + } + + return out; +} + +static DWORD GetWceConsoleModeFromWin32(DWORD win32ConsoleMode) +{ + DWORD out = 0; + + if (win32ConsoleMode & ENABLE_ECHO_INPUT) + { + out |= CECONSOLE_MODE_ECHO_INPUT; + } + if (win32ConsoleMode & ENABLE_LINE_INPUT) + { + out |= CECONSOLE_MODE_LINE_INPUT; + } + if (win32ConsoleMode & ENABLE_PROCESSED_OUTPUT) + { + out |= CECONSOLE_MODE_PROCESSED_OUTPUT; + } + + return out; +} + +static BOOL WceclConsoleSetMode( + HANDLE hDevice, + DWORD* lpInBuf, + DWORD nInBufSize) +{ + if (nInBufSize < sizeof(DWORD)) + { + return FALSE; + } + return SetConsoleMode( + hDevice, + GetWin32ConsoleModeFromWce(*lpInBuf)); +} + +static BOOL WceclConsoleGetMode( + HANDLE hDevice, + DWORD* lpOutBuf, + DWORD nOutBufSize) +{ + DWORD win32ConsoleMode; + BOOL result; + + if (nOutBufSize < sizeof(DWORD)) + { + return FALSE; + } + result = GetConsoleMode(hDevice, &win32ConsoleMode); + if (!result) + { + return FALSE; + } + *((DWORD*)lpOutBuf) = GetWceConsoleModeFromWin32(win32ConsoleMode); + return TRUE; +} + +static BOOL WceclConsoleSetTitle( + LPCSTR lpInBuf, + DWORD nInBufSize) +{ + BOOL result; + + /* Create a copy of the buffer to not read garbage if the original buffer + is short. */ + char* bufferCopy = new char[nInBufSize + 1]; + bufferCopy[nInBufSize] = '\0'; + memcpy(bufferCopy, lpInBuf, nInBufSize); + + result = SetConsoleTitleA(bufferCopy); + + delete[] bufferCopy; + return result; +} + +static BOOL WceclConsoleGetTitle( + LPSTR lpOutBuf, + DWORD nOutBufSize) +{ + return GetConsoleTitleA(lpOutBuf, nOutBufSize); +} + +BOOL WceclConsoleIoControl( + HANDLE hDevice, + DWORD dwIoControlCode, + LPVOID lpInBuf, + DWORD nInBufSize, + LPVOID lpOutBuf, + DWORD nOutBufSize, + LPDWORD lpBytesReturned, + LPOVERLAPPED lpOverlapped) +{ + switch (dwIoControlCode) + { + case IOCTL_CONSOLE_SETMODE: + return WceclConsoleSetMode(hDevice, (DWORD*)lpInBuf, nInBufSize); + case IOCTL_CONSOLE_GETMODE: + return WceclConsoleGetMode(hDevice, (DWORD*)lpOutBuf, nOutBufSize); + case IOCTL_CONSOLE_SETTITLE: + return WceclConsoleSetTitle((LPCSTR)lpInBuf, nInBufSize); + case IOCTL_CONSOLE_GETTITLE: + return WceclConsoleGetTitle((LPSTR)lpOutBuf, nOutBufSize); + case IOCTL_CONSOLE_CLS: + /* TODO */ + return TRUE; + default: + /* TODO */ + return FALSE; + } + + return FALSE; +} + +FILE* WINAPI _getstdfilex_WCECL(DWORD type) +{ + switch (type) + { + case 0: + return stdin; + case 1: + return stdout; + case 2: + return stderr; + default: + Assert32(FALSE); + return NULL; + } +} + +BOOL WINAPI SetStdioPathW_WCECL( + DWORD id, + PWSTR pwszPath) +{ + /* TODO: test */ + switch (id) + { + case 0: + return (_wfreopen(pwszPath, L"r", stdin) != NULL); + case 1: + return (_wfreopen(pwszPath, L"w", stdout) != NULL); + case 2: + return (_wfreopen(pwszPath, L"w", stderr) != NULL); + default: + Assert32(FALSE); + return NULL; + } +} + +BOOL WINAPI GetStdioPathW_WCECL( + DWORD id, + PWSTR pwszBuf, + LPDWORD lpdwLen) +{ + /* TODO: test */ + FILE* filePtr = _getstdfilex_WCECL(id); + HANDLE hFile = (HANDLE)_get_osfhandle(_fileno(filePtr)); + if (GetFinalPathNameByHandleW(hFile, pwszBuf, *lpdwLen, 0) < *lpdwLen) + { + return TRUE; + } + + return FALSE; +} \ No newline at end of file diff --git a/COREDLL/winbase_wcecl.cpp b/COREDLL/winbase_wcecl.cpp index 2d2444e..983577c 100644 --- a/COREDLL/winbase_wcecl.cpp +++ b/COREDLL/winbase_wcecl.cpp @@ -487,6 +487,21 @@ BOOL WINAPI DeviceIoControl_WCECL( LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) { + USHORT type = ((dwIoControlCode & 0xFFFF0000) >> 16); + + if (type == FILE_DEVICE_CONSOLE) + { + return WceclConsoleIoControl( + hDevice, + dwIoControlCode, + lpInBuf, + nInBufSize, + lpOutBuf, + nOutBufSize, + lpBytesReturned, + lpOverlapped); + } + auto result = DeviceIoControl( hDevice, dwIoControlCode,