diff --git a/reactos/dll/win32/kernel32/misc/console.c b/reactos/dll/win32/kernel32/misc/console.c index 298f79b8e59..aaf48ac882f 100644 --- a/reactos/dll/win32/kernel32/misc/console.c +++ b/reactos/dll/win32/kernel32/misc/console.c @@ -1467,6 +1467,12 @@ IntWriteConsole(HANDLE hConsoleOutput, max(sizeof(CSR_API_MESSAGE), CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE) + SizeBytes)); + if (Status == STATUS_PENDING) + { + WaitForSingleObject(Request->Data.WriteConsoleRequest.UnpauseEvent, INFINITE); + CloseHandle(Request->Data.WriteConsoleRequest.UnpauseEvent); + continue; + } if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request->Status)) { RtlFreeHeap(RtlGetProcessHeap(), 0, Request); diff --git a/reactos/include/reactos/subsys/csrss/csrss.h b/reactos/include/reactos/subsys/csrss/csrss.h index 62fe387633c..0b707582f6f 100644 --- a/reactos/include/reactos/subsys/csrss/csrss.h +++ b/reactos/include/reactos/subsys/csrss/csrss.h @@ -62,6 +62,7 @@ typedef struct BOOL Unicode; ULONG NrCharactersToWrite; ULONG NrCharactersWritten; + HANDLE UnpauseEvent; BYTE Buffer[0]; } CSRSS_WRITE_CONSOLE, *PCSRSS_WRITE_CONSOLE; diff --git a/reactos/subsystems/win32/csrss/win32csr/conio.c b/reactos/subsystems/win32/csrss/win32csr/conio.c index 60b93cf9b3f..51e320fdcef 100644 --- a/reactos/subsystems/win32/csrss/win32csr/conio.c +++ b/reactos/subsystems/win32/csrss/win32csr/conio.c @@ -849,6 +849,15 @@ CSR_API(CsrWriteConsole) } Console = Buff->Header.Console; + if (Console->UnpauseEvent) + { + Status = NtDuplicateObject(GetCurrentProcess(), Console->UnpauseEvent, + ProcessData->Process, &Request->Data.WriteConsoleRequest.UnpauseEvent, + SYNCHRONIZE, 0, 0); + ConioUnlockScreenBuffer(Buff); + return NT_SUCCESS(Status) ? STATUS_PENDING : Status; + } + if(Request->Data.WriteConsoleRequest.Unicode) { Length = WideCharToMultiByte(Console->OutputCodePage, 0, @@ -953,6 +962,7 @@ ConioDeleteConsole(Object_t *Object) } CloseHandle(Console->ActiveEvent); + if (Console->UnpauseEvent) CloseHandle(Console->UnpauseEvent); DeleteCriticalSection(&Console->Lock); RtlFreeUnicodeString(&Console->Title); IntDeleteAllAliases(Console->Aliases); @@ -967,6 +977,26 @@ CsrInitConsoleSupport(VOID) /* Should call LoadKeyboardLayout */ } +VOID FASTCALL +ConioPause(PCSRSS_CONSOLE Console, UINT Flags) +{ + Console->PauseFlags |= Flags; + if (!Console->UnpauseEvent) + Console->UnpauseEvent = CreateEvent(NULL, TRUE, FALSE, NULL); +} + +VOID FASTCALL +ConioUnpause(PCSRSS_CONSOLE Console, UINT Flags) +{ + Console->PauseFlags &= ~Flags; + if (Console->PauseFlags == 0 && Console->UnpauseEvent) + { + SetEvent(Console->UnpauseEvent); + CloseHandle(Console->UnpauseEvent); + Console->UnpauseEvent = NULL; + } +} + static VOID FASTCALL ConioProcessChar(PCSRSS_CONSOLE Console, ConsoleInput *KeyEventRecord) @@ -974,6 +1004,35 @@ ConioProcessChar(PCSRSS_CONSOLE Console, BOOL updown; ConsoleInput *TempInput; + if (KeyEventRecord->InputEvent.EventType == KEY_EVENT && + KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown) + { + WORD vk = KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode; + if (!(Console->PauseFlags & PAUSED_FROM_KEYBOARD)) + { + DWORD cks = KeyEventRecord->InputEvent.Event.KeyEvent.dwControlKeyState; + if (Console->Mode & ENABLE_LINE_INPUT && + (vk == VK_PAUSE || (vk == 'S' && + (cks & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) && + !(cks & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED))))) + { + ConioPause(Console, PAUSED_FROM_KEYBOARD); + HeapFree(Win32CsrApiHeap, 0, KeyEventRecord); + return; + } + } + else + { + if ((vk < VK_SHIFT || vk > VK_CAPITAL) && vk != VK_LWIN && + vk != VK_RWIN && vk != VK_NUMLOCK && vk != VK_SCROLL) + { + ConioUnpause(Console, PAUSED_FROM_KEYBOARD); + HeapFree(Win32CsrApiHeap, 0, KeyEventRecord); + return; + } + } + } + if (0 != (Console->Mode & (ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT))) { switch(KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar) diff --git a/reactos/subsystems/win32/csrss/win32csr/conio.h b/reactos/subsystems/win32/csrss/win32csr/conio.h index 8645351f96a..9b0c6905ce8 100644 --- a/reactos/subsystems/win32/csrss/win32csr/conio.h +++ b/reactos/subsystems/win32/csrss/win32csr/conio.h @@ -93,6 +93,8 @@ typedef struct tagCSRSS_CONSOLE LIST_ENTRY ProcessList; struct tagALIAS_HEADER *Aliases; CONSOLE_SELECTION_INFO Selection; + BYTE PauseFlags; + HANDLE UnpauseEvent; } CSRSS_CONSOLE; typedef struct ConsoleInput_t @@ -111,10 +113,17 @@ typedef struct ConsoleInput_t #define CONSOLE_MOUSE_SELECTION 0x4 #define CONSOLE_MOUSE_DOWN 0x8 +/* PauseFlags values (internal only) */ +#define PAUSED_FROM_KEYBOARD 0x1 +#define PAUSED_FROM_SCROLLBAR 0x2 +#define PAUSED_FROM_SELECTION 0x4 + NTSTATUS FASTCALL ConioConsoleFromProcessData(PCSRSS_PROCESS_DATA ProcessData, PCSRSS_CONSOLE *Console); VOID WINAPI ConioDeleteConsole(Object_t *Object); VOID WINAPI ConioDeleteScreenBuffer(PCSRSS_SCREEN_BUFFER Buffer); VOID WINAPI CsrInitConsoleSupport(VOID); +VOID FASTCALL ConioPause(PCSRSS_CONSOLE Console, UINT Flags); +VOID FASTCALL ConioUnpause(PCSRSS_CONSOLE Console, UINT Flags); void WINAPI ConioProcessKey(MSG *msg, PCSRSS_CONSOLE Console, BOOL TextMode); PBYTE FASTCALL ConioCoordToPointer(PCSRSS_SCREEN_BUFFER Buf, ULONG X, ULONG Y); VOID FASTCALL ConioDrawConsole(PCSRSS_CONSOLE Console); diff --git a/reactos/subsystems/win32/csrss/win32csr/guiconsole.c b/reactos/subsystems/win32/csrss/win32csr/guiconsole.c index b89edbd304e..5398fd40a4e 100644 --- a/reactos/subsystems/win32/csrss/win32csr/guiconsole.c +++ b/reactos/subsystems/win32/csrss/win32csr/guiconsole.c @@ -844,6 +844,7 @@ GuiConsoleUpdateSelection(PCSRSS_CONSOLE Console, PCOORD coord) } Console->Selection.dwFlags |= CONSOLE_SELECTION_NOT_EMPTY; Console->Selection.srSelection = rc; + ConioPause(Console, PAUSED_FROM_SELECTION); } else { @@ -853,6 +854,7 @@ GuiConsoleUpdateSelection(PCSRSS_CONSOLE Console, PCOORD coord) InvalidateRect(hWnd, &oldRect, FALSE); } Console->Selection.dwFlags = CONSOLE_NO_SELECTION; + ConioUnpause(Console, PAUSED_FROM_SELECTION); } } @@ -1803,6 +1805,11 @@ GuiConsoleHandleScroll(HWND hwnd, UINT uMsg, WPARAM wParam) case SB_THUMBTRACK: sInfo.nPos = sInfo.nTrackPos; + ConioPause(Console, PAUSED_FROM_SCROLLBAR); + break; + + case SB_THUMBPOSITION: + ConioUnpause(Console, PAUSED_FROM_SCROLLBAR); break; case SB_TOP: