From 7a1f204af1d120e28f279c92f5c63bc9941eb923 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Wed, 6 Aug 2014 21:01:23 +0000 Subject: [PATCH] [KERNEL32][CONSRV] - Fix FreeConsole API. - Implement undocumented GetConsoleKeyboardLayoutNameA/W API (same usage as GetKeyboardLayoutName), needed for ConEmu. See some examples here: http://www.opensource.apple.com/source/vim/vim-44/src/os_win32.c , and there: https://bitbucket.org/jaroslav/lswitcher/src/700bab23f294814235812c5cb07710bd380b1862/lswitch.c CORE-7931 #comment ConsolepFree fixed in revision 63820. svn path=/branches/condrv_restructure/; revision=63820 --- dll/win32/kernel32/client/console/console.c | 96 +++++++++++++++++---- include/reactos/subsys/win/conmsg.h | 13 ++- win32ss/user/winsrv/consrv/console.c | 17 +++- 3 files changed, 103 insertions(+), 23 deletions(-) diff --git a/dll/win32/kernel32/client/console/console.c b/dll/win32/kernel32/client/console/console.c index 7ce38ad3f78..fe4a08461a8 100644 --- a/dll/win32/kernel32/client/console/console.c +++ b/dll/win32/kernel32/client/console/console.c @@ -1076,24 +1076,37 @@ BOOL WINAPI FreeConsole(VOID) { - // AG: I'm not sure if this is correct (what happens to std handles?) - // but I just tried to reverse what AllocConsole() does... - - NTSTATUS Status; CONSOLE_API_MESSAGE ApiMessage; + PCONSOLE_FREECONSOLE FreeConsoleRequest = &ApiMessage.Data.FreeConsoleRequest; + HANDLE ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; - Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, - NULL, - CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepFree), - sizeof(CONSOLE_FREECONSOLE)); - if (!NT_SUCCESS(Status)) + /* We must have a non-trivial handle to close */ + if (ConsoleHandle == NULL) // IsConsoleHandle(ConsoleHandle) { - BaseSetLastNTError(Status); + SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } + /* Set up the data to send to the Console Server */ + FreeConsoleRequest->ConsoleHandle = ConsoleHandle; + + /* Call the server */ + CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, + NULL, + CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepFree), + sizeof(*FreeConsoleRequest)); + + /* Check for success */ + if (!NT_SUCCESS(ApiMessage.Status)) + { + BaseSetLastNTError(ApiMessage.Status); + return FALSE; + } + + /* Reset the console handle */ NtCurrentPeb()->ProcessParameters->ConsoleHandle = NULL; + /* Close the associated input handle */ CloseHandle(InputWaitHandle); InputWaitHandle = INVALID_HANDLE_VALUE; @@ -1311,7 +1324,7 @@ GetLargestConsoleWindowSize(HANDLE hConsoleOutput) BaseSetLastNTError(ApiMessage.Status); } - DPRINT1("GetLargestConsoleWindowSize, X = %d, Y = %d\n", GetLargestWindowSizeRequest->Size.X, GetLargestWindowSizeRequest->Size.Y); + DPRINT("GetLargestConsoleWindowSize, X = %d, Y = %d\n", GetLargestWindowSizeRequest->Size.X, GetLargestWindowSizeRequest->Size.Y); return GetLargestWindowSizeRequest->Size; } @@ -2602,22 +2615,67 @@ UnregisterConsoleIME(VOID) } +BOOL +IntGetConsoleKeyboardLayoutName(OUT PVOID pszLayoutName, + IN BOOL bAnsi) +{ + CONSOLE_API_MESSAGE ApiMessage; + PCONSOLE_GETKBDLAYOUTNAME GetKbdLayoutNameRequest = &ApiMessage.Data.GetKbdLayoutNameRequest; + + /* Set up the data to send to the Console Server */ + GetKbdLayoutNameRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; + GetKbdLayoutNameRequest->Ansi = bAnsi; + + /* Call the server */ + CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, + NULL, + CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetKeyboardLayoutName), + sizeof(*GetKbdLayoutNameRequest)); + + /* Check for success */ + if (!NT_SUCCESS(ApiMessage.Status)) + { + BaseSetLastNTError(ApiMessage.Status); + return FALSE; + } + + /* Retrieve the results */ + _SEH2_TRY + { + /* Copy only KL_NAMELENGTH == 9 characters, ANSI or UNICODE */ + if (bAnsi) + strncpy(pszLayoutName, (PCHAR)GetKbdLayoutNameRequest->LayoutBuffer, KL_NAMELENGTH); + else + wcsncpy(pszLayoutName, (PWCHAR)GetKbdLayoutNameRequest->LayoutBuffer, KL_NAMELENGTH); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + SetLastError(ERROR_INVALID_ACCESS); + _SEH2_YIELD(return FALSE); + } + _SEH2_END; + + return TRUE; +} + /* - * @unimplemented + * @implemented (undocumented) */ -BOOL WINAPI GetConsoleKeyboardLayoutNameA(LPSTR name) +BOOL +WINAPI +GetConsoleKeyboardLayoutNameA(OUT LPSTR pszLayoutName) { - STUB; - return 0; + return IntGetConsoleKeyboardLayoutName(pszLayoutName, TRUE); } /* - * @unimplemented + * @implemented (undocumented) */ -BOOL WINAPI GetConsoleKeyboardLayoutNameW(LPWSTR name) +BOOL +WINAPI +GetConsoleKeyboardLayoutNameW(OUT LPWSTR pszLayoutName) { - STUB; - return 0; + return IntGetConsoleKeyboardLayoutName(pszLayoutName, FALSE); } /* diff --git a/include/reactos/subsys/win/conmsg.h b/include/reactos/subsys/win/conmsg.h index 56870f4e94e..a11d0bf64b8 100644 --- a/include/reactos/subsys/win/conmsg.h +++ b/include/reactos/subsys/win/conmsg.h @@ -164,6 +164,7 @@ typedef struct _CONSOLE_START_INFO DWORD dwHotKey; DWORD dwStartupFlags; CONSOLE_PROPERTIES; + BOOLEAN ConsoleNeeded; // Used for GUI apps only. LPTHREAD_START_ROUTINE CtrlDispatcher; LPTHREAD_START_ROUTINE ImeDispatcher; @@ -281,7 +282,7 @@ typedef struct typedef struct { - ULONG Dummy; + HANDLE ConsoleHandle; } CONSOLE_FREECONSOLE, *PCONSOLE_FREECONSOLE; typedef struct @@ -793,6 +794,13 @@ typedef struct HANDLE EventHandle; } CONSOLE_SETINPUTOUTPUTCP, *PCONSOLE_SETINPUTOUTPUTCP; +typedef struct +{ + HANDLE ConsoleHandle; + CHAR LayoutBuffer[KL_NAMELENGTH * sizeof(WCHAR)]; // Can hold up to 9 wchars + BOOL Ansi; +} CONSOLE_GETKBDLAYOUTNAME, *PCONSOLE_GETKBDLAYOUTNAME; + typedef struct _CONSOLE_API_MESSAGE { PORT_MESSAGE Header; @@ -886,9 +894,10 @@ typedef struct _CONSOLE_API_MESSAGE CONSOLE_SETHISTORYNUMBERCOMMANDS SetHistoryNumberCommandsRequest; CONSOLE_SETHISTORYMODE SetHistoryModeRequest; - /* Input and Output Code Pages */ + /* Input and Output Code Pages; keyboard */ CONSOLE_GETINPUTOUTPUTCP GetConsoleCPRequest; CONSOLE_SETINPUTOUTPUTCP SetConsoleCPRequest; + CONSOLE_GETKBDLAYOUTNAME GetKbdLayoutNameRequest; } Data; } CONSOLE_API_MESSAGE, *PCONSOLE_API_MESSAGE; diff --git a/win32ss/user/winsrv/consrv/console.c b/win32ss/user/winsrv/consrv/console.c index b4f0d4ffd01..fb0ddf7bd14 100644 --- a/win32ss/user/winsrv/consrv/console.c +++ b/win32ss/user/winsrv/consrv/console.c @@ -999,8 +999,21 @@ CSR_API(SrvSetConsoleKeyShortcuts) CSR_API(SrvGetConsoleKeyboardLayoutName) { - DPRINT1("%s not yet implemented\n", __FUNCTION__); - return STATUS_NOT_IMPLEMENTED; + NTSTATUS Status; + PCONSOLE_GETKBDLAYOUTNAME GetKbdLayoutNameRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetKbdLayoutNameRequest; + PCONSOLE Console; + + Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE); + if (!NT_SUCCESS(Status)) return Status; + + /* Retrieve the keyboard layout name of the system */ + if (GetKbdLayoutNameRequest->Ansi) + GetKeyboardLayoutNameA((PCHAR)GetKbdLayoutNameRequest->LayoutBuffer); + else + GetKeyboardLayoutNameW((PWCHAR)GetKbdLayoutNameRequest->LayoutBuffer); + + ConSrvReleaseConsole(Console, TRUE); + return STATUS_SUCCESS; } CSR_API(SrvGetConsoleCharType) -- 2.17.1