/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries * FILE: dll/win32/kernel32/client/console/console.c * PURPOSE: Win32 server console functions * PROGRAMMERS: James Tabor * Hermes Belusca-Maito (hermes.belusca@sfr.fr) */ /* INCLUDES *******************************************************************/ #include #define NDEBUG #include /* GLOBALS ********************************************************************/ extern RTL_CRITICAL_SECTION ConsoleLock; extern BOOLEAN ConsoleInitialized; /* Console reserved "file" names */ static LPCWSTR BaseConFileName = CONSOLE_FILE_NAME; static LPCWSTR BaseConInputFileName = CONSOLE_INPUT_FILE_NAME; static LPCWSTR BaseConOutputFileName = CONSOLE_OUTPUT_FILE_NAME; /* Console Control handling */ static PHANDLER_ROUTINE InitialHandler[1]; static PHANDLER_ROUTINE* CtrlHandlers; static ULONG NrCtrlHandlers; static ULONG NrAllocatedHandlers; static BOOLEAN LastCloseNotify = FALSE; extern BOOL WINAPI IsDebuggerPresent(VOID); /* Console Input facilities */ HANDLE InputWaitHandle = INVALID_HANDLE_VALUE; #define EXENAME_LENGTH (255 + 1) static RTL_CRITICAL_SECTION ExeNameLock; static BOOLEAN ExeNameInitialized; static WCHAR ExeNameBuffer[EXENAME_LENGTH]; // NULL-terminated static USHORT ExeNameLength; // Count in number of characters without NULL static WCHAR StartDirBuffer[MAX_PATH + 1]; // NULL-terminated static USHORT StartDirLength; // Count in number of characters without NULL /* Default Console Control Handler ********************************************/ static BOOL WINAPI DefaultConsoleCtrlHandler(DWORD Event) { DPRINT("Default handler called: %lx\n", Event); switch(Event) { case CTRL_C_EVENT: DPRINT("Ctrl-C Event\n"); break; case CTRL_BREAK_EVENT: DPRINT("Ctrl-Break Event\n"); break; case CTRL_CLOSE_EVENT: DPRINT("Ctrl Close Event\n"); break; case CTRL_LAST_CLOSE_EVENT: DPRINT("Ctrl Last Close Event\n"); break; case CTRL_LOGOFF_EVENT: DPRINT("Ctrl Logoff Event\n"); break; case CTRL_SHUTDOWN_EVENT: DPRINT("Ctrl Shutdown Event\n"); break; } ExitProcess(CONTROL_C_EXIT); return TRUE; } DWORD WINAPI ConsoleControlDispatcher(IN LPVOID lpThreadParameter) { DWORD nExitCode = 0; DWORD CodeAndFlag = PtrToUlong(lpThreadParameter); DWORD nCode = CodeAndFlag & MAXLONG; UINT i; EXCEPTION_RECORD erException; DPRINT1("Console Dispatcher Active: %lx %lx\n", CodeAndFlag, nCode); SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST); switch(nCode) { case CTRL_C_EVENT: case CTRL_BREAK_EVENT: { if (IsDebuggerPresent()) { erException.ExceptionCode = (nCode == CTRL_C_EVENT ? DBG_CONTROL_C : DBG_CONTROL_BREAK); erException.ExceptionFlags = 0; erException.ExceptionRecord = NULL; erException.ExceptionAddress = DefaultConsoleCtrlHandler; erException.NumberParameters = 0; _SEH2_TRY { RtlRaiseException(&erException); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { RtlEnterCriticalSection(&ConsoleLock); if ((nCode != CTRL_C_EVENT) || (NtCurrentPeb()->ProcessParameters->ConsoleFlags != 1)) { for (i = NrCtrlHandlers; i > 0; i--) { if (CtrlHandlers[i - 1](nCode)) break; } } RtlLeaveCriticalSection(&ConsoleLock); } _SEH2_END; ExitThread(0); } break; } case CTRL_CLOSE_EVENT: case CTRL_LOGOFF_EVENT: case CTRL_SHUTDOWN_EVENT: break; case CTRL_LAST_CLOSE_EVENT: /* * In case the console app hasn't register for last close notification, * just kill this console handler thread. We don't want that such apps * get killed for unexpected reasons. On the contrary apps that registered * can be killed because they expect to be. */ if (!LastCloseNotify) ExitThread(0); break; case 4: ExitProcess(CONTROL_C_EXIT); break; default: ASSERT(FALSE); break; } ASSERT(ConsoleInitialized); RtlEnterCriticalSection(&ConsoleLock); nExitCode = 0; if ((nCode != CTRL_C_EVENT) || (NtCurrentPeb()->ProcessParameters->ConsoleFlags != 1)) { for (i = NrCtrlHandlers; i > 0; i--) { if ((i == 1) && (CodeAndFlag & MINLONG) && ((nCode == CTRL_LOGOFF_EVENT) || (nCode == CTRL_SHUTDOWN_EVENT))) { DPRINT("Skipping system/service apps\n"); break; } if (CtrlHandlers[i - 1](nCode)) { switch(nCode) { case CTRL_CLOSE_EVENT: case CTRL_LAST_CLOSE_EVENT: case CTRL_LOGOFF_EVENT: case CTRL_SHUTDOWN_EVENT: nExitCode = CodeAndFlag; break; } break; } } } RtlLeaveCriticalSection(&ConsoleLock); ExitThread(nExitCode); return STATUS_SUCCESS; } VOID InitializeCtrlHandling(VOID) { /* Initialize Console Ctrl Handler */ NrAllocatedHandlers = NrCtrlHandlers = 1; CtrlHandlers = InitialHandler; CtrlHandlers[0] = DefaultConsoleCtrlHandler; } /* Input EXE Name Support *****************************************************/ VOID InitExeName(VOID) { NTSTATUS Status; PPEB Peb = NtCurrentPeb(); PCURDIR CurrentDirectory = &Peb->ProcessParameters->CurrentDirectory; PLDR_DATA_TABLE_ENTRY ImageEntry; if (ExeNameInitialized) return; /* Initialize the EXE name lock */ Status = RtlInitializeCriticalSection(&ExeNameLock); if (!NT_SUCCESS(Status)) return; ExeNameInitialized = TRUE; ImageEntry = CONTAINING_RECORD(Peb->Ldr->InLoadOrderModuleList.Flink, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); /* Retrieve the EXE name, NULL-terminate it... */ ExeNameLength = min(sizeof(ExeNameBuffer)/sizeof(ExeNameBuffer[0]), ImageEntry->BaseDllName.Length / sizeof(WCHAR)); RtlCopyMemory(ExeNameBuffer, ImageEntry->BaseDllName.Buffer, ImageEntry->BaseDllName.Length); ExeNameBuffer[ExeNameLength] = UNICODE_NULL; /* ... and retrieve the current directory path and NULL-terminate it. */ StartDirLength = min(sizeof(StartDirBuffer)/sizeof(StartDirBuffer[0]), CurrentDirectory->DosPath.Length / sizeof(WCHAR)); RtlCopyMemory(StartDirBuffer, CurrentDirectory->DosPath.Buffer, CurrentDirectory->DosPath.Length); StartDirBuffer[StartDirLength] = UNICODE_NULL; } /* * NOTE: * The "LPDWORD Length" parameters point on input to the maximum size of * the buffers that can hold data (if != 0), and on output they hold the * real size of the data. If "Length" are == 0 on input, then on output * they receive the full size of the data. * The "LPWSTR* String" parameters have a double meaning: * - when "CaptureStrings" is TRUE, data is copied to the buffers pointed * by the pointers (*String). * - when "CaptureStrings" is FALSE, "*String" are set to the addresses of * the source data. */ VOID SetUpAppName(IN BOOLEAN CaptureStrings, IN OUT LPDWORD CurDirLength, IN OUT LPWSTR* CurDir, IN OUT LPDWORD AppNameLength, IN OUT LPWSTR* AppName) { DWORD Length; /* Retrieve the needed buffer size */ Length = (StartDirLength + 1) * sizeof(WCHAR); if (*CurDirLength > 0) Length = min(Length, *CurDirLength); *CurDirLength = Length; /* Capture the data if needed, or, return a pointer to it */ if (CaptureStrings) { /* * Length is always >= sizeof(WCHAR). Copy everything but the * possible trailing NULL character, and then NULL-terminate. */ Length -= sizeof(WCHAR); RtlCopyMemory(*CurDir, StartDirBuffer, Length); (*CurDir)[Length / sizeof(WCHAR)] = UNICODE_NULL; } else { *CurDir = StartDirBuffer; } /* Retrieve the needed buffer size */ Length = (ExeNameLength + 1) * sizeof(WCHAR); if (*AppNameLength > 0) Length = min(Length, *AppNameLength); *AppNameLength = Length; /* Capture the data if needed, or, return a pointer to it */ if (CaptureStrings) { /* * Length is always >= sizeof(WCHAR). Copy everything but the * possible trailing NULL character, and then NULL-terminate. */ Length -= sizeof(WCHAR); RtlCopyMemory(*AppName, ExeNameBuffer, Length); (*AppName)[Length / sizeof(WCHAR)] = UNICODE_NULL; } else { *AppName = ExeNameBuffer; } } USHORT GetCurrentExeName(OUT PWCHAR ExeName, IN USHORT BufferSize) { USHORT ExeLength; if (ExeNameInitialized) { RtlEnterCriticalSection(&ExeNameLock); if (BufferSize > ExeNameLength * sizeof(WCHAR)) BufferSize = ExeNameLength * sizeof(WCHAR); RtlCopyMemory(ExeName, ExeNameBuffer, BufferSize); RtlLeaveCriticalSection(&ExeNameLock); ExeLength = BufferSize; } else { *ExeName = UNICODE_NULL; ExeLength = 0; } return ExeLength; } /* FUNCTIONS ******************************************************************/ LPCWSTR IntCheckForConsoleFileName(IN LPCWSTR pszName, IN DWORD dwDesiredAccess) { LPCWSTR ConsoleName = pszName; ULONG DeviceNameInfo; /* * Check whether we deal with a DOS device, and if so, * strip the path till the file name. * Therefore, things like \\.\CON or C:\some_path\CONIN$ * are transformed into CON or CONIN$, for example. */ DeviceNameInfo = RtlIsDosDeviceName_U(pszName); if (DeviceNameInfo != 0) { ConsoleName = (LPCWSTR)((ULONG_PTR)ConsoleName + ((DeviceNameInfo >> 16) & 0xFFFF)); } /* Return a standard console "file" name according to what we passed in parameters */ if (_wcsicmp(ConsoleName, BaseConInputFileName) == 0) { return BaseConInputFileName; } else if (_wcsicmp(ConsoleName, BaseConOutputFileName) == 0) { return BaseConOutputFileName; } else if (_wcsicmp(ConsoleName, BaseConFileName) == 0) { if ((dwDesiredAccess & (GENERIC_READ | GENERIC_WRITE)) == GENERIC_READ) { return BaseConInputFileName; } else if ((dwDesiredAccess & (GENERIC_READ | GENERIC_WRITE)) == GENERIC_WRITE) { return BaseConOutputFileName; } } /* If we are there, that means that either the file name or the desired access are wrong */ return NULL; } /* * @implemented (Undocumented) * @note See http://undoc.airesoft.co.uk/kernel32.dll/ConsoleMenuControl.php */ HMENU WINAPI DECLSPEC_HOTPATCH ConsoleMenuControl(HANDLE hConsoleOutput, DWORD dwCmdIdLow, DWORD dwCmdIdHigh) { CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_MENUCONTROL MenuControlRequest = &ApiMessage.Data.MenuControlRequest; MenuControlRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; MenuControlRequest->OutputHandle = hConsoleOutput; MenuControlRequest->CmdIdLow = dwCmdIdLow; MenuControlRequest->CmdIdHigh = dwCmdIdHigh; MenuControlRequest->MenuHandle = NULL; CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, NULL, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepMenuControl), sizeof(*MenuControlRequest)); return MenuControlRequest->MenuHandle; } /* * @implemented */ HANDLE WINAPI DECLSPEC_HOTPATCH DuplicateConsoleHandle(HANDLE hConsole, DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwOptions) { CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_DUPLICATEHANDLE DuplicateHandleRequest = &ApiMessage.Data.DuplicateHandleRequest; if ( (dwOptions & ~(DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) || (!(dwOptions & DUPLICATE_SAME_ACCESS) && (dwDesiredAccess & ~(GENERIC_READ | GENERIC_WRITE))) ) { SetLastError(ERROR_INVALID_PARAMETER); return INVALID_HANDLE_VALUE; } DuplicateHandleRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; DuplicateHandleRequest->SourceHandle = hConsole; DuplicateHandleRequest->DesiredAccess = dwDesiredAccess; DuplicateHandleRequest->InheritHandle = bInheritHandle; DuplicateHandleRequest->Options = dwOptions; CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, NULL, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepDuplicateHandle), sizeof(*DuplicateHandleRequest)); if (!NT_SUCCESS(ApiMessage.Status)) { BaseSetLastNTError(ApiMessage.Status); return INVALID_HANDLE_VALUE; } return DuplicateHandleRequest->TargetHandle; } /* * @implemented */ BOOL WINAPI GetConsoleHandleInformation(IN HANDLE hHandle, OUT LPDWORD lpdwFlags) { CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_GETHANDLEINFO GetHandleInfoRequest = &ApiMessage.Data.GetHandleInfoRequest; GetHandleInfoRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; GetHandleInfoRequest->Handle = hHandle; CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, NULL, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetHandleInformation), sizeof(*GetHandleInfoRequest)); if (!NT_SUCCESS(ApiMessage.Status)) { BaseSetLastNTError(ApiMessage.Status); return FALSE; } *lpdwFlags = GetHandleInfoRequest->Flags; return TRUE; } /* * @implemented */ BOOL WINAPI SetConsoleHandleInformation(IN HANDLE hHandle, IN DWORD dwMask, IN DWORD dwFlags) { CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_SETHANDLEINFO SetHandleInfoRequest = &ApiMessage.Data.SetHandleInfoRequest; SetHandleInfoRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; SetHandleInfoRequest->Handle = hHandle; SetHandleInfoRequest->Mask = dwMask; SetHandleInfoRequest->Flags = dwFlags; CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, NULL, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetHandleInformation), sizeof(*SetHandleInfoRequest)); if (!NT_SUCCESS(ApiMessage.Status)) { BaseSetLastNTError(ApiMessage.Status); return FALSE; } return TRUE; } /* * @implemented */ BOOL WINAPI GetConsoleDisplayMode(LPDWORD lpModeFlags) { CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_GETDISPLAYMODE GetDisplayModeRequest = &ApiMessage.Data.GetDisplayModeRequest; if (lpModeFlags == NULL) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } GetDisplayModeRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, NULL, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetDisplayMode), sizeof(*GetDisplayModeRequest)); if (!NT_SUCCESS(ApiMessage.Status)) { BaseSetLastNTError(ApiMessage.Status); return FALSE; } *lpModeFlags = GetDisplayModeRequest->DisplayMode; // ModeFlags return TRUE; } /* * @implemented (Undocumented) * @note See http://cboard.cprogramming.com/windows-programming/102187-console-font-size.html */ DWORD WINAPI GetConsoleFontInfo(IN HANDLE hConsoleOutput, IN BOOL bMaximumWindow, IN DWORD nFontCount, OUT PCONSOLE_FONT_INFO lpConsoleFontInfo) { CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_GETFONTINFO GetFontInfoRequest = &ApiMessage.Data.GetFontInfoRequest; PCSR_CAPTURE_BUFFER CaptureBuffer; GetFontInfoRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; GetFontInfoRequest->OutputHandle = hConsoleOutput; GetFontInfoRequest->MaximumWindow = bMaximumWindow; GetFontInfoRequest->NumFonts = nFontCount; CaptureBuffer = CsrAllocateCaptureBuffer(1, nFontCount * sizeof(CONSOLE_FONT_INFO)); if (CaptureBuffer == NULL) { DPRINT1("CsrAllocateCaptureBuffer failed!\n"); SetLastError(ERROR_NOT_ENOUGH_MEMORY); return 0; } CsrAllocateMessagePointer(CaptureBuffer, nFontCount * sizeof(CONSOLE_FONT_INFO), (PVOID*)&GetFontInfoRequest->FontInfo); CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, CaptureBuffer, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetFontInfo), sizeof(*GetFontInfoRequest)); if (!NT_SUCCESS(ApiMessage.Status)) { BaseSetLastNTError(ApiMessage.Status); } else { RtlCopyMemory(lpConsoleFontInfo, GetFontInfoRequest->FontInfo, GetFontInfoRequest->NumFonts * sizeof(CONSOLE_FONT_INFO)); } CsrFreeCaptureBuffer(CaptureBuffer); return GetFontInfoRequest->NumFonts; } /* * @implemented */ COORD WINAPI DECLSPEC_HOTPATCH GetConsoleFontSize(IN HANDLE hConsoleOutput, IN DWORD nFont) { CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_GETFONTSIZE GetFontSizeRequest = &ApiMessage.Data.GetFontSizeRequest; COORD Empty = {0, 0}; GetFontSizeRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; GetFontSizeRequest->OutputHandle = hConsoleOutput; GetFontSizeRequest->FontIndex = nFont; CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, NULL, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetFontSize), sizeof(*GetFontSizeRequest)); if (!NT_SUCCESS(ApiMessage.Status)) { BaseSetLastNTError(ApiMessage.Status); return Empty; } return GetFontSizeRequest->FontSize; } /* * @implemented (Undocumented) */ BOOL WINAPI GetConsoleHardwareState(HANDLE hConsoleOutput, PDWORD Flags, PDWORD State) { CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_GETSETHWSTATE HardwareStateRequest = &ApiMessage.Data.HardwareStateRequest; DPRINT1("GetConsoleHardwareState(%lu, 0x%p) UNIMPLEMENTED!\n", Flags, State); if (Flags == NULL || State == NULL) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } HardwareStateRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; HardwareStateRequest->OutputHandle = hConsoleOutput; CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, NULL, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetHardwareState), sizeof(*HardwareStateRequest)); if (!NT_SUCCESS(ApiMessage.Status)) { BaseSetLastNTError(ApiMessage.Status); return FALSE; } *Flags = HardwareStateRequest->Flags; *State = HardwareStateRequest->State; return TRUE; } /* * @implemented (Undocumented) */ HANDLE WINAPI GetConsoleInputWaitHandle(VOID) { return InputWaitHandle; } /* * @implemented */ BOOL WINAPI GetCurrentConsoleFont(IN HANDLE hConsoleOutput, IN BOOL bMaximumWindow, OUT PCONSOLE_FONT_INFO lpConsoleCurrentFont) { CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_GETCURRENTFONT GetCurrentFontRequest = &ApiMessage.Data.GetCurrentFontRequest; GetCurrentFontRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; GetCurrentFontRequest->OutputHandle = hConsoleOutput; GetCurrentFontRequest->MaximumWindow = bMaximumWindow; CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, NULL, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetCurrentFont), sizeof(*GetCurrentFontRequest)); if (!NT_SUCCESS(ApiMessage.Status)) { BaseSetLastNTError(ApiMessage.Status); return FALSE; } lpConsoleCurrentFont->dwFontSize = GetCurrentFontRequest->FontSize; lpConsoleCurrentFont->nFont = GetCurrentFontRequest->FontIndex; return TRUE; } /* * @implemented (Undocumented) * @note See http://cboard.cprogramming.com/windows-programming/102187-console-font-size.html */ DWORD WINAPI DECLSPEC_HOTPATCH GetNumberOfConsoleFonts(VOID) { CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_GETNUMFONTS GetNumFontsRequest = &ApiMessage.Data.GetNumFontsRequest; GetNumFontsRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, NULL, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetNumberOfFonts), sizeof(*GetNumFontsRequest)); if (!NT_SUCCESS(ApiMessage.Status)) { BaseSetLastNTError(ApiMessage.Status); return 0; } return GetNumFontsRequest->NumFonts; } /* * @implemented (Undocumented) * @note See http://blog.airesoft.co.uk/2012/10/things-ms-can-do-that-they-dont-tell-you-about-console-graphics/ */ BOOL WINAPI InvalidateConsoleDIBits(IN HANDLE hConsoleOutput, IN PSMALL_RECT lpRect) { CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_INVALIDATEDIBITS InvalidateDIBitsRequest = &ApiMessage.Data.InvalidateDIBitsRequest; if (lpRect == NULL) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } InvalidateDIBitsRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; InvalidateDIBitsRequest->OutputHandle = hConsoleOutput; InvalidateDIBitsRequest->Region = *lpRect; CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, NULL, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepInvalidateBitMapRect), sizeof(*InvalidateDIBitsRequest)); if (!NT_SUCCESS(ApiMessage.Status)) { BaseSetLastNTError(ApiMessage.Status); return FALSE; } return TRUE; } /* * @implemented (Undocumented) */ HANDLE WINAPI OpenConsoleW(LPCWSTR wsName, DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwShareMode) { CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_OPENCONSOLE OpenConsoleRequest = &ApiMessage.Data.OpenConsoleRequest; CONSOLE_HANDLE_TYPE HandleType; if (wsName && (_wcsicmp(wsName, BaseConInputFileName) == 0)) { HandleType = HANDLE_INPUT; } else if (wsName && (_wcsicmp(wsName, BaseConOutputFileName) == 0)) { HandleType = HANDLE_OUTPUT; } else { SetLastError(ERROR_INVALID_PARAMETER); return INVALID_HANDLE_VALUE; } if ( (dwDesiredAccess & ~(GENERIC_READ | GENERIC_WRITE)) || (dwShareMode & ~(FILE_SHARE_READ | FILE_SHARE_WRITE)) ) { SetLastError(ERROR_INVALID_PARAMETER); return INVALID_HANDLE_VALUE; } OpenConsoleRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; OpenConsoleRequest->HandleType = HandleType; OpenConsoleRequest->DesiredAccess = dwDesiredAccess; OpenConsoleRequest->InheritHandle = bInheritHandle; OpenConsoleRequest->ShareMode = dwShareMode; CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, NULL, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepOpenConsole), sizeof(*OpenConsoleRequest)); if (!NT_SUCCESS(ApiMessage.Status)) { BaseSetLastNTError(ApiMessage.Status); return INVALID_HANDLE_VALUE; } return OpenConsoleRequest->Handle; } /* * @implemented (Undocumented) * @note See http://undoc.airesoft.co.uk/kernel32.dll/SetConsoleCursor.php */ BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleCursor(HANDLE hConsoleOutput, HCURSOR hCursor) { CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_SETCURSOR SetCursorRequest = &ApiMessage.Data.SetCursorRequest; SetCursorRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; SetCursorRequest->OutputHandle = hConsoleOutput; SetCursorRequest->CursorHandle = hCursor; CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, NULL, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetCursor), sizeof(*SetCursorRequest)); if (!NT_SUCCESS(ApiMessage.Status)) { BaseSetLastNTError(ApiMessage.Status); return FALSE; } return TRUE; } /* * @implemented */ BOOL WINAPI SetConsoleDisplayMode(HANDLE hConsoleOutput, DWORD dwFlags, // dwModeFlags PCOORD lpNewScreenBufferDimensions) { CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_SETDISPLAYMODE SetDisplayModeRequest = &ApiMessage.Data.SetDisplayModeRequest; SetDisplayModeRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; SetDisplayModeRequest->OutputHandle = hConsoleOutput; SetDisplayModeRequest->DisplayMode = dwFlags; // ModeFlags ; dwModeFlags SetDisplayModeRequest->NewSBDim.X = 0; SetDisplayModeRequest->NewSBDim.Y = 0; /* SetDisplayModeRequest->EventHandle; */ CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, NULL, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetDisplayMode), sizeof(*SetDisplayModeRequest)); if (!NT_SUCCESS(ApiMessage.Status)) { BaseSetLastNTError(ApiMessage.Status); return FALSE; } if (lpNewScreenBufferDimensions) *lpNewScreenBufferDimensions = SetDisplayModeRequest->NewSBDim; return TRUE; } /* * @implemented (Undocumented) * @note See http://cboard.cprogramming.com/windows-programming/102187-console-font-size.html */ BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleFont(IN HANDLE hConsoleOutput, IN DWORD nFont) { CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_SETFONT SetFontRequest = &ApiMessage.Data.SetFontRequest; SetFontRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; SetFontRequest->OutputHandle = hConsoleOutput; SetFontRequest->FontIndex = nFont; CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, NULL, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetFont), sizeof(*SetFontRequest)); if (!NT_SUCCESS(ApiMessage.Status)) { BaseSetLastNTError(ApiMessage.Status); return FALSE; } return TRUE; } /* * @implemented (Undocumented) */ BOOL WINAPI SetConsoleHardwareState(HANDLE hConsoleOutput, DWORD Flags, DWORD State) { CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_GETSETHWSTATE HardwareStateRequest = &ApiMessage.Data.HardwareStateRequest; DPRINT1("SetConsoleHardwareState(%lu, %lu) UNIMPLEMENTED!\n", Flags, State); HardwareStateRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; HardwareStateRequest->OutputHandle = hConsoleOutput; HardwareStateRequest->Flags = Flags; HardwareStateRequest->State = State; CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, NULL, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetHardwareState), sizeof(*HardwareStateRequest)); if (!NT_SUCCESS(ApiMessage.Status)) { BaseSetLastNTError(ApiMessage.Status); return FALSE; } return TRUE; } /* * @unimplemented (Undocumented) */ BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleKeyShortcuts(DWORD Unknown0, DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) { DPRINT1("SetConsoleKeyShortcuts(0x%x, 0x%x, 0x%x, 0x%x) UNIMPLEMENTED!\n", Unknown0, Unknown1, Unknown2, Unknown3); SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return FALSE; } /* * @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(HANDLE hConsoleOutput, COORD dwMaximumSize) { DPRINT1("SetConsoleMaximumWindowSize(0x%p, {%d, %d}) does nothing\n", hConsoleOutput, dwMaximumSize.X, dwMaximumSize.Y); return TRUE; } /* * @implemented (Undocumented) */ BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleMenuClose(BOOL bEnable) { CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_SETMENUCLOSE SetMenuCloseRequest = &ApiMessage.Data.SetMenuCloseRequest; SetMenuCloseRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; SetMenuCloseRequest->Enable = bEnable; CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, NULL, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetMenuClose), sizeof(*SetMenuCloseRequest)); if (!NT_SUCCESS(ApiMessage.Status)) { BaseSetLastNTError(ApiMessage.Status); return FALSE; } return TRUE; } /* * @implemented (Undocumented) * @note See http://comments.gmane.org/gmane.comp.lang.harbour.devel/27844 * Usage example: https://github.com/harbour/core/commit/d79a1b7b812cbde6ddf718ebfd6939a24f633e52 */ BOOL WINAPI DECLSPEC_HOTPATCH SetConsolePalette(HANDLE hConsoleOutput, HPALETTE hPalette, UINT dwUsage) { CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_SETPALETTE SetPaletteRequest = &ApiMessage.Data.SetPaletteRequest; SetPaletteRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; SetPaletteRequest->OutputHandle = hConsoleOutput; SetPaletteRequest->PaletteHandle = hPalette; SetPaletteRequest->Usage = dwUsage; CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, NULL, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetPalette), sizeof(*SetPaletteRequest)); if (!NT_SUCCESS(ApiMessage.Status)) { BaseSetLastNTError(ApiMessage.Status); return FALSE; } return TRUE; } /* * @implemented (Undocumented) * @note See http://undoc.airesoft.co.uk/kernel32.dll/ShowConsoleCursor.php */ INT WINAPI DECLSPEC_HOTPATCH ShowConsoleCursor(HANDLE hConsoleOutput, BOOL bShow) { CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_SHOWCURSOR ShowCursorRequest = &ApiMessage.Data.ShowCursorRequest; ShowCursorRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; ShowCursorRequest->OutputHandle = hConsoleOutput; ShowCursorRequest->Show = bShow; ShowCursorRequest->RefCount = 0; CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, NULL, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepShowCursor), sizeof(*ShowCursorRequest)); return ShowCursorRequest->RefCount; } /* * FUNCTION: Checks whether the given handle is a valid console handle. * * ARGUMENTS: * hIoHandle - Handle to be checked. * * RETURNS: * TRUE : Handle is a valid console handle. * FALSE: Handle is not a valid console handle. * * STATUS: Officially undocumented * * @implemented */ BOOL WINAPI DECLSPEC_HOTPATCH VerifyConsoleIoHandle(HANDLE hIoHandle) { CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_VERIFYHANDLE VerifyHandleRequest = &ApiMessage.Data.VerifyHandleRequest; VerifyHandleRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; VerifyHandleRequest->Handle = hIoHandle; VerifyHandleRequest->IsValid = FALSE; /* If the process is not attached to a console, return invalid handle */ if (VerifyHandleRequest->ConsoleHandle == NULL) return FALSE; CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, NULL, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepVerifyIoHandle), sizeof(*VerifyHandleRequest)); if (!NT_SUCCESS(ApiMessage.Status)) { BaseSetLastNTError(ApiMessage.Status); return FALSE; } return VerifyHandleRequest->IsValid; } /* * @implemented (Undocumented) */ BOOL WINAPI DECLSPEC_HOTPATCH CloseConsoleHandle(HANDLE hHandle) { CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_CLOSEHANDLE CloseHandleRequest = &ApiMessage.Data.CloseHandleRequest; CloseHandleRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; CloseHandleRequest->Handle = hHandle; CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, NULL, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepCloseHandle), sizeof(*CloseHandleRequest)); if (!NT_SUCCESS(ApiMessage.Status)) { BaseSetLastNTError(ApiMessage.Status); return FALSE; } return TRUE; } /* * @implemented */ HANDLE WINAPI DECLSPEC_HOTPATCH GetStdHandle(DWORD nStdHandle) /* * FUNCTION: Get a handle for the standard input, standard output * and a standard error device. * * ARGUMENTS: * nStdHandle - Specifies the device for which to return the handle. * * RETURNS: If the function succeeds, the return value is the handle * of the specified device. Otherwise the value is INVALID_HANDLE_VALUE. */ { PRTL_USER_PROCESS_PARAMETERS Ppb = NtCurrentPeb()->ProcessParameters; HANDLE Handle = INVALID_HANDLE_VALUE; switch (nStdHandle) { case STD_INPUT_HANDLE: Handle = Ppb->StandardInput; break; case STD_OUTPUT_HANDLE: Handle = Ppb->StandardOutput; break; case STD_ERROR_HANDLE: Handle = Ppb->StandardError; break; } /* If the returned handle is invalid, set last error */ if (Handle == INVALID_HANDLE_VALUE) SetLastError(ERROR_INVALID_HANDLE); return Handle; } /* * @implemented */ BOOL WINAPI DECLSPEC_HOTPATCH SetStdHandle(DWORD nStdHandle, HANDLE hHandle) /* * FUNCTION: Set the handle for the standard input, standard output or * the standard error device. * * ARGUMENTS: * nStdHandle - Specifies the handle to be set. * hHandle - The handle to set. * * RETURNS: TRUE if the function succeeds, FALSE otherwise. */ { PRTL_USER_PROCESS_PARAMETERS Ppb = NtCurrentPeb()->ProcessParameters; /* No need to check if hHandle == INVALID_HANDLE_VALUE */ switch (nStdHandle) { case STD_INPUT_HANDLE: Ppb->StandardInput = hHandle; return TRUE; case STD_OUTPUT_HANDLE: Ppb->StandardOutput = hHandle; return TRUE; case STD_ERROR_HANDLE: Ppb->StandardError = hHandle; return TRUE; } /* nStdHandle was invalid, bail out */ SetLastError(ERROR_INVALID_HANDLE); return FALSE; } /* * @implemented */ static BOOL IntAllocConsole(LPWSTR Title, DWORD TitleLength, LPWSTR Desktop, DWORD DesktopLength, LPWSTR CurDir, DWORD CurDirLength, LPWSTR AppName, DWORD AppNameLength, LPTHREAD_START_ROUTINE CtrlRoutine, LPTHREAD_START_ROUTINE PropRoutine, PCONSOLE_START_INFO ConsoleStartInfo) { BOOL Success = TRUE; NTSTATUS Status; CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_ALLOCCONSOLE AllocConsoleRequest = &ApiMessage.Data.AllocConsoleRequest; PCSR_CAPTURE_BUFFER CaptureBuffer; AllocConsoleRequest->CtrlRoutine = CtrlRoutine; AllocConsoleRequest->PropRoutine = PropRoutine; CaptureBuffer = CsrAllocateCaptureBuffer(5, TitleLength + DesktopLength + CurDirLength + AppNameLength + sizeof(CONSOLE_START_INFO)); if (CaptureBuffer == NULL) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); Success = FALSE; goto Quit; } CsrCaptureMessageBuffer(CaptureBuffer, ConsoleStartInfo, sizeof(CONSOLE_START_INFO), (PVOID*)&AllocConsoleRequest->ConsoleStartInfo); AllocConsoleRequest->TitleLength = TitleLength; CsrCaptureMessageBuffer(CaptureBuffer, Title, TitleLength, (PVOID*)&AllocConsoleRequest->ConsoleTitle); AllocConsoleRequest->DesktopLength = DesktopLength; CsrCaptureMessageBuffer(CaptureBuffer, Desktop, DesktopLength, (PVOID*)&AllocConsoleRequest->Desktop); AllocConsoleRequest->CurDirLength = CurDirLength; CsrCaptureMessageBuffer(CaptureBuffer, CurDir, CurDirLength, (PVOID*)&AllocConsoleRequest->CurDir); AllocConsoleRequest->AppNameLength = AppNameLength; CsrCaptureMessageBuffer(CaptureBuffer, AppName, AppNameLength, (PVOID*)&AllocConsoleRequest->AppName); CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, CaptureBuffer, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepAlloc), sizeof(*AllocConsoleRequest)); if (!NT_SUCCESS(ApiMessage.Status)) { BaseSetLastNTError(ApiMessage.Status); Success = FALSE; goto Quit; } // Is AllocConsoleRequest->ConsoleStartInfo->InitEvents aligned on handle boundary ???? Status = NtWaitForMultipleObjects(MAX_INIT_EVENTS, AllocConsoleRequest->ConsoleStartInfo->InitEvents, WaitAny, FALSE, NULL); if (!NT_SUCCESS(Status)) { BaseSetLastNTError(Status); Success = FALSE; goto Quit; } NtClose(AllocConsoleRequest->ConsoleStartInfo->InitEvents[INIT_SUCCESS]); NtClose(AllocConsoleRequest->ConsoleStartInfo->InitEvents[INIT_FAILURE]); if (Status != INIT_SUCCESS) { NtCurrentPeb()->ProcessParameters->ConsoleHandle = NULL; Success = FALSE; } else { RtlCopyMemory(ConsoleStartInfo, AllocConsoleRequest->ConsoleStartInfo, sizeof(CONSOLE_START_INFO)); Success = TRUE; } Quit: if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer); return Success; } BOOL WINAPI DECLSPEC_HOTPATCH AllocConsole(VOID) { BOOL Success; CONSOLE_START_INFO ConsoleStartInfo; PWCHAR ConsoleTitle; PWCHAR Desktop; PWCHAR AppName; PWCHAR CurDir; ULONG TitleLength = (MAX_PATH + 1) * sizeof(WCHAR); ULONG DesktopLength = (MAX_PATH + 1) * sizeof(WCHAR); ULONG AppNameLength = 128 * sizeof(WCHAR); ULONG CurDirLength = (MAX_PATH + 1) * sizeof(WCHAR); LCID lcid; RtlEnterCriticalSection(&ConsoleLock); if (NtCurrentPeb()->ProcessParameters->ConsoleHandle) { DPRINT1("AllocConsole: Allocating a console to a process already having one\n"); SetLastError(ERROR_ACCESS_DENIED); Success = FALSE; goto Quit; } /* Set up the console properties */ SetUpConsoleInfo(FALSE, &TitleLength, &ConsoleTitle, &DesktopLength, &Desktop, &ConsoleStartInfo); DPRINT("ConsoleTitle = '%S' - Desktop = '%S'\n", ConsoleTitle, Desktop); /* Initialize the Input EXE name */ InitExeName(); SetUpAppName(FALSE, &CurDirLength, &CurDir, &AppNameLength, &AppName); DPRINT("CurDir = '%S' - AppName = '%S'\n", CurDir, AppName); Success = IntAllocConsole(ConsoleTitle, TitleLength, Desktop, DesktopLength, CurDir, CurDirLength, AppName, AppNameLength, ConsoleControlDispatcher, PropDialogHandler, &ConsoleStartInfo); if (Success) { /* Set up the handles */ SetUpHandles(&ConsoleStartInfo); InputWaitHandle = ConsoleStartInfo.InputWaitHandle; /* Initialize Console Ctrl Handling */ InitializeCtrlHandling(); /* Sets the current console locale for this thread */ SetTEBLangID(lcid); } Quit: RtlLeaveCriticalSection(&ConsoleLock); return Success; } /* * @implemented */ BOOL WINAPI DECLSPEC_HOTPATCH FreeConsole(VOID) { BOOL Success = TRUE; CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_FREECONSOLE FreeConsoleRequest = &ApiMessage.Data.FreeConsoleRequest; HANDLE ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; RtlEnterCriticalSection(&ConsoleLock); /* We must have a non-trivial handle to close */ if (ConsoleHandle == NULL) // IsConsoleHandle(ConsoleHandle) { SetLastError(ERROR_INVALID_PARAMETER); Success = FALSE; goto Quit; } /* 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); Success = FALSE; goto Quit; } /* Reset the console handle */ NtCurrentPeb()->ProcessParameters->ConsoleHandle = NULL; /* Close the associated input handle */ CloseHandle(InputWaitHandle); InputWaitHandle = INVALID_HANDLE_VALUE; Quit: RtlLeaveCriticalSection(&ConsoleLock); return Success; } /* * @implemented */ BOOL WINAPI GetConsoleScreenBufferInfo(HANDLE hConsoleOutput, PCONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo) { CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_GETSCREENBUFFERINFO ScreenBufferInfoRequest = &ApiMessage.Data.ScreenBufferInfoRequest; if (lpConsoleScreenBufferInfo == NULL) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } ScreenBufferInfoRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; ScreenBufferInfoRequest->OutputHandle = hConsoleOutput; CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, NULL, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetScreenBufferInfo), sizeof(*ScreenBufferInfoRequest)); if (!NT_SUCCESS(ApiMessage.Status)) { BaseSetLastNTError(ApiMessage.Status); return FALSE; } lpConsoleScreenBufferInfo->dwSize = ScreenBufferInfoRequest->ScreenBufferSize; lpConsoleScreenBufferInfo->dwCursorPosition = ScreenBufferInfoRequest->CursorPosition; lpConsoleScreenBufferInfo->wAttributes = ScreenBufferInfoRequest->Attributes; lpConsoleScreenBufferInfo->srWindow.Left = ScreenBufferInfoRequest->ViewOrigin.X; lpConsoleScreenBufferInfo->srWindow.Top = ScreenBufferInfoRequest->ViewOrigin.Y; lpConsoleScreenBufferInfo->srWindow.Right = ScreenBufferInfoRequest->ViewOrigin.X + ScreenBufferInfoRequest->ViewSize.X - 1; lpConsoleScreenBufferInfo->srWindow.Bottom = ScreenBufferInfoRequest->ViewOrigin.Y + ScreenBufferInfoRequest->ViewSize.Y - 1; lpConsoleScreenBufferInfo->dwMaximumWindowSize = ScreenBufferInfoRequest->MaximumViewSize; return TRUE; } /* * @implemented */ BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleCursorPosition(HANDLE hConsoleOutput, COORD dwCursorPosition) { CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_SETCURSORPOSITION SetCursorPositionRequest = &ApiMessage.Data.SetCursorPositionRequest; SetCursorPositionRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; SetCursorPositionRequest->OutputHandle = hConsoleOutput; SetCursorPositionRequest->Position = dwCursorPosition; CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, NULL, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetCursorPosition), sizeof(*SetCursorPositionRequest)); if (!NT_SUCCESS(ApiMessage.Status)) { BaseSetLastNTError(ApiMessage.Status); return FALSE; } return TRUE; } /* * @implemented */ BOOL WINAPI GetConsoleMode(HANDLE hConsoleHandle, LPDWORD lpMode) { CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_GETSETCONSOLEMODE ConsoleModeRequest = &ApiMessage.Data.ConsoleModeRequest; if (lpMode == NULL) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } ConsoleModeRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; ConsoleModeRequest->Handle = hConsoleHandle; CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, NULL, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetMode), sizeof(*ConsoleModeRequest)); if (!NT_SUCCESS(ApiMessage.Status)) { BaseSetLastNTError(ApiMessage.Status); return FALSE; } *lpMode = ConsoleModeRequest->Mode; return TRUE; } /* * @implemented */ BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleMode(HANDLE hConsoleHandle, DWORD dwMode) { CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_GETSETCONSOLEMODE ConsoleModeRequest = &ApiMessage.Data.ConsoleModeRequest; ConsoleModeRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; ConsoleModeRequest->Handle = hConsoleHandle; ConsoleModeRequest->Mode = dwMode; CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, NULL, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetMode), sizeof(*ConsoleModeRequest)); if (!NT_SUCCESS(ApiMessage.Status)) { BaseSetLastNTError(ApiMessage.Status); return FALSE; } return TRUE; } /* * @implemented */ BOOL WINAPI GetNumberOfConsoleInputEvents(HANDLE hConsoleInput, LPDWORD lpNumberOfEvents) { CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_GETNUMINPUTEVENTS GetNumInputEventsRequest = &ApiMessage.Data.GetNumInputEventsRequest; GetNumInputEventsRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; GetNumInputEventsRequest->InputHandle = hConsoleInput; GetNumInputEventsRequest->NumberOfEvents = 0; CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, NULL, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetNumberOfInputEvents), sizeof(*GetNumInputEventsRequest)); if (!NT_SUCCESS(ApiMessage.Status)) { BaseSetLastNTError(ApiMessage.Status); return FALSE; } if (lpNumberOfEvents == NULL) { SetLastError(ERROR_INVALID_ACCESS); return FALSE; } *lpNumberOfEvents = GetNumInputEventsRequest->NumberOfEvents; return TRUE; } /* * @implemented */ COORD WINAPI DECLSPEC_HOTPATCH GetLargestConsoleWindowSize(HANDLE hConsoleOutput) { CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_GETLARGESTWINDOWSIZE GetLargestWindowSizeRequest = &ApiMessage.Data.GetLargestWindowSizeRequest; GetLargestWindowSizeRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; GetLargestWindowSizeRequest->OutputHandle = hConsoleOutput; GetLargestWindowSizeRequest->Size.X = 0; GetLargestWindowSizeRequest->Size.Y = 0; CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, NULL, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetLargestWindowSize), sizeof(*GetLargestWindowSizeRequest)); if (!NT_SUCCESS(ApiMessage.Status)) { BaseSetLastNTError(ApiMessage.Status); } DPRINT("GetLargestConsoleWindowSize, X = %d, Y = %d\n", GetLargestWindowSizeRequest->Size.X, GetLargestWindowSizeRequest->Size.Y); return GetLargestWindowSizeRequest->Size; } /* * @implemented */ BOOL WINAPI GetConsoleCursorInfo(HANDLE hConsoleOutput, PCONSOLE_CURSOR_INFO lpConsoleCursorInfo) { CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_GETSETCURSORINFO CursorInfoRequest = &ApiMessage.Data.CursorInfoRequest; if (!lpConsoleCursorInfo) { if (!hConsoleOutput) SetLastError(ERROR_INVALID_HANDLE); else SetLastError(ERROR_INVALID_ACCESS); return FALSE; } CursorInfoRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; CursorInfoRequest->OutputHandle = hConsoleOutput; CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, NULL, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetCursorInfo), sizeof(*CursorInfoRequest)); if (!NT_SUCCESS(ApiMessage.Status)) { BaseSetLastNTError(ApiMessage.Status); return FALSE; } *lpConsoleCursorInfo = CursorInfoRequest->Info; return TRUE; } /* * @implemented */ BOOL WINAPI SetConsoleCursorInfo(HANDLE hConsoleOutput, CONST CONSOLE_CURSOR_INFO *lpConsoleCursorInfo) { CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_GETSETCURSORINFO CursorInfoRequest = &ApiMessage.Data.CursorInfoRequest; CursorInfoRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; CursorInfoRequest->OutputHandle = hConsoleOutput; CursorInfoRequest->Info = *lpConsoleCursorInfo; CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, NULL, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetCursorInfo), sizeof(*CursorInfoRequest)); if (!NT_SUCCESS(ApiMessage.Status)) { BaseSetLastNTError(ApiMessage.Status); return FALSE; } return TRUE; } /* * @implemented */ BOOL WINAPI GetNumberOfConsoleMouseButtons(LPDWORD lpNumberOfMouseButtons) { CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_GETMOUSEINFO GetMouseInfoRequest = &ApiMessage.Data.GetMouseInfoRequest; GetMouseInfoRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, NULL, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetMouseInfo), sizeof(*GetMouseInfoRequest)); if (!NT_SUCCESS(ApiMessage.Status)) { BaseSetLastNTError(ApiMessage.Status); return FALSE; } *lpNumberOfMouseButtons = GetMouseInfoRequest->NumButtons; return TRUE; } /* * @implemented */ BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleActiveScreenBuffer(HANDLE hConsoleOutput) { CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_SETACTIVESCREENBUFFER SetScreenBufferRequest = &ApiMessage.Data.SetScreenBufferRequest; SetScreenBufferRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; SetScreenBufferRequest->OutputHandle = hConsoleOutput; CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, NULL, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetActiveScreenBuffer), sizeof(*SetScreenBufferRequest)); if (!NT_SUCCESS(ApiMessage.Status)) { BaseSetLastNTError(ApiMessage.Status); return FALSE; } return TRUE; } /* * @implemented */ BOOL WINAPI DECLSPEC_HOTPATCH FlushConsoleInputBuffer(HANDLE hConsoleInput) { CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_FLUSHINPUTBUFFER FlushInputBufferRequest = &ApiMessage.Data.FlushInputBufferRequest; FlushInputBufferRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; FlushInputBufferRequest->InputHandle = hConsoleInput; CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, NULL, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepFlushInputBuffer), sizeof(*FlushInputBufferRequest)); if (!NT_SUCCESS(ApiMessage.Status)) { BaseSetLastNTError(ApiMessage.Status); return FALSE; } return TRUE; } /* * @implemented */ BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleScreenBufferSize(HANDLE hConsoleOutput, COORD dwSize) { CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_SETSCREENBUFFERSIZE SetScreenBufferSizeRequest = &ApiMessage.Data.SetScreenBufferSizeRequest; SetScreenBufferSizeRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; SetScreenBufferSizeRequest->OutputHandle = hConsoleOutput; SetScreenBufferSizeRequest->Size = dwSize; CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, NULL, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetScreenBufferSize), sizeof(*SetScreenBufferSizeRequest)); if (!NT_SUCCESS(ApiMessage.Status)) { BaseSetLastNTError(ApiMessage.Status); return FALSE; } return TRUE; } static BOOL IntScrollConsoleScreenBuffer(HANDLE hConsoleOutput, CONST SMALL_RECT* lpScrollRectangle, CONST SMALL_RECT* lpClipRectangle, COORD dwDestinationOrigin, CONST CHAR_INFO* lpFill, BOOL bUnicode) { CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_SCROLLSCREENBUFFER ScrollScreenBufferRequest = &ApiMessage.Data.ScrollScreenBufferRequest; ScrollScreenBufferRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; ScrollScreenBufferRequest->OutputHandle = hConsoleOutput; ScrollScreenBufferRequest->ScrollRectangle = *lpScrollRectangle; if (lpClipRectangle != NULL) { ScrollScreenBufferRequest->UseClipRectangle = TRUE; ScrollScreenBufferRequest->ClipRectangle = *lpClipRectangle; } else { ScrollScreenBufferRequest->UseClipRectangle = FALSE; } ScrollScreenBufferRequest->DestinationOrigin = dwDestinationOrigin; ScrollScreenBufferRequest->Fill = *lpFill; ScrollScreenBufferRequest->Unicode = bUnicode; CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, NULL, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepScrollScreenBuffer), sizeof(*ScrollScreenBufferRequest)); if (!NT_SUCCESS(ApiMessage.Status)) { BaseSetLastNTError(ApiMessage.Status); return FALSE; } return TRUE; } /* * @implemented */ BOOL WINAPI DECLSPEC_HOTPATCH ScrollConsoleScreenBufferA(HANDLE hConsoleOutput, CONST SMALL_RECT* lpScrollRectangle, CONST SMALL_RECT* lpClipRectangle, COORD dwDestinationOrigin, CONST CHAR_INFO* lpFill) { return IntScrollConsoleScreenBuffer(hConsoleOutput, lpScrollRectangle, lpClipRectangle, dwDestinationOrigin, lpFill, FALSE); } /* * @implemented */ BOOL WINAPI DECLSPEC_HOTPATCH ScrollConsoleScreenBufferW(HANDLE hConsoleOutput, CONST SMALL_RECT *lpScrollRectangle, CONST SMALL_RECT *lpClipRectangle, COORD dwDestinationOrigin, CONST CHAR_INFO *lpFill) { return IntScrollConsoleScreenBuffer(hConsoleOutput, lpScrollRectangle, lpClipRectangle, dwDestinationOrigin, lpFill, TRUE); } /* * @implemented */ BOOL WINAPI SetConsoleWindowInfo(HANDLE hConsoleOutput, BOOL bAbsolute, CONST SMALL_RECT *lpConsoleWindow) { CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_SETWINDOWINFO SetWindowInfoRequest = &ApiMessage.Data.SetWindowInfoRequest; if (lpConsoleWindow == NULL) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } SetWindowInfoRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; SetWindowInfoRequest->OutputHandle = hConsoleOutput; SetWindowInfoRequest->Absolute = bAbsolute; SetWindowInfoRequest->WindowRect = *lpConsoleWindow; CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, NULL, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetWindowInfo), sizeof(*SetWindowInfoRequest)); if (!NT_SUCCESS(ApiMessage.Status)) { BaseSetLastNTError(ApiMessage.Status); return FALSE; } return TRUE; } /* * @implemented */ BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleTextAttribute(HANDLE hConsoleOutput, WORD wAttributes) { CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_SETTEXTATTRIB SetTextAttribRequest = &ApiMessage.Data.SetTextAttribRequest; SetTextAttribRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; SetTextAttribRequest->OutputHandle = hConsoleOutput; SetTextAttribRequest->Attributes = wAttributes; CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, NULL, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetTextAttribute), sizeof(*SetTextAttribRequest)); if (!NT_SUCCESS(ApiMessage.Status)) { BaseSetLastNTError(ApiMessage.Status); return FALSE; } return TRUE; } static BOOL AddConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine) { PHANDLER_ROUTINE* NewCtrlHandlers = NULL; if (HandlerRoutine == NULL) { NtCurrentPeb()->ProcessParameters->ConsoleFlags = TRUE; return TRUE; } if (NrCtrlHandlers == NrAllocatedHandlers) { NewCtrlHandlers = RtlAllocateHeap(RtlGetProcessHeap(), 0, (NrCtrlHandlers + 4) * sizeof(PHANDLER_ROUTINE)); if (NewCtrlHandlers == NULL) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return FALSE; } memmove(NewCtrlHandlers, CtrlHandlers, sizeof(PHANDLER_ROUTINE) * NrCtrlHandlers); if (NrAllocatedHandlers > 1) RtlFreeHeap(RtlGetProcessHeap(), 0, CtrlHandlers); CtrlHandlers = NewCtrlHandlers; NrAllocatedHandlers += 4; } ASSERT(NrCtrlHandlers < NrAllocatedHandlers); CtrlHandlers[NrCtrlHandlers++] = HandlerRoutine; return TRUE; } static BOOL RemoveConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine) { ULONG i; if (HandlerRoutine == NULL) { NtCurrentPeb()->ProcessParameters->ConsoleFlags = FALSE; return TRUE; } for (i = 0; i < NrCtrlHandlers; i++) { if (CtrlHandlers[i] == HandlerRoutine) { if (i < (NrCtrlHandlers - 1)) { memmove(&CtrlHandlers[i], &CtrlHandlers[i+1], (NrCtrlHandlers - i + 1) * sizeof(PHANDLER_ROUTINE)); } NrCtrlHandlers--; return TRUE; } } SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } /* * @implemented */ BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine, BOOL Add) { BOOL Ret; RtlEnterCriticalSection(&ConsoleLock); if (Add) Ret = AddConsoleCtrlHandler(HandlerRoutine); else Ret = RemoveConsoleCtrlHandler(HandlerRoutine); RtlLeaveCriticalSection(&ConsoleLock); return Ret; } /* * @implemented */ BOOL WINAPI DECLSPEC_HOTPATCH GenerateConsoleCtrlEvent(DWORD dwCtrlEvent, DWORD dwProcessGroupId) { CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_GENERATECTRLEVENT GenerateCtrlEventRequest = &ApiMessage.Data.GenerateCtrlEventRequest; if (dwCtrlEvent != CTRL_C_EVENT && dwCtrlEvent != CTRL_BREAK_EVENT) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } GenerateCtrlEventRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; GenerateCtrlEventRequest->CtrlEvent = dwCtrlEvent; GenerateCtrlEventRequest->ProcessGroupId = dwProcessGroupId; CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, NULL, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGenerateCtrlEvent), sizeof(*GenerateCtrlEventRequest)); if (!NT_SUCCESS(ApiMessage.Status)) { BaseSetLastNTError(ApiMessage.Status); return FALSE; } return TRUE; } static DWORD IntGetConsoleTitle(LPVOID lpConsoleTitle, DWORD dwNumChars, BOOLEAN bUnicode) { CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_GETSETCONSOLETITLE TitleRequest = &ApiMessage.Data.TitleRequest; PCSR_CAPTURE_BUFFER CaptureBuffer; if (dwNumChars == 0) return 0; TitleRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; TitleRequest->Length = dwNumChars * (bUnicode ? sizeof(WCHAR) : sizeof(CHAR)); TitleRequest->Unicode = bUnicode; CaptureBuffer = CsrAllocateCaptureBuffer(1, TitleRequest->Length); if (CaptureBuffer == NULL) { DPRINT1("CsrAllocateCaptureBuffer failed!\n"); SetLastError(ERROR_NOT_ENOUGH_MEMORY); return 0; } CsrAllocateMessagePointer(CaptureBuffer, TitleRequest->Length, (PVOID*)&TitleRequest->Title); CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, CaptureBuffer, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetTitle), sizeof(*TitleRequest)); if (!NT_SUCCESS(ApiMessage.Status)) { CsrFreeCaptureBuffer(CaptureBuffer); BaseSetLastNTError(ApiMessage.Status); return 0; } dwNumChars = TitleRequest->Length / (bUnicode ? sizeof(WCHAR) : sizeof(CHAR)); if (dwNumChars > 0) { RtlCopyMemory(lpConsoleTitle, TitleRequest->Title, TitleRequest->Length); if (bUnicode) ((LPWSTR)lpConsoleTitle)[dwNumChars] = UNICODE_NULL; else ((LPSTR)lpConsoleTitle)[dwNumChars] = ANSI_NULL; } CsrFreeCaptureBuffer(CaptureBuffer); return dwNumChars; } /* * @implemented */ DWORD WINAPI DECLSPEC_HOTPATCH GetConsoleTitleW(LPWSTR lpConsoleTitle, DWORD nSize) { return IntGetConsoleTitle(lpConsoleTitle, nSize, TRUE); } /* * @implemented */ DWORD WINAPI DECLSPEC_HOTPATCH GetConsoleTitleA(LPSTR lpConsoleTitle, DWORD nSize) { return IntGetConsoleTitle(lpConsoleTitle, nSize, FALSE); } static BOOL IntSetConsoleTitle(CONST VOID *lpConsoleTitle, BOOLEAN bUnicode) { CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_GETSETCONSOLETITLE TitleRequest = &ApiMessage.Data.TitleRequest; PCSR_CAPTURE_BUFFER CaptureBuffer; ULONG NumChars = (ULONG)(lpConsoleTitle ? (bUnicode ? wcslen(lpConsoleTitle) : strlen(lpConsoleTitle)) : 0); TitleRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; TitleRequest->Length = NumChars * (bUnicode ? sizeof(WCHAR) : sizeof(CHAR)); TitleRequest->Unicode = bUnicode; CaptureBuffer = CsrAllocateCaptureBuffer(1, TitleRequest->Length); if (CaptureBuffer == NULL) { DPRINT1("CsrAllocateCaptureBuffer failed!\n"); SetLastError(ERROR_NOT_ENOUGH_MEMORY); return FALSE; } CsrCaptureMessageBuffer(CaptureBuffer, (PVOID)lpConsoleTitle, TitleRequest->Length, (PVOID*)&TitleRequest->Title); CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, CaptureBuffer, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetTitle), sizeof(*TitleRequest)); CsrFreeCaptureBuffer(CaptureBuffer); if (!NT_SUCCESS(ApiMessage.Status)) { BaseSetLastNTError(ApiMessage.Status); return FALSE; } return TRUE; } /* * @implemented */ BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleTitleW(LPCWSTR lpConsoleTitle) { return IntSetConsoleTitle(lpConsoleTitle, TRUE); } /* * @implemented */ BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleTitleA(LPCSTR lpConsoleTitle) { return IntSetConsoleTitle(lpConsoleTitle, FALSE); } /* * @implemented */ HANDLE WINAPI CreateConsoleScreenBuffer(DWORD dwDesiredAccess, DWORD dwShareMode, CONST SECURITY_ATTRIBUTES *lpSecurityAttributes, DWORD dwFlags, LPVOID lpScreenBufferData) { CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_CREATESCREENBUFFER CreateScreenBufferRequest = &ApiMessage.Data.CreateScreenBufferRequest; PCSR_CAPTURE_BUFFER CaptureBuffer = NULL; PCONSOLE_GRAPHICS_BUFFER_INFO GraphicsBufferInfo = lpScreenBufferData; if ( (dwDesiredAccess & ~(GENERIC_READ | GENERIC_WRITE)) || (dwShareMode & ~(FILE_SHARE_READ | FILE_SHARE_WRITE)) || (dwFlags != CONSOLE_TEXTMODE_BUFFER && dwFlags != CONSOLE_GRAPHICS_BUFFER) ) { SetLastError(ERROR_INVALID_PARAMETER); return INVALID_HANDLE_VALUE; } CreateScreenBufferRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; CreateScreenBufferRequest->DesiredAccess = dwDesiredAccess; CreateScreenBufferRequest->InheritHandle = (lpSecurityAttributes ? lpSecurityAttributes->bInheritHandle : FALSE); CreateScreenBufferRequest->ShareMode = dwShareMode; CreateScreenBufferRequest->ScreenBufferType = dwFlags; if (dwFlags == CONSOLE_GRAPHICS_BUFFER) { if (CreateScreenBufferRequest->InheritHandle || GraphicsBufferInfo == NULL) { SetLastError(ERROR_INVALID_PARAMETER); return INVALID_HANDLE_VALUE; } CreateScreenBufferRequest->GraphicsBufferInfo = *GraphicsBufferInfo; CaptureBuffer = CsrAllocateCaptureBuffer(1, GraphicsBufferInfo->dwBitMapInfoLength); if (CaptureBuffer == NULL) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return INVALID_HANDLE_VALUE; } CsrCaptureMessageBuffer(CaptureBuffer, (PVOID)GraphicsBufferInfo->lpBitMapInfo, GraphicsBufferInfo->dwBitMapInfoLength, (PVOID*)&CreateScreenBufferRequest->GraphicsBufferInfo.lpBitMapInfo); } CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, CaptureBuffer, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepCreateScreenBuffer), sizeof(*CreateScreenBufferRequest)); if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer); if (!NT_SUCCESS(ApiMessage.Status)) { BaseSetLastNTError(ApiMessage.Status); return INVALID_HANDLE_VALUE; } if (dwFlags == CONSOLE_GRAPHICS_BUFFER && GraphicsBufferInfo) { GraphicsBufferInfo->hMutex = CreateScreenBufferRequest->hMutex ; // CreateScreenBufferRequest->GraphicsBufferInfo.hMutex ; GraphicsBufferInfo->lpBitMap = CreateScreenBufferRequest->lpBitMap; // CreateScreenBufferRequest->GraphicsBufferInfo.lpBitMap; } return CreateScreenBufferRequest->OutputHandle; } /* * @implemented */ UINT WINAPI DECLSPEC_HOTPATCH GetConsoleCP(VOID) { CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_GETINPUTOUTPUTCP GetConsoleCPRequest = &ApiMessage.Data.GetConsoleCPRequest; /* Get the Input Code Page */ GetConsoleCPRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; GetConsoleCPRequest->OutputCP = FALSE; CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, NULL, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetCP), sizeof(*GetConsoleCPRequest)); if (!NT_SUCCESS(ApiMessage.Status)) { BaseSetLastNTError(ApiMessage.Status); return 0; } return GetConsoleCPRequest->CodePage; } /* * @implemented */ BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleCP(UINT wCodePageID) { CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_SETINPUTOUTPUTCP SetConsoleCPRequest = &ApiMessage.Data.SetConsoleCPRequest; /* Set the Input Code Page */ SetConsoleCPRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; SetConsoleCPRequest->CodePage = wCodePageID; SetConsoleCPRequest->OutputCP = FALSE; /* SetConsoleCPRequest->EventHandle; */ CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, NULL, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetCP), sizeof(*SetConsoleCPRequest)); if (!NT_SUCCESS(ApiMessage.Status)) { BaseSetLastNTError(ApiMessage.Status); return FALSE; } return TRUE; } /* * @implemented */ UINT WINAPI DECLSPEC_HOTPATCH GetConsoleOutputCP(VOID) { CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_GETINPUTOUTPUTCP GetConsoleCPRequest = &ApiMessage.Data.GetConsoleCPRequest; /* Get the Output Code Page */ GetConsoleCPRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; GetConsoleCPRequest->OutputCP = TRUE; CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, NULL, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetCP), sizeof(*GetConsoleCPRequest)); if (!NT_SUCCESS(ApiMessage.Status)) { BaseSetLastNTError(ApiMessage.Status); return 0; } return GetConsoleCPRequest->CodePage; } /* * @implemented */ BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleOutputCP(UINT wCodePageID) { CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_SETINPUTOUTPUTCP SetConsoleCPRequest = &ApiMessage.Data.SetConsoleCPRequest; /* Set the Output Code Page */ SetConsoleCPRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; SetConsoleCPRequest->CodePage = wCodePageID; SetConsoleCPRequest->OutputCP = TRUE; /* SetConsoleCPRequest->EventHandle; */ CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, NULL, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetCP), sizeof(*SetConsoleCPRequest)); if (!NT_SUCCESS(ApiMessage.Status)) { BaseSetLastNTError(ApiMessage.Status); return FALSE; } return TRUE; } /* * @implemented */ DWORD WINAPI GetConsoleProcessList(LPDWORD lpdwProcessList, DWORD dwProcessCount) { CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_GETPROCESSLIST GetProcessListRequest = &ApiMessage.Data.GetProcessListRequest; PCSR_CAPTURE_BUFFER CaptureBuffer; ULONG nProcesses = 0; if (lpdwProcessList == NULL || dwProcessCount == 0) { SetLastError(ERROR_INVALID_PARAMETER); return 0; } CaptureBuffer = CsrAllocateCaptureBuffer(1, dwProcessCount * sizeof(DWORD)); if (CaptureBuffer == NULL) { DPRINT1("CsrAllocateCaptureBuffer failed!\n"); SetLastError(ERROR_NOT_ENOUGH_MEMORY); return 0; } GetProcessListRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; GetProcessListRequest->ProcessCount = dwProcessCount; CsrAllocateMessagePointer(CaptureBuffer, dwProcessCount * sizeof(DWORD), (PVOID*)&GetProcessListRequest->ProcessIdsList); CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, CaptureBuffer, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetProcessList), sizeof(*GetProcessListRequest)); if (!NT_SUCCESS(ApiMessage.Status)) { BaseSetLastNTError(ApiMessage.Status); } else { nProcesses = GetProcessListRequest->ProcessCount; if (dwProcessCount >= nProcesses) { RtlCopyMemory(lpdwProcessList, GetProcessListRequest->ProcessIdsList, nProcesses * sizeof(DWORD)); } } CsrFreeCaptureBuffer(CaptureBuffer); return nProcesses; } /* * @implemented */ BOOL WINAPI GetConsoleSelectionInfo(PCONSOLE_SELECTION_INFO lpConsoleSelectionInfo) { CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_GETSELECTIONINFO GetSelectionInfoRequest = &ApiMessage.Data.GetSelectionInfoRequest; if (lpConsoleSelectionInfo == NULL) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } GetSelectionInfoRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, NULL, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetSelectionInfo), sizeof(*GetSelectionInfoRequest)); if (!NT_SUCCESS(ApiMessage.Status)) { BaseSetLastNTError(ApiMessage.Status); return FALSE; } *lpConsoleSelectionInfo = GetSelectionInfoRequest->Info; return TRUE; } /* * @implemented * @note Strongly inspired by AllocConsole. */ static BOOL IntAttachConsole(DWORD ProcessId, LPTHREAD_START_ROUTINE CtrlRoutine, LPTHREAD_START_ROUTINE PropRoutine, PCONSOLE_START_INFO ConsoleStartInfo) { BOOL Success = TRUE; NTSTATUS Status; CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_ATTACHCONSOLE AttachConsoleRequest = &ApiMessage.Data.AttachConsoleRequest; PCSR_CAPTURE_BUFFER CaptureBuffer; AttachConsoleRequest->ProcessId = ProcessId; AttachConsoleRequest->CtrlRoutine = CtrlRoutine; AttachConsoleRequest->PropRoutine = PropRoutine; CaptureBuffer = CsrAllocateCaptureBuffer(1, sizeof(CONSOLE_START_INFO)); if (CaptureBuffer == NULL) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); Success = FALSE; goto Quit; } CsrCaptureMessageBuffer(CaptureBuffer, ConsoleStartInfo, sizeof(CONSOLE_START_INFO), (PVOID*)&AttachConsoleRequest->ConsoleStartInfo); CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, CaptureBuffer, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepAttach), sizeof(*AttachConsoleRequest)); if (!NT_SUCCESS(ApiMessage.Status)) { BaseSetLastNTError(ApiMessage.Status); Success = FALSE; goto Quit; } // Is AttachConsoleRequest->ConsoleStartInfo->InitEvents aligned on handle boundary ???? Status = NtWaitForMultipleObjects(MAX_INIT_EVENTS, AttachConsoleRequest->ConsoleStartInfo->InitEvents, WaitAny, FALSE, NULL); if (!NT_SUCCESS(Status)) { BaseSetLastNTError(Status); Success = FALSE; goto Quit; } NtClose(AttachConsoleRequest->ConsoleStartInfo->InitEvents[INIT_SUCCESS]); NtClose(AttachConsoleRequest->ConsoleStartInfo->InitEvents[INIT_FAILURE]); if (Status != INIT_SUCCESS) { NtCurrentPeb()->ProcessParameters->ConsoleHandle = NULL; Success = FALSE; } else { RtlCopyMemory(ConsoleStartInfo, AttachConsoleRequest->ConsoleStartInfo, sizeof(CONSOLE_START_INFO)); Success = TRUE; } Quit: if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer); return Success; } BOOL WINAPI AttachConsole(DWORD dwProcessId) { BOOL Success; CONSOLE_START_INFO ConsoleStartInfo; DWORD dummy; LCID lcid; RtlEnterCriticalSection(&ConsoleLock); if (NtCurrentPeb()->ProcessParameters->ConsoleHandle) { DPRINT1("AttachConsole: Attaching a console to a process already having one\n"); SetLastError(ERROR_ACCESS_DENIED); Success = FALSE; goto Quit; } /* Set up the console properties */ SetUpConsoleInfo(FALSE, &dummy, NULL, &dummy, NULL, &ConsoleStartInfo); Success = IntAttachConsole(dwProcessId, ConsoleControlDispatcher, PropDialogHandler, &ConsoleStartInfo); if (Success) { /* Set up the handles */ SetUpHandles(&ConsoleStartInfo); InputWaitHandle = ConsoleStartInfo.InputWaitHandle; /* Initialize Console Ctrl Handling */ InitializeCtrlHandling(); /* Sets the current console locale for this thread */ SetTEBLangID(lcid); } Quit: RtlLeaveCriticalSection(&ConsoleLock); return Success; } /* * @implemented */ HWND WINAPI DECLSPEC_HOTPATCH GetConsoleWindow(VOID) { CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_GETWINDOW GetWindowRequest = &ApiMessage.Data.GetWindowRequest; GetWindowRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, NULL, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetConsoleWindow), sizeof(*GetWindowRequest)); if (!NT_SUCCESS(ApiMessage.Status)) { BaseSetLastNTError(ApiMessage.Status); return (HWND)NULL; } return GetWindowRequest->WindowHandle; } /* * @implemented */ BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleIcon(HICON hIcon) { CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_SETICON SetIconRequest = &ApiMessage.Data.SetIconRequest; SetIconRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; SetIconRequest->IconHandle = hIcon; CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, NULL, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetIcon), sizeof(*SetIconRequest)); if (!NT_SUCCESS(ApiMessage.Status)) { BaseSetLastNTError(ApiMessage.Status); return FALSE; } return TRUE; } /****************************************************************************** * \name SetConsoleInputExeNameW * \brief Sets the console input file name from a unicode string. * \param lpExeName Pointer to a unicode string with the name. * \return TRUE if successful, FALSE if unsuccessful. * \remarks If lpExeName is 0 or the string length is 0 or greater than 255, * the function fails and sets last error to ERROR_INVALID_PARAMETER. */ BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleInputExeNameW(IN LPCWSTR lpExeName) { DWORD ExeLength; ExeLength = lstrlenW(lpExeName); if ((ExeLength == 0) || (ExeLength >= EXENAME_LENGTH)) { /* Fail if string is empty or too long */ SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } RtlEnterCriticalSection(&ExeNameLock); _SEH2_TRY { /* Set the input EXE name, not NULL terminated */ RtlCopyMemory(ExeNameBuffer, lpExeName, ExeLength * sizeof(WCHAR)); ExeNameLength = (USHORT)ExeLength; } _SEH2_FINALLY { RtlLeaveCriticalSection(&ExeNameLock); } _SEH2_END; return TRUE; } /****************************************************************************** * \name SetConsoleInputExeNameA * \brief Sets the console input file name from an ansi string. * \param lpExeName Pointer to an ansi string with the name. * \return TRUE if successful, FALSE if unsuccessful. * \remarks If lpExeName is 0 or the string length is 0 or greater than 255, * the function fails and sets last error to ERROR_INVALID_PARAMETER. */ BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleInputExeNameA(IN LPCSTR lpExeName) { NTSTATUS Status; #ifdef USE_TEB_STATIC_USTR PUNICODE_STRING ExeNameU; #else UNICODE_STRING ExeNameU; #endif ANSI_STRING ExeNameA; #ifndef USE_TEB_STATIC_USTR WCHAR Buffer[EXENAME_LENGTH]; #endif #ifdef USE_TEB_STATIC_USTR /* * Use the TEB static UNICODE string for storage. It is already * initialized at process creation time by the Memory Manager. */ ExeNameU = &NtCurrentTeb()->StaticUnicodeString; #endif /* Initialize string for conversion */ RtlInitAnsiString(&ExeNameA, lpExeName); #if 1 if ((ExeNameA.Length == 0) || (ExeNameA.Length >= EXENAME_LENGTH)) { /* Fail if string is empty or too long */ SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } #endif #ifndef USE_TEB_STATIC_USTR ExeNameU.Length = 0; ExeNameU.MaximumLength = (USHORT)sizeof(Buffer); ExeNameU.Buffer = Buffer; #endif #ifdef USE_TEB_STATIC_USTR Status = RtlAnsiStringToUnicodeString(ExeNameU, &ExeNameA, FALSE); #else Status = RtlAnsiStringToUnicodeString(&ExeNameU, &ExeNameA, FALSE); #endif if (!NT_SUCCESS(Status)) { /* Fail if string is empty or too long */ if (Status == STATUS_BUFFER_OVERFLOW) SetLastError(ERROR_FILENAME_EXCED_RANGE); else SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } #ifdef USE_TEB_STATIC_USTR return SetConsoleInputExeNameW(ExeNameU->Buffer); #else return SetConsoleInputExeNameW(ExeNameU.Buffer); #endif } /****************************************************************************** * \name GetConsoleInputExeNameW * \brief Retrieves the console input file name as unicode string. * \param nBufferLength Length of the buffer in WCHARs. * Specify 0 to receive the needed buffer length. * \param lpBuffer Pointer to a buffer that receives the string. * \return Needed buffer size if \p nBufferLength is 0. * Otherwise 1 if successful, 2 if buffer is too small. * \remarks Sets last error value to ERROR_BUFFER_OVERFLOW if the buffer * is not big enough. */ DWORD WINAPI DECLSPEC_HOTPATCH GetConsoleInputExeNameW(IN DWORD nBufferLength, OUT LPWSTR lpExeName) { if (nBufferLength <= ExeNameLength) { /* Buffer is not large enough! Return the correct size. */ SetLastError(ERROR_BUFFER_OVERFLOW); return ExeNameLength + 1; } RtlEnterCriticalSection(&ExeNameLock); _SEH2_TRY { /* Copy the input EXE name and NULL-terminate it */ RtlCopyMemory(lpExeName, ExeNameBuffer, ExeNameLength * sizeof(WCHAR)); lpExeName[ExeNameLength] = UNICODE_NULL; } _SEH2_FINALLY { RtlLeaveCriticalSection(&ExeNameLock); } _SEH2_END; return TRUE; } /****************************************************************************** * \name GetConsoleInputExeNameA * \brief Retrieves the console input file name as ansi string. * \param nBufferLength Length of the buffer in CHARs. * \param lpBuffer Pointer to a buffer that receives the string. * \return 1 if successful, 2 if buffer is too small. * \remarks Sets last error value to ERROR_BUFFER_OVERFLOW if the buffer * is not big enough. The buffer receives as much characters as fit. */ DWORD WINAPI DECLSPEC_HOTPATCH GetConsoleInputExeNameA(IN DWORD nBufferLength, OUT LPSTR lpExeName) { NTSTATUS Status; DWORD ExeLength; UNICODE_STRING BufferU; ANSI_STRING BufferA; WCHAR Buffer[EXENAME_LENGTH]; /* Get the UNICODE name */ ExeLength = GetConsoleInputExeNameW(EXENAME_LENGTH, Buffer); if ((ExeLength == 0) || (ExeLength >= EXENAME_LENGTH)) return ExeLength; /* Initialize the strings for conversion */ RtlInitUnicodeString(&BufferU, Buffer); BufferA.Length = 0; BufferA.MaximumLength = (USHORT)nBufferLength; BufferA.Buffer = lpExeName; /* Convert UNICODE name to ANSI, copying as much chars as it can fit */ Status = RtlUnicodeStringToAnsiString(&BufferA, &BufferU, FALSE); if (!NT_SUCCESS(Status)) { if (Status == STATUS_BUFFER_OVERFLOW) { SetLastError(ERROR_BUFFER_OVERFLOW); return ExeLength + 1; } SetLastError(ERROR_INVALID_PARAMETER); } return ExeLength; } BOOL WINAPI GetConsoleCharType(HANDLE hConsole, COORD Coord, PDWORD Type) { STUB; return FALSE; } BOOL WINAPI DECLSPEC_HOTPATCH GetConsoleCursorMode(HANDLE hConsole, PBOOL pUnknown1, PBOOL pUnknown2) { STUB; return FALSE; } BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleCursorMode(HANDLE hConsole, BOOL Unknown1, BOOL Unknown2) { STUB; return FALSE; } BOOL WINAPI DECLSPEC_HOTPATCH GetConsoleNlsMode(HANDLE hConsole, LPDWORD lpMode) { STUB; return FALSE; } BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleNlsMode(HANDLE hConsole, DWORD dwMode) { STUB; return FALSE; } BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleLocalEUDC(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) { STUB; return FALSE; } BOOL WINAPI DECLSPEC_HOTPATCH RegisterConsoleIME(HWND hWnd, LPDWORD ThreadId) { STUB; return FALSE; } BOOL WINAPI DECLSPEC_HOTPATCH RegisterConsoleOS2(BOOL bUnknown) { STUB; return FALSE; } BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleOS2OemFormat(BOOL bUnknown) { STUB; return FALSE; } BOOL WINAPI DECLSPEC_HOTPATCH UnregisterConsoleIME(VOID) { STUB; return FALSE; } static 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; } /* * @implemented (undocumented) */ BOOL WINAPI DECLSPEC_HOTPATCH GetConsoleKeyboardLayoutNameA(OUT LPSTR pszLayoutName) { return IntGetConsoleKeyboardLayoutName(pszLayoutName, TRUE); } /* * @implemented (undocumented) */ BOOL WINAPI DECLSPEC_HOTPATCH GetConsoleKeyboardLayoutNameW(OUT LPWSTR pszLayoutName) { return IntGetConsoleKeyboardLayoutName(pszLayoutName, FALSE); } /* * @implemented */ DWORD WINAPI SetLastConsoleEventActive(VOID) { CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_NOTIFYLASTCLOSE NotifyLastCloseRequest = &ApiMessage.Data.NotifyLastCloseRequest; /* Set the flag used by the console control dispatcher */ LastCloseNotify = TRUE; /* Set up the input arguments */ NotifyLastCloseRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; /* Call CSRSS; just return the NTSTATUS cast to DWORD */ return CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, NULL, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepNotifyLastClose), sizeof(*NotifyLastCloseRequest)); } /* EOF */