From 828b4eb7d67333455cac5c9da81f21212d57555c 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 1/6] 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, From 4c73dbb31593e6935e5001a220a34bdcb9f331f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Jab=C5=82o=C5=84ski?= Date: Sun, 14 Apr 2024 14:07:17 +0200 Subject: [PATCH 2/6] Commit some changes missing from the previous commit --- COREDLL/COREDLL.vcxproj | 1 + COREDLL/COREDLL.vcxproj.filters | 3 ++ COREDLL/other.cpp | 51 --------------------------------- 3 files changed, 4 insertions(+), 51 deletions(-) diff --git a/COREDLL/COREDLL.vcxproj b/COREDLL/COREDLL.vcxproj index 2865c7c..622c779 100644 --- a/COREDLL/COREDLL.vcxproj +++ b/COREDLL/COREDLL.vcxproj @@ -259,6 +259,7 @@ Create Create + diff --git a/COREDLL/COREDLL.vcxproj.filters b/COREDLL/COREDLL.vcxproj.filters index 6aa94bb..db9da89 100644 --- a/COREDLL/COREDLL.vcxproj.filters +++ b/COREDLL/COREDLL.vcxproj.filters @@ -80,6 +80,9 @@ Source Files + + Source Files + diff --git a/COREDLL/other.cpp b/COREDLL/other.cpp index 065ddee..6112ed8 100644 --- a/COREDLL/other.cpp +++ b/COREDLL/other.cpp @@ -194,57 +194,6 @@ void CeLogSetZones(DWORD dwZoneUser, // User-defined zones // wtf!? } -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; -} - void* _fileno_WCECL(FILE* file) { return (void*)_get_osfhandle(_fileno(file)); From d585815866abefc001d4dbe93bd3853d0e4281a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Jab=C5=82o=C5=84ski?= Date: Sun, 14 Apr 2024 15:51:33 +0200 Subject: [PATCH 3/6] Implement on demand stdio allocation --- COREDLL/Exports.def | 2 +- COREDLL/other.cpp | 22 ++--- COREDLL/stdio_wcecl.cpp | 194 +++++++++++++++++++++++++++++++++++++++- COREDLL/stdio_wcecl.h | 32 +++++++ 4 files changed, 231 insertions(+), 19 deletions(-) create mode 100644 COREDLL/stdio_wcecl.h diff --git a/COREDLL/Exports.def b/COREDLL/Exports.def index 5b139af..36295d3 100644 --- a/COREDLL/Exports.def +++ b/COREDLL/Exports.def @@ -31,7 +31,7 @@ EXPORTS _wcsupr @232 vfwprintf=vfwprintf_WCECL @721 fflush @1122 - fgetws=fgetws_WCECL @1143 + fgetws @1143 fputwc @1141 fputws @1144 _getstdfilex=_getstdfilex_WCECL @1100 diff --git a/COREDLL/other.cpp b/COREDLL/other.cpp index 6112ed8..0ac01ac 100644 --- a/COREDLL/other.cpp +++ b/COREDLL/other.cpp @@ -196,6 +196,12 @@ void CeLogSetZones(DWORD dwZoneUser, // User-defined zones void* _fileno_WCECL(FILE* file) { + void* result = WceclTryGetOrAllocStdHandle(file); + if (result != NULL) + { + return result; + } + return (void*)_get_osfhandle(_fileno(file)); } @@ -220,22 +226,6 @@ int WINAPI WideCharToMultiByte_WCECL( lpUsedDefaultChar); } -wchar_t* fgetws_WCECL(wchar_t* w, int count, FILE* file) -{ - wchar_t* result = fgetws(w, count, file); - if (result == NULL && - file == stdin && count > 2) - { - result = w; - wsprintf(w, L""); - } - else - { - return result; - } - return result; -} - // Stubs Stub(_chkstk_WCECL); Stub(WaitForAPIReady); diff --git a/COREDLL/stdio_wcecl.cpp b/COREDLL/stdio_wcecl.cpp index 57c1bda..72888ef 100644 --- a/COREDLL/stdio_wcecl.cpp +++ b/COREDLL/stdio_wcecl.cpp @@ -2,6 +2,47 @@ #include #include +/* https://learn.microsoft.com/en-us/windows/console/clearing-the-screen */ +static BOOL WceclConsoleClearScreen( + HANDLE hDevice) +{ + CHAR_INFO charInfo; + COORD scrollTarget; + SMALL_RECT scrollRect; + CONSOLE_SCREEN_BUFFER_INFO screenInfo; + + if (!GetConsoleScreenBufferInfo(hDevice, &screenInfo)) + { + return FALSE; + } + + charInfo.Char.UnicodeChar = L' '; + charInfo.Attributes = screenInfo.wAttributes; + + scrollRect.Left = 0; + scrollRect.Top = 0; + scrollRect.Right = screenInfo.dwSize.X; + scrollRect.Bottom = screenInfo.dwSize.Y; + + scrollTarget.X = 0; + scrollTarget.Y = -screenInfo.dwSize.Y; + + if (ScrollConsoleScreenBufferW( + hDevice, + &scrollRect, + NULL, + scrollTarget, + &charInfo) == 0) + { + return FALSE; + } + + screenInfo.dwCursorPosition.X = 0; + screenInfo.dwCursorPosition.Y = 0; + + SetConsoleCursorPosition(hDevice, screenInfo.dwCursorPosition); +} + static DWORD GetWin32ConsoleModeFromWce(DWORD wceConsoleMode) { DWORD out = 0; @@ -102,6 +143,44 @@ static BOOL WceclConsoleGetTitle( return GetConsoleTitleA(lpOutBuf, nOutBufSize); } + +static BOOL WceclConsoleGetRowsCols( + HANDLE hDevice, + PDWORD lpCols, + PDWORD lpRows, + DWORD nOutBufSize) +{ + CONSOLE_SCREEN_BUFFER_INFO screenInfo; + DWORD win32ConsoleMode; + BOOL result; + + if (nOutBufSize < sizeof(DWORD)) + { + return FALSE; + } + + if (!GetConsoleScreenBufferInfo(hDevice, &screenInfo)) + { + return FALSE; + } + + if (lpRows != NULL) + { + *lpRows = screenInfo.dwSize.Y; + } + if (lpCols != NULL) + { + *lpCols = screenInfo.dwSize.X; + } + if (lpCols == NULL && lpRows == NULL) + { + return FALSE; + } + + return TRUE; +} + + BOOL WceclConsoleIoControl( HANDLE hDevice, DWORD dwIoControlCode, @@ -123,8 +202,13 @@ BOOL WceclConsoleIoControl( case IOCTL_CONSOLE_GETTITLE: return WceclConsoleGetTitle((LPSTR)lpOutBuf, nOutBufSize); case IOCTL_CONSOLE_CLS: - /* TODO */ - return TRUE; + return WceclConsoleClearScreen(hDevice); + case IOCTL_CONSOLE_FLUSHINPUT: + return FlushConsoleInputBuffer(hDevice); + case IOCTL_CONSOLE_GETSCREENROWS: + return WceclConsoleGetRowsCols(hDevice, NULL, (PDWORD)lpOutBuf, nOutBufSize); + case IOCTL_CONSOLE_GETSCREENCOLS: + return WceclConsoleGetRowsCols(hDevice, (PDWORD)lpOutBuf, NULL, nOutBufSize); default: /* TODO */ return FALSE; @@ -182,4 +266,110 @@ BOOL WINAPI GetStdioPathW_WCECL( } return FALSE; +} + +static BOOL WceclTryGetStdHandle(FILE* file, PHANDLE handle) +{ + if (file == stdin) + { + *handle = GetStdHandle(STD_INPUT_HANDLE); + } + else if (file == stdout) + { + *handle = GetStdHandle(STD_OUTPUT_HANDLE); + } + else if (file == stderr) + { + *handle = GetStdHandle(STD_ERROR_HANDLE); + } + else + { + return FALSE; + } + return TRUE; +} + +static BOOL WceclAllocateStdio() +{ + HWND hWndConsole; + BOOL bConsoleAllocated; + + HANDLE hOldStdIn, hOldStdOut, hOldStdErr; + + hWndConsole = GetConsoleWindow(); + + hOldStdIn = GetStdHandle(STD_INPUT_HANDLE); + hOldStdOut = GetStdHandle(STD_OUTPUT_HANDLE); + hOldStdErr = GetStdHandle(STD_ERROR_HANDLE); + + if (hWndConsole == NULL) + { + AllocConsole(); + hWndConsole = GetConsoleWindow(); + + if (hWndConsole == NULL) + { + return FALSE; + } + + bConsoleAllocated = TRUE; + } + else + { + bConsoleAllocated = FALSE; + } + + assert(hOldStdErr == NULL || hOldStdIn == NULL || hOldStdOut == NULL); + + if (hOldStdIn == NULL) + { + if (freopen("CONIN$", "r", stdin) == NULL) + { + goto CLEANUP; + } + } + if (hOldStdOut == NULL) + { + if(freopen("CONOUT$", "w", stdout) == NULL) + { + goto CLEANUP; + } + } + if (hOldStdErr == NULL) + { + if(freopen("CONERR$", "w", stderr) == NULL) + { + goto CLEANUP; + } + } + + return TRUE; +CLEANUP: + if (bConsoleAllocated) + { + FreeConsole(); + } + return FALSE; +} + +/* It seems that CE programs launch a console only when it is about to be + used. */ +HANDLE WceclTryGetOrAllocStdHandle(FILE* file) +{ + HANDLE hFile; + + if (WceclTryGetStdHandle(file, &hFile) == FALSE) + { + return NULL; + } + + if (hFile == NULL) + { + if (WceclAllocateStdio() == FALSE) + { + return FALSE; + } + } + + return hFile; } \ No newline at end of file diff --git a/COREDLL/stdio_wcecl.h b/COREDLL/stdio_wcecl.h new file mode 100644 index 0000000..84d2680 --- /dev/null +++ b/COREDLL/stdio_wcecl.h @@ -0,0 +1,32 @@ +#pragma once +#include "stdafx.h" + +#define FILE_DEVICE_CONSOLE 0x0102 + +#define CECONSOLE_MODE_ECHO_INPUT 0x01 +#define CECONSOLE_MODE_LINE_INPUT 0x02 +#define CECONSOLE_MODE_PROCESSED_OUTPUT 0x04 + +#define CONSOLE_CTL(i) ((FILE_DEVICE_CONSOLE<<16)|(i << 2)) +#define IOCTL_CONSOLE_SETMODE CONSOLE_CTL(1) +#define IOCTL_CONSOLE_GETMODE CONSOLE_CTL(2) +#define IOCTL_CONSOLE_SETTITLE CONSOLE_CTL(3) +#define IOCTL_CONSOLE_GETTITLE CONSOLE_CTL(4) +#define IOCTL_CONSOLE_CLS CONSOLE_CTL(5) +#define IOCTL_CONSOLE_FLUSHINPUT CONSOLE_CTL(6) +#define IOCTL_CONSOLE_GETSCREENROWS CONSOLE_CTL(7) +#define IOCTL_CONSOLE_SETCONTROLCHANDLER CONSOLE_CTL(8) +#define IOCTL_CONSOLE_GETSCREENCOLS CONSOLE_CTL(9) +#define IOCTL_CONSOLE_SETCONTROLCEVENT CONSOLE_CTL(10) + +BOOL WceclConsoleIoControl( + HANDLE hDevice, + DWORD dwIoControlCode, + LPVOID lpInBuf, + DWORD nInBufSize, + LPVOID lpOutBuf, + DWORD nOutBufSize, + LPDWORD lpBytesReturned, + LPOVERLAPPED lpOverlapped); + +HANDLE WceclTryGetOrAllocStdHandle(FILE* file); From b667bfc4c832bdac7691c53ee2206aa4760628cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Jab=C5=82o=C5=84ski?= Date: Sun, 14 Apr 2024 16:02:12 +0200 Subject: [PATCH 4/6] Fix programs not using parent process consoles --- COREDLL/stdio_wcecl.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/COREDLL/stdio_wcecl.cpp b/COREDLL/stdio_wcecl.cpp index 72888ef..7684abb 100644 --- a/COREDLL/stdio_wcecl.cpp +++ b/COREDLL/stdio_wcecl.cpp @@ -302,6 +302,12 @@ static BOOL WceclAllocateStdio() hOldStdOut = GetStdHandle(STD_OUTPUT_HANDLE); hOldStdErr = GetStdHandle(STD_ERROR_HANDLE); + if (hWndConsole == NULL && + AttachConsole(ATTACH_PARENT_PROCESS)) + { + hWndConsole = GetConsoleWindow(); + } + if (hWndConsole == NULL) { AllocConsole(); From 81d257babdd1506e8677b5c9331546661a27c65f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Jab=C5=82o=C5=84ski?= Date: Sun, 14 Apr 2024 16:36:33 +0200 Subject: [PATCH 5/6] Revert the previous commit, and add a comment --- COREDLL/stdio_wcecl.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/COREDLL/stdio_wcecl.cpp b/COREDLL/stdio_wcecl.cpp index 7684abb..db87513 100644 --- a/COREDLL/stdio_wcecl.cpp +++ b/COREDLL/stdio_wcecl.cpp @@ -289,6 +289,8 @@ static BOOL WceclTryGetStdHandle(FILE* file, PHANDLE handle) return TRUE; } +/* This is only really executed, if the WinCE application has been converted to + Win32 GUI application (WinCE has no distinction between GUI and CUI subsystems) */ static BOOL WceclAllocateStdio() { HWND hWndConsole; @@ -302,12 +304,6 @@ static BOOL WceclAllocateStdio() hOldStdOut = GetStdHandle(STD_OUTPUT_HANDLE); hOldStdErr = GetStdHandle(STD_ERROR_HANDLE); - if (hWndConsole == NULL && - AttachConsole(ATTACH_PARENT_PROCESS)) - { - hWndConsole = GetConsoleWindow(); - } - if (hWndConsole == NULL) { AllocConsole(); From df55bb791aacb1a7325f4e3ce7f958b89129a706 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Jab=C5=82o=C5=84ski?= Date: Sun, 14 Apr 2024 16:55:08 +0200 Subject: [PATCH 6/6] Implement IOCTL_CONSOLE_SETCONTROLXXX codes --- COREDLL/stdio_wcecl.cpp | 43 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/COREDLL/stdio_wcecl.cpp b/COREDLL/stdio_wcecl.cpp index db87513..4f63dcf 100644 --- a/COREDLL/stdio_wcecl.cpp +++ b/COREDLL/stdio_wcecl.cpp @@ -2,6 +2,8 @@ #include #include +static HANDLE ControlEvent = NULL; + /* https://learn.microsoft.com/en-us/windows/console/clearing-the-screen */ static BOOL WceclConsoleClearScreen( HANDLE hDevice) @@ -90,6 +92,7 @@ static BOOL WceclConsoleSetMode( { if (nInBufSize < sizeof(DWORD)) { + SetLastError(ERROR_INSUFFICIENT_BUFFER); return FALSE; } return SetConsoleMode( @@ -107,6 +110,7 @@ static BOOL WceclConsoleGetMode( if (nOutBufSize < sizeof(DWORD)) { + SetLastError(ERROR_INSUFFICIENT_BUFFER); return FALSE; } result = GetConsoleMode(hDevice, &win32ConsoleMode); @@ -156,6 +160,7 @@ static BOOL WceclConsoleGetRowsCols( if (nOutBufSize < sizeof(DWORD)) { + SetLastError(ERROR_INSUFFICIENT_BUFFER); return FALSE; } @@ -180,7 +185,38 @@ static BOOL WceclConsoleGetRowsCols( return TRUE; } +BOOL WceclConsoleSetControlHandler(PHANDLER_ROUTINE* pInBuffer, DWORD nInBufSize) +{ + if (nInBufSize < sizeof(PHANDLER_ROUTINE)) + { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return FALSE; + } + return SetConsoleCtrlHandler(*pInBuffer, FALSE); +} +BOOL __stdcall WceclConsoleSignalControlEvent(DWORD ctrlType) +{ + if (ControlEvent != NULL) + { + SetEvent(ControlEvent); + + /* TODO: what should this return? */ + return TRUE; + } + return FALSE; +} + +BOOL WceclConsoleSetControlEvent(HANDLE* pInBuffer, DWORD nInBufSize) +{ + if (nInBufSize < sizeof(HANDLE)) + { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return FALSE; + } + ControlEvent = *pInBuffer; + return SetConsoleCtrlHandler(WceclConsoleSignalControlEvent, FALSE); +} BOOL WceclConsoleIoControl( HANDLE hDevice, DWORD dwIoControlCode, @@ -209,9 +245,10 @@ BOOL WceclConsoleIoControl( return WceclConsoleGetRowsCols(hDevice, NULL, (PDWORD)lpOutBuf, nOutBufSize); case IOCTL_CONSOLE_GETSCREENCOLS: return WceclConsoleGetRowsCols(hDevice, (PDWORD)lpOutBuf, NULL, nOutBufSize); - default: - /* TODO */ - return FALSE; + case IOCTL_CONSOLE_SETCONTROLCHANDLER: + return WceclConsoleSetControlHandler((PHANDLER_ROUTINE*)lpInBuf, nInBufSize); + case IOCTL_CONSOLE_SETCONTROLCEVENT: + return WceclConsoleSetControlEvent((PHANDLE)lpInBuf, nInBufSize); } return FALSE;