[KERNEL32-CONSRV]

- Implement SetConsoleCursor and ShowConsoleCursor (set the shape of the cursor, and show/hide it). It appears that SetConsoleCursor acts only on graphics screen buffers (tested on Windows).
  I personnaly think it's a limitation we can suppress, but at the moment I keep it.
- Implement SetConsoleMaximumWindowSize which does nothing else than returning TRUE but doesn't give any constraint on the maximum size of the console window (tested on Windows Server 2003).

See http://undoc.airesoft.co.uk/kernel32.dll/SetConsoleCursor.php , http://undoc.airesoft.co.uk/kernel32.dll/ShowConsoleCursor.php and http://undoc.airesoft.co.uk/kernel32.dll/SetConsoleMaximumWindowSize.php for more details.

Useful for the NTVDM interface !

[CONSRV:Gui frontend]
- Fix "Select all" action.
- Enable or disable "Copy" and "Paste" commands in the edition menu.

svn path=/trunk/; revision=59135
This commit is contained in:
Hermès Bélusca-Maïto 2013-06-01 22:49:50 +00:00
parent 6c59bd48c4
commit 1e2b31b8bc
11 changed files with 282 additions and 32 deletions

View file

@ -541,16 +541,32 @@ OpenConsoleW(LPCWSTR wsName,
/*
* @unimplemented (Undocumented)
* @implemented (Undocumented)
* @note See http://undoc.airesoft.co.uk/kernel32.dll/SetConsoleCursor.php
*/
BOOL
WINAPI
SetConsoleCursor(DWORD Unknown0,
DWORD Unknown1)
SetConsoleCursor(HANDLE hConsoleOutput,
HCURSOR hCursor)
{
DPRINT1("SetConsoleCursor(0x%x, 0x%x) UNIMPLEMENTED!\n", Unknown0, Unknown1);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
NTSTATUS Status;
CONSOLE_API_MESSAGE ApiMessage;
PCONSOLE_SETCURSOR SetCursorRequest = &ApiMessage.Data.SetCursorRequest;
SetCursorRequest->OutputHandle = hConsoleOutput;
SetCursorRequest->hCursor = hCursor;
Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
NULL,
CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetCursor),
sizeof(CONSOLE_SETCURSOR));
if (!NT_SUCCESS(Status))
{
BaseSetLastNTError(Status);
return FALSE;
}
return TRUE;
}
@ -652,16 +668,18 @@ SetConsoleKeyShortcuts(DWORD Unknown0,
/*
* @unimplemented (Undocumented)
* @implemented (Undocumented)
* @note See http://undoc.airesoft.co.uk/kernel32.dll/SetConsoleMaximumWindowSize.php
* Does nothing, returns TRUE only. Checked on Windows Server 2003.
*/
BOOL
WINAPI
SetConsoleMaximumWindowSize(DWORD Unknown0,
DWORD Unknown1)
SetConsoleMaximumWindowSize(HANDLE hConsoleOutput,
COORD dwMaximumSize)
{
DPRINT1("SetConsoleMaximumWindowSize(0x%x, 0x%x) UNIMPLEMENTED!\n", Unknown0, Unknown1);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
DPRINT1("SetConsoleMaximumWindowSize(0x%x, {%d, %d}) does nothing\n",
hConsoleOutput, dwMaximumSize.X, dwMaximumSize.Y);
return TRUE;
}
@ -707,16 +725,27 @@ SetConsolePalette(DWORD Unknown0,
}
/*
* @unimplemented (Undocumented)
* @implemented (Undocumented)
* @note See http://undoc.airesoft.co.uk/kernel32.dll/ShowConsoleCursor.php
*/
DWORD
INT
WINAPI
ShowConsoleCursor(DWORD Unknown0,
DWORD Unknown1)
ShowConsoleCursor(HANDLE hConsoleOutput,
BOOL bShow)
{
DPRINT1("ShowConsoleCursor(0x%x, 0x%x) UNIMPLEMENTED!\n", Unknown0, Unknown1);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return 0;
CONSOLE_API_MESSAGE ApiMessage;
PCONSOLE_SHOWCURSOR ShowCursorRequest = &ApiMessage.Data.ShowCursorRequest;
ShowCursorRequest->OutputHandle = hConsoleOutput;
ShowCursorRequest->Show = bShow;
ShowCursorRequest->RefCount = 0;
CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
NULL,
CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepShowCursor),
sizeof(CONSOLE_SHOWCURSOR));
return ShowCursorRequest->RefCount;
}

View file

@ -456,6 +456,10 @@ BOOL WINAPI SetConsoleWindowInfo(_In_ HANDLE, _In_ BOOL, _In_ const SMALL_RECT*)
HMENU WINAPI ConsoleMenuControl(_In_ HANDLE, _In_ DWORD, _In_ DWORD);
/* Undocumented */
BOOL WINAPI SetConsoleMenuClose(_In_ BOOL);
/* Undocumented, see http://undoc.airesoft.co.uk/kernel32.dll/SetConsoleCursor.php */
BOOL WINAPI SetConsoleCursor(_In_ HANDLE, _In_ HCURSOR);
/* Undocumented, see http://undoc.airesoft.co.uk/kernel32.dll/ShowConsoleCursor.php */
INT WINAPI ShowConsoleCursor(_In_ HANDLE, _In_ BOOL);
BOOL WINAPI WriteConsoleA(HANDLE,CONST VOID*,DWORD,LPDWORD,LPVOID);
BOOL WINAPI WriteConsoleW(HANDLE,CONST VOID*,DWORD,LPDWORD,LPVOID);

View file

@ -62,8 +62,8 @@ typedef enum _CONSRV_API_NUMBER
ConsolepCreateScreenBuffer,
ConsolepInvalidateBitMapRect,
// ConsolepVDMOperation,
// ConsolepSetCursor,
// ConsolepShowCursor,
ConsolepSetCursor,
ConsolepShowCursor,
ConsolepMenuControl,
// ConsolepSetPalette,
ConsolepSetDisplayMode,
@ -218,6 +218,19 @@ typedef struct
COORD Position;
} CONSOLE_SETCURSORPOSITION, *PCONSOLE_SETCURSORPOSITION;
typedef struct
{
HANDLE OutputHandle;
BOOL Show;
INT RefCount;
} CONSOLE_SHOWCURSOR, *PCONSOLE_SHOWCURSOR;
typedef struct
{
HANDLE OutputHandle;
HCURSOR hCursor;
} CONSOLE_SETCURSOR, *PCONSOLE_SETCURSOR;
typedef struct
{
HANDLE OutputHandle;
@ -627,6 +640,8 @@ typedef struct _CONSOLE_API_MESSAGE
CONSOLE_DUPLICATEHANDLE DuplicateHandleRequest;
/* Cursor */
CONSOLE_SHOWCURSOR ShowCursorRequest;
CONSOLE_SETCURSOR SetCursorRequest;
CONSOLE_GETSETCURSORINFO CursorInfoRequest;
CONSOLE_SETCURSORPOSITION SetCursorPositionRequest;

View file

@ -54,6 +54,8 @@ CSR_API(SrvSetConsoleHardwareState);
CSR_API(SrvGetConsoleDisplayMode);
CSR_API(SrvSetConsoleDisplayMode);
CSR_API(SrvGetLargestConsoleWindowSize);
CSR_API(SrvShowConsoleCursor);
CSR_API(SrvSetConsoleCursor);
CSR_API(SrvConsoleMenuControl);
CSR_API(SrvSetConsoleMenuClose);
CSR_API(SrvSetConsoleWindowInfo);

View file

@ -40,6 +40,10 @@
(Console)->TermIFace.Vtbl->GetDisplayMode(Console)
#define ConioSetDisplayMode(Console, NewMode) \
(Console)->TermIFace.Vtbl->SetDisplayMode((Console), (NewMode))
#define ConioShowMouseCursor(Console, Show) \
(Console)->TermIFace.Vtbl->ShowMouseCursor((Console), (Show))
#define ConioSetMouseCursor(Console, hCursor) \
(Console)->TermIFace.Vtbl->SetMouseCursor((Console), (hCursor))
#define ConioMenuControl(Console, CmdIdLow, CmdIdHigh) \
(Console)->TermIFace.Vtbl->MenuControl((Console), (CmdIdLow), (CmdIdHigh))
#define ConioSetMenuClose(Console, Enable) \

View file

@ -617,7 +617,8 @@ ConSrvInitConsole(OUT PCONSOLE* NewConsole,
Console->LineMaxSize = Console->LineSize = Console->LinePos = 0;
Console->LineComplete = Console->LineUpPressed = Console->LineInsertToggle = FALSE;
// LineWakeupMask
// Selection
RtlZeroMemory(&Console->Selection, sizeof(CONSOLE_SELECTION_INFO));
Console->Selection.dwFlags = CONSOLE_NO_SELECTION;
// dwSelectionCursor
Console->CodePage = GetOEMCP();
@ -1398,6 +1399,54 @@ CSR_API(SrvGetLargestConsoleWindowSize)
return STATUS_SUCCESS;
}
CSR_API(SrvShowConsoleCursor)
{
NTSTATUS Status;
PCONSOLE_SHOWCURSOR ShowCursorRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ShowCursorRequest;
PCONSOLE Console;
PCONSOLE_SCREEN_BUFFER Buff;
Status = ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
ShowCursorRequest->OutputHandle,
&Buff,
GENERIC_WRITE,
TRUE);
if (!NT_SUCCESS(Status)) return Status;
Console = Buff->Header.Console;
ShowCursorRequest->RefCount = ConioShowMouseCursor(Console, ShowCursorRequest->Show);
ConSrvReleaseScreenBuffer(Buff, TRUE);
return STATUS_SUCCESS;
}
CSR_API(SrvSetConsoleCursor)
{
NTSTATUS Status;
BOOL Success;
PCONSOLE_SETCURSOR SetCursorRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetCursorRequest;
PCONSOLE Console;
PCONSOLE_SCREEN_BUFFER Buff;
// FIXME: Tests show that this function is used only for graphics screen buffers
// and otherwise it returns false + set last error to invalid handle.
// NOTE: I find that behaviour is ridiculous but ok, let's accept that at the moment...
Status = ConSrvGetGraphicsBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
SetCursorRequest->OutputHandle,
&Buff,
GENERIC_WRITE,
TRUE);
if (!NT_SUCCESS(Status)) return Status;
Console = Buff->Header.Console;
Success = ConioSetMouseCursor(Console, SetCursorRequest->hCursor);
ConSrvReleaseScreenBuffer(Buff, TRUE);
return (Success ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
}
CSR_API(SrvConsoleMenuControl)
{
NTSTATUS Status;

View file

@ -47,9 +47,12 @@ typedef struct _GUI_CONSOLE_DATA
HWND hWindow; /* Handle to the console's window */
HICON hIcon; /* Handle to the console's icon (big) */
HICON hIconSm; /* Handle to the console's icon (small) */
HCURSOR hCursor; /* Handle to the mouse cursor */
INT MouseCursorRefCount; /* The reference counter associated with the mouse cursor. >= 0 and the cursor is shown; < 0 and the cursor is hidden. */
BOOL IgnoreNextMouseSignal; /* Used in cases where we don't want to treat a mouse signal */
BOOL IsCloseButtonEnabled; /* TRUE if the Close button and the corresponding system menu item are enabled, FALSE otherwise */
BOOL IsCloseButtonEnabled; /* TRUE if the Close button and the corresponding system menu item are enabled (default), FALSE otherwise */
UINT cmdIdLow ; /* Lowest menu id of the user-reserved menu id range */
UINT cmdIdHigh; /* Highest menu id of the user-reserved menu id range */

View file

@ -276,11 +276,23 @@ GuiConsoleHandleSysMenuCommand(PGUI_CONSOLE_DATA GuiData, WPARAM wParam, LPARAM
case ID_SYSTEM_EDIT_SELECTALL:
{
LPWSTR WindowTitle = NULL;
SIZE_T Length = 0;
Console->Selection.dwSelectionAnchor.X = 0;
Console->Selection.dwSelectionAnchor.Y = 0;
Console->dwSelectionCursor.X = ActiveBuffer->ViewSize.X - 1;
Console->dwSelectionCursor.Y = ActiveBuffer->ViewSize.Y - 1;
Console->Selection.dwFlags |= CONSOLE_SELECTION_IN_PROGRESS | CONSOLE_MOUSE_SELECTION;
GuiConsoleUpdateSelection(Console, &Console->dwSelectionCursor);
Length = Console->Title.Length + sizeof(L"Selection - ")/sizeof(WCHAR) + 1;
WindowTitle = ConsoleAllocHeap(0, Length * sizeof(WCHAR));
wcscpy(WindowTitle, L"Selection - ");
wcscat(WindowTitle, Console->Title.Buffer);
SetWindowText(GuiData->hWindow, WindowTitle);
ConsoleFreeHeap(WindowTitle);
break;
}
@ -1636,6 +1648,54 @@ GuiConsoleWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
GuiConsoleHandleTimer(GuiData);
break;
case WM_SETCURSOR:
{
/*
* The message was sent because we are manually triggering a change.
* Check whether the mouse is indeed present on this console window
* and take appropriate decisions.
*/
if (wParam == -1 && lParam == -1)
{
POINT mouseCoords;
HWND hWndHit;
/* Get the placement of the mouse */
GetCursorPos(&mouseCoords);
/* On which window is placed the mouse ? */
hWndHit = WindowFromPoint(mouseCoords);
/* It's our window. Perform the hit-test to be used later on. */
if (hWndHit == hWnd)
{
wParam = (WPARAM)hWnd;
lParam = DefWindowProcW(hWndHit, WM_NCHITTEST, 0,
MAKELPARAM(mouseCoords.x, mouseCoords.y));
}
}
/* Set the mouse cursor only when we are in the client area */
if ((HWND)wParam == hWnd && LOWORD(lParam) == HTCLIENT)
{
if (GuiData->MouseCursorRefCount >= 0)
{
/* Show the cursor */
SetCursor(GuiData->hCursor);
}
else
{
/* Hide the cursor if the reference count is negative */
SetCursor(NULL);
}
return TRUE;
}
else
{
goto Default;
}
}
case WM_LBUTTONDOWN:
case WM_MBUTTONDOWN:
case WM_RBUTTONDOWN:
@ -1711,8 +1771,17 @@ GuiConsoleWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
HMENU hMenu = (HMENU)wParam;
if (hMenu != NULL)
{
/* Enables or disables the Close menu item */
EnableMenuItem(hMenu, SC_CLOSE, MF_BYCOMMAND | (GuiData->IsCloseButtonEnabled ? MF_ENABLED : MF_GRAYED));
/* Enable or disable the Close menu item */
EnableMenuItem(hMenu, SC_CLOSE, MF_BYCOMMAND |
(GuiData->IsCloseButtonEnabled ? MF_ENABLED : MF_GRAYED));
/* Enable or disable the Copy and Paste items */
EnableMenuItem(hMenu, ID_SYSTEM_EDIT_COPY , MF_BYCOMMAND |
((Console->Selection.dwFlags & CONSOLE_SELECTION_IN_PROGRESS) &&
(Console->Selection.dwFlags & CONSOLE_SELECTION_NOT_EMPTY) ? MF_ENABLED : MF_GRAYED));
EnableMenuItem(hMenu, ID_SYSTEM_EDIT_PASTE, MF_BYCOMMAND |
(!(Console->Selection.dwFlags & CONSOLE_SELECTION_IN_PROGRESS) &&
IsClipboardFormatAvailable(CF_UNICODETEXT) ? MF_ENABLED : MF_GRAYED));
}
if (ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
@ -2229,6 +2298,9 @@ GuiProcessKeyCallback(PCONSOLE Console, MSG* msg, BYTE KeyStateMenu, DWORD Shift
return FALSE;
}
static BOOL WINAPI
GuiSetMouseCursor(PCONSOLE Console, HCURSOR hCursor);
static VOID WINAPI
GuiRefreshInternalInfo(PCONSOLE Console)
{
@ -2236,6 +2308,19 @@ GuiRefreshInternalInfo(PCONSOLE Console)
/* Update the console leader information held by the window */
SetConsoleWndConsoleLeaderCID(GuiData);
/*
* HACK:
* We reset the cursor here so that, when a console app quits, we reset
* the cursor to the default one. It's quite a hack since it doesn't proceed
* per - console process... This must be fixed.
*
* See GuiInitConsole(...) for more information.
*/
/* Mouse is shown by default with its default cursor shape */
GuiData->MouseCursorRefCount = 0; // Reinitialize the reference counter
GuiSetMouseCursor(Console, NULL);
}
static VOID WINAPI
@ -2373,6 +2458,38 @@ GuiSetDisplayMode(PCONSOLE Console, ULONG NewMode)
return TRUE;
}
static INT WINAPI
GuiShowMouseCursor(PCONSOLE Console, BOOL Show)
{
PGUI_CONSOLE_DATA GuiData = Console->TermIFace.Data;
/* Set the reference count */
if (Show) ++GuiData->MouseCursorRefCount;
else --GuiData->MouseCursorRefCount;
/* Effectively show (or hide) the cursor (use special values for (w|l)Param) */
PostMessageW(GuiData->hWindow, WM_SETCURSOR, -1, -1);
return GuiData->MouseCursorRefCount;
}
static BOOL WINAPI
GuiSetMouseCursor(PCONSOLE Console, HCURSOR hCursor)
{
PGUI_CONSOLE_DATA GuiData = Console->TermIFace.Data;
/*
* Set the cursor's handle. If the given handle is NULL,
* then restore the default cursor.
*/
GuiData->hCursor = (hCursor ? hCursor : ghDefaultCursor);
/* Effectively modify the shape of the cursor (use special values for (w|l)Param) */
PostMessageW(GuiData->hWindow, WM_SETCURSOR, -1, -1);
return TRUE;
}
static HMENU WINAPI
GuiMenuControl(PCONSOLE Console, UINT cmdIdLow, UINT cmdIdHigh)
{
@ -2420,6 +2537,8 @@ static FRONTEND_VTBL GuiVtbl =
GuiGetLargestConsoleWindowSize,
GuiGetDisplayMode,
GuiSetDisplayMode,
GuiShowMouseCursor,
GuiSetMouseCursor,
GuiMenuControl,
GuiSetMenuClose,
};
@ -2544,6 +2663,13 @@ GuiInitConsole(PCONSOLE Console,
}
}
/* Mouse is shown by default with its default cursor shape */
GuiData->hCursor = ghDefaultCursor;
GuiData->MouseCursorRefCount = 0;
/* A priori don't ignore mouse signals */
GuiData->IgnoreNextMouseSignal = FALSE;
/* Close button and the corresponding system menu item are enabled by default */
GuiData->IsCloseButtonEnabled = TRUE;

View file

@ -643,6 +643,18 @@ TuiSetDisplayMode(PCONSOLE Console, ULONG NewMode)
return TRUE;
}
static INT WINAPI
TuiShowMouseCursor(PCONSOLE Console, BOOL Show)
{
return 0;
}
static BOOL WINAPI
TuiSetMouseCursor(PCONSOLE Console, HCURSOR hCursor)
{
return TRUE;
}
static HMENU WINAPI
TuiMenuControl(PCONSOLE Console, UINT cmdIdLow, UINT cmdIdHigh)
{
@ -652,7 +664,7 @@ TuiMenuControl(PCONSOLE Console, UINT cmdIdLow, UINT cmdIdHigh)
static BOOL WINAPI
TuiSetMenuClose(PCONSOLE Console, BOOL Enable)
{
return FALSE;
return TRUE;
}
static FRONTEND_VTBL TuiVtbl =
@ -671,6 +683,8 @@ static FRONTEND_VTBL TuiVtbl =
TuiGetLargestConsoleWindowSize,
TuiGetDisplayMode,
TuiSetDisplayMode,
TuiShowMouseCursor,
TuiSetMouseCursor,
TuiMenuControl,
TuiSetMenuClose,
};

View file

@ -218,6 +218,10 @@ typedef struct _FRONTEND_VTBL
ULONG (WINAPI *GetDisplayMode)(struct _CONSOLE* Console);
BOOL (WINAPI *SetDisplayMode)(struct _CONSOLE* Console,
ULONG NewMode);
INT (WINAPI *ShowMouseCursor)(struct _CONSOLE* Console,
BOOL Show);
BOOL (WINAPI *SetMouseCursor)(struct _CONSOLE* Console,
HCURSOR hCursor);
HMENU (WINAPI *MenuControl)(struct _CONSOLE* Console,
UINT cmdIdLow,
UINT cmdIdHigh);

View file

@ -72,8 +72,8 @@ PCSR_API_ROUTINE ConsoleServerApiDispatchTable[ConsolepMaxApiNumber - CONSRV_FIR
SrvCreateConsoleScreenBuffer,
SrvInvalidateBitMapRect,
// SrvVDMConsoleOperation,
// SrvSetConsoleCursor,
// SrvShowConsoleCursor,
SrvSetConsoleCursor,
SrvShowConsoleCursor,
SrvConsoleMenuControl,
// SrvSetConsolePalette,
SrvSetConsoleDisplayMode,
@ -163,8 +163,8 @@ BOOLEAN ConsoleServerApiServerValidTable[ConsolepMaxApiNumber - CONSRV_FIRST_API
FALSE, // SrvCreateConsoleScreenBuffer,
FALSE, // SrvInvalidateBitMapRect,
// FALSE, // SrvVDMConsoleOperation,
// FALSE, // SrvSetConsoleCursor,
// FALSE, // SrvShowConsoleCursor,
FALSE, // SrvSetConsoleCursor,
FALSE, // SrvShowConsoleCursor,
FALSE, // SrvConsoleMenuControl,
// FALSE, // SrvSetConsolePalette,
FALSE, // SrvSetConsoleDisplayMode,
@ -254,8 +254,8 @@ PCHAR ConsoleServerApiNameTable[ConsolepMaxApiNumber - CONSRV_FIRST_API_NUMBER]
"CreateConsoleScreenBuffer",
"InvalidateBitMapRect",
// "VDMConsoleOperation",
// "SetConsoleCursor",
// "ShowConsoleCursor",
"SetConsoleCursor",
"ShowConsoleCursor",
"ConsoleMenuControl",
// "SetConsolePalette",
"SetConsoleDisplayMode",